Original reply
Use different caches
fastcgi_cache_path /dev/shm/c1 levels=1:2 keys_zone=C1:50m inactive=1440m;
fastcgi_cache_path /dev/shm/c2 levels=1:2 keys_zone=C2:50m inactive=500m;
fastcgi_cache_path /dev/shm/c3 levels=1:2 keys_zone=C2:50m inactive=10m;
# absolute path
location = /path/to/resource {
fastcgi_cache C1; # etc
}
# regular expression
location ~* wp-admin {
fastcgi_cache C2; # etc
}
# catch-all
location ~ \.php$ {
fastcgi_cache C3; # etc
}
Note you'll have to understand the order Nginx processes requests to get this right, and you'll probably have to use regular expression matching - I find this regex website very useful for testing. Don't use "if". If is evil.
Update. This idea comes from my Nginx configuration files, which are working on my websites. You can download my configurations on my nginx tutorial, part one.
Update 1
As requested, here's a more complete config. This is cut down from the link on the page above as it's pretty long. This shows just the main PHP block, not the other stuff I do such as wp-admin, static image hotlink protection, and forwards from http to https, etc
# Caching. Putting the cache into /dev/shm keeps it in RAM, limited to 10MB, for one day.
# You can move to disk if you like, or extend the caching time
fastcgi_cache_path /dev/shm/hr_nginxcache levels=1:2 keys_zone=HR_CACHE:50m inactive=1440m; #RAM
upstream php {
server 127.0.0.1:9001;
}
# http production headphone reviews server
server {
server_name www.example.com;
listen 443 ssl http2;
ssl_certificate /var/lib/acme/certs/***CERT_DIRECTORY/fullchain;
ssl_certificate_key /var/lib/acme/certs/***CERT_DIRECTORY/privkey;
# Set up preferred protocols and ciphers. TLS1.2 is required for HTTP/2
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
root /var/www/***folder;
# First line is a cached access log, second logs immediately
access_log /var/log/nginx/hr.access.log main buffer=128k flush=60 if=$log_ua;
# Rules to work out when cache should/shouldn't be used
set $skip_cache 0;
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache uris containing the following segments. 'admin' is for one of my websites, it's not required
# for everyone. I've removed index.php as I want pages cached.
#if ($request_uri ~* "/wp-admin/|/admin-*|/purge*|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
if ($request_uri ~* "/wp-admin/|/admin-*|/purge*|/xmlrpc.php|wp-.*.php|/feed/|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenters
# if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|code|PHPSESSID") {
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wordpress_logged_in|code") {
set $skip_cache 1;
}
# If we skip the cache it's likely customised for one user. Set the caching headers to match.
# http://www.mobify.com/blog/beginners-guide-to-http-cache-headers/
if ($skip_cache = 1) {
set $cacheControl "private, max-age=0, s-maxage=0, no-cache, no-store";
}
if ($skip_cache = 0) {
set $cacheControl "public, max-age=86400, s-maxage=86400";
}
# Default location to serve
location / {
# If the file can't be found try adding a slash on the end - it might be
# a directory the client is looking for. Then try the Wordpress blog URL
# this might send a few requests to PHP that don't need to go that way
try_files $uri $uri/ /blog/index.php?$args;
more_clear_headers Server; more_clear_headers "Pragma"; more_clear_headers "Expires";
# add_header Z_LOCATION "hr_root"; add_header URI $uri; # DEBUG
}
# Send HipHop and PHP requests to HHVM
location ~ \.(hh|php)$ {
fastcgi_keep_conn on;
fastcgi_intercept_errors on;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Use the cache defined above. Cache 200 (success) status's, for 24 hours, and cache
# specific other status's for an hour. This helps mitigate DDOS attacks.
# Only cache GET and HEAD requests
fastcgi_cache HR_CACHE;
fastcgi_cache_valid 200 1440m;
fastcgi_cache_valid 403 404 405 410 414 301 302 307 60m;
add_header X-Cache $upstream_cache_status;
fastcgi_cache_methods GET HEAD;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
# Set the cache control headers we prepared earlier. Remove the old unnecessary Pragma and hide
# the server version. Clearing existing headers seems necessary
more_clear_headers "Cache-Control";
add_header Cache-Control $cacheControl;
more_clear_headers "Pragma"; more_clear_headers Server; more_clear_headers "Expires";
}
}
Update 2, putting the two above parts together
fastcgi_cache_path /dev/shm/c1 levels=1:2 keys_zone=C1:50m inactive=1440m;
fastcgi_cache_path /dev/shm/c2 levels=1:2 keys_zone=C2:50m inactive=500m;
fastcgi_cache_path /dev/shm/c3 levels=1:2 keys_zone=C2:50m inactive=10m;
# regular expression for directory app1
location ~* ^\/.*app1\/.*.php$ {
fastcgi_cache C1; # etc
}
# regular expression for directory app2
location ~ ^\/.*app2\/.*.php$ {
fastcgi_cache C2; # etc
}
# regular expression for directory app3
location ~ ^\/.*app3\/.*.php$ {
fastcgi_cache C3; # etc
}