“WP Fastest Cache” Configuration for Nginx

Wordpress Nginx WP Fastest Cache Configuration

Scope

This article only covers the configuration part of Nginx. If WP Fastest Cache isn’t already installed, and if you are completely new to either Nginx or WP Fastest Cache, then DO NOT read beyond at this point, as it’s not worth the time. This article is for those who have a working Nginx web server, a working wordpress site where WP Fastest Cache is installed, but not configured to work with Nginx.

Introduction

I have been using many cache plugins for wordpress ever since I started using wordpress platform for writing blog articles, but I didn’t like anything so far except WP Fastest Cache. Unlike the other cache plugins, WP Fastest Cache has been working fine from the beginning smoothly without any problems and without bloating its source codes. Even though it has less features compared to W3 Total Cache, WP Total Cache, it is sufficient for me, and is extremely lightweight for the server. This whole things made me to stick with WP Fastest Cache from the beginning, and didn’t make my mind to leave it and look for another even when I changed the web server to Nginx.

The plugin stated in its FAQ section, it supports to Nginx, but it turned out it only supports when Nginx is setup as a proxy server for Apache, where Nginx works in the front-end, meanwhile the apache does all the heavy dynamic content processing while sitting in the back-end. I contacted author and asked from him how to make this plugin works with Nginx, as you might have guessed, he stated the same thing what I also found through another reply as stated earlier. This almost made me to give up on WP Fastest Cache, and look elsewhere, but I couldn’t leave it due to its uniqueness and performance. Even though while I had been searching, I could find a working code, it wasn’t enough for me as it  doesn’t cover certain conditions. so I decided to write my own code, and test it in my own server to see how it turns out. With a load of trials and errors, finally I could produce something working, optimized, and almost equal to its apache counterpart.

Code Snippet

Copy and paste the following code snippet in the server { } block of “default” file (or whatever the file is being used) located in /etc/nginx/sites-enabled/. Make sure to remove the existing location / { } block before using the one in the following code snippet.

server {
  listen 80;
  root /var/www/html;
  index index.php index.html index.htm;
  server_name nucuta.com www.nucuta.com;
  
  #CACHE
    set $condition '';
    if ($request_method = POST)
    {
      set $condition "null";
    }
    if ($query_string)
    {
      set $condition "null";
    }
    if ($http_cookie ~* (comment_author|comment_author_|wordpress_logged_in|wp_woocommerce_session))
    {
      set $condition "null";
    }
    set $fullurl '/wp-content/cache/all${condition}';
  #CACHE ENDING
  
  
  location / {
    set $serve_URL $fullurl${uri}index.html;
    add_header Nucuta-Cache-Location $serve_URL;
    try_files $serve_URL $uri $uri/ /index.php$is_args$args;
    
  }

  location ~* \.(css|gif|ico|jpeg|jpg|js|png|woff|woff2|ttf|ttc|otf|eot)$ {
    expires max;
    log_not_found off;
  }

}

Explanation of Code Snippet

  • It creates a variable and assigns nothing to its container.
  • It checks for the the request_method, and if it’s POST, it sets the aforesaid variable – condition to null, which is just a string NOT a boolean.
  • In the next block it checks for query string, such as anything that comes after ? in a link (in youtube ?v=_lx9pZbhAhc). It checks for the presence of any query string, meaning when there is a query string in the URL, it sets the condition to null.
  • In the next block, it checks for the cookies, which is useful to ignore logged in users/admins/people who made comments/if it’s an e-commerce website, then customers. Basically if request header contains one of these cookie names, it sets the condition variable to null, implying the users who sent such requests are ignored from serving cache files. ~* operating means, it doesn’t strictly checks cases, meaning it works in case-insensitive ways (no uppercase and lowercase difference when checking). Logged off state is also taken into consideration, meaning if an user logged out , and starts using the same browser for exploring the site, they are served the cached contents just as to a guest visitor.
  • In the last block before the “CACHE” comment, It creates another variable and names it $fullurl, and assigns itself the path where the cached files are stored (generated HTML files), in my server since the cache files are stored in “/var/www/html/wp-content/cache/all/” , that path is used. Here cached contents means generated HTML files from PHP pages, and thus no database call, PHP engine is used.
    The $condition variable in the same line is for triggering an artificial 404 state if the given conditions are met. As an example, if an logged in user visited the site, the $fullurl’s path returns as /var/www/html/wp-content/cache/allnull, since it doesn’t exist, a fresh content is served to that particular user (PHP is called)
  • Make sure to enable gzip in /etc/nginx/nginx.conf in your server as well to compress static files on the fly to reduce the download time. text/html also known as HTML files are compressed by default without even mentioning the gzip_types directive. Please refer this article for more information.
    Again another variable is created $serve_URL and is assigned with $fullurl${uri}index.html. This is quite useful when debugging the code. In the production environment, it’s advised to comment it out.

