10 Steps To Configure Nginx For WordPress, Drop Varnish And Cut Your CPU Load By 50%
Are you using Varnish on your WordPress blog? Possibly the Varnish script by Unixy? Great! Get rid off it. Here’s why you should drop Varnish immediately and configure Nginx and W3 Total Cache properly.
I started with an open mind, but quickly discovered that Nginx (frontend) + Apache (backend) is a far superior combination than Varnish (cache) + Apache (backend). I also discovered that Varnish is basically useless in many scenarios and more of a burden and that Nginx is far superior (not necessarily because its faster, see below).
Varnish: Inferior Cache With Bugs And Configuration Hell
First let me point out that Varnish is a great script and it definitely has a few use-cases, but for smaller and medium sized WordPress sites with up to 50,000 hits per day it is the worst thing you can possibly install. Varnish is not easy to maintain and it has to be updated frequently. It is also consuming a lot more resources than Nginx.
Last, and most importantly, Nginx already includes everything that Varnish provides. A built-in cache and support for 3,000+ simultaneous connections. It is rare that you hit more than 3,000 connections. If you know how to properly configure Nginx as a front-end proxy and enable the built-in caching system, nginx can handle even more than that.
Varnish Does Not Work Well With WordPress
You see, WordPress sessions require all sorts of cookies. Unfortunately, Varnish is an inferior cache when it comes to configuration. Varnish out of the box will stuff everything into a single config file, whereas Nginx scripts such as Nginx admin neatly put vhosts, proxy and server settings into different files. As a programmer or server administrator, you will learn to appreciate a tidy environment and Varnish is a complete mess (out of the box).
Nginx, WordPress and W3 Total Cache: How To Make Them Work Nicely Together
WordPress and Nginx are an excellent combination. After benchmarking various configurations for a few days, here are my findings:
1 CRITICAL: Turn Of W3 Total Cache Browser Cache GZIP Compression
It is critical that you turn off GZIP compression within W3 Total Cache and turn on GZIP compression via Nginx. By default W3 Total Cache and Nginx may both have GZIP turned on and it’s never a good thing to compress already compressed files. This should be #1 on your to-do list. If you do not turn off the compression you will run into all sorts of issues and Nginx may serve no html files at all and instead will bypass W3TC completely, serving WordPress PHP files. There are obviously compatibility issues. You could write some Nginx location rules, which I tried, but gave up on after realizing how superior Nginx’s compression algorithm is. Let Nginx handle the compression and W3 Total Cache the minification, CDN, database, enhanced page and object caches.
2 Adding Expires Headers To HTML FIles
It is recommend that you set an expires header EVEN to your HTML files if you do not deploy frequently.
If you post once or twice per day, there should absolutely be an expires header on all your HTML files. 1 hour caching will deliver outstanding results and will not greatly affect user experience.
If you are serious about performance, there is only one way to go. And you can always create cronjobs to delete critical files like your frontpage. I learnt not to rely on W3 Total Cache due to its many bugs and flaws (not so rare for a complex plugin such as this one).
3 Turn On Nginx Caching (MUST DO For 0.00 CPU LOAD!)
If you use Nginx admin open up /nginx/proxy.inc and change
proxy_buffering off to ON to enable the built-in cache. This cache will GREATLY increase your Nginx performance and GREATLY decrease CPU load. During my tests I went from 0.6 CPU load to 0.3 avg CPU load and eventually even 0.00 despite numerous Apache processes running. Enabling this cache is a must. Set the cache size to 1500 and your site will fly and your resource usage will go down by half or more!
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=microcache:150m inactive=24h max_size=1500m;
4 Avoid File Cookies
Cookies are bad. Period. Always avoid all cookies except session cookies. Don’t set cookies for static files.
5 Turn On W3TC Cache Compatibility
Enable W3 Total Cache Compatibility (General Settings Page) – the 20% decrease is incorrect, it’s barely noticeable and will prevent all sorts of issues that I encountered. I tested for quite a while. In fact, I was about to drop W3 Total Cache for one of the alternatives until I found this setting.
6 Disable UTF8 File Encoding (W3TC)
Check the option “Disable UTF8” – this will prevent improper character encoding by W3 Total Cache. During my test I discovered that W3 Total Cache will add incorrectly encoded code to the first line of all html files. This will cause major issues from time to time and even cause rendering issues. Please note that this will only effect file encoding and will not affect your site negatively.
7 Debugging WordPress
Make sure to debug everything you find. W3 Total Cache, Nginx and WordPress will only play well together if they don’t encounter any fatal PHP crashes. PHP crashes may not be apparent when you load your site yourself, but turn on your debug log and use
tail -f debug.log within your WordPress content dir (wp-content) to monitor the debug file for a while. You will see how well your site works and if there is anything to debug.
8 Nginx High Keep-Alive Values: 40 To 100
Nginx much like Apache requires a high keep-alive value. Test values from 40 to 100. Yes, I am serious 100. Apache may only be able to handle 5 to 15, but Nginx can handle much higher keep-alive times while keeping CPU load at 0.00 – quite incredible. (Please note my setup: 16GB RAM, SSD – you may have to experiment a little on a VPS or shared hosting!)
9 Nginx Timeouts
A lot of idle connections will kill your resources. Although Nginx is kind of a wunderkind, you should set some timeouts that are more reasonable than the default 3m (minutes!) that Nginx uses by default.
You should experiment a little, try this too:
10 Up Your Worker Connections
Finally, make sure to have enough worker connections.
In your nginx.conf change it to:
On a server with 16GB RAM and Quad-Core or better:
The more workers the better Nginx will handle incoming connections. Far superior to anything Apache and Varnish could do.