One of the big strengths of WordPress is its flexibility. Administrators are often given a wealth of configuration options they can use to bend WordPress to their needs, including which theme to use, what plugins to have turned on, how to format dates, what timezone is set, how many posts to show in listings, etc. And that is barely scratching the surface – add in configuration of plugins and there are quite literally hundreds of configuration options to think about, and that’s not even taking into account a multisite setup.

How do you manage all of these configuration considerations across multiple WordPress environments?

Option 1: Manually

Managing configuration manually is of course an option. If most of the time you are not veering far from the defaults, and your ‘configuration footprint’ is fairly small this is probably ok, although you may wish to document somewhere the configuration you do change, so that it’s captured somewhere. When we’ve done this in the past, we’ve reserved a page on our Confluence space for such documentation.

Option 2: WP DB Migrate Pro

WP DB Migrate Pro is a terrific tool that allows you to easily migrate database content between environments. You can do the entire database or just select tables, and it allows you to run find/replace if you need to replace host names and other things. We’ve used it in the past and it’s an impressive tool. If migration of your database is your sole aim, this is a good choice. However, there are some drawbacks.

It’s a pretty opaque tool; you can’t see what the configuration options are, or what is being changed across environments. You can’t version control configuration easily; it depends on you having a master database which you sync from. You can’t easily diff the changes between environments, or see how configuration may have changed over time.

Another issue here is you need to be really careful with syncing across database content, not only because of risk of overwriting important data but also from a GDPR point of view, as you need to ensure no personal data is present on non-production environments (or similar) at all points.

Other syncing tools

There are other syncing tools as well, one example is WordPress VIP’s sync tool. This works not too dissimilarly to WP Migrate DB Pro, and again works by replacing the database. However like WP Migrate DB Pro, it doesn’t give easy visibility of configuration being updated, and there are similar concerns about data being overwritten as well as GDPR risks.

Option 3: Dictator

So, what do we use? Well, a little known tool developed in the halcyon days of 2014 called Dictator.

Developed by Daniel Bachhuber with the goal of improving the portability of WordPress and to automate away the problems of manual configuration, it was exactly the tool we were looking for.

How does it work?

The basics of Dictator are thus:

It allows you to define configuration values in a human readable YAML file which can be imposed on to WordPress.

An example file might look something like this:

state: site
settings:
  title: WordPress Site
  description: Just another WordPress site
  date_format: F j, Y
  time_format: g:i a
  active_theme: twentytwenty

Dictator works via a concept of states and regions. A state is a collection of regions and is typically a site or a network. Regions hold a schema in which is defined the human readable configuration that translates to what is stored in the database. Some examples of regions are settings, users and terms.

For clarity, this is not to be confused with environment configuration, such as the constants and things that you might find in wp-config.php or the configuration described in bedrock. It’s all about configuration of WordPress, i.e. what would typically be done via the admin UI.

What does this give us?

Easy visibility of configuration

We’re no longer blindly copying across database tables, but imposing a known state from a human readable text (yaml) file. The configuration is available for humans to read, compare and easily change.

Ability to version control configuration (it’s just another file in git)

Although through something such as VersionPress you are able to version control the database, it’s levels of complexity above a simple text file included in a git repo which will allow for a complete history of changes to the file, along with relevant commit titles and descriptions on what has changed and why. It allows for the easy creation of diffs between versions as well as the ability for any changes to configuration to go through a review process, just as you might for any other file added to version control.

Ability to easily ‘impose’ against a site on any environment

Through a single command, you are able to impose the easy to read configuration against a site or a network. The command takes seconds to run and provides an easy to read diff of what’s changed. This is easier than having to set up connections between environments and having to blindly pick and choose which database tables to migrate, however it does require a knowledge of the command line as well as SSH. If this is alien to you, then perhaps Dictator isn’t the tool for you.

Easy adjustment of settings

Want to change a setting? Want that change to quickly be distributed among all the other developers and on other environments? There is no easier way than a simple change to a text file.

Easily diffable to see at what point and why settings changed

