Separating your project and environment settings in Drupal 7

For Drupal 7 sites it’s best that you split up your settings.php in 2 different files: settings.php and env.settings.php.

The logic behind this is:

Given this logic, it’s safe to commit the settings.php to our git repository while keeping env.settings.php out of it. The env.settings.php is created manual when setting up an environment.

Examples files

Settings.php contains certain module includes, php ini settings, etc. while env.settings.php contains database connection info, memcache prefixes, reverse proxy configuration, etc.

A simple settings.php file:

$update_free_access = FALSE;
$drupal_hash_salt = 'averysecrethash';

ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);
ini_set('session.gc_maxlifetime', 200000);
ini_set('session.cookie_lifetime', 2000000);

$conf['memcache_persistent'] = TRUE;
$conf['cache_backends'][] = 'sites/all/modules/contrib/memcache/memcache.inc';
$conf['cache_default_class'] = 'MemCacheDrupal';
## The 'cache_form' bin must be assigned no non-volatile storage.
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';

$conf['404_fast_paths_exclude'] = '/\/(?:styles)\//';
$conf['404_fast_paths'] = '#\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$#i';
$conf['404_fast_html'] = '<html xmlns="http:##www.w3.org#1999#xhtml"><head><title>404 Not Found</title></head><body>
<h1>Not Found</h1>
The requested URL "@path" was not found on this server.</body></html>';

$conf['drupal_http_request_fails'] = FALSE;

# environment-specific settings
$settings = DRUPAL_ROOT . '/sites/default/env.settings.php';
if (file_exists($settings)) {
 require_once($settings);
}

An example env.settings.php file:

$databases = array (
 'default' => array (
   'default' => array (
     'database' => 'db_name',
     'username' => 'db_user',
     'password' => '',
     'host' => 'localhost',
     'port' => '',
     'driver' => 'mysql',
     'prefix' => '',
    ),
  ),
);

## We use a memcache prefix as multiple sites use the same bin
$conf['memcache_key_prefix'] = 'prod';
$conf['drupal_http_request_fails'] = FALSE;

## See https://www.karelbemelmans.com/2015/07/reverse-proxy-configuration-for-apache-or-nginx-with-varnish/
$conf['reverse_proxy'] = TRUE;
$conf['reverse_proxy_addresses'] = array('127.0.0.1');
$conf['reverse_proxy_header'] = 'HTTP_X_FORWARDED_FOR';

## Zen-theme option
$conf['theme_narfum_settings']['zen_rebuild_registry'] = 0;

## Caching is on for production
$conf['cache'] = 1;
$conf['block_cache'] = 1;

## Error display is off for production
$conf['error_level'] = 0;

## Turn off js and css aggregation ON
$conf['preprocess_css'] = 1;
$conf['preprocess_js'] = 1;

## GD image quality
$conf['image_jpeg_quality'] = 90;

## Maintenance mode?
$conf['maintenance_mode'] = 0;

Directory structure

How we use this in practise is that settings.php is always deployed with the rest of the Drupal code, while the env.settings.php is kept outside of the website root but linked to with a symbolic link.

Example directory structure:

httpdocs/
  - sites/
    - default/
      - settings.php
      - env.settings.php -> $HOME/shared/env.settings.php
      - files -> $HOME/shared/files
shared/
  - env.settings.php
  - files/

You can see we use symbolic links for the files and env.settings.php file. These links are actually made by our deployment script. The httpdocs directory (= the website root) is actually also a symbolic to a specific release, like this:

httpdocs -> $HOME/releases/release-1.0.3
shared/
  - env.settings.php
  - files/
releases/
  - release-1.0.3/
    - sites/
      - default/
        - settings.php
        - env.settings.php -> $HOME/shared/env.settings.php
        - files -> $HOME/shared/files

If you maintain this logic, setting up an automated deployment is easy and you will never have to do bad stuff like committing passwords or environment specific settings to your Drupal code.

comments powered by Disqus