vcl 4.1; import std; probe default_probe { .url = "/health"; .timeout = 2s; .interval = 5s; .window = 5; .threshold = 3; } backend default { .host = "klz-app"; .port = "3000"; .connect_timeout = 10s; .first_byte_timeout = 300s; .between_bytes_timeout = 10s; .probe = default_probe; } acl purge { "localhost"; "127.0.0.1"; } sub vcl_recv { # Only allow PURGE from the ACL if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(405, "Not allowed.")); } return (purge); } # Only cache GET and HEAD requests if (req.method != "GET" && req.method != "HEAD") { return (pass); } # Bypass cache for Gatekeeper, Directus and CMS proxy if (req.url ~ "^/gatekeeper" || req.url ~ "^/directus" || req.url ~ "^/admin" || req.url ~ "^/cms") { return (pass); } # Bypass cache for Next.js preview mode / health checks if (req.url ~ "^/api/preview" || req.url ~ "^/health") { return (pass); } # Remove all cookies for static files to improve cache hits if (req.url ~ "\.(png|gif|jpg|jpeg|svg|ico|webp|js|css|woff|woff2|otf|ttf)$") { unset req.http.Cookie; } # Normalize Cookies: Remove tracking cookies that don't affect page content # This keeps cookies like NEXT_LOCALE or AUTH cookies if needed, but strips others if (req.http.Cookie) { # Strip Google Analytics cookies set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__utm.|_ga.|_gid.|_gat)(=[^;]*)?", ""); # Strip empty cookies set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", ""); if (req.http.Cookie ~ "^\s*$") { unset req.http.Cookie; } } return (hash); } sub vcl_backend_response { # Cache static assets for a long time if (bereq.url ~ "\.(png|gif|jpg|jpeg|svg|ico|webp|js|css|woff|woff2|otf|ttf)$") { set beresp.ttl = 1w; } # Respect Cache-Control from Next.js # If the response should not be cached, Next.js will usually send Cache-Control: no-cache, no-store, etc. if (beresp.http.Cache-Control ~ "private" || beresp.http.Cache-Control ~ "no-cache" || beresp.http.Cache-Control ~ "no-store") { set beresp.uncacheable = true; return (deliver); } # Set a default TTL if none is provided by the backend if (beresp.ttl <= 0s) { set beresp.ttl = 120s; } return (deliver); } sub vcl_deliver { # Add a debug header to show if it was a hit or miss if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; set resp.http.X-Cache-Hits = obj.hits; } else { set resp.http.X-Cache = "MISS"; } }