Update: This article is updated for WordPress 3.5 multisite’s file-handling.
This article is direct extension of yesterday’s article: WordPress + Nginx + fastcgi_cache with fastcgi_cache_purge module.
Please read that article to check if Nginx is complied withfastcgi_cache_purge module and help on installing Nginx Helper plugin.
WordPress-Multisite (Subdirectories) + Nginx + fastcgi_cache with fastcgi_cache_purge module
Make changes to /etc/nginx/sites-available/example.com file so it looks like one below:
#move next 3 lines to /etc/nginx/nginx.conf if you want to use fastcgi_cache across many sites
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:500m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
server {
#@DM - uncomment following line for domain mapping or you will need to add every mapped-domain to server_name list
#listen 80 default_server;
server_name example.com *.example.com ;
#@DM - uncomment following line for domain mapping
#server_name_in_redirect off;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
root /var/www/example.com/htdocs;
index index.php;
#fastcgi_cache start
set $skip_cache 0;
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache uris containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
rewrite ^(/[^/]+)?(/wp-.*) $2 last;
rewrite ^/[^/]+(/.*.php)$ $1 last;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ .php$ {
try_files $uri /index.php;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 60m;
}
location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
location = /robots.txt { access_log off; log_not_found off; }
location ~ /. { deny all; access_log off; log_not_found off; }
}
The line fastcgi_cache_use_stale is what makes caching on Nginx-side unique. This line tells nginx to use old (stale) cached version of page if PHP crashes. This is something not possible with WordPress caching plugins.
Domain Mapping
You need to uncomment few lines in above nginx-config to get domain-mapping working. Apart from above config changes, you can read this guide to setup/configure domain-mapping.
Must Read:
- Checklist For Perfect WordPress-Nginx Setup - It will help you verify if your caching will work after PHP/MySQL crash.
- Nginx Maps for Better Static File Handling in WordPress-Multisite - useful for multisite created before WordPress 3.5 released
- WordPress-Nginx tutorials

nginx: [emerg] pcre_compile() failed: unrecognized character after (? or (?- in “^(?/[_0-9a-zA-Z-]+/)files/(.*)” at “/[_0-9a-zA-Z-]+/)files/(.*)” in /etc/nginx/sites-enabled/default:7
nginx: configuration file /etc/nginx/nginx.conf test failed
Getting this error message on test. Something wrong here?
Looks like a PCRE version issue.
On Ubuntu, try:
apt-get install libpcre3 libpcre3-devAnother workaround is to use following line instead:
Shouldn’t we allow /purge only from localhost?
I use “/purge” from browser sometime to manually purge cache for a WordPress URL (post/page/archive etc).
You can restrict it to localhost if you do not wish to use “/purge” manually.