Nginx Rewrite Rules for W3 Total Cache Plugin

We have been using nginx from long time to run our WPMU + domain mapping configuration for rtBlogs network.

Recently when we decided to switch from Wp Super Cache to W3 Total Cache plugin, we were stuck while translating apache’s (.htaccess) rewrite rules to nginx configuration.

Now, after some efforts we managed to get nginx working with W3 Total Cache plugin with following rewrite rules.

# if the requested file exists, return it immediately
if (-f $request_filename) {

## W3 Total CACHE BEGIN set $totalcache_file ''; set $totalcache_uri $request_uri; if ($request_method = POST) { set $totalcache_uri ''; } # Using pretty permalinks, so bypass the cache for any query string if ($query_string) { set $totalcache_uri ''; } if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) { set $totalcache_uri ''; }
# if we haven't bypassed the cache, specify our totalcache file if ($totalcache_uri ~ ^(.+)$) { set $totalcache_file /wp-content/w3tc-$http_host/pgcache/$1/_default_.html; } # only rewrite to the totalcache file if it actually exists if (-f $document_root$totalcache_file) { rewrite ^(.*)$ $totalcache_file break; } ##W3 Total CACHE END # all other requests go to WordPress if (!-e $request_filename) { rewrite . /index.php last; }

Above codes will sit inside server{ location{ } } block.


Our original configuration file is too big and contains many unwanted things so I am not publishing it here.

Anyway, if you stuck somewhere, feel free to use comment form below. 😉

Update: For those who are faceing issues with gzip (compression)…

I have a code block at the beginning of  location /{} block in our nginx configuration file as below:

          location / {
               gzip  on;
               gzip_http_version 1.0;
               gzip_vary on;
               gzip_comp_level 3;
               gzip_proxied any;
               gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
               gzip_buffers 16 8k;

Above code-block basically “asks” nginx to turn on compression when files with listed mime types (see line gzip_types) being served

When above lines are present in your configuration, you can altogether disable compression settings from w3 Total Cache as nginx webserver will automatically handle compression for those requests. Not tested though.

29 replies on “Nginx Rewrite Rules for W3 Total Cache Plugin”

  1. Awesome thank you for sharing – does it matter if we’re using disk/apc/xcache or whatever for caching?

    1. @Steve
      Rewrite rules are needed for disk-based caching only.
      In other modes like APC/xcache/memcache/etc you do not need any kind of rewrite rules at all.

  2. A few issues with this setup – it will only actually rewrite to the cached disk files, so this setup isn’t actually any better than using supercache. It won’t work with minified files, and the CDN integration probably won’t work either.

    1. @Michael


      A few issues with this setup – it will only actually rewrite to the cached disk files, so this setup isn’t actually any better than using supercache

      There cannot be comparison in this context as the whole point of adding these code was to remove wp-super-cache and use only one plugin for CDN, page-caching & to minify js/css.


      It won’t work with minified files, and the CDN integration probably won’t work either.

      I will check minified files regarding issue as on the setup on which this is tested, minification is not turned on yet.
      But CDN, in origin-pull (mirror) mode is configured and working fine.

      Thanks for your inputs though. 🙂

  3. All seems to be working with the exception of minify. As soon as I try to minify a css file it fails to find it. It seems the url is getting written wrong.

    That just doesn’t look right to me. searching the file system it seems the file doesn’t even exist either. I also found out that if I uncheck “Rewrite URL Structure” it works but much much slower than it should be.

    Any idea’s?

    1. @Scott
      As noted by Michael in above comment, rewrite rules given by me wont work with minifiy settings.
      I will find a work-around soon.
      Thanks for your feedback. 🙂

  4. I had to remove -$http_host and append .gzip from my rule, so it now looks like:
    set $totalcache_file /wordpress/wp-content/w3tc/pgcache/$1/_default_.html.gzip;
    Are you guys using the dev version of w3tc? I am using the stable released..
    It seems to work though so far! Haven’t tested heavily yet..

    1. @marco
      I am using stable release of w3 total cache.

      I am not using compression option in w3 total cache.
      In my case, I am using nginx gzip settings which I added in above post just now.

      If you still want to use gzip from w3 total cache I guess you can use try_files block.
      I will do my bit of research and will soon update nginx conf that will work with gzip as well as minify options given in w3 total cache.

      1. @Rahul: Since W3 Total Cache can already create static gzipped files for you, why would you have nginx do compression on the fly every time?

        At least nginx won’t attempt to recompress a .gzip file because it doesn’t match it’s mime types of what to serve compressed.

        I also noticed no HTTP host reference in my pgcache directory path (currently testing and the cache file base name was _index.html and not _default_.html.

        1. @Joost
          I faced some issues in getting .gzip files to work from disk storage.
          So I opted-in for APC cache. Also Doncha used nginx on-the-fly compression in his guide here.
          In my case, I have 2GB RAM on my VPS. APC eats up less than 60MB for storing cached pages in RAM so I went for APC.
          You can also check my discussion with Fredrick (w3 total cache developer) and others on APC v/s disk-storage here.

          I was really expecting better support for nginx in recent w3 total cache release but nginx support is moved to future release (1.0 version).
          For my clients, I still want to figure out pure nginx configuration which should work with disk-based gzip compression, js/css minification with rewrites.
          As playing with nginx consumes a lot of time, I am not sure if I will be able to figure out nginx rules myself in this month 😐

  5. Thanks for your rewrite rule.

    I am testing the W3 total cache as well. But I found that there is no page generated under pgcache directory. I already enable page cache and I think it will generate some files under that directory, am I correct?

    I am running nginx + wordpress 3.01 + multisite(subdirectory) + domain mapping. Thanks.

  6. I came across this whilst looking for answers to a similar problem. I have Apache, W3TC, WordPress and phpBB and wanted to install eaccelerator. I then had all kinds of strange rewrite failures on the phpBB rewrite rules, haven’t solved them yet, but will leave a trail of my investigations over here in case it helps others.

  7. When using minify settings, are you able to bypass nginx to get php to generate the combined css or js files? For me I’m noticing it hit’s the missing file on request and php never get’s the request…

  8. Ok I’m pretty sure everything is working with my install of nginx, wordpress and w3 total cache.. this is without playing with any re-writes except the permalinks in the wordpress.conf file. However, after doing speed page testing at I keep getting a grade of “F” on browser caching. Can anyone help?

    By the way I am using the development version of w3 total cache which is stated to have nginx support.

    If anyone has any answers it would be greatly appreciated. Thank you

  9. I give up on private server till SOMEBODY ON THE INTERNET can figure out how to make this whole process of having a speedy wordpress site simpler on a nginx server. I’ve seen about 10,000 solutions to rewrites and no one agrees on it. It’s all incredibly confusing for newcomers.

  10. Totally untested, but the first block could be written something like this:

    location / {
    if( $request_method = POST ) { set $w3tc_pass = 1;}
    if( $query_string) { set $w3tc_pass = 1;}
    if ($http_cookie ~* “comment_author_|wordpress|wp-postpass_” ){ set $w3tc_pass = 1;}
    try_files $uri $uri/ /wp-content/w3tc-$http_host/pgcache/$request_uri/_default_.html /index.php?$args;

    try_files is recommended over rewrites and testing for existance of files (it does’s it internally..)
    Will try this somewhere and see if it works…

  11. Here we go – still untested, still four if’s (would be great to reduce that):

    location / {
    if( $request_method = POST ) { set $w3tc_pass = 1;}
    if( $query_string) { set $w3tc_pass = 1;}
    if ($http_cookie ~* “comment_author_|wordpress|wp-postpass_” ){ set $w3tc_pass = 1;}
    try_files $uri $uri/ /index.php?$args;
    try_files $uri $uri/ /wp-content/w3tc-$http_host/pgcache/$request_uri/_default_.html /index.php?$args;

Comments are closed.