Skip to content

Drupal Configuration Management — Sync, Import, Export and Deploy

DodaTech Updated 2026-06-27 10 min read

In this tutorial, you'll learn how Drupal configuration management works: setting up the config sync directory, exporting and importing configuration, understanding simple config versus entity config, using config split for environment-specific differences, and building a deployment workflow around configuration management.

What You'll Learn

  • What Configuration Management (CMI) is and how Drupal stores config as YAML files
  • Simple config versus entity config
  • Config sync directory configuration in settings.php
  • Exporting configuration with Drush cex and the admin UI
  • Importing configuration with Drush cim and the admin UI
  • Viewing config differences before import
  • Single-item export and import
  • Configuration overrides in settings.php
  • The Config Split module for environment-specific settings
  • The Features module for bundling config into modules
  • Deployment workflow: export, commit, deploy, import
  • Config validation before import

Why It Matters

Before Configuration Management, Drupal teams copied databases between environments or manually recreated configuration on each server. Configuration Management changed this entirely. Now, every configuration change is a file on disk that you version-control, review in pull requests, and deploy like code. This means no more "it works on my machine" problems, no more manual setup on production, and no more configuration drift between environments.

Real-World Use

A development team of five works on a Drupal site. Each developer creates content types, adds fields, configures views, and updates permissions on their local environment. At the end of a sprint, the lead developer exports all configuration, commits it to Git, and creates a pull request. A reviewer can see exactly what changed by examining the YAML diffs. When the PR is merged, the CI/CD pipeline deploys and runs drush cim on production. All configuration is consistent across environments.

Learning Path

flowchart LR
  A[Drush Commands] --> B[Configuration Management]
  B --> C[Config Types]
  C --> D[Config Sync Directory]
  D --> E[Export and Import]
  E --> F[Config Split]
  F --> G[Features Module]
  G --> H[Deployment Workflow]
  H --> I[Migrate and Go-Live]

What is Configuration Management?

Drupal Configuration Management (CMI) stores the site's configuration in YAML files instead of only in the database. This allows you to track configuration changes in version control and deploy them across environments.

Configuration includes:

  • Content types and fields
  • Views, blocks, and menus
  • User roles and permissions
  • Site settings (site name, email, timezone)
  • Module settings

Configuration does NOT include:

  • Content (nodes, users, taxonomy terms)
  • State data (temporary values like last cron run)

Config Types

Drupal has two types of configuration:

Simple Config

Simple config stores key-value pairs. It is a single flat file per configuration object.

# config/sync/system.site.yml
name: 'My Site'
mail: admin@example.com
slogan: ''
page:
  403: ''
  404: ''
  front: /node
admin_compact_mode: false
weight_select_max: 100
default_langcode: en
<?php
// Accessing simple config
$site_name = \Drupal::config('system.site')->get('name');
$admin_email = \Drupal::config('system.site')->get('mail');

Entity Config

Entity config stores configuration for Drupal entities like content types, views, and roles. Each entity instance gets its own file.

# config/sync/node.type.article.yml
uuid: 123e4567-e89b-12d3-a456-426614174000
langcode: en
status: true
dependencies:
  module:
    - menu_ui
    - node
name: Article
type: article
description: 'Use articles for time-sensitive content.'
help: ''
new_revision: true
preview_mode: 1
display_submitted: true
<?php
// Accessing entity config
$article_config = \Drupal::config('node.type.article');
$label = $article_config->get('name');

Config Sync Directory

The config sync directory stores your exported configuration files. Configure it in settings.php:

<?php
// settings.php
$settings['config_sync_directory'] = '../config/sync';

// Or an absolute path outside the web root
$settings['config_sync_directory'] = '/var/www/config/sync';

Best practice: place the config directory outside the web root so it is not directly accessible via the browser.

# Typical project structure
/var/www/
|-- config/
|   |-- sync/
|       |-- system.site.yml
|       |-- node.type.article.yml
|       |-- core.extension.yml
|-- web/
    |-- index.php
    |-- sites/
    |-- modules/
    |-- themes/

