# Twelve-Factor WordPress App #3: Config

Factor #3: [Config](http://12factor.net/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.

### Decisions

Let's look at some things that should be included in your standard WP `wp-config.php`:

```
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:

1. Could the codebase be made open source at any moment, without compromising any credentials?
2. Does it vary between deploys/environments?

And here's a few things that should *not* be included:

- `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `DB_HOST`, `AUTH_KEY`, `SECURE_AUTH_KEY`, `LOGGED_IN_KEY`, `NONCE_KEY`, `AUTH_SALT`, `SECURE_AUTH_SALT`, `LOGGED_IN_SALT`, `NONCE_SALT`

Not only should these constants vary between environments, you definitely wouldn't include them if you were open sourcing your codebase.

## In Practice

> 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 `$HOME` or `$PATH`. Those are env vars.

You can assign them from the command line like this:

`export DB_NAME=wp`

Or prefix a command with them to exported as real env vars to the program:

`MYSQL_TCP_PORT=3306 mysql`

### Database Credentials

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:

`export DB_NAME=wp`
`export DB_USER=wp_user`
`export DB_PASSWORD=wp_pass`

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.

#### Nginx

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
```

The `$` variables just reference the variables we set in our shell using `export`.

#### Apache2

Apache2 is a bit more complicated. But the easier method is just straight defining the variables in your Virtual Host or `.htaccess`.

Virtual Host:

```
<VirtualHost hostname:80>
  ...
  SetEnv DB_NAME wp
  SetEnv DB_USER wp_user
  SetEnv DB_PASSWORD wp_pass
  ...
</VirtualHost>
```

`.htaccess`:

```
  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.

### Config

Now that your web server has the needed environment variables, we need to read in our `wp-config.php`.

```
define('DB_NAME', getenv('DB_NAME'));
define('DB_USER', getenv('DB_USER'));
define('DB_PASSWORD', getenv('DB_PASSWORD'));
```

[`getenv`](http://php.net/manual/en/function.getenv.php) is probably the safest way to retrieve env vars in PHP. Note that they also might be available in `$_SERVER` and `$_ENV`.

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.

#### [Turning a WordPress site into a Twelve-Factor App](/twelve-factor-wordpress/)

1. [Codebase](/twelve-factor-01-codebase/)
2. [Dependencies](/twelve-factor-02-dependencies/)
3. **[Config](/twelve-factor-03-config/)**
4. [Backing Services](/twelve-factor-04-backing-services/)
5. [Build, release, run](/twelve-factor-05-build-release-run/)
6. [Processes](/twelve-factor-06-processes/)
7. [Port binding](/twelve-factor-07-port-binding/)
8. [Concurrency](/twelve-factor-08-concurrency/)
9. [Disposability](/twelve-factor-09-disposability/)
10. [Dev/prod parity](/twelve-factor-10-dev-prod-parity/)
11. [Logs](/twelve-factor-11-logs/)
12. [Admin processes](/twelve-factor-12-admin-processes/)

Want to turn your WordPress site into a Twelve-factor App? [**Bedrock**](/bedrock/) is a modern WordPress stack to help you get started with the best tools and practices.