| name | config-management |
| description | Guide for Drupal configuration management including Features, config splits, environment handling, and deployment workflows. |
Configuration Management Skill
Comprehensive guide for managing Drupal configuration.
Configuration Systems
| System | Use Case | Location |
|---|
| Config Sync | Full site config export/import | config/sync/ |
| Features | Module-specific config bundles | modules/*/config/install/ |
| Config Split | Environment-specific config | Per-split directories |
1. Features (Module-Level Config)
Structure
modules/custom/mymodule/
├── config/
│ ├── install/ # Config installed with module
│ │ ├── field.storage.node.field_example_date.yml
│ │ ├── field.field.node.example.field_example_date.yml
│ │ └── views.view.example_listing.yml
│ └── optional/ # Config installed if dependencies exist
│ └── block.block.example_sidebar.yml
├── mymodule.info.yml
└── mymodule.module
Feature Commands
./vendor/bin/drush features:status
./vendor/bin/drush features:list --status=overridden
./vendor/bin/drush fr <module> -y
./vendor/bin/drush fr mymodule_news mymodule_events -y
./vendor/bin/drush config:export --diff
Feature Info File
name: 'My Module'
type: module
description: 'Content type and functionality'
package: Custom
core_version_requirement: ^10 || ^11
dependencies:
- drupal:node
- drupal:views
- drupal:datetime
features:
bundle: example
excluded:
- system.site
config/install Rules
DO include:
- Field storage definitions
- Field instance configurations
- View configurations
- Content type configurations
- Taxonomy vocabulary configurations
- Image styles
- Custom block types
DO NOT include:
- UUIDs (remove them!)
- Site-specific config (system.site)
- User accounts
- Environment-specific paths
- API keys or secrets
Removing UUIDs
grep -r "^uuid:" modules/custom/*/config/install/*.yml
sed -i '/^uuid:/d' modules/custom/mymodule/config/install/*.yml
2. Configuration Export/Import
Full Export
./vendor/bin/drush config:export -y
./vendor/bin/drush config:export --destination=/tmp/config-export
Single Config Export
./vendor/bin/drush config:get views.view.example_listing --include-overridden > example_view.yml
./vendor/bin/drush config:get views.view.example_listing
Import
./vendor/bin/drush config:import -y
./vendor/bin/drush config:set views.view.example_listing -y < example_view.yml
Config Status
./vendor/bin/drush config:status
./vendor/bin/drush config:diff views.view.example_listing
3. Environment-Specific Configuration
Settings Per Environment
$config['system.logging']['error_level'] = 'verbose';
$config['system.performance']['css']['preprocess'] = FALSE;
$config['system.performance']['js']['preprocess'] = FALSE;
$config['system.logging']['error_level'] = 'hide';
$config['system.performance']['css']['preprocess'] = TRUE;
$config['system.performance']['js']['preprocess'] = TRUE;
Config Overrides in Settings
$config['core.extension']['module']['devel'] = 0;
$config['core.extension']['module']['kint'] = 0;
$config['mymodule.settings']['api_url'] = getenv('API_URL');
$config['mymodule.settings']['api_key'] = getenv('API_KEY');
$config['environment_indicator.indicator']['bg_color'] = '#ff0000';
$config['environment_indicator.indicator']['name'] = 'PRODUCTION';
Using Config Split
id: development
label: Development
status: true
folder: ../config/split/development
blacklist:
- system.logging
- system.performance
graylist: []
graylist_dependents: true
graylist_skip_equal: true
4. Configuration Validation
Pre-Deployment Checklist
./vendor/bin/drush config:status
./vendor/bin/drush features:status
grep -r "^uuid:" modules/custom/*/config/install/
grep -rE "(localhost|127\.0\.0\.1|dev\.|test\.)" modules/custom/*/config/install/
find modules/custom -name "*.yml" -exec php -r "yaml_parse_file('{}');" \;
Common Issues
| Issue | Symptom | Solution |
|---|
| UUID conflict | "Config already exists" | Remove UUIDs from config/install |
| Missing dependency | Import fails | Add to module's dependencies |
| Schema mismatch | Warnings on import | Update config schema |
| Overridden feature | Changes lost on revert | Export changes to code |
5. Configuration Schema
Schema Definition
mymodule.settings:
type: config_object
label: 'My Module settings'
mapping:
enabled:
type: boolean
label: 'Enable feature'
api_url:
type: string
label: 'API URL'
items_per_page:
type: integer
label: 'Items per page'
allowed_types:
type: sequence
label: 'Allowed content types'
sequence:
type: string
Validate Schema
./vendor/bin/drush config:inspect
./vendor/bin/drush config:inspect mymodule.settings
6. Deployment Workflow
Standard Deployment
./vendor/bin/drush state:set system.maintenance_mode 1 -y
./vendor/bin/drush sql:dump --gzip > backup-$(date +%Y%m%d-%H%M%S).sql.gz
./vendor/bin/drush updb -y
./vendor/bin/drush fr <module_1> <module_2> -y
./vendor/bin/drush cim -y
./vendor/bin/drush cr
./vendor/bin/drush state:set system.maintenance_mode 0 -y
7. Configuration Best Practices
Module Configuration
<?php
$config = \Drupal::config('mymodule.settings');
$value = $config->get('api_url');
$config = \Drupal::configFactory()->getEditable('mymodule.settings');
$config->set('api_url', 'https://api.example.com');
$config->save();
State vs Config
| Use Config For | Use State For |
|---|
| Settings that deploy | Runtime data |
| User-configurable options | Temporary values |
| Feature behavior | Cron timestamps |
| API endpoints | Last sync time |
\Drupal::state()->set('mymodule.last_sync', time());
$lastSync = \Drupal::state()->get('mymodule.last_sync');
Config Dependencies
dependencies:
config:
- field.storage.node.field_example
- node.type.article
module:
- node
- datetime
enforced:
module:
- mymodule
8. Troubleshooting
Config Won't Import
./vendor/bin/drush config:import --preview
./vendor/bin/drush config:import --partial -y
Feature Won't Revert
./vendor/bin/drush features:status <module>
./vendor/bin/drush cr
./vendor/bin/drush fr <module> -y
Find Config Changes
./vendor/bin/drush config:export -y
git diff config/sync/
Reset Config to Code
./vendor/bin/drush config:delete views.view.example_listing
./vendor/bin/drush cr
./vendor/bin/drush fr <module> -y