Bedrock with WP Super Cache

For all of the benefits that come with using Bedrock it is sometimes at odds with the way that vanilla WordPress works. I recently ran into issues when adding a caching plugin to a Bedrock based site which was deployed by Capistrano.

The problem

Unlike most plugins, WP Super Cache has to make changes to other files in your site. It has to make changes to your wp-config.php and also add new files and folders to app/web. Some of these changes are useful configuration options, allowing you to easily port your settings between environments. Unfortunately there are a number of hardcoded filesystem paths interspersed in these files, which don’t translate so easily between environments.

If you commit these files into your git repo then the paths will be wrong when you deploy, but if you don’t you’ll have to reconfigure the plugin after each Capistrano deploy to have them rebuilt.

Working around the issues

It’s worth saying upfront that this might not be totally in the spirit of how Bedrock is supposed to be used, the following is my pragmatic approach to getting it working in a maintainable manner.

Setup locally and modify .gitignore

As normal, add the plugin to your composer file and do a composer update. By enabling the plugin locally all the changes to the filesystem become apparent. After enabling, configure the plugin from the UI for the settings you need. The following files will now have been edited/created:

Add a .gitkeep file to web/app/cache and then edit your projects .gitignore file, adding the following lines:

web/app/cache/*
!web/app/cache/.gitkeep

Commit all the changes to your repo.

Move environmental configuration into .env

WP Super Cache adds a couple of lines to your app/wp-config.php file, by default your file will now look something like this:

<?php
// WP Super Cache
define('WPCACHEHOME', '/absolute/path/to/wp-super-cache'); //Added by WP-Cache Manager
define('WP_CACHE', true); //Added by WP-Cache Manager

/**
 * Do not edit this file. Edit the config files found in the config/ dir instead.
 * This file is required in the root directory so WordPress can find it.
 * WP is hardcoded to look in its own directory or one directory up for wp-config.php.
 */
require_once(dirname(__DIR__) . '/vendor/autoload.php');
require_once(dirname(__DIR__) . '/config/application.php');
require_once(ABSPATH . 'wp-settings.php');

The absolute path here is a problem but Bedrock makes use of .env files, so we can abstract this away to an environmental variable. It’s important to note that the getenv function only gets setup after the config/application.php file is included. So to achieve what we want we need to move the define statements down the file, to look something like this:

<?php
/**
 * Do not edit this file. Edit the config files found in the config/ dir instead.
 * This file is required in the root directory so WordPress can find it.
 * WP is hardcoded to look in its own directory or one directory up for wp-config.php.
 */
require_once(dirname(__DIR__) . '/vendor/autoload.php');
require_once(dirname(__DIR__) . '/config/application.php');

// WP Super Cache
define('WPCACHEHOME', getenv('WPCACHEHOME')); //Added by WP-Cache Manager
define('WP_CACHE', true); //Added by WP-Cache Manager

require_once(ABSPATH . 'wp-settings.php');

You can now add the path to the WP Super Cache plugin to your .env file using the key WPCACHEHOME.

We also need to perform a similar task in web/app/wp-cache-config.php and change the $cache_path definition so that it too comes from .env. Look for the line similar to:

$cache_path = '/absolute/path/to/web/app/cache'; //Added by WP-Cache Manager

and replace it with:

$cache_path = getenv('CACHE_PATH'); //Added by WP-Cache Manager

As before, we can now add CACHE_PATH to our .env file.

Commit the changes to these two files to your git repo.

Note: WP Super Cache is quite agressive about changing these values back to what it thinks they ought to be, it appears to happen when you disable/enable the plugin. Be careful to check you don’t commit these changes into your repo later in the project!

Add cache folder to shared folder

Our websites are deployed via Capistrano by a low privileged system user deploy. We have the Apache user added to the deploy group, which means we want all files to be created with both the user and group deploy. We use the chmod sticky bit to ensure that all new files retain the right permissions. Critically, both the deploy and Apache user need write access to all files. Apache so that users can uploaded assets from the UI and deploy so that we can remove old releases.

Ordinarily WordPress respects these settings when files are uploaded from the UI into the shared folder and everything just works. WP Super Cache however does not obey these settings when building cached assets and instead only the Apache user has write access.

Ideally, we wouldn’t want to have to do this but to work around this you can add web/app/cache to the list of linked directories. This way the cache files are persistent across deploys so your deploy user never needs to clean them out, this job can be left to the Super Cache UI.

To do this, add the following line to your Capistrano config/deploy.rb file:

set :linked_dirs, fetch(:linked_dirs, []).push('web/app/cache')

Modify the Super Cache plugins path (optional)

If you use the optional plugins for WP Super Cache to extend its functionality then you may want to consider changing where these are stored. By default they live within the WP Super Cache plugin folder, which becomes an issue if you need to add a customisation.

First edit your web/app/wp-cache-config.php file again and find where $wp_cache_plugins_dir is set, change this to be:

$wp_cache_plugins_dir = WP_CONTENT_DIR . '/sc-plugins';

Then create the folder web/app/sc-plugins and place your custom code in there.

It’s worth noting that historically I’ve much more experience with W3 Total Cache but for this particular project I ran into a separate issue where W3TC didn’t like being run from an Alias in the VirtualHost. As it turned out it seems that WP Super Cache is easier to fit into the Bedrock/Capistrano model but I’m sure with some work the same could be achieved with W3TC.