Using Nginx as a caching proxy with Wordpress+Apache
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
Configure Nginx cache logging¶
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;
Nginx configuration for backend servers¶
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; }
Configure cache path/parameters¶
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.
Example Apache/Wordpress configuration that disabled the Nginx cache¶
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¶
Comments
Hi,
I have googled a couple of days to find any info about configuring nginx+apache+wordpress with proxy cahce. It seems your post is the only one! Thank you for this work!
I have a gap in understanding how the nginx's proxy_cache actually works: does it cache only statics or apache genrated html?
Thank you in advance!
Hi Vitol, I'm glad you found the post-- hopefully it will be helpful to you. The Nginx forum also has a lot of information. Do a search for "proxy_cache" there.
To answer your question, Nginx can cache both static media files and apache generated html.
Hi Eliot,
How do you deal with cache purging? For example, if some user who is not logged in posted a comment, you need to invalidate the cached page. Or else, that user will get a cached version of a page without his own comment.
Oren
Hi Oren,
This is an issue that we faced. This Nginx module doesn't support purging the cache so we just have to wait the short time (10 minutes in our case) for the cached page to expire.
Regarding the comment pages, we actually added the comment author's name and email from the Wordpress cookie as part of the cache key so each person sees their own page. I added a link to our updated conf file at the top of the post.
Eliot
Cool, this helped me a lot. My WP is running on nginx and admin works, thanks!
Info for Nginx proxy cache invalidation (purging content) on site: http://linux-sysadmin.org/2010/08/nginx-invalidation-purging-content
Hi,
Instead of using Apache+WP combination, you can directly use NginX + W3 Total Cache which will be much faster and easier to use.
I've written an article on setting up NginX with PHP - http://tutspundit.com/howto-install-nginx-php-fpm-mysql-php533-wordpress-ubuntu-part-1/
Let me know what you think.
Pranav: I'm no longer using WordPress, but thanks for the tip. Your articles look really good.
For those who are reading this article.
You might be interested in this plugin http://wordpress.org/extend/plugins/nginx-manager/
It keep the NGINX cache always fresh by purging pages each time a new post/comment is published/modified.
Enjoy
-- Simone
Thx, got the cache running now!
I had a lot of work to do to make the cache running, but I finally done it thanks to you.
thanks for this info