WP Rocket – Nginx configuration

I prefer open-source software and have been a long-time advocate of OSS in general. Recently, I started liking WP Rocket plugin that offers some unique features. I already have a perfect Nginx configuration for WP Super Cache plugin (that I consider as the best full-cache plugin till date). Since, WP Rocket uses disk caching like WPSC, I wanted to quickly convert the existing configurations to fit WP Rocket. I did succeed in it and you can find it in my WordPress-Nginx repo. Here I explain how WP Rocket stores the cached content and how it could be integrated into Nginx.

We begin with the classic location block that looks like this…

<span class="hljs-comment"># version 1</span>
<span class="hljs-attribute">location</span> / {
  <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

Our aim is to modify it to fit WP Rocket by the end of this little article.

Let’s start with the home page. The cache for the home page is stored at /wp-content/cache/wp-rocket/example.com/index.html . We can easily find the value of example.com through the variable named $host in Nginx. The following code will search for the cached content before passing the request to the PHP.

<span class="hljs-comment"># version 2</span>
<span class="hljs-attribute">location</span> / {
  <span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

It’s time to by-pass cache on particular scenarios, such as logged-in users. We need to use version #1 mentioned earlier for logged-in users and version #2 for others who can use cached content, if exists. So, how can we split the requests based on cookies (or any other similar factor)? There is no doubt that we need to use if statement and we need to use two location block to match different kind of requests (logged-in users and non-logged-in users). The recommend solution is to use a non-standard HTTP status code and then divert the configuration based on a condition. Here’s the snippet taken directly from the official Nginx page…

<span class="hljs-attribute">location</span> / {
  <span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@other</span>;
  <span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;

  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$something</span>) {
      <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>;
  }

  <span class="hljs-comment"># some configuration</span>
  ...
}

<span class="hljs-attribute">location</span> <span class="hljs-variable">@other</span> {
  <span class="hljs-comment"># some other configuration</span>
  ...
}

In the above code, if the condition $something is false, then # some configuration is executed. If the condition is true, then # some other configuration is executed. Did you get it? I know it could take a while to grab in. When you are ready, let’s use the same technique to divert our requests based on the cookie for logged-in user…

<span class="hljs-comment"># version 3</span>
<span class="hljs-attribute">location</span> / {
  <span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@cachemiss</span>;
  <span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;

  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wordpress_logged_in_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }

  <span class="hljs-comment"># executed only for general visitors (who are not logged-in)</span>
  <span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

<span class="hljs-attribute">location</span> <span class="hljs-variable">@cachemiss</span> {
  <span class="hljs-comment"># executed only for logged-in users</span>
  <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

Note: you may use any HTTP status code that isn’t used elsewhere.

Let’s add a couple of more cookie checks to bypass cache for commenters and password-protected posts…

<span class="hljs-comment"># version 4</span>
<span class="hljs-attribute">location</span> / {
  <span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@cachemiss</span>;
  <span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;

  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wordpress_logged_in_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># logged-in users</span>
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "comment_author_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># commenters</span>
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wp_postpass_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># password protected posts</span>

  <span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

<span class="hljs-attribute">location</span> <span class="hljs-variable">@cachemiss</span> {
  <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

Now, cookies are taken care. We also need to bypass the cache on the following conditions…

  • For POST requests.
  • For search requests (format: example.com/?s=search_query).
  • To view pages by ID (format: example.com/?p=id_of_the_post)
  • For AMP test requests (format: example.com/?amp=1)
  • For previewing of posts while editing them (format: example.com/?preview=true).

When we add support for all the above, our config would become…

<span class="hljs-comment"># version 5</span>
<span class="hljs-attribute">location</span> / {
  <span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@cachemiss</span>;
  <span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;

  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wordpress_logged_in_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "comment_author_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wp_postpass_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }

  <span class="hljs-comment"># bypass cache for common query strings</span>
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_s</span> != <span class="hljs-string">""</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># search query</span>
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_p</span> != <span class="hljs-string">""</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># request a post / page by ID</span>
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_amp</span> != <span class="hljs-string">""</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># amp test</span>
  <span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_preview</span> = <span class="hljs-string">"true"</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># preview post / page</span>

  <span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

<span class="hljs-attribute">location</span> <span class="hljs-variable">@cachemiss</span> {
  <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}

Well, now, we have a working configuration to server cached content from WP Rocket Plugin. There are lot more to it than what’s discussed above. For example, I’ve only talked about home page so far. Also, we need to add support for SSL. You can find the complete Nginx configuration for WP Rocket Plugin at my repo. If you need explanation for the entire configuration, please say so in the comment section below. If there is enough interest, I will add it later. Happy caching!

14 Replies to “WP Rocket – Nginx configuration”

  1. Hola,

    Fenomena la explicación, pero la configuracion completa no aparece. Hay un 404 en el enlace que pusiste. Se puede ver la configuracion completa en nginx?

  2. This line is wrong:
    try_files “/wp-content/cache/wp-rocket/$host${uri}$is_args$args/index$https_suffix.html” $uri $uri/ /index.php$is_args$args;

    When I run nginx -t it say:
    nginx: [emerg] unknown “https_suffix” variable …test failed

    Can you fix that code ????

  3. you just forget declare Map on nginx.conf
    like this
    > # For SSL Compatibility – WP Super Cache and WP Rocket depend on this
    > map $scheme $https_suffix { default ”; https ‘-https’; }

  4. Hey Pothi,

    quick question,
    WPSUperCache generate files like meta-wp-cache-UUID.php and wp-cache-UUID.php

    but in your configuration we call index.html and sometimes with suffix-https

    something wrong, my server always render pages :/ BCQ nginx can’t see cache static files

    1. Please make sure that in example.com/wp-admin/options-general.php?page=wpsupercache , under Advanced => Cache Delivery Method, “Expert” is selected instead of “Simple”. Save and clear the cache. WP Super Cache would start creating index.html files going forward.

    1. Unfortunately, my configuration wouldn’t work with Nginx cache, as both types of Nginx cache, particularly the purging method, are available only as part of commercial subscription from Nginx. Thank you.

Leave a Reply

Your email address will not be published. We use cookies to prevent spam comments. Required fields are marked *