PhpRiot
News Archive
PhpRiot Newsletter
Your Email Address:

More information

Slapping some Varnish on WordPress

Note: This article was originally published at Planet PHP on 15 October 2012.
Planet PHP

So last week I published my review of PHPNW12 and instantly my whole server went down in flames. My current WP setup has a few issues with multi-lingual plugins which I can't get over yet, as it requires a bit more of invested time. But this can't go on, I needed a solution, a fast and simple one to give my blog a fighting chance.

As it stood I already had caching, but i'm guessing that was not enough or decently handled, so I gave a shout out to @thijsferyn to see if putting up Varnish would be a simple enough task. This is BTW one of the reasons I dedicate so much time to helping and growing the community, because when I tread into new waters like this, I can call on smart people who are always willing to lend me a hand. It was no different with Thijs and by the next day I had a recommended setup to try and get Varnish up.

Varnish + WP + ServerGrove

My server is a 1Gb VPS with Servergrove and it runs 3 blogs and a personal website, all smallish with the occasional peak access, so I went on to get things up. Thijs had recommended running Apache on 8080 and leaving Varnish on port 80, but Servergrove is still working on alternative port configuration in their dashboard and they quickly got back to me with the suggestion of putting Apache to listen to localhost on 80 and leaving varnish to handle outside requests. This change was pretty simple I just had to tell Apache to listen to that and change my vhosts:

NameVirtualHost 127.0.0.1:80 Listen 127.0.0.1:80

Problem solved. Now to get varnish. Thijs pointed me to some easy to follow tutorials for each common OS: Ubuntu, Debian, Redhat or CentOS.

Once that was done, I needed to do was configure the basic setup, so I basically had to edit /etc/default/varnish to listen to external requests on port 80:

DAEMON_OPTS="-a :80 \ -T localhost:6082 \ -f /etc/varnish/default.vcl \ -S /etc/varnish/secret \ -s malloc,256m"

This is enough to get Varnish listening and do the trick, but now the important part is to get the right VCL configuration so that you don't run into troubles with your admin pages, cookies being ignored and so forth. If you want more details on the out-of-the-box setup, go see Thijs' Vanish in Action slides. So next step, the vcl: I had a gist from Thijs to get is sorted, but I had to make a few changes to it to get it just right, but in general its very straight forward, the main highlights are:

  • It ignores admin pages
  • It ignores logged users
  • It allows purges from WP
  • It adds a HIT/MISS header you can track to see if its being effective.
backend default { .host = "127.0.0.1"; .port = "80"; } acl purge { "localhost"; ""; } sub vcl_recv { # Allow purging if(req.request == "PURGE"){ if(!client.ip ~ purge){ error 405 "Purging not allowed."; } return(lookup); } # Always cache the following file types for all users. if (req.url ~ "(?i)\.(png|gif|jpeg|jpg|ico|swf|css|js|html|htm)(\?[a-z0-9]+)?$") { unset req.http.cookie; } # Don't serve cached pages to logged in users if (req.http.cookie ~ "wordpress_logged_in" || req.url ~ "vaultpress=true") { return(pass); } # Drop any cookies sent to WordPress. if (! (req.url ~ "wp-(login|admin)")) { unset req.http.cookie; } # Handle compression correctly. Different browsers send different # "Accept-Encoding" headers, even though they mostly all support the same # compression mechanisms. By consolidating these compression headers into # a consistent format, we can reduce the size of the cache and get more hits. # @see: http://varnish.projects.linpro.no/wiki/FAQ/Compression if (req.http.Accept-Encoding) { if (req.http.Accept-Encoding ~ "gzip") { # If the browser supports it, we'll use gzip. set req.http.Accept-Encoding = "gzip"; } else if (req.http.Accept-Encoding ~ "deflate") { # Next, try deflate if it is supported. set req.http.Accept-Encoding = "deflate"; } else { # Unknown algorithm. Remove it and send unencoded. unset req.http.Accept-Encoding; }}}sub vcl_fetch { # Allow items to be stale if needed. set beresp.grace

Truncated by Planet PHP, read more at the original (another 3216 bytes)