It is harmless to install and activate this plugin before you’ve got the nginx proxy set up. To install:
/wp-content/plugins/
Sample nginx configuration
# The main config file, probably /etc/nginx/nginx.conf user nginx; worker_processes 4; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { #A maximum of 1024 concurrent connections. worker_connections 1024; } http { server_tokens off; include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; client_body_temp_path /var/lib/nginx/body 1 2; gzip_buffers 32 8k; sendfile on; keepalive_timeout 65; tcp_nodelay on; #gzipping lets you serve more requests quicker. gzip on; gzip_types text/html application/javascript text/javascript text/css text/xml application/atom+xml application/xml; include /etc/nginx/sites-enabled/*; } # And then in the file /etc/nginx/sites-enabled/default # This file shows you a few ways you can tweak your caching policies by inspecting URLs. # The most important rule is to leave admin-looking URLs uncached, otherwise you won't be able to log in. # From there, please feel free to set longer or shorter cache times based on your particular traffic. # set some parameters: two levels deep for the filesystem # set the name of the cache to "staticfilecache", giving it a maximum cache time of 3 hours and 500meg in size. proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=staticfilecache:180m max_size=500m; proxy_temp_path /var/lib/nginx/proxy; proxy_connect_timeout 30; proxy_read_timeout 120; proxy_send_timeout 120; #IMPORTANT - this sets the basic cache key that's used in the static file cache. proxy_cache_key "$scheme://$host$request_uri"; upstream wordpressapache { #The upstream apache server. You can have many of these and weight them accordingly, #allowing nginx to function as a caching load balancer (oh my. Awesomeness abounds.) server 127.0.0.1:8200 weight=1 fail_timeout=120s; } server { #Only cache 200 responses, and for a default of 20 minutes. proxy_cache_valid 200 20m; #Listen to your public IP listen 111.11.111.111:80; #Probably not needed, as the proxy will pass back the host in "proxy_set_header" server_name blog.example.org; # "combined" matches apache's concept of "combined". Neat. access_log /var/log/apache2/nginx-access.log combined; # Set the real IP. proxy_set_header X-Real-IP $remote_addr; # Set the hostname proxy_set_header Host $host; #Set the forwarded-for header. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { # If logged in, don't cache. if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) { set $do_not_cache 1; } proxy_cache_key "$scheme://$host$request_uri $do_not_cache"; proxy_cache staticfilecache; proxy_pass http://wordpressapache; } location ~* wp\-.*\.php|wp\-admin { # Don't static file cache admin-looking things. proxy_pass http://wordpressapache; } location ~* \.(jpg|png|gif|jpeg|css|js|mp3|wav|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx)$ { # Cache static-looking files for 120 minutes, setting a 10 day expiry time in the HTTP header, # whether logged in or not (may be too heavy-handed). proxy_cache_valid 200 120m; expires 864000; proxy_pass http://wordpressapache; proxy_cache staticfilecache; } location ~* \/[^\/]+\/(feed|\.xml)\/? { # Cache RSS looking feeds for 45 minutes unless logged in. if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) { set $do_not_cache 1; } proxy_cache_key "$scheme://$host$request_uri $do_not_cache"; proxy_cache_valid 200 45m; proxy_cache staticfilecache; proxy_pass http://wordpressapache; } location = /50x.html { root /var/www/nginx-default; } # No access to .htaccess files. location ~ /\.ht { deny all; } }
And a sample apache configuration
########## Backend Apache # This apache only listens on localhost to port 8200. # It also has php and mod_rpaf installed. It does not gzip/deflate or access.log. It *Does* error log. # Basically, your backend apache is fairly normal. You should disable keepalive too by setting # Keepalive Off # in your main config. # mod_rpaf allows your backend apache to see the real IP address of the request, instead of the address of # your frontend proxy. <VirtualHost 127.0.0.1:8200> ServerName blog.example.org RewriteEngine on DocumentRoot /home/wp/wordpress/ ServerAdmin you@example.com #block POSTS without referrers. RewriteCond %{REQUEST_METHOD} POST RewriteCond %{REQUEST_URI} .wp-comments-post\.php* RewriteCond %{HTTP_REFERER} !.*blog.example.org.* [OR] RewriteCond %{HTTP_USER_AGENT} ^$ RewriteRule (.*) - [R=403,L] </VirtualHost>
It’s less intimidating than it looks.
Need for Speed?
This plugin handles the wordpress/php side of a statically cached nginx-fronted wordpress (or wordpress mu) site. It makes WordPress emit an “X-Accel-Expires: 0” header when a user is logged in or has taken actions that should cause them to get a customized page on your frontend. This – along with the nginx configuration below – will ensure logged-in users aren’t impacted by your static nginx cache.
Why would you want to statically cache wordpress with nginx?
We’ve been using a caching nginx proxy at the fairly busy blogs.law.harvard.edu since September, 2009. The results have been dramatic: we’ve halved the amount of RAM we need, doubled our outgoing network throughput (nginx is fast!) and have had essentially no significant load spikes.
Drawbacks
There are a few.
Notes
This plugin could be set up to allow you to manage caching policies entirely from a wordpress control panel. We’d do this by manipulating the timeout in the “X-Accel-Expires” header based on the type of resource that’s been requested.
It’d be nice to de-cache when pages change via some call from the backend to the nginx frontend.