Update: This article is updated for WordPress 3.5 multisite’s file-handling.
ee site create example.com --wpsubdir --wpfc
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 =404; include fastcgi_params; fastcgi_pass 127.0.0.1:9000; 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-dev
Another 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.
Is this compatible with W3 Total Cache? I’d like to use NGINX caching, but I also have W3 and Memcached.
We are using nginx fastcgi-caching AND w3-total-cache for database/object cache with memcached backend here. 🙂
Hi Rahul.
I installed this WP settings with easy engine:
ee site create wpsubdir wpfc mydomain.com
but I noticed that this lines of code were not added:
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;
Should I adding it manually?
Yoy say “use_stale” makes the difference, thats what I think It should be there.
Those lines are added only once in
/etc/nginx/conf.d/fastcgi.conf
and reused again and again.About “use_stale”, that is handled by line
fastcgi_cache_use_stale
Hi Rahul, it’s been a while. Hope you are doing fine! 🙂
I’m going to ‘re-use’ a site that was running a subdomain install before for a new subdirectory install. Can you confirm that the only (essential) difference in the Nginx config files between subdir and subdomain intallations is this part?
if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
rewrite ^(/[^/]+)?(/wp-.*) $2 last;
rewrite ^/[^/]+(/.*.php)$ $1 last;
}
Or am I missing something else that will come back to haunt me later?
Thanks for you insights. 🙂
I am fine. 🙂
Hope you are fine as well.
subdomain and domain are same thing from config perspective.
for subdir, if its wordpress site you can try adding:
If you many sites in different subdir (top-level subdirs), you can try:
By the way if you are trying to copy “nginx config” from multisite-subdomain to multisite-subdir, then there will be better to use config from above article and change directory paths e.g.
root
.Hi Rahul, yes it’s a multisite and it seems to be working fine with the above config except for one thing:
I created a second multisite (with another root) and moved the fastcgi_cache block to the main nginx.conf. On the first multisite caching is still working fine but on that second site, cache is not working. In the response header I always get “Fast-Cgi: MISS”…
The two sites configs are exactly the same except for root, server_name (obviously) and log locations. I cannot for the life of me figure out why this is happening. If it would be something like request variables or cookies the I’d see “Fast-Cgi: BYPASS”, right? IIf I log in or do a search on the second multisite I get BYPASS. But I never see HIT.
Whatever could be happening?
Update: I found the culprit. It was the MarketPress (e-commerce) plugin that I had activated Network wide. The plugin has a start_session() in the main class __constuct() method… Looks like that will make fastcgi_cache back down, is that correct?
Is there any way around that? The plugin sets a cookie that starts with ‘mp_globalcart_’ as soon as something is added to the cart. It would be nice to keep caching active until that moment.
Thanks for any tips 🙂
I faced similar problem with WooCommerce and this is config I am using – https://gist.github.com/rahul286/dc64ae84c97868b862c4
You may try to adapt it for your marketpress issue.
Important lines are: https://gist.github.com/rahul286/dc64ae84c97868b862c4#file-woo-nginx-conf-L44-L55
Rahul, you’re amazing! I’ll try to adapt this for MarketPress 🙂
By the way (off topic) that rtAccount / Social Login thing you have going on on this site, is that a plugin and will it be for sale or shared on WP Extend at some point?
rtAccount wordpress plugin requires a rails app.
We use this rails app + plugin to sync userbase among all our sites with proxy for social-login.
This is complex and unfinished app so it won’t go on sell anytime soon.
For our rails app, https://www.dailycred.com/ is good alternative. All you need is to code a WordPress plugin for that service.