Apache to Nginx Migration Tips

Using WP Super Cache with Nginx

While utilizing permalinks for WordPress on nginx is incredibly easy, getting WP Super Cache to work to the best of its ability requires a bit more elbow grease. WP Super Cache can save you a great deal of bandwidth by proving both uncompressed and gzip compressed versions of your pages and articles in a cached html format. And it saves both versions of these in the /wp-content/cache/supercache/ folder. The problem is we need to make sure that Nginx serves these files when the conditions are appropriate thus completely bypassing the PHP interpreter when not needed. Since Nginx does an incredible job serving static files, getting this one right can be of great benefit.

Below is the current Nginx configuration used for Kbeezie.com with WP Super Cache enabled.

location / {
        # Enables the Gzip Static Module (this must be added via --with-http_gzip_static_module
        # Compile option when you compile Nginx in order to use Gzip Precompression
        # If you don't have it installed you'll only be able to serve the uncompressed html files
        gzip_static on;
        # Disables serving of Gzipped content to IE6 and earlier
        gzip_disable        "MSIE [1-6]\.";
        # Sets the default mime type to text/html	
	default_type text/html;
        if (-f $request_filename) {
        # Prepares some variables to aid us in determining the existance of the cache
        set $supercache_file '';
        set $supercache_uri $request_uri;
        # Do not use the cache when submitting something such as a comment (ie: goto PHP)
        if ($request_method = POST) {
                set $supercache_uri '';
        # Do not use the cache when submitting a query (ie: goto PHP for parsing)
        if ($query_string) {
                set $supercache_uri '';
        # Do not use the cache where it may cause problems
        if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) {
                set $supercache_uri '';
        # If the variable has not been emptied assign the usual cached file location
        if ($supercache_uri ~ ^(.+)$) {
                set $supercache_file /wp-content/cache/supercache/$http_host/$1index.html;
        # If the cached file exists, rewrite the browsers request to the cached file location
        if (-f $document_root$supercache_file) {
                rewrite ^(.*)$ $supercache_file break;
        # If the cached file location does not exit, or is blank, and the file requested does not exist
        # Fall back to index.php to be parsed dynamically
        if (!-e $request_filename) {
                rewrite . /index.php last;

You’ll notice in the above we only rewrite to the .html file. With the Gzip Precompression module enabled nginx will automatically serve a *.gz file of the same name (ie: index.html vs index.html.gz) to browsers that support gzip encoding. With the above configuration paired with WP Super Cache should help save considerable bandwidth as well as improve site response time when serving up cached results.

Basic Rewrite Conversions

Rewrites are internal by default in Nginx, that is to say by default they’re the equivalent of apache’s [PT] Pass-Thru flag.

A pretty common rewrite setup in .htaccess may look something like this:

RewriteEngine On
Options +FollowSymlinks
RewriteBase /
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://www.domain/$1 [R,L]
RewriteRule ^-(.*)/ /index.php?page=$1 [L]
RewriteRule ^track.png /track.php [L]

Just to show a couple examples. A configuration such as above could be represented as such:

For the last two

location / {
     rewrite ^/-(.*)/ /index.php?page=$1 last;
     rewrite ^/track.png /track.php last;

Typically in a very simple rewrite string you usually just have use rewrite instead of RewriteRule, add a leading slash, and change [L] to last;

For the forced SSL redirect you can do something like this:

server { server_name domain.com; rewrite ^ https://$server_name$request_uri permanent; }
server {
	listen 443;
	server_name domain.com;

This article is still being added on to, and will be updated as each new tip is added


  1. Tom says:

    Great stuff but there are some disadvantages in this configuration. The biggest problem is nginx and it’s lack of proper php module (and thus, slower processing). I tried nginx, then lighttpd and while they both are great pieces of software it’s just swimming against the flow using any other webserver than apache.

    So i decided to go with it, there are many tutorials how to pimp it to better performance. And I did not stop there. I installed HTTP accelerator named Varnish in front of it. That way varnish takes care of static files and cache, and when PHP processing is needed, Apache takes over.


  2. kbeezie says:

    I actually don’t see Nginx’s lack of a ‘module’ to be a disadvantage, its not a modular webserver like apache. And even though they may be ‘swimming against the flow’ per se, they still outperform Apache, and work great on low resource systems.

  3. Victory says:

    I have been using nginx as a reverse proxy to a paster’s server to serve up my Pylons apps and its beautiful how easy it is on the hardware as compared to Apache.

    I still use Apache for a lot of stuff like wordpress, just because i am use to it, but when the big traffic comes, nginx really does shine.