In this tutorial we will show you how to take advantage of Nginx caching to speed up your WordPress web application.
2020 Update : Easy Nginx FastCGI/Proxy Cache in RunCloud
IMPORTANT! For RunCloud users, we have implemented Nginx Caching in our new feature, RunCache, as part of RunCloud Hub.
You can apply RunCache to your web application from RunCloud dashboard without having to do manual setup from this post.
Using RunCache in RunCloud Hub, you will also get extra features, including cache exclusion and cache preloading.
Latest guide on how to install RunCache and RunCloud Hub →
Latest guide on how to use RunCache Nginx FastCGI/Proxy Cache →
Nginx Caching vs Varnish Caching
Varnish is an HTTP Accelerator software that is often used by DevOps and Sysadmins in optimizations to their web server setups.
What many people don’t know however, is that Nginx comes with its own highly performant default caching mechanism, fastcgi_cache. Whilst the vanilla implementation is considered imperfect, due to some inconsistencies with cache purging, the guys at FRiCKLE Labs have solved this problem with their ngx_cache_purge module.
The result is a caching mechanism every bit as performant as Varnish. But one that requires a less complex web server architecture. This means fewer potential points of failure and a more resilient platform solution.
At RunCloud we have implemented this module inside our Nginx build since day one, and this tutorial will take you through the steps necessary to take advantage of it.
Just so you know, we keep good company in our belief in the Nginx caching solution. For example the CEO at MaxCDN has said that you don’t need Varnish under Nginx. While the guy behind EasyEngine has spoken at length about this subject, saying that he doesn’t need Varnish since Nginx can do everything.
To be honest, like many other systems, I agree with both of them. RunCloud has chosen to use Nginx Caching over Varnish.
Nginx Helper Plugin
Before setting up our configuration, you need to install the Nginx Helper Plugin from rtCamp. This is the same company that created EasyEngine.
After you have installed the plugin, you need to configure the plugin as follows
FastCGI or Proxy Cache?
Inside RunCloud, we offer two web server stacks for you to choose from. You can choose either Native Nginx or an Nginx + Apache2 Hybrid. If you are using the Native Nginx stack, you need to use FastCGI cache. And if you are using the hybrid setup, you need to use the proxy cache. Got it?
Cache Zone Setup (For both Native Nginx and Nginx + Apache2 Hybrid)
Open /etc/nginx-rc/main-extra.conf with your favorite text editor, and paste the config below.
fastcgi_cache_path /var/run/nginx-fastcgi-cache levels=1:2 keys_zone=FASTCGICACHE:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
proxy_cache_path /var/run/nginx-proxy-cache levels=1:2 keys_zone=PROXYCACHE:100m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_use_stale error timeout invalid_header http_500;
proxy_ignore_headers Cache-Control Expires Set-Cookie;
You may be asking, “why do I need to add both fastcgi and proxy cache?”
Well, this is to give you the option to deploy web applications with either an Native Nginx or Nginx + Apache2 Hybrid stack, without needing to return to edit the configuration. Why not do them both now, does that make sense?
Implementation for Native NGINX
If you are using Nginx + Apache2 Hybrid, skip ahead to the implementation for Nginx + Apache2 Hybrid.
Now you need to know your web application’s name. Remember Linux is case sensitive, so ensure your web application’s name is correct. In this tutorial I will be using {WEBAPP} as a web application name placeholder, wherever you see {WEBAPP} in this tutorial, remember to change it to your web application name.
Now create and edit /etc/nginx-rc/extra.d/{WEBAPP}.location.main.cache.conf. E.g: If your web application’s name is app-jebat, then it will be /etc/nginx-rc/extra.d/app-jebat.location.main.cache.conf.
Inside there, add the config below
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-.*.php|/feed/|index.php|sitemap(_index)?.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;
}
location ~ /purge(/.*) {
fastcgi_cache_purge FASTCGICACHE "$scheme$request_method$host$1";
}
Now create and edit /etc/nginx-rc/extra.d/{WEBAPP}.location.proxy.cache.conf. Inside there, add the following config.
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache FASTCGICACHE;
fastcgi_cache_valid 60m;
add_header X-RunCloud-Cache $upstream_cache_status;
Once you have have done that, make sure that your Nginx config files are syntax error free by issuing the following command.
# nginx-rc -t
You should receive a message saying there are no errors. If the terminal tells you the syntax check has failed, then return to the previous config files and recheck everything.
Finally, once you have passed the syntax check, restart your Nginx server using the following command.
# systemctl restart nginx-rc
Implementation for Nginx + Apache2 Hybrid
Now you need to know your web application name. Make sure your web application name is correct because Linux is case sensitive. Please remember, I will be using {WEBAPP} as a web application name placeholder. Wherever you see {WEBAPP} inside this tutorial, remember to change it to your web application name.
Now create and edit /etc/nginx-rc/extra.d/{WEBAPP}.location.main.cache.conf. E.g: If your web application’s name is app-jebat, it will be /etc/nginx-rc/extra.d/app-jebat.location.main.cache.conf.
Inside there, add the config below
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-.*.php|/feed/|index.php|sitemap(_index)?.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;
}
location ~ /purge(/.*) {
proxy_cache_purge PROXYCACHE "$scheme$request_method$host$1";
}
After that, create and edit /etc/nginx-rc/extra.d/{WEBAPP}.location.proxy.cache.conf. Inside there, add this config.
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
proxy_cache PROXYCACHE;
proxy_cache_valid 60m;
add_header X-RunCloud-Cache $upstream_cache_status;
Once you have have done that, make sure that your Nginx config files are syntax error free by issuing the following command.
# nginx-rc -t
You should receive a message saying there are no errors. If the terminal tells you the syntax check has failed, then return to the previous config files and recheck everything.
Finally, once you have passed the syntax check, restart your Nginx server using the following command.
# systemctl restart nginx-rc
Verifying The Setup
To verify your setup is running, you need to inspect the browser response header. If you are using Mac or Linux, luckily Terminal will do the job.
The command you need to run is:
curl -I https://blog.runcloud.io
Change the URL with your own URL. The response that you receive should be similar to.
From this result you can see, the first request was a MISS and then the second was a HIT. Therefore, this demonstrates that Nginx cache is successfully running.
Now you can enjoy both dramatically increased page load speeds and lower server resource usage, great news!
No offence, but I think a simple page caching like WP-Rocket will give much more better results.
WITHOUT FASTCGI CACHE: Request ===> DNS ===> Nginx ===> PHP/WordPress ===> Cache File
WITH FASTCGI CACHE: Request ===> DNS ===> Nginx ===> Cache File
https://www.littlebizzy.com/blog/fastcgi-cache-homepage
You could combine WP-Rocket with Rocket-Nginx to get optimal results: https://github.com/maximejobin/rocket-nginx
Disclaimer: I’m the creator of Rocket-Nginx.
Thank you Maxime for creating such a great plugin. Will do a tutorial on how to implement it
Most WordPress caching plugins fall over under real load. Run a Load Impact test and then see what happens.
When’s the tutorial coming out?
Is this still the case in a hybrid/proxy setup where Nginx is the proxy in front of Apache? (using ServerPilot here)
It’s never been clear to me whether PHP is even a factor in this setup, since the proxy already serves HTML that was generated by WP Rocket. Would rocket-nginx still improve speeds?
Great job!
How about a PHP site with no purge plugin support?
Edit “inactive=60m;” ?
You can create a php file to request /purge/ URL path to purge. This will give you the idea although won’t fully answer your question https://www.digitalocean.com/community/tutorials/how-to-setup-fastcgi-caching-with-nginx-on-your-vps#purging-the-cache
So would you just have to visit http://www.example.com/purge/some-page to purge the cache on http://www.example.com/some-page?
Nope. There is a calculation on how to do that. Check Purging The Cache section here https://www.digitalocean.com/community/tutorials/how-to-setup-fastcgi-caching-with-nginx-on-your-vps
Hi,
I followed the steps as instructed but the nginx helper plugin isn’t purging the cache. I’m havnig to go in manually and do it. Any idea whats up?
OK I think I might see why… the code for main-extra.config calls for the path to be /var/run/nginx-fastcgi-cache but the cache is actually being stored in /run/nginx-fastcgi-cache (no var). I’m going to try removing the var section and reloading nginx and see what happens
Ok scratch that. I think the problem may be that php-fpm doesn’t have permission to write/change
There is this plugin: https://wordpress.org/plugins/nginx-cache/
I have added path: var/run/nginx-fastcgi-cache but plugin wont work. Is that the correct path?
The same question for this plugin too: https://wordpress.org/plugins/snipe-nginx-cache/
Still have the same problem. Cache won’t clear no matter what plugin I use. I think, and you tell me, the issue may be with the permissions set in the cache folder itself?
Chip, in the mean time clear it using SSH.
cd /run/nginx-fastcgi-cache
rm -rf *
Cache is cleared and will start to rebuild.
we noticed that purging all cache didn’t work. But it works when adding new post or adding new comment. This is due to the caching module itself doesn’t receive purge all cache command. So, the plugin doing rm -rf behind the scene and that won’t work because inside runcloud, nginx user is not web app user.
Hmmm ok interesting — that makes sense. I assume you don’t have a workaround just yet or you would have included it. I’ll see what I can find out over the weekend.
In the meantime — would it be best to set the site or app name for each site on the /var/run/nginx-fastcgi-cache line?
Like /var/run/nginx-fastcgi-cache/app-name
If I’m running multiple sites/apps on the same server/runcloud?
Having the same issue on an Apache/NGINX hybrid of a site I migrated in. Initial loading of site had screwed up pages and the “purge” function in the nginx helper plugin is not purging the entire cache. I had to manually delete all files/folders in /var/run/nginx-proxy-cache to get the site to load.
Will a workaround even be possible?
Nothing on my end yet but ignore my question about the path to the caching folder. I see now that fastcgi_cache_key handles that
I’ve been banging my head against this “flush entire cache” issue and would really love some insight from RunCloud.
I came to the same conclusion as https://github.com/FRiCKLE/ngx_cache_purge/issues/10#issuecomment-24024716 did. The unlinkRecursive function is just recursively deleting folders, which won’t since the web app user doesn’t have permissions. I tried to solve by following the next comment there, which suggested I “add PHP process user to nginx users’ group”. I made a new group, assigned the user my web app is running under and chmod /var/run/nginx-proxy-cache to give that group ownership. I also added define(‘RT_WP_NGINX_HELPER_CACHE_PATH’,’/var/run/nginx-proxy-cache/’); to wp-config.php to point to the correct folder and added that path to my web app’s OPEN_BASEDIR paths. Still no luck.
I think there isn’t any workaround yet. The guys behind the plugin haven’t found one. Perhaps the only solution would be to have this caching functionality built into the RunClouad dashboard per webapp with a purge cache button. The RunCloud platform is only a year old, and incredibly powerful and good value compared to it’s direct competitors, so I am not too fussed about this, fingers crossed they work out a solution in future. And remember, the cache clears perfectly well for things like post and page updates, it’s just the purge all that we need to login to the server to do.
In any case, what I’ve done is updated the code so that my cache is stored in my User login folder at the same level as my webapps, and mounted that folder in memory (tmpfs – got the instructions from the EasyEngine page about using the NGINX helper plugin). I’ve also adjusted it so that each site has its own separate cache.
It isn’t a complete solution, but it means I can just SSH into my server and my cache folders are all there immediately, which makes deleting them a bit easier/faster than having to change directory to var/run and then delete the entire cache for all the sites.
I’m looking forward to have this integrated with only one click and also wp-cli
Does runcloud provide all the WooCommerce configurations for NGINX as well with WordPress installation?
Not sure. But a lot of customers already using WooCommerce without asking anything to be fixed
This response is a little weird.. you’re part of the Runcloud team, why don’t you ask your team to confirm?
Nginx helper doesn’t flush when requested.
Have to delete cache manually from terminal.
Run in terminal to remove cache in folder without deleting the folder :
rm -rf /var/run/nginx-fastcgi-cache/*
Same problem here, no way to clear the nginx fastcgi cache from Wordpress itself, only via ssh.
This is suboptimal, has anyone found a solution yet?
Thanks
Any updates when we can get a nginx cache we can manually flush in WordPress? The article isn’t very useful without any option to flush. It would be great to see the Rocket-Nginx integration as well. Is it on a roadmap or similar?
If you are using WP with woocommerce: you’ll need to add the following to ask fastcgi cache not to cache woocommerce related pages etc to
/etc/nginx-rc/extra.d/{WEBAPP}.location.main.cache.conf
by using your favourite editor, mine is NANO.
************Start here ***************
Skip cache on WooCommerce pages
if ($request_uri ~* “/store.|/cart.|/my-account.|/checkout.|/addons.*”) {
set $skip_cache 1;
}
Skip cache for WooCommerce query string
if ( $arg_add-to-cart != “” ) {
set $skip_cache 1;
}
#true only when the cookie exists
if ( $cookie_woocommerce_items_in_cart ) {
set $skip_cache 1;
}
**************End here************
If you are using W3 total cache, add the following
************Start here ***************
location ~ ^/wp-content/cache/minify/(.+.(css|js))$ {
try_files $uri /wp-content/plugins/w3-total-cache/pub/minify.php?file=$$
}
**************End here************
Ressource : https://gist.github.com/pelmered/616efcde63c17a4dc3cd
can you just run a cron job to clear the cache ever 5-10 mins??
I just followed this tutorial and its clearing my cache when I update a page. I havent tried to add a new post yet.
It works if you’re updating a page, create a new post or leave a comment. But it won’t clear cache if you try to purge all cache
Would be stellar to have a solution for purging the cache without having to SSH into the server and issue an rm command.
Any ideas?
Server-side caching will always beat a WordPress plugin for caching.
Definitely. I keep having this discussion in the WordPress speed up Facebook group.
Another great thing about NGINX caching is that it will continue to serve your static cached pages, even if your server PHP has gone down, that’s really cool.
so now i had to delete a plugin and even if I clear the folder in /run the cache is not cleared. this is insane. any help??
For all of you guys who are still having the cache purging issue, you might want to try adding /var/run/nginx-fastcgi-cache to your OPEN_BASEDIR list in your Web Application settings.
that isn’t going to help because the created cache file is owned by runcloud-www while the web app owner is “runcloud” or other user
Are you ever going to fix this? I know someone mentioned server-side clearing is better than a plugin but not for those of us with clients who need to purge cache themselves and without having to post.
I ended up having to cancel my account with you guys and I HATED doing it but I needed cache purging to work cause of my clients.
If it ever gets fixed please post an update as I would love to come back!
Yeah. We got a solution. However, we need to build our own plugin for the solution to works. Will do a new blog post once we have modified the original plugin
Hi,
Would you mind sharing the solution? Also, What about caching other PHP applications such as Drupal or WHMCS apart for just WordPress. Would you suggest any modified versions of the above script?
Outstanding, really look forward to that!
Except me to come back once this is released!
When you will make this work?
Do you have solution for this?
Bueller?
Any update on this? I was considering developing something myself for my own clients but decided to check here first and saw this.
Hi I was just wondering what’s the timeline on RunCloud’s own nginx purge cache plugin release?
Were all the more recent comments deleted off of this guide?
I check back regularly on this post for ANY update, even if this plugin has been put on hold, that’s okay, at least it’s an update.
But now it seems my comment and a lot of other comments were deleted…?
Anyone tried this https://en-gb.wordpress.org/plugins/nginx-cache/
This doesn’t work.
[emerg] “proxy_cache” zone “PROXYCACHE” is unknown in /etc/nginx-rc/nginx.conf
I believe this will help to clear Nginx cache
New Update from WP Rocket
3.3.0.1 April 9, 2019
Third Party Compatibility: Synchronize with NGINX Helper to clear NGINX Cache when WP Rocket cache is cleared (#793)
Has anyone confirmed that the WP Rocket release actually works with NGINX Helper correctly on a RunCloud hybrid deployment?
hi, spinwpup was able to handle cache clearing with extra daemon – https://spinupwp.com/doc/cache-daemon/
any news there, runcloud?
Dearp RC Team why not do an article for WP rocket, Hummingbird and afew other populer caching plugins.
thanks for the suggestion
Plugin NGINX Helper dont work….. :/
Two questions.
Does config work for multisite?
Is it possible to have both the fast cgi and redis cache cleared in one hit?
With our new RunCache feature, it definitely is Peter!
So FastCGI is installed by default but not enabled???
FastCGI is enabled with the Apache2 stack, Johnny.
(Sorry for my English..)
If anyone instereded I find a solution..
After create one fresh droplet in digitalocean and setup in runcloud (and before create app or setup cache) I open /etc/nginx.conf
and change line:
user runcloud-www runcloud-www
to
user runcloud runcloud
(to match php user to nginx user)
After that I create one app and put directory /var/run/nginx-fastcgi-cache in opendir settings. Next I setup one WP install and add nginx helper plugin AND add in wp-config.php that:
define( ‘RT_WP_NGINX_HELPER_CACHE_PATH’, ‘/var/run/nginx-fastcgi-cache’ );
..to find the correct path.
And it’s working like a charm…
Comments are closed for this article as it is no longer relevant in 2019 and beyond. Please refer to the new RunCache article. https://blog.runcloud.io/2019/09/26/introducing-new-feature-runcache.html