We have been evaluating caching reverse proxy servers at work. We looked at Nginx+memcached, Squid, and Varnish. Most recently, we found that Nginx version 0.7 has support for caching static files using the proxy_cache
directive in the NginxHttpProxyModule. This allows us to use Nginx as a caching proxy without having to handle the complication (or flexibility depending on how you look at it) of setting and invalidating the cache as with the Nginx+memcached setup. Here are my notes for setting it up with an Apache+Wordpress backend.
Update 2010-01-05: Over a couple months, we switched to Nginx 0.8 and we made a few tweaks to our Nginx configuration. Here is our updated conf file: nginx_wordpress_100105.conf.
Install Nginx 0.7¶
The version of Nginx in Ubuntu is an older version so we used a PPA created by Jeff Waugh: https://launchpad.net/~jdub/+archive/ppa. (He also has a development PPA which contains Nginx 0.8.)
- Add the following to /etc/apt/sources.list:
deb http://ppa.launchpad.net/jdub/ppa/ubuntu hardy main
deb-src http://ppa.launchpad.net/jdub/ppa/ubuntu hardy main
- Tell Ubuntu how to authenticate the PPA
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E9EEF4A1
Alternively, if the keyserver is down, you can follow the instructions for copying the public key from http://forum.nginx.org/read.php?2,5177,11272.
- Install Nginx from new PPA
apt-get update
apt-get install nginx
- Check the version of Nginx
nginx -V
nginx version: nginx/0.7.62
configure arguments: --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-debug --with-http_stub_status_module --with-http_flv_module --with-http_ssl_module --with-http_dav_module --with-http_gzip_static_module --with-ipv6 --with-http_realip_module --with-http_xslt_module --with-http_image_filter_module --with-sha1=/usr/include/openssl
Within the http {}
block, add:
log_format cache '***$time_local '
'$upstream_cache_status '
'Cache-Control: $upstream_http_cache_control '
'Expires: $upstream_http_expires '
'"$request" ($status) '
'"$http_user_agent" ';
access_log /var/log/nginx/cache.log cache;
Within the http {}
block, add:
include /etc/nginx/app-servers.include;
And /etc/nginx/app-servers.include
looks like:
upstream backend {
ip_hash;
server 10.245.275.88:80;
server 10.292.150.34:80;
}
Within the http {}
block, add:
proxy_cache_path /var/www/nginx_cache levels=1:2
keys_zone=one:10m;
inactive=7d max_size=200m;
proxy_temp_path /var/www/nginx_temp;
More proxy cache configuration¶
We added the username from the wordpress_logged_in_* cookie as part of the cache key so that different logged in users will get the appropriate page from the cache. However, our Wordpress configuration sends HTTP headers disabling the cache when a user is logged in so this is actually not used. But it does not hurt to include this, in case we change our Wordpress configuration in the future.
Within the server {}
block, add:
location / {
# capture cookie for use in cache key
if ($http_cookie ~* "wordpress_logged_in_[^=]*=([^%]+)%7C") {
set $my_cookie $1;
}
proxy_pass http://backend;
proxy_cache one;
proxy_cache_key $scheme$proxy_host$uri$is_args$args$my_cookie;
proxy_cache_valid 200 302 304 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m;
}
Configure locations that shouldn't be cached¶
If WordPress sends the appropriate HTTP Cache-Control headers, this step is not necessary. But we have added it to be on the safe side. Within the server {}
block, add:
location /wp-admin { proxy_pass http://backend; }
location /wp-login.php { proxy_pass http://backend; }
Restart Nginx¶
The Nginx reverse proxy cache should work without modification to the Apache configuration. In our case, we had to disable WP Super Cache because we had been using that previously.
/etc/init.d/nginx restart
View the log¶
Check the /var/log/nginx/cache.log
to see if everything is working correctly. The log should diplay HIT, MISS, and EXPIRED appropriately. If the log shows only misses, check the Cache-Control and Expires HTTP headers that are sent from Apache+Wordpress.
Part of the WP Super Cache configuration included the following in the .htaccess
file. It had to be removed for Nginx cache the pages. (In particular, the must-revalidate part had to be removed.)
Header set Cache-Control 'max-age=300, must-revalidate'
Links¶