Exporting Configuration

# Export all configuration to the sync directory
drush config:export
# Short form
drush cex

# Export to a specific directory
drush cex --destination=/path/to/config

# Export a single configuration item
drush config:export --filter=system.site

# Export with a custom label (creates a diff directory)
drush cex --label="before-feature-x"

Via Admin UI

Navigate to Configuration > Development > Configuration synchronization (/admin/config/development/configuration). Click Export to download a full or partial archive.

The UI is useful for one-off exports, but Drush is better for regular workflows.

Importing Configuration

Via Drush

# Import all configuration from the sync directory
drush config:import
# Short form
drush cim

# Import a single configuration item
drush config:import --filter=system.site

# Import from a specific directory
drush cim --source=/path/to/config

# Partial import (skip validation)
drush cim --partial

Via Admin UI

Navigate to Configuration > Development > Configuration synchronization. The UI shows:

  • Differences between active config and sync config
  • A list of changes grouped by add, change, delete
  • A confirmation step before importing

Viewing Configuration Differences

Always check what will change before importing:

# Show all differences between active and sync config
drush config:diff

# Show differences for a specific item
drush config:diff views.view.articles

The diff output looks like:

--- Active config
+++ Staged config
@@ -3,7 +3,7 @@
 langcode: en
 status: true
 dependencies:
-  module:
-    - node
+  module:
+    - node
 name: 'New Site Name'

Single Item Export and Import

For granular control:

# Export a single configuration item
drush config:export --filter=core.extension

# Import a single item
drush cim --filter=system.site

# Delete a configuration item
drush config:delete node.type.article

Configuration Overrides in settings.php

Override configuration values without modifying the exported files:

<?php
// settings.php overrides
// These override config values at runtime without
// affecting the stored configuration.

// Override site name for a specific environment
$config['system.site']['name'] = 'My Site (Development)';

// Override a module setting
$config['my_module.settings']['api_endpoint'] = 'https://dev-api.example.com';

// Disable CSS/JS aggregation on development
$config['system.performance']['css']['preprocess'] = false;
$config['system.performance']['js']['preprocess'] = false;

// Override system performance defaults
$config['system.performance']['cache']['page']['use_internal'] = false;

Overrides are environment-specific and never exported. They live in settings.php which is excluded from configuration export.

Config Split Module

The Config Split module lets you have different configuration for different environments:

# Install config_split
composer require drush/drush
composer require drupal/config_split
drush pm:enable config_split
# config/sync/config_split.config_split.dev.yml
name: 'Development Settings'
folder: '../config/splits/dev'
module:
  devel: true
  views_ui: true
theme:
  olivero: false
weight: 0
status: true

Create splits for each environment:

# Create a config split for development
drush config-split:create dev \
  --label="Development" \
  --folder="../config/splits/dev" \
  --module="{devel: true, views_ui: true}"
# config/splits/dev/system.performance.yml
# Development performance settings
css:
  preprocess: false
js:
  preprocess: false
cache:
  page:
    use_internal: false

Activate the split in settings.php:

<?php
// settings.php
$config['config_split.config_split.dev']['status'] = true;

Features Module

The Features module bundles configuration into installable modules:

# Install features
composer require drupal/features
drush pm:enable features
# Generate a feature module from selected configuration
drush features:generate my_blog \
  node.type.article \
  field.field.node.article.body \
  views.view.articles

# Package the feature
drush features:export my_blog

# The feature becomes a module that can be installed
# on any Drupal site to recreate the configuration

Deployment Workflow

A complete configuration deployment workflow:

# Step 1: Export configuration locally
drush cex
git add config/sync/
git commit -m "Export configuration: added article content type"

# Step 2: Push to remote
git push

# Step 3: On the target environment (staging/production)
git pull

# Step 4: Run database updates (if any)
drush updatedb

