• Note: This post has not been updated for Varnish 4 yet.

This post is a guide to increase responsiveness and page load times for those who host WordPress on their own machines. Caching helps reduce page load times dramatically and handle traffic spikes to a certain extent.

Varnish is a reverse caching proxy which I use to cache all static content and my pages. This returns cached pages from instead of asking php to render the pages for us each time which can bring down the server at high loads.

Installing Varnish

I run the entire setup on Ubuntu 14.04.

Varnish runs on port 80 which is exposed to the web. Apache listens to Varnish on port 8888. Only port 80 and my SSH port are exposed to the outside world(refer AWS Security Groups).

Install Varnish
sudo apt-get install varnish

Varnish Config Files:

# Adapted from https://gist.github.com/4651531.git with a few mods according to my needs
backend default {
.host = "";
.port = "8888";
.connect_timeout = 60s;
.first_byte_timeout = 60s;
.between_bytes_timeout = 60s;
.max_connections = 800;
acl purge {
sub vcl_recv {
set req.grace = 2m;
# Set X-Forwarded-For header for logging in nginx
remove req.http.X-Forwarded-For;
set req.http.X-Forwarded-For = client.ip;
# Remove has_js and CloudFlare/Google Analytics __* cookies and statcounter is_unique
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js|is_unique)=[^;]*", "");
# Remove a ";" prefix, if present.
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
# Either the admin pages or the login, don't cache
if (req.url ~ "/wp-(login|admin|cron)") {
return (pass);
# Remove the wp-settings-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");
# Remove the wp-settings-time-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");
# Remove the wp test cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");
# Static content can be cached (so no user uploaded images)
if (req.url ~ "wp-content/themes/" && req.url ~ "\.(css|js|png|gif|jp(e)?g)") {
unset req.http.cookie;
# Check the cookies for wordpress-specific items
if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
# A wordpress specific cookie has been set
return (pass);
# allow PURGE from localhost
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
return (lookup);
# Force lookup if the request is a no-cache request from the client
if (req.http.Cache-Control ~ "no-cache") {
return (pass);
# Try a cache-lookup
return (lookup);
sub vcl_fetch {
#set obj.grace = 5m;
set beresp.grace = 2m;
sub vcl_hit {
if (req.request == "PURGE") {
error 200 "Purged.";
sub vcl_miss {
if (req.request == "PURGE") {
error 200 "Purged.";
# Should we start varnishd at boot? Set to "no" to disable.
# Maximum number of open files (for ulimit -n)
# Maximum locked memory size (for ulimit -l)
# Used for locking the shared memory log in memory. If you increase log size,
# you need to increase this number as well
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-t 120 \
-s malloc,256m"

Configure Apache to listen to a different port

In the file, /etc/apache2/ports.conf, edit the Listen line the following line to Listen 8888

You will need to update your Virtual Hosts file. In my case, the file is /etc/apache2/sites-enabled/100-default.conf