# The nginx side of the nginx Cache plugin, in the three pieces it comes in. # # This is the configuration the plugin's self-test was written against and verified on: # nginx 1.31.3 with ngx_cache_purge built as a dynamic module. The Setup page prints these # same blocks filled in for a particular install; this file is the source they come from. # # It extends the reference micro-cache in Shopclass core (.docker/nginx/nginx.conf) rather # than replacing it: same zone, same key, same bypass rules. The only additions are a # longer `inactive` — an entry the app may hold for an hour must not be evicted for idling # after sixty seconds — and the purge location. # ── main context, before anything else ─────────────────────────────────────────────────── # load_module must be in the main context, above `http {`, not in conf.d. load_module modules/ngx_http_cache_purge_module.so; # ── http{} scope ───────────────────────────────────────────────────────────────────────── fastcgi_cache_path /var/cache/nginx/microcache levels=1:2 keys_zone=MICROCACHE:10m max_size=500m inactive=1d use_temp_path=off; # Bypass the cache only for a request carrying one of core's personalization cookies. # See the caching contract in core for why third-party cookies are deliberately ignored. map $http_cookie $mc_private { default 0; "~(^|;\s*)(oc_cache_bypass|oc_userLocale|osclass|PHPSESSID)=" 1; } # ── server{} scope: the purge location ─────────────────────────────────────────────────── # # $1 is the target's path and $is_args$args carries its query, so the key built here is # byte-identical to the one the php location below stored the page under. Drop either and # every purge of a URL with a query string answers 412 having deleted nothing. # # The allow list is the whole of the access control: a purge takes no credentials, so this # must not be reachable from outside. 172.16/12 covers the default Docker bridge networks; # narrow or widen it to wherever PHP actually runs. # # With real_ip (set_real_ip_from + real_ip_header X-Forwarded-For), nginx replaces the # client address with the forwarded one. If set_real_ip_from trusts more than the proxy # itself, an internet client can send "X-Forwarded-For: 127.0.0.1" and pass this allow # list. Narrow set_real_ip_from to the proxy's own address. The same applies to the # purge_all line below. # # location ~ ^/purge(/.*)$ { # allow 127.0.0.1; # allow 172.16.0.0/12; # deny all; # fastcgi_cache_purge MICROCACHE "$scheme$request_method$host$1$is_args$args"; # } # ── location ~ \.php$ scope ────────────────────────────────────────────────────────────── # # fastcgi_cache MICROCACHE; # fastcgi_cache_key "$scheme$request_method$host$request_uri"; # fastcgi_cache_bypass $mc_private; # fastcgi_no_cache $mc_private; # fastcgi_cache_lock on; # fastcgi_cache_use_stale updating error timeout http_500 http_503; # fastcgi_cache_background_update on; # add_header X-Cache $upstream_cache_status always; # # # Purge everything: one `PURGE /index.php` from PHP clears the whole zone. Sent on # # theme, plugin and settings changes, which touch every page. Loopback only; where # # PHP runs in another container, add that container's address here. # fastcgi_cache_purge PURGE purge_all from 127.0.0.1; # # X-Cache is not decoration: the plugin's self-test reads it to tell "the page was cached # and then purged" from "nothing was ever cached", and refuses to lengthen any window # without it. # # Still deliberately absent, exactly as in core's reference config: no fastcgi_ignore_headers # and no fastcgi_cache_valid. The application's own Cache-Control decides what is stored and # for how long -- which is what makes this plugin a filter on a TTL rather than an nginx change.