Implementing FastCGI Cache with NGINX can dramatically improve the performance of your WordPress and WooCommerce websites. This guide provides a step-by-step approach to setting up NGINX with PHP-FPM to leverage FastCGI caching effectively with help of NPP wordpress plugin.
Table of Contents
- Introduction to FastCGI Cache
- Prerequisites
- Installing and Configuring NGINX and PHP-FPM
- Configuring NGINX for FastCGI Cache
- Configuring FastCGI Cache for WordPress
- Optimizing FastCGI Cache for WooCommerce
- Advanced Configuration and Optimization
- Testing and Validation
- Maintenance and Cache Purging
- Conclusion
1. Introduction to FastCGI Cache
FastCGI Cache is a powerful feature in NGINX that stores dynamic content generated by PHP scripts. For WordPress and WooCommerce, this means faster page load times and reduced server load, leading to a smoother user experience and better SEO rankings.
2. Prerequisites
Before setting up FastCGI Cache, ensure you have the following. These are also the prerequisities for wordpress NPP plugin.
- A server running a Linux distribution (e.g., Ubuntu 20.04).
- Root or sudo access to the server.
- NGINX installed and running.
- PHP-FPM installed and configured.
- Properly connect NGINX and PHP-FPM (Check the basic template at the end of the article)
- WordPress and WooCommerce installed.
- If you use NPP plugin, wget needed for Preload action (required), cpulimit for CPU usage control (optional)
- If you use NPP plugin, you can use below one liner bash script giving write permission to PHP-FPM users with associated Nginx Cache paths automatically. This is required for fully functional purge and preload actions without permission issues.
bash <(curl -Ss https://psaux-it.github.io/install.sh)
What does install.sh do? Is it safe?
This Bash script automates the management of inotify/setfacl operations, ensuring efficiency and security. It enhances the efficiency and security of cache management tasks by automating the setup and configuration processes. The install.sh script serves as a wrapper that facilitates the execution of the main fastcgi_ops_root.sh script from psaux-it.github.io. It acts as a convenient entry point for users to initiate the setup and configuration procedures seamlessly. Rest assured, this solution is entirely safe to use, providing a reliable and straightforward method for managing Nginx FastCGI cache purge operations on WordPress front-end.
- Automated Setup: Quickly sets up FastCGI cache paths and associated PHP-FPM users.
- Dynamic Configuration: Detects Nginx configuration dynamically for seamless integration.
- ACL Verification: Ensures filesystem ACL configuration for proper functionality.
- Systemd Integration: Generates and enables systemd service for continuous operation.
- Manual Configuration Support: Allows manual configuration for customized setups.
- Inotify Operations: Listens to FastCGI cache folder events for real-time updates.
3. Installing and Configuring NGINX and PHP-FPM
Step 1: Install NGINX and PHP-FPM
sudo apt update sudo apt install nginx php-fpm
Step 2: Configure PHP-FPM
Edit the PHP-FPM configuration file /etc/php/7.4/fpm/php.ini:
cgi.fix_pathinfo=0
Restart PHP-FPM to apply the changes:
sudo systemctl restart php7.4-fpm
4. Configuring NGINX for FastCGI Cache
Step 1: Create Cache Directories
Create directories where NGINX will store cache files:
sudo mkdir -p /var/cache/nginx/fastcgi_cache sudo chown -R www-data:www-data /var/cache/nginx
Step 2: Update NGINX Configuration
Edit your NGINX configuration file /etc/nginx/nginx.conf to include the following settings:
http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server_tokens off; fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m use_temp_path=off; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Step 3: Site Configuration for WordPress
Edit your site configuration file /etc/nginx/sites-available/yourdomain.com:
server { listen 80; server_name yourdomain.com www.yourdomain.com; root /var/www/html; index index.php index.html index.htm; set $skip_cache 0; # POST requests and URLs with query parameters should not be cached if ($request_method = POST) { set $skip_cache 1; } if ($query_string != "") { set $skip_cache 1; } # Don't cache URIs containing specific strings if ($request_uri ~* "/cart.*$|/checkout.*$|/my-account.*$|/wc-api.*$|/add-to-cart.*$|/admin.*$|/login.*$|/register.*$") { set $skip_cache 1; } # Don't cache for logged-in users or recent commenters if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in|woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session") { set $skip_cache 1; } location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; fastcgi_cache WORDPRESS; fastcgi_cache_valid 60m; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires max; log_not_found off; } # Additional security headers add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; }
5. Configuring FastCGI Cache for WordPress
To further refine the caching setup, configure additional directives in your site configuration file:
Step 1: Adjust Cache Conditions
set $skip_cache 0; # Don't cache POST requests if ($request_method = POST) { set $skip_cache 1; } # Don't cache URLs with query parameters if ($query_string != "") { set $skip_cache 1; } # Don't cache for logged-in users or recent commenters if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") { set $skip_cache 1; } # Enable cache for non-admin pages location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; fastcgi_cache WORDPRESS; fastcgi_cache_valid 60m; }
Step 2: Setting Custom Cache Validity
You can set different cache validity periods for different types of content. For example:
fastcgi_cache_valid 200 60m; fastcgi_cache_valid 301 302 10m; fastcgi_cache_valid 404 1m;
6. Optimizing FastCGI Cache for WooCommerce
WooCommerce requires more specific caching rules due to its dynamic nature, especially for cart, checkout, and account pages:
Step 1: Custom Cache Conditions
Add these rules to ensure dynamic pages are not cached:
set $skip_cache 0; if ($request_uri ~* "/cart.*$|/checkout.*$|/my-account.*$|/wc-api.*$|/add-to-cart.*$|/admin.*$|/login.*$|/register.*$") { set $skip_cache 1; } if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in|woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session") { set $skip_cache 1; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; fastcgi_cache WORDPRESS; fastcgi_cache_valid 60m; }
7. Advanced Configuration and Optimization
Step 1: Gzip Compression
Enable gzip compression to reduce the size of transmitted data:
gzip on; gzip_vary on; gzip_min_length 1024; gzip_proxied any; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
Step 2: HTTP/2
Enable HTTP/2 for better performance:
server { listen 443 ssl http2; server_name yourdomain.com www.yourdomain.com; ssl_certificate /etc/ssl/certs/yourdomain.com.crt; ssl_certificate_key /etc/ssl/private/yourdomain.com.key; ... }
Step 3: Rate Limiting
Implement rate limiting to protect your server from abuse:
http { limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; ... server { ... location / { limit_req zone=one burst=5 nodelay; ... } } }
8. Testing and Validation
Step 1: Validate NGINX Configuration
Before restarting NGINX, validate the configuration:
sudo nginx -t
Step 2: Restart NGINX
sudo systemctl restart nginx
Step 3: Test Cache Functionality
To test if caching works, use the following command to inspect headers:
curl -I https://yourdomain.com
Look for X-FastCGI-Cache header. It should display HIT or MISS.
9. Maintenance and Cache Purging
Step 1: Manual Cache Purge
To manually purge the cache, delete the cache files:
sudo rm -rf /var/cache/nginx/fastcgi_cache/*
Step 2: Automated Cache Purge & Preload
The WordPress plugin NPP addresses the challenge of automating Nginx FastCGI cache purging and preloading (WordPress) in Nginx environments where two distinct users, WEBSERVER-USER and PHP-FPM-USER, are involved.
Problem Statement
- WEBSERVER-USER: Responsible for creating cache folders and files with strict permissions.
- PHP-FPM-USER: Handles cache purge operations but lacks privileges
Challenges
- Permission Issues: Adding PHP-FPM-USER to the WEBSERVER-GROUP doesn’t resolve permission conflicts.
- Nginx Overrides: Nginx overrides default setfacl settings, ignoring ACLs. Nginx creates cache folders and files with strict permissions.
Surprisingly, Nginx cache doesn’t adhere to DEFAULT ACLs.
setfacl -R -m d:u:php-fpm-user:rwX /var/cache/nginx/fastcgi_cache/
Solution
Solution involves combining inotifywait with setfacl under root: Here there is a well written bash script by PSAUXIT that take care of this process automatically.
- fastcgi_ops_root.sh grants PHP-FPM-USER write permissions recursively for Nginx Cache paths for multi instances.
For automate purging and preloading the cache, use plugins like NPP . NPP is a feature rich WordPress plugin that handle Nginx FastCGI Cache Purge and Preload operations automatically on WordPress admin dashboard and totally free.
Step 3: Monitoring Cache Performance
Regularly monitor your cache performance using tools like Munin, New Relic, or built-in NGINX logs to ensure optimal performance.
10. Conclusion
Implementing FastCGI Cache with NGINX can significantly enhance the performance of WordPress and WooCommerce websites by reducing load times and server load. By following this detailed guide, you ensure a properly configured caching system, leading to a smoother user experience and improved SEO rankings. Regular maintenance and proper testing ensure that your cache setup continues to perform optimally.
Proper PHP-FPM & Nginx Setup for WordPress NPP Plugin
PHP-FPM-USER (as known as the website user)
The PHP-FPM user should be a special user that you create for running your website, whether it is Magento, WordPress, or anything.
WEBSERVER-USER (as known as the webserver user)
NGINX must run with it own unprivileged user, which is nginx (RHEL-based systems) or www-data (Debian-based systems).
Connecting PHP-FPM-USER and WEBSERVER-USER
We must connect things up so that WEBSERVER-USER can read files that belong to the PHP-FPM-GROUP This will allow us to control what WEBSERVER-USER can read or not, via group chmod permission bit.
IMPORTANT:
Granting additional group permissions to the “nginx/www-data” user can potentially introduce security risks due to the principle of least privilege. Your PHP-FPM-USER should never have sudo privileges, even if it’s not listed in the sudoer list, as this can still pose security drawbacks.
Therefore, we will set the website content’s group permission to “g=rX” so that “nginx/www-data” can read all files and traverse all directories, but not write to them.
usermod -a -G PHP-FPM-GROUP WEBSERVER-USER
chown -R PHP-FPM-USER:PHP-FPM-GROUP /home/websiteuser/websitefiles
chmod -R u=rwX,g=rX,o= /home/websiteuser/websitefiles
- This reads as: add WEBSERVER-USER (nginx/www-data) to PHP-FPM-GROUP (websiteuser group).
- Here is a simple rule: all the files should be owned by the PHP-FPM-USER and the PHP-FPM-GROUP:
- This translates to the following:
-
- PHP-FPM-USER can read, write all files, and read all directories
- PHP-FPM-GROUP (meantime WEBSERVER-USER) can read all files and traverse all directories, but not write
- All other users cannot read or write anything
PHP-FPM POOL SETTINGS
../fpm-php/fpm.d/websiteuser.conf
[websiteuser.com] user = PHP-FPM-USER group = PHP-FPM-GROUP listen.owner = WEBSERVER-USER listen.group = WEBSERVER-GROUP listen.mode = 0660 listen = /run/php/php7.4-fpm.sock
Also you can check great more in depth tutorial from here linuxbabe