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:
web/app/cache
newweb/app/advanced-cache.php
newweb/app/wp-cache-config.php
newweb/wp-config.php
edited
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.