Optimizing WordPress with Varnish and W3 Total Cache
This tutorial follows up Installing WordPress in the Amazon Cloud, showing how to optimize your site with caching.
If you self-host WordPress, it's advisable to implement some kind of caching solution. Whether you want to run your blog in an economical micro instance at Amazon's Cloud (AWS) or expect your blog to get significant scale or traffic spikes, caching will be critical to manage performance. Caching can also help improve your Google Page Speed which impacts your search engine ranking.
Depending on your site traffic and the complexity of your WordPress theme, performance can actually be quite slow on AWS. My recommendation is to combine use of the open source Varnish Cache with the free W3 Total Cache (W3TC) plugin.
Varnish is a cache which stores copies of pages for users that aren’t logged in (most readers aren’t). When requests come in to your server, Varnish returns these pre-built pages instantly rather than requiring Apache, PHP and WordPress to rebuild the page for each request. As traffic scales, rebuilding every page through the WordPress stack can literally crash your server. Later, W3 Total Cache can be set up to regularly pre-build pages of your site so they are always ready for Varnish.
The power of Varnish is dramatic when interest in your site spikes. I've successfully run my own site with this configuration using an Amazon small instance for about $14.95 monthly successfully handling many appearances on BoingBoing, Slashdot et al.
If you'd like to learn more about caching, its benefits and W3TC, read Ahmad Awais' introduction to caching.
Installing Varnish Cache
Varnish Cache is a caching module for Linux. We’ll set up Varnish to listen for HTTP (web) traffic on port 80 with Apache listening only to Varnish on port 8080. When Varnish needs a page to be built manually, it will pass the request on to Apache port 8080.
This can be a bit confusing at first - but yes, we're essentially moving Apache behind the scenes. Varnish will act as the front door on port 80 for all your web requests. Apache will act in a supporting role for Varnish on port 8080. There's no public traffic on port 8080, only private requests from Varnish. If you're curious about how this relates to AWS security groups, there is no need to open port 8080.
To get started, we need to install Varnish on our instance:
sudo apt-get install varnish
Edit Apache’s ports.conf file to listen on port 8080:
sudo nano /etc/apache2/ports.conf
Here’s what it should look like:
Edit your Apache site configuration file to respond to port 8080:
sudo nano /etc/apache2/sites-available/wordpress.conf
Change the VirtualHost line from *:80 to *:8080
You may need to change your Apache default site to listen on port 8080 or disable it:
sudo a2dissite 000-default
Move the original Varnish configuration files to your home directory as backups (in case you decide to review them later):
sudo mv /etc/default/varnish ~/default-varnish-old sudo mv /etc/varnish/default.vcl ~/varnish-default-vcl.old
Replace the Varnish default configuration with the file available here on gist. You can use copy and paste.
sudo nano /etc/default/varnish
Then, replace the Varnish VCL configuration with the gist file here (again copy and paste).
Warning: you may get VCL errors when you attempt to restart Varnish if you do not properly maintain line breaks when pasting. The line breaks can be hard to detect, so review it carefully. If there are errors when restarting Varnish, it's pretty good about telling you which line number to look at.
sudo nano /etc/varnish/default.vcl
Now, let’s restart Apache and Varnish:
sudo service apache2 restart sudo service varnish restart
Remember, if you get VCL errors at this point, it may be because of broken line-breaks from pasting in the Varnish default.vcl file.
Visit your site at http://yourdomain.com and everything should begin working with Varnish. The second time you load a static page, it should be significantly faster.
Installing W3 Total Cache
W3 Total Cache is an outstanding WordPress plugin. It’s free and provides a tremendous performance optimization for your site. You can learn more about W3 Total Cache at its plugin site.
Log in to your WordPress administration page at http://yourdomain.com/wp-admin using the username and password you configured during setup. Select Plugins -> Add New from the left sidebar menu. Search for W3 Total Cache.
Because of its power and sophistication, W3 Total Cache has a wide variety of settings which can seem overwhelming. Below, I provide some recommended settings that make getting started easier.
Don’t get overwhelmed. Start with the General Settings shown below and go from there. If you're interested in starting more quickly, I’ve provided instructions for downloading my default settings and importing them (shown further below).
Alternatively, W3 Total Cache offers paid installation and support from $150 and up. You can reach them through its plugin Dashboard page or their website. This is a great plugin so I feel good about recommending them. I've had some experience with their paid support and it is generally good. You may also want to review the W3 Total Cache installation overview and FAQ on the plugin website for more details.
At a high level, I recommend activating the following settings which I detail more fully below:
- Page Caching: Caches pages for faster loading and more efficient delivery (separate from Varnish).
- Minify: Shrinks and combines JS and CSS files for faster loading and more efficient delivery.
- Object Cache: Speeds up generation of content by WordPress.
- Browser Cache: Properly tags content so that browser clients minimize downloads of pages.
- Reverse Proxy: Instructs W3TC to purge the Varnish cache when posts, pages, et al. are updated.
- Amazon CloudFront CDN: Ensures the delivery of static files and images quickly, reliably and geographically near to your visitors.
- Miscellaneous: Use a sitemap index file to pre-cache high priority pages.
Installing Supporting Components
Before we configure W3 Total Cache, let’s install and activate a number of Linux components that it will require. Again, connect to your instance and perform the following steps:
sudo apt-get install php5-dev php5-memcache memcached php-pear build-essential php5-tidy php5-curl apache2-dev php-apc
Edit your php.ini file to activate memcache:
sudo nano /etc/php5/apache2/php.ini
In the Dynamic Extensions section, add the lines below:
Tell Apache to activate these modules and restart it:
sudo a2enmod rewrite sudo a2enmod expires sudo a2enmod headers sudo service apache2 restart
Edit your wp-config.php file to enable caching:
sudo nano /var/www/wordpress/wp-config.php
Add the following WP_CACHE definition above the stop editing line:
define('WP_CACHE', true); /* That's all, stop editing! Happy blogging. */
Reviewing Configuration Status
At this point, it’s useful to visit the W3TC plugin Dashboard and check that all the proper components are active. But first, we need to enable Fancy Permalinks for URL formats, which will optimize our site for search engine indexing. From the WordPress Admin Dashboard, select Settings -> Permalinks, choose Day and Name and click Save Changes.
Then, from the left sidebar, click Performance -> Dashboard, then click the Compatibility Check button. It should look something like this:
Note: you may save some time if you choose a theme and install the other plugins you plan to use before completing the rest of the W3 Total Cache configuration process. Changing themes and adding plugins will likely require you to purge and retest your W3 Total Cache settings.
W3TC generally works well with its default settings. So, we’ll primarily need to configure the General Settings page and not go into each individual feature area.
Visit the W3TC General Settings page. From the left sidebar, click Performance -> General Settings. We can perform high level set up here but then we’ll also do more detailed set up on individual settings pages. I leave off (unchecked) “Toggle all caching types on or off (at once)” in the general box.
Enable Page Cache with Opcode Alternative PHP Cache (APC):
Enable Minify with the following settings. I use manual mode because minify can break some themes if your settings are too aggressive (however, your chosen theme may work fine):
I leave unchecked/off Database Caching as this is recommended only if you do not activate Object Caching.
Enable the Object Cache:
Enable the Browser Cache:
Enable Reverse Proxy:
Configure W3TC to regularly purge the Varnish Cache from 127.0.0.1 (localhost).
Page Cache Settings
From the left sidebar, click Performance -> Page Cache. Scroll down to the Cache Preload box. Enable “Automatically prime the page cache”. Enter your sitemap URL.
Note: You will need to have installed the Better WordPress Google XML Sitemaps plugin before this will function properly.
If you use a CAPTCHA on contact forms, you’ll want to include the path to these pages in the cache exclusion. Caching a CAPTCHA will break the functionality. Scroll down to the Advanced Setting box. Add your file path e.g. contacts here:
User Agent Groups
If you wish to do this, enable High and Low User Agent Groups:
I also enable Referrer Groups for search engines:
Minify compresses your HTML, JS and CSS code and combines files when possible. This speeds up delivery of your pages and reduces bandwidth. However, it can sometimes break theme code.
You may have to adjust the settings for your chosen theme. I found that by turning off inline CSS minification, my theme works well. From the left sidebar, click Performance -> Minify:
Importing Example Settings (Optional)
If you prefer to start by importing my settings file, follow these steps:
- Download the example settings file
- Visit the W3TC General Settings e.g. left sidebar, Performance -> General Settings and scroll to the bottom area with Import/Export Settings (see below).
- Beside Import configuration, click Choose File and select the example settings file you downloaded. Then, click upload.
- Browse your W3TC settings and ensure they make sense for your WordPress site.
- You may need to customize settings for your site after the import e.g. Google PageSpeed, Amazon CloudFront CDN, etc.
Using The Amazon CloudFront CDN
It’s definitely worthwhile to activate a CDN. The CDN Is very helpful for reducing the overall load on your server. For example, W3TC can redirect requests for images and static files such as scripts and css to Amazon's CDN.
If you wish to do so, follow the instructions on my site for Activating the Amazon CloudFront. I'm currently using the Pull method (my tutorial describes the older Push method).
There are many different ways to monitor the performance of your server. W3TC supports integration with the New Relic monitoring module. W3TC offers a dashboard widget for Google Page Speed and there is also a Google Page Speed plugin for WordPress. These will be helpful to you in assessing your blogs ongoing performance.
You should now be the proud owner of a fully optimized, self-hosted WordPress site in the Amazon Cloud using Varnish and W3 Total Cache. I hope that you've found this two part series helpful. Please let us know what worked well for you and what didn't.