How to enable server-side FastCGI caching with Nginx and PHP

Nginx is an open-source and high-performance web server that can be used to speed up content and application delivery. Nginx enhances security, improves scalability, and also can be used as a high availability load balancer. It can be used as a reverse proxy and one of the most important uses of Nginx is content caching. One of the best approaches is to use Nginx as content caching. In this article, we will discuss Nginx FastCGI content caching for better performance of websites.

Enabling FastCGI caching in Nginx

In this article, we assume that you have already installed Nginx with PHP on your Linux machine.

To start enabling FastCGI caching, edit the virtual host configuration file in which caching is to be enabled.

$ cd /etc/nginx/conf.d
$ vi example.conf

Add the following content to the top of the file. Remember that the lines should be outside the server {} directive.

fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

Configure fastcgi cache path

Where,

  • fastcgi_cache_path – location of the cache
  • levels – hierarchy level of cache, it sets up two-level directory hierarchy under /etc/nginx/cache
  • keys_zone – memory zone name (In this example I have used MYAPP. You can have your own preference)
  • inactive – specifies the time after which cached data that are not accessed during the time specified gets deleted from the cache. In this example, inactive time is set 60m which can be increased or decreased.
  • fastcgi_cache_key – It specifies how the cache filenames will be hashed

Variables used in factcgi_cache_key

  • $scheme – request scheme HTTPS or HTTP
  • $request_method – specifies the request methods such as GET or POST
  • $host – Name of the server matching the request
  • $request_uri – Full request URI

The location of the cache file can be anywhere on the hard disk but the size should be less than the system’s RAM+swap to avoid the “Can not allocate memory ” issue.

Now go to the location directive where the PHP request is passed to php-fpm. Inside “location ~ \.php$ {}” add the following lines

fastcgi_cache MYAPP;
fastcgi_cache_valid 200 1m;

Where MYAPP is the memory zone name and fastcgi_cache_valid 200 caches all the HTTP 200 responses.

If only time is defined, then 200, 301, and 302 responses are cached.

Configure cache period

Run the following command to test the Nginx vhost configuration.

$ nginx -t

Test nginx configuration syntax

Now restart the Nginx service.

$ systemctl restart nginx

A complete vhost configuration file looks like

fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

server {
  listen 80;
  root /usr/share/nginx/html;
  index index.php index.html index.htm;
  server_name your_server_name;
  location / {
    try_files $uri $uri/ /index.html;
  }
  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass unix:unix:/run/php/php8.0-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_cache MYAPP;
    fastcgi_cache_valid 200 60m;
  }
}

Testing FastCGI caching

Create a simple PHP file in the document root directory.

$ vi /usr/share/nginx/html/info.php

Paste the following content and save

<?php
phpinfo();
?>

Now request the file using curl command or using a browser

If the caching works fine, then you can list the caching directory under /etc/nginx/cache

Test nginx cache

Add the following line above server{} directive to indicate if the cache was missed or hit

add_header X-Cache $upstream_cache_status;

Restart the Nginx and run the curl command as

$ curl -I http://localhost/info.php

Cache hit

Setting cache exceptions in Nginx fastCGI Cache

Sometimes we may not need to cache dynamic contents such as basic authentications pages. These types of contents can be avoided from being cached based on different variables like “$request_method” “”$request_uri” “$http_cookie” etc.

Below is the sample configuration for cache exception and should be used inside the server{}

directive.

#Cache everything by default

set $no_cache 0;

#Don't cache POST requests
if ($request_method = POST)
{
set $no_cache 1;
}


#Don't cache if the URL contains a query string
if ($query_string != "")
{
set $no_cache 1;
}


#Don't cache the following URLs
if ($request_uri ~* "/(cp/)")
{
set $no_cache 1;
}

#Don't cache if there is a cookie called PHPSESSID
if ($http_cookie = "PHPSESSID")
{
set $no_cache 1;
}

Conclusion

In this article, we learned how to configure Nginx with PHP for dynamic content caching. Also, we learned about different tips to set up cache exceptions.