Drupal 8 Configuration Management - Solving the Configuration Conundrum

Drupal 8 Configuration Management

A common difficulty in web development is keeping configuration consistent between environments. Drupal keeps most configuration settings in the database and it can be a pain to keep databases across environments synchronized. Solving this conundrum was one of Drupal 8's goals and the focus of D8's Configuration Management Initiative (CMI). All site configuration is saved in YAML files (hooray for version control!) and can be shared between site environments.

The Way We Were

Let's take a classic example from before D8, using the beloved Views module. When you build a great new view on your local machine you still need to get it onto the production site. You could repeat what you did on your local machine and build the View by hand on prod, but that's just repeating all the work you have already completed, not to mention, prone to user error. Most developers are too lazy to do that anyways, so they depend on Drupal's Features module. The Features module works by exporting db configuration settings into Drupal module code which can be shared amongst environments. It usually works pretty well, but it turns out the Features module was not built for handling deployment and configuration. These tasks have fallen into its lap because, until now, it was the only game in town.

The Way We're Going

With every Drupal 8 installation, the configuration system creates a configuration directory*, sync, to hold the aforementioned YAML configuration files. The directory is actually created as a sub-directory in sites/default/files, into a folder with a long, random hash as its name, prefaced by config_. (Including a random hash makes it near impossible for bad guys to guess the configuration folder name.)

* At the time of writing the default installation actually created two directories: active and staging, but that was changed to just one, the staging directory which subsequently was changed to sync. The blog post has been updated to reflect this.

In picture form...a folder with a really, really long, random name

Config Sync Folder

So in the above screenshot the configuration directory's name is

config_Z1fHk5YnKXiTdJl9lAfz_dqGmrMTzqT9lNnbUF6z4kwKxglnC8srJZBTcI1dIMSCOmOwvEMZ5g

and the full path of the sync directory is:

sites/default/files/config_Z1fHk5YnKXiTdJl9lAfz_dqGmrMTzqT9lNnbUF6z4kwKxglnC8srJZBTcI1dIMSCOmOwvEMZ5g/sync

So that's where the site configuration files live, but by default, for reasons of speed and security, the actual configuration settings are saved in the database. So all the configuration from those YAML files actually gets imported into the database.

The configuration management system provides a UI for uploading and double-checking changes before applying them to the live site. (Of course, there are Drush commands, drush config-export and drush config-import that allow you to import/export through the command line too.)

How do you Feel About Clones?

Now hold on, you can't upload one site's configuration to any old site; you can only synchronize configuration settings between cloned instances of a site. This restriction was a conscious decision made by the Drupal CMI team. So you need to start with one environment and then clone it. If you don't do this, Drupal simply will not allow configuration settings to be imported.

Steps for cloning a site:

  1. Do a db dump of the original database and import it into an empty database for your new clone environment.

  2. Assuming you are using git, (you are using git, right?) you can run git clone to clone the original site files into the clone environment.

  3. Check folder permissions (Did .htaccess come across? Does sites/default/files have sufficient permissions?).

  4. Change settings.php in cloned site to point to the fresh db from step 1.

Assuming your cloned site is working, you are ready to import settings from one environment to another. In my case, I created a new view called bookshelf that needs to get to prod. Below are screenshots of what the process looks like.

Export and Download from Dev

In this screenshot, I have just exported and downloaded my dev environment's configuration tar.gz file.

Config Export

Upload into Prod

Having switched to my prod environment, I select the downloaded tar.gz file and upload it.

Config Import

Successful Upload

After a successful upload you can see that there are changes. Note that my new bookshelf view is there. I can click the View differences button to compare the changes.

Config Success

Vive la Difference

Having clicked the View differences button, I see the changes that are about to be made.

Config Diff

Import All

Satisfied with what I see, I can click Import all to apply the changes.

d8-config-bookshelf-import-all

Import Progress

A progress bar displays as Drupal imports the settings.

d8-config-bookshelf-progress

A Site With a View

Voilà, the new view is on my prod site.

d8-config-view-is-there

Whew, so there were a bunch of steps to get things set up, but once you have your environments in place, it's easy to move settings between them. Of course, in a full-on, professional development environment you would harness the power of Drush and use scripts to do all the dirty work. But that's a tutorial for another time.