Nginx FastCGI caching dramatically reduces PHP processing load by storing rendered responses on disk and serving them directly to subsequent visitors. On RHEL 8, combining Nginx with a PHP-FPM backend and a well-configured cache can cut backend response times by 80–95% for cacheable pages. This tutorial walks through configuring the fastcgi_cache_path directive, defining cache keys, bypassing the cache for authenticated users, and verifying hits with curl. By the end you will have a production-ready caching layer protecting your PHP application.

Prerequisites

  • RHEL 8 server with a sudo-capable user
  • Nginx installed and running (dnf install -y nginx)
  • PHP-FPM installed and configured (dnf install -y php-fpm)
  • A PHP application (WordPress or similar) accessible via PHP-FPM socket or TCP
  • SELinux in enforcing mode (default on RHEL 8)
  • firewalld active and HTTP/HTTPS ports open

Step 1 — Define the Cache Path in the http Block

Open the main Nginx configuration file and add the cache zone definition inside the http block. This allocates a 256 MB shared memory zone named PHP_CACHE and reserves 2 GB of disk storage under /var/cache/nginx/fastcgi.

sudo mkdir -p /var/cache/nginx/fastcgi
sudo chown nginx:nginx /var/cache/nginx/fastcgi

# Add inside the http { } block in /etc/nginx/nginx.conf
# fastcgi_cache_path /var/cache/nginx/fastcgi
#     levels=1:2
#     keys_zone=PHP_CACHE:256m
#     max_size=2g
#     inactive=60m
#     use_temp_path=off;

Edit the file directly:

sudo nano /etc/nginx/nginx.conf

Add the fastcgi_cache_path line after the http { opening brace, then save.

Step 2 — Set the Cache Key and Global Cache Settings

Still inside the http block, define the cache key and a global ignore-headers directive so cookies do not accidentally fragment the cache.

fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout updating invalid_header http_500;
fastcgi_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;

Step 3 — Enable Caching in the Server Block

Inside your virtual-host server block, create two map variables that determine whether a request should bypass the cache — one for active PHP sessions, another for POST requests. Then enable caching in the PHP location block.

# /etc/nginx/conf.d/example.com.conf

map $http_cookie $no_cache_cookie {
    default 0;
    "~*wordpress_logged_in" 1;
    "~*comment_author"      1;
}

map $request_method $no_cache_method {
    default 0;
    POST    1;
}

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/html;
    index index.php;

    location ~ .php$ {
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        fastcgi_cache        PHP_CACHE;
        fastcgi_cache_valid  200 301 302 10m;
        fastcgi_cache_valid  404 1m;
        fastcgi_cache_bypass $no_cache_cookie $no_cache_method;
        fastcgi_no_cache     $no_cache_cookie $no_cache_method;
    }
}

Step 4 — Apply SELinux Context and Reload Nginx

RHEL 8 SELinux policy requires the cache directory to carry the httpd_cache_t context so Nginx can write to it.

sudo semanage fcontext -a -t httpd_cache_t "/var/cache/nginx/fastcgi(/.*)?"
sudo restorecon -Rv /var/cache/nginx/fastcgi

sudo nginx -t
sudo systemctl reload nginx

Step 5 — Test Cache Hits with curl

Send two requests to the same URL and inspect the X-Cache-Status response header. The first request populates the cache (MISS); subsequent requests return HIT.

curl -sI http://example.com/ | grep -i x-cache
# X-Cache-Status: MISS

curl -sI http://example.com/ | grep -i x-cache
# X-Cache-Status: HIT

Step 6 — Purge the Cache

Nginx open-source does not include a built-in purge module, but you can delete cache files directly. The cache path uses the MD5 of the cache key as its filename hierarchy.

# Remove all cached objects
sudo find /var/cache/nginx/fastcgi -type f -delete
sudo systemctl reload nginx

# Alternatively, install nginx-mod-http-cache-purge from EPEL
# and add `fastcgi_cache_purge PURGE from 127.0.0.1;` to the location block

Conclusion

You have configured Nginx FastCGI caching on RHEL 8, defined a per-request cache key, added bypass rules for logged-in users and POST submissions, applied the correct SELinux file context, and verified cache behavior with curl -I. The X-Cache-Status header gives you real-time visibility into cache hits and misses without touching log files. This setup is safe to deploy behind Cloudflare or any upstream CDN because the bypass logic prevents stale authenticated content from leaking to other users.

Next steps: How to Set Up Varnish Cache as a Reverse Proxy on RHEL 8, How to Configure HAProxy for HTTP and TCP Load Balancing on RHEL 8, and How to Set Up a LEMP Stack on RHEL 8.