Factor #3: Config
Store config in the environment
An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc). This includes:
- Resource handles to the database, Memcached, and other backing services
- Credentials to external services such as Amazon S3 or Twitter
- Per-deploy values such as the canonical hostname for the deploy
This once again starts to conflict with the normal WordPress way of doing things (a sign that we're onto something good).
wp-config.php is usually treated as a catch-all for any configuration variables. But to be a proper Twelve-Factor App, anything that is likely to vary shouldn't be included in that file.
Note that this definition of “config” does not include internal application config. This type of config does not vary between deploys, and so is best done in the code.
This means that
wp-config.php has its place and certain things should be included in code. It's important to know what belongs and what doesn't.
Let's look at some things that should be included in your standard WP
define('CONTENT_DIR', '/app'); define('WP_CONTENT_DIR', dirname(__FILE__) . CONTENT_DIR); define('WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] . CONTENT_DIR); define('DB_CHARSET', 'utf8'); $table_prefix = 'wp_';
All of these pass the 2 tests:
- Could the codebase be made open source at any moment, without compromising any credentials?
- Does it vary between deploys/environments?
And here's a few things that should not be included:
Not only should these constants vary between environments, you definitely wouldn't include them if you were open sourcing your codebase.
The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally;
So if we're not including our database credentials, for example, in our WP config, we need to store them in environment variables.
Environment variables are a set of dynamic named values that can affect the way running processes will behave on a computer.
If you're familiar with Linux, you've probably seen variables like
$PATH. Those are env vars.
You can assign them from the command line like this:
Or prefix a command with them to exported as real env vars to the program:
Let's complete the example of moving WordPress DB credentials from
wp-config.php to env vars.
First, we need to define all the env vars we'll need on our server:
Now we need to make sure these variables are exposed/passed into our web server. We'll look at both Nginx (PHP-FPM) and Apache2 (mod-php) options.
Assuming you've already got PHP-FPM setup, it means you have a working
php-fpm.conf file. At the bottom you need to explicitly define which variables you want to use:
env[DB_NAME] = $DB_NAME env[DB_USER] = $DB_USER env[DB_PASSWORD] = $DB_PASSWORD
$ variables just reference the variables we set in our shell using
Apache2 is a bit more complicated. But the easier method is just straight defining the variables in your Virtual Host or
<VirtualHost hostname:80> ... SetEnv DB_NAME wp SetEnv DB_USER wp_user SetEnv DB_PASSWORD wp_pass ... </VirtualHost>
SetEnv DB_NAME wp SetEnv DB_USER wp_user SetEnv DB_PASSWORD wp_pass
This has the slight annoyance that you can't re-use the variables you exported before. In this case, just skip that first step and set them straight in your Apache config.
Now that your web server has the needed environment variables, we need to read in our
define('DB_NAME', getenv('DB_NAME')); define('DB_USER', getenv('DB_USER')); define('DB_PASSWORD', getenv('DB_PASSWORD'));
getenv is probably the safest way to retrieve env vars in PHP. Note that they also might be available in
Yes, this is a lot of work to do up-front. But once it's done and you're comfortable with it, your app becomes much more flexible.
- Backing Services
- Build, release, run
- Port binding
- Dev/prod parity
- Admin processes
Want to turn your WordPress site into a Twelve-factor App? Bedrock is a modern WordPress stack to help you get started with the best tools and practices.