# Step 5: Import configuration
drush cim

# Step 6: Rebuild cache
drush cr

Safest Import Workflow

For production, add safety checks:

#!/bin/bash
# deploy.sh - Safe deployment script

# Check for differences first
drush config:diff
if [ $? -ne 0 ]; then
  echo "Config differences found. Review before importing."
  exit 1
fi

# Maintenance mode
drush state:set system.maintenance_mode 1

# Import configuration
drush cim --no-interaction

# Rebuild cache
drush cr

# Maintenance mode off
drush state:set system.maintenance_mode 0

echo "Deployment complete."

Common Mistakes

  1. Storing config inside the web root: If the config directory is inside web/, it might be accessible via the browser. Always store it outside the web root.

  2. Not exporting config after changes: After adding a content type, field, or view, you must export configuration. If you do not, the changes exist only in the database and will be lost when the database is refreshed.

  3. Importing config without reviewing differences first: Importing blindly can change settings you did not intend to change. Always run drush config:diff first.

  4. Committing config from different environments into the same directory: If two developers export config from the same site, they might overwrite each other's changes. Coordinate exports and use config splits for environment-specific differences.

  5. Not excluding config overrides from version control: If you use settings.php overrides, exclude them from version control so they do not override production settings. Use a .gitignore for environment-specific files.

Practice Questions

  1. What is the difference between simple config and entity config, and how can you tell which is which from the YAML file?
  2. A developer adds a new field to the article content type on their local site but forgets to export config. What happens when they deploy to production?
  3. How would you have different caching settings on development (caching disabled) versus production (caching enabled) using the Config Split module?
  4. Challenge: Create a deployment workflow for a team of four developers working on the same Drupal site. Define: the branching strategy (feature branches, release branches), the config export Process (who exports, when), the code review process for config YAML files, the deployment stages (dev, staging, production), and the rollback procedure if config import fails. Write a bash script that automates the staging deployment.

FAQ

What is the difference between config and state in Drupal?

Configuration is exportable, version-controllable site settings that should be identical across environments (content types, views, permissions). State is temporary runtime data (last cron run, cache timestamps) that is specific to each environment and never exported.

Can I import configuration on a site that already has content?

Yes. Configuration import only affects configuration, not content. Your nodes, users, and taxonomy terms remain unchanged. However, if you change field definitions, you might need to run drush updatedb to apply field updates.

What happens if configuration import fails?

Drupal validates configuration before importing. If validation fails, the import stops and no changes are applied. Check the error message, fix the issue, and try again. Common issues: missing dependencies, invalid YAML, or incompatible module versions.

How do I handle environment-specific configuration?

Use the Config Split module. It allows you to define splits for each environment (dev, staging, production). Splits override specific configuration items without modifying the main sync directory. Activate the appropriate split in settings.php.

Should I put config changes in the same commit as code changes?

Yes, ideally. When a code change requires configuration (a module needs a content type, a field needs a view), commit both the code and configuration together. This keeps the deploy atomic and prevents incompatibilities.

Mini Project

Goal: Set up a complete configuration management workflow for a Drupal site.

  1. Configure the config sync directory in settings.php (outside web root)
  2. Create a new content type "Product" with fields: name, price, description, category
  3. Create a view that lists products
  4. Export all configuration using drush cex
  5. Review the exported YAML files and identify: simple config files, entity config files, the core.extension.yml file
  6. Commit the exported config to a Git Repository
  7. Set up two config splits: one for development (disable caching, enable devel module) and one for production (enable caching, enable CDN module)
  8. Simulate a deployment: clone the repo to a second environment, run drush cim, and verify the Product content type exists
  9. Make a configuration change on one environment, export it, and import it on another environment to verify the sync

What's Next

Now that you understand configuration management, proceed to migrate API to learn how to migrate content from WordPress and other platforms to Drupal. Then explore performance optimization to speed up your Drupal site.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro