These forums are read-only!
nginx rewrite rules for Wordpress + WP Super Cache
  • If you're using a Wordpress blog, one thing you can do to significantly improve performance is install the WP Super Cache plugin. This will store static copies of pages accessed by users who don't require any dynamic content generation (e.g., users who haven't logged in or posted a comment) which should make up the vast majority of your visitors if your site is getting a lot of traffic. These static copies are set up on the filesystem so that they are easily accessible via some simple rewrite rules, so if the cache file already exists the web server can just serve it directly - the request never needs to be passed to PHP. This effectively turns your blog into a static site, allowing you to handle a lot of traffic using very few resources.

    WP Super Cache goes a step further with an option to pre-gzip the content so the server doesn't even need to do that. You probably have CPU to spare so the performance gain here is minimal, but the plugin provides it so I'll show you how to use it.

    Under Apache with mod_rewrite the rules to accomplish all this look something like so:

    RewriteCond %{REQUEST_METHOD} !=POST
    RewriteCond %{QUERY_STRING} !.*s=.*
    RewriteCond %{QUERY_STRING} !.*attachment_id=.*
    RewriteCond %{HTTP_COOKIE} !^.*(comment_author_|wordpress|wp-postpass_).*$
    RewriteCond %{HTTP:Accept-Encoding} gzip
    RewriteCond %{DOCUMENT_ROOT}/blog/wp-content/cache/supercache/%{HTTP_HOST}/blog/$1/index.html.gz -f
    RewriteRule ^(.*) /blog/wp-content/cache/supercache/%{HTTP_HOST}/blog/$1/index.html.gz [L]

    ...
    (similar rules for serving non-gzipped .html)


    If you're using nginx as your primary or front-end web server, translating these isn't exactly straightforward, but it can be done with a little help from nginx's support for variables:

    location /blog/ {
    # enable search for precompressed files ending in .gz
    # nginx needs to be complied using –-with-http_gzip_static_module
    # for this to work, comment out if using nginx from aptitude
    gzip_static on;

    # 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 /blog/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;
    }

    # all other requests go to Wordpress
    if (!-e $request_filename) {
    rewrite . /blog/index.php last;
    }
    }


    Since nginx doesn't support complex tests or nested if statements, the above is a little complex but will provide you with full Wordpress capabilities plus all the benefits of WP Super Cache. Any time that a cached static file exists and is appropriate to use, nginx will serve it directly and the request is never proxied to Apache or FastCGI.
  • thanks for sharing
  • Is it possible there's an easier way to do this using embedded perl or javascript? I've read the docs but still can't make heads or tails out of how nginx is supposed to behave according to the return value of the embedded Perl (or JS), but it seems like a real scripting language could do this testing much more easily and then just pass back the redirect to nginx.