As it’s just text, it’s really easy to create a diff of what has changed to the configuration between versions. It also has a compare function so you can compare the settings in the file against the database, usage is:

wp dictator compare site-state.yml
A known correct state which can be compared against and tested against

The state file (site-state.yml for example) should be the master of configuration options and this allows you to compare the state of a WordPress database against it. So for any environment you can run the compare command (described above) and it will inform you of any deviation. This will allow you to run ‘configuration validation tests’, which basically means being able to periodically (daily for example) test that configuration is what is expected. Building on this, you could have it alert you if this has happened, it may be fine (client has updated an address for example) in which case you may want to back port changes to the state file, or it may be problematic (client has accidentally changed permalink structure for example) in which case you can remedy quickly before it escalates.

Consistent correctness – no chance of human error from manual input

Any kind of manual work has an element of human error, similarly any kind of blind copying of database tables has an element of risk and unknowns. This takes both of those away, with a consistently correct version of the configuration being in a human readable text file that is automatically imposed upon the database.

Typical dictator workflow

Dictator can be used from local development right through to production. Here’s what a typical workflow might look like:

1. Developer configures a local instance with some good starting point options (the defaults may well suffice).

2. Developer then exports to a yaml file: wp dictator export site site-state.yml.

3. site-state.yml included in version control.

4. Any further update to options is done via site-state.yml and imposed via wp dictator impose site-state.yml.

5. Developers keep their configuration up to date with wp dictator impose site-state.yml (much like you might do with migrations on non WP projects).

6. site-state.yml can also be used upon staging and production to ensure configuration is consistent across environments. We have baked this into our deployment scripts, for example.

That’s pretty much it! It can be useful to maintain multiple state files for different environments if, for example, you want to set up different users for each environment or a different set of options. So you could imagine something like:

dev.yml
staging.yml
production.yml

Or similar depending on your setup. Another thing you could do (which we’re not doing just yet but plan to) is make use of the compare functionality to ensure configuration hasn’t changed unexpectedly. This could be done as part of deployment or part of a testing pipeline which you run from time to time.

Alpha

So a little known library created over 6 years ago is our go to tool for managing WordPress configuration across environments.

In fact, the library has recently been marked as abandoned by Bachhuber at our request, so we’ve decided to pick up the reins with a recognised fork.

The library should still be considered as being in alpha. It’s great, we love it, but it’s still really early in its development (despite being around for so long). Some of the things, it doesn’t yet support or we think could be improved:

YAML inheritance

In the example of different environmental state files above, we currently have to maintain the same options across all 3 files, whereas with YAML inheritance we could have one overwrite the other (similar to what Symfony does with importing configuration files).

Nested regions

Currently regions are expected to be at a single level, when sometimes you may want them to be nested. We found this with the WooCommerce extension we created. We ended up with regions such as woocommerce-general, woocommerce-advanced etc. when preferred would have been to have something akin to:

woocommerce:
  general:
    # ...
  advanced:
    # ...

Dynamic schema

Dictator was written and released before the REST API was included as part of WordPress. Therefore, the schema for settings and similar is hard coded. What might be better, is to leverage the schema defined by the REST API. This can be retrieved via an OPTIONS call.

Note as well, that although a lot of the basic settings are supported, not everything is supported (widgets for example), and plugins would require someone writing an extension, as we’ve done for WooCommerce.

Summing up

2014 brought us many things: a brilliant World Cup; a Ukranian revolution; and a little known WordPress library which would shape how we configure and deploy WordPress sites several years later. We’re always looking for tools to help automate away the pain and when it comes to WordPress configuration, Dictator has proved just the ticket.

If you’re familiar with the problems we faced and feel Dictator could help you, then take a look at the repo we’ve now forked and reach out to me on GitHub, or on Twitter @jenko, if you have any further questions.

About the Author

Ian Jenkins

Ian Jenkins is a Principal Developer at Box UK. He has wide range of development experience in various platforms and languages, in particular PHP and Symfony. Ian has worked on and delivered a number of successful projects and is currently most interested in maintaining and transforming troublesome legacy projects into well-tested, high-performance web applications.