Mechanism and try_files

The basic logic here is, if none of the above conditions are met, $condition variable is nothing, and thus the $fullurl  is simply “/var/www/html/wp-content/cache/all” as it is supposed to be, but if at least one condition is met, it turns out to be /var/www/html/wp-content/cache/allnull. Finally in the location block, try_files directive is used to serve contents depending on their availability. First it tries to serve $firsturl which is declared in the server block, as explained early, If at least one condition is met, it comes out as /var/www/html/wp-content/cache/allnull/index.html , leading to throw 404 error, but since try_files directive is used, it passes to the next order which is /index.php$is_args$args, meaning let the wordpress to take care of the request, meaning serve a fresh content. Basically, if cached files are not available fresh contents are served, otherwise cached files are served. Fresh contents require access to database, and utilize PHP; hence it costs CPU, and RAM, but cached contents virtually cost nothing, since the webserver is Nginx, contents are just HTML files, serving rate is extremely high. This tremendously decreases the page loading time, and improves the conversion, and retention rate.

In $fullurl${uri}index.html, when an user requests a content of the root folder, $uri returns as “/”, if it to either a post or a page, then it would be “/<post or page name>/” (as an example /how-to-change-your-wifi-password/ in http://nucuta.com/how-to-change-your-wifi-password/) (ignore the double quotations).

Relative to root path /var/www/htmlIf none of the conditions are metIf at least one of the condition is met
try_files$fullurl${uri}index.html$fullurl${uri}index.html
Request to root/wp-content/cache/all / index.html/wp-content/cache/allnull / index.html
Request to a page/wp-content/cache/all /<page name>/ index.html/wp-content/cache/allnull /<page name>/ index.html
Request to a post/wp-content/cache/all /<post name>/ index.html/wp-content/cache/allnull /<post name>/ index.html

In try_files directory, after $serve_URL, use $uri if you intend to serve any file format other than html/php, use $uri/ if you intend to serve directories, be aware that if directory listing is enabled, any request to such directory will lead the browser to show all the contents in that particular folder as in windows explorer. It’s strongly recommended to use $uri, because otherwise static contents like images, text files etc.. are not served.

You may remove “add_header” header, as they are used to debug the codes. If you want to see the result yourself, then let it to be in the code, and examine the header through F12 -> Network in Chrome to make sure the codes are working as they are supposed to be.

Don’t forget to use the respective…

listen 80;
root /var/www/html;
index index.php index.html index.htm;
server_name nucuta.com www.nucuta.com;

pertain to your server, but the root folder should always be somewhere up in the same line as the cache folder. As an example, if the root folder is /var/www/html, the cache folder should be under the html folder, the position is not relevant, the cache folder can be in /var/www/html/cache  or /var/www/html/1/2/3/cache. Make sure to use the index.php before index.html, in index directive.

Wp Fastest Cache Settings

The following changes had been made in “WP Fastest Cache” plugin. Cache System option has to be enabled to make the plugin active, Preload makes sure the plugin regularly takes and stores caches without the intervention of the users. Additionally, it provides more options to store caches of specific sections of the website in a given time frame, currently as sections it supports Home Page, Posts, Categories, Pages, Tags, Attachments and the Interval to take caches. As the Interval 8 to 12 pages per minutes is recommended depending on the hardware configuration of the server. For shared hosts keep it minimal as possible, for VPS it’s best to keep it around 8 to 10, for dedicated server anything above is fine as long as it’s not overdone. If preload is disabled, a visit to pages has to be made to store their caches. Logged in Users option restricts the cache for non-logged users, and thereby only visitors see the cache pages. This is quite useful to test any changes made in the website before deploying to public. New Post option clears the entire cache files whenever a new post is published, the new version of wp fastest cache now has additional options to clear out the cache files of all the sections or caches of home page, categories and tag, and this is same for Update Post option as well except it clears caches whenever an existing post is updated.

wp fastest cache settings

Tags:

Leave a Reply to Don Dilanga Cancel reply

Your email address will not be published. Required fields are marked *


This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

20 comments

  1. Avatar

    I wonder… isn’t this article a bit outdated?

    Here is why: WP Fastest Cache already does almost all work for you, out of the box. Beyond any WordPress-specific things, all you need to do is check if an URL has been stored in the cache or not. You don’t need Nginx to figure out first if a user is logged in etc. etc. since WP Fastest Cache already deals with all of that — you might get everything you’ve typed with just

    location / {
    try_files /wp-content/cache/all/${uri}/index.html $uri $uri/ /index.php$is_args$args;
    }

    That’s all it takes. The rest is up to WP Fastest Cache to figure out, and it does a remarkably good job at that.

    Granted, if you really want to, you can add a bit more code to properly set header files. That would require adding another location section, specifically just to find if something is already cached, and, if so, do the appropriate reply with an additional header showing that; if not, it falls back to the usual WP try_files.

    For multisite installations, you’d use a variant:

    location / {
    try_files /wp-content/cache/$host/all/$uri/index.html $uri $uri/ /index.php$is_args$args;
    }

    And as Anastasia already explained, WP Fastest Cache can also deal with different languages as well with yet another twist.

    Things just become slightly more complicated if you have enabled separate caches for mobile and non-mobile versions of your website. In such a scenario, you’ll need to split things among both — because WP Fastest Cache will keep two separate directory structures for that.

    However, these days, the burden of figuring out what to render for a mobile device has been mostly addresses at the HTML side of things; mobile devices basically just pull whatever HTML is there and formats it accordingly. The option for having two separate structures made sense around 2007, when the iPhone was launched, and most websites were not designed for such a small form factor, so website owners would just use a very basic template for mobile, and switch to it according to the device being used. But nobody bothers to do so any more in the 2020s — it’s so much easier to build your HTML/CSS around flex or similar technologies to make it fully responsible. As such, I would simply forget about mobile, and just worry about the rest.

    Granted, if you’re lazy and want a one-size-fits all solution, nothing prevents you from doing a try_files on all possible combinations, even if you know beforehand that some don’t exist. The way the Nginx engine works, anything done with try_files is way faster to evaluate than doing complex queries to figure out how exactly you should construct your URL/path. Instead, Nginx is super-accelerated to execute
    try_files blindingly fast — so long as it gets some help from the other end, i.e. the caching plugin. And that’s one of the reasons why WP Fastest Cache is so useful: it’s got a very regular and logic way of organising the cache on disk, so that web servers can very easily check if a file is on cache or not.

    Hint: if you want things even faster, put Cloudflare in front of your website. It’s free, and WP Fastest Cache will very easily integrate with it. With a bit of magic, you can essentially push a substantial part of your website (HTML, CSS, JS, images, fonts, and other media) to Cloudflare — and force people’s browsers to cache as much as possible on their end — and essentially let Nginx take a break (not that it needs to). Watch carefully as your server’s CPU usage drops to zero and how MySQL suddenly has little to do, while getting insanely fast performance (well, if you pick a modern WP theme that was designed from scratch for performance…) and unbelievably low overall latency. The results are simply fantastic.

    To be honest, while I’ve been using WP Fastest Cache for an eternity now (with Cloudflare), I’ve only noticed all of the above relatively recently. The more I simplified the Nginx configuration to pt as much as possible inside try_files and as few conditions outside it as I could master (these days, they are hardly more than listing what is static content and flagging it as such; all the rest is up to try_files), the faster were the results, to a certain degree of bafflement. Like you, I started from a reasonably complex set of rules to figure out which cases needed to be retrieved from the cache, and how to properly construct URLs or pathnames for each scenario. At the end of the day, however, I figured out that most of that is absolutely unnecessary. All these tools work seamlessly together, and there is no need for giving all those “hints” to any of them — that’s just overoptimisation (which might have been important a decade ago) which will consume CPU to replicate what the many components already do on their own without further configuration…

  2. Avatar

    Thanks so much for this article! Since PHP is not involved and nginx is now just serving a static WFC cached asset, my load times have drastically decreased. In Chrome’s Inspector, the time waiting for first byte went from ~330ms to ~40ms!

  3. Avatar

    Good evening, is this setting still valid for nginx?

  4. Avatar

    thanks. quite useful

  5. Avatar

    Please help me with the caching problem.
    I’ve already wrote to your support e-mail all the details.
    I will really appreciate if you can help me.

    Hello Dear Sir or Madam.

    I have a problem with caching of URL QueryString format /post-name/?lang=en
    I was trying to fix it using your article: https://nucuta.com/wp-fastest-cache-configuration-for-nginx/
    Our site has two languages: Russian (main) and English.
    Using plugins: WPML Multilingual CMS v4.0.3 and WP Fastest Cache v0.8.8.2
    In file wp-config.php I added define(‘WPFC_CACHE_QUERYSTRING’, true);
    Plugin wp-fastest-cache creates folders for each language
    /wp-content/cache/all/ru
    /wp-content/cache/all/en

    I changed settings in Nginx conf:
    set $fullurl ‘/wp-content/cache/all/ru${condition}’;
    set $fullurlen ‘/wp-content/cache/all/en${condition}’;

    And added section:
    location ~ /?lang=.* {
    set $serve_URL $fullurlen${uri}index.html;
    try_files $serve_URL $uri $uri/ /index.php$is_args$args;
    }

    Russion version is working right but English one is caching only via php as I saw in tag
    Also in catalogue /wp-content/cache/all/en there are cache pages.

    Please tell me how to fix this. I really appreciate.
    Or probably you will want to write a decision in your article which I think will be so usefull for other people.

    Thank you so much.
    Have a good day.

    1. Badde Liyanage

      I read your question. In this guide, it doesn’t cache if the URL contains a query string. That’s what it shows here. If the URL contains a $query_string, which is an embedded variable, then it sets the condition to null, and thereby the fullURL contains null string; hence the PHP content are served since wordpress is unable to find null folder. So I suggest you to remove it. Let me know how it goes. I don’t think this is valid in nginx. “location ~ /?lang=.* “. I suggest to use $query_string variable provided by nginx for matching query strings. nginx also has $arg_name variable, where name is the parameter. You can use it in between location to match en and ru so easily. like $arg_lang, or you can use map too, which is very simple, but use it outside of the server block.


      #Use this outside of Server block
      map $query_string $lang{
      ~lang=en en/
      ~lang=ru ru/
      }

      #remove this, as you use query string with cache on
      if ($query_string)
      {
      set $condition "null";
      }

      In your case the code can be corrected as this.

      set $condition '';
      if ($request_method = POST)
      {
      set $condition "null";
      }

      if ($http_cookie ~* (comment_author|comment_author_|wordpress_logged_in|wp_woocommerce_session))
      {
      set $condition "null";
      }
      set $fullurl '/wp-content/cache/all${condition}';
      #CACHE ENDING

      location / {
      set $serve_URL $fullurl${uri}${lang}index.html;
      try_files $serve_URL $uri $uri/ /index.php$is_args$args;

      }

      I didn’t test this, so let me know the result. This works like this. first condition variable is created and assigned nothing, then it checks the request method, if it’s post then condition is null, or it’s ”. likewise it checks the http cookie, if request has any of mentioned cookie then condition is null, otherwise ”. It creates a new variable fullURL, and is assigned /wp-content/cache/all${condition}. If the condition is null, then it’s /wp-content/cache/allnull, otherwise /wp-content/cache/all, which is the correct one to make cache works. So now cache only works if POST request isn’t used, and mentioned cookies are not used. When the URL matches /, meaning anything like yourwebsite.com/, then it creates a variable serve_URL and is assigned, $fullurl${uri}${lang}index.html. it has three variables, FULLURL, which you used, URI meaning the requested URL, and lang url, which calls map module to checks. Map module evaluates the value in query_string, if it’s lang=en, then lang variable is assigned en, if it’s lang=en, then lang variable is assigned ru. If no query string presents, then lang is an empty string. you can use default too, but it’s not needed. ~ is used in front to imply it’s a case sensitive check.
      https://stackoverflow.com/a/45129826/7409460

      Assuming the condition variable is ”. if query string is lang=en, then lang is en, if uri is /, then serve URL is
      ignore +, I used it so it’s clear.


      $fullurl${uri}${lang}index.html
      /wp-content/cache/all + / + en/ + index.html
      /wp-content/cache/all/en/index.html

      Assuming the condition variable is ”. if query string is lang=en, then lang is en, if uri is /wp-fastest-cache-configuration-for-nginx/, then serve URL is
      ignore +, I used it so it’s clear.


      $fullurl${uri}${lang}index.html
      /wp-content/cache/all + /wp-fastest-cache-configuration-for-nginx/ + en/ + index.html
      /wp-content/cache/all/wp-fastest-cache-configuration-for-nginx/en/index.html

      You can change the position of lang variable too, like if en comes before URI, but pay attention to forward slash always.


      $fullurl${lang}${uri}index.html

      so if it comes first use in map
      ~lang=en /en
      instead of
      ~lang=en en/


      $fullurl${lang}${uri}index.html
      /wp-content/cache/all + /en + / + index.html
      /wp-content/cache/all + /en + /wp-fastest-cache-configuration-for-nginx/ + index.html

    2. Badde Liyanage

      I made a small video tutorial. check this out

  6. Avatar

    php block was removed to make the code compatible with other php versions as well.

  7. Avatar

    gzip_static directory was removed as it’s not useful unless there are pre-compressed files of files in the same directory. Now the code is optimized to compress files on the fly. So make sure to add gzip directory as explained in the tutorial.

  8. Avatar

    Could you update the post with a screenshot also of your WP Fastest Cache settings? It would be interesting for readers to know what settings you made in wp fastest cache in combination with nginx. I assume Gzip and Browser caching are disabled as long as they are part of nginx configuration. Thank you!

    1. Avatar

      Thanks for your feedback. I updated the post, please check at end of the post. 🙂

  9. Avatar

    Hello,

    I am total newbie to all this.
    I have a new server that I manage with Webuzo. I’m using Nginx and WordPress. Basic settings (configs) are made by Webuzo, my blog it’s live and works fine.
    I did however added the code needed for pretty permalinks.
    For example I have created permalinks.conf file with content:
    try_files $uri $uri/ /index.php?q=$uri&$args;
    So if I need new settings I just create new .conf files and Webuzo will load them from a specific folder. For me, this is fine.

    So, in this case I would need to create WPFastestCache.conf and add your code. Must I add it in full, with server {} and all that?

    Thank you kindly.

    1. Avatar

      Use Nginx in Configuration, and then add my codes within the existing codes.

  10. […] to cover all the methods in one article. So, this tutorial teaches how to prevent web scraping with Nginx with the help of geo module which is technically known as ngx_http_geo_module in nginx […]

  11. Avatar

    set $serve_URL $fullurl${uri}index.html;
    add_header Nucuta-Cache-Location $serve_URL;
    try_files $serve_URL $uri $uri/ /index.php$is_args$args;

    Were added. now it’s much more neat, also in the header (with this name -> Nucuta-Cache-Location) the real cache location from where the files are served display too.

  12. Avatar

    Article was again edited. if ($query_string !~ “”) was replaced with if ($query_string).

  13. Avatar

    You should change “request_uri” to “uri” in “try_files” in order to fix UTF-8 requests for cached files.
    Since you use request_uri, this rule will not work for any requests which contain UTF-8 symbols.

    1. Avatar

      Thanks for the feedback.

nucuta header blue