How To Speed Up WordPress With Nginx And WP Super Cache

Edit: Fixes suggested in the comments have been applied to this howto
We recently moved tech.nocr.at over to a bunch of VPSs in order to achieve some decent load balancing and speed. Even though SliceHost isn’t a sponsor, I’d like to give them a quick plug. SliceHost is easily the greatest VPS provider bar none. You pick the Distro you want, you tweak it, you set it up, all ports are available, you do as you wish. If you setup multiple VPS with them you can even have private IP’s between them in order to load balance or cluster. Prices start as low as $20/month. If you use them, click this link so that I can get some referral love. Now on to the article..
WordPress can be a blessing and a pain at the same time. It’s great for displaying dynamic content yet it’s displaying that exact dynamic content that can put a massive stress load on your system. WordPress’s query routines aren’t exactly the best. Let’s not even go into how much of a hog Apache can be, but for running dynamic content and prettying up your url’s, mod_rewrite can’t be beat. By using WP Super Cache to help reduce the load on your SQL queries and by placing Nginx in front of Apache as a reverse proxy, you’d be amazed and how quickly your site will load and respond, even enough to withstand a digg of slashdot effect.
Here’s what you are going to need.
- WordPress (of course)
- Apache2
- Nginx
- Wp-Super-Cache
This how-to system assumes that you have your Webserver running under a debian style distro like Ubuntu, but It can easily be modified for other distros like Fedora or CentOS.
Assuming that you already have WordPress running under Apache the first thing we are going to do is install the Wp-Super-Cache plugin and active it under your plugin folder of your WordPress installation. Pay close attention to the installation steps in the included readme.txt file, you have to follow each step properly in order to ensure proper caching.
Wp-Super-Cache creates static html files of your pages lessening the load on your SQL queries. Once you have it running and working let’s move on to our next step, reconfiguring Apache.
Apache can be a resource hog, especially when it has to span multiple child processes in order to serve up content. We are going to have to do some tweaking to apache’s conf file so that it will work behind Nginx.
Open up your /etc/apache2/ports.conf file
sudo nano /etc/apache2/ports.conf
We need to change Apache from port 80 to 8080 as Nginx will be server content to the real world via port 80.
Listen 8080Next we are going to turn KeepAlives off on Apache since Nginx will be dealing with all of the actual browser connections. This will ensure that all of the child processes in Apache die quickly and don’t hang around chewing up memory
Find the KeepAlive entry in your /etc/apache2/apache2.conf file and set it to off
KeepAlive Off
Now that we have made the needed changes in apache we need to restart it so that they take effect.
sudo /etc/init.d/apache2 restart
Next we are going to install Nginx which is a powerful and extremely lightweight http server that is perfect for reverse proxying or load balancing to backend servers like Apache.
sudo apt-get update | sudo apt-get install nginx
Once nginx is installed we are going to need to modify it’s config file located at /etc/nginx/nginx.conf
sudo nano /etc/nginx/nginx.conf
Your conf file should look like this.
user www-data; worker_processes 2; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; sendfile on; tcp_nopush on; keepalive_timeout 3; tcp_nodelay on; gzip on; include /etc/nginx/sites-enabled/*; }
Now we need to move on to the actual site config file for our Nginx setup
sudo nano /etc/nginx/sites-available/default
Your file should look something like this (replace domain.com of course)
server { listen 80; server_name domain.com www.domain.com; error_log /var/log/nginx/domain.com.error.log; access_log /var/log/nginx/domain.com.access.log; # Main location (path to you blog, relative to your domain root) location / { proxy_pass http://127.0.0.1:8080/; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; } # Static files location location ~* ^.+\.(htm|html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ { root /; } # if the requested file exists, return it immediately if (-f $request_filename) { break; } set $supercache_file ''; set $supercache_uri $request_uri; if ($request_method = POST) { set $supercache_uri ''; } # Using pretty permalinks, so bypass the cache for any query string if ($query_string) { set $supercache_uri ''; } if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) { set $supercache_uri ''; } # if we haven't bypassed the cache, specify our supercache file if ($supercache_uri ~ ^(.+)$) { set $supercache_file /wp-content/cache/supercache/$http_host/$1index.html; } # only rewrite to the supercache file if it actually exists if (-f $document_root$supercache_file) { rewrite ^(.*)$ $supercache_file break; } }
The above (especially the if statements) help Ngnix pass the static html files that are created by WP Super Cache directly to the users thus freeing up Apache to do nothing more than handle the dynamic requests.
Now it’s time to restart Ngnix and get the whole ball of wax working
/etc/init.d/nginx restart
What we have essentially done is taken the load of serving static files like images, css, and js files off of apache and passed it on to Ngnix which runs a lot faster and leaner than apache for serving static content. All requests for any dynamic content like php still gets passed on to apache. Clean and simple.
In closing let me mention that this is just what works for me, i’m sure that there might be a better way to use WP Super Cache and Ngnix to speed up WordPress, but what you see above has really helped with the load on both of the tech.nocr.at front-end web servers.

Pingback: Linux tips | builder2
Pingback: HOWTO: Wordpress pretty URLs with Nginx 0.6 (the proper way) at bluebottle
Pingback: Back To Apache | Chesty's Blog
Pingback: nginx 参考资料 » LINKIDEA
Pingback: Wordpress deployment on the live server using chef (and vagrant)
Pingback: nginx giving of 404 when using set in an if-block
Pingback: nginx giving of 404 when using set in an if-block - Question Lounge