Varnish Konfiguration
vcl 4.0; | |
# Default backend definition. Set this to point to your content server. | |
backend default { | |
.host = "127.0.0.1"; | |
.port = "8080"; | |
.connect_timeout = 600s; | |
.first_byte_timeout = 600s; | |
.between_bytes_timeout = 600s; | |
} | |
# Only allow purging from specific IPs | |
acl purge { | |
"localhost"; | |
"127.0.0.1"; | |
} | |
sub vcl_recv { | |
# Normalize the header, remove the port (in case you're testing this on various TCP ports) | |
set req.http.Host = regsub(req.http.Host, ":[0-9]+", ""); | |
# Remove the proxy header (see https://httpoxy.org/#mitigate-varnish) | |
unset req.http.proxy; | |
# Allow purging | |
if (req.method == "PURGE") { | |
if (!client.ip ~ purge) { | |
return (synth(405, "This IP is not allowed to send PURGE requests.")); | |
} | |
ban("req.http.host == " + req.http.host + " && req.url ~ " + req.url); | |
return (purge); | |
} | |
# Only deal with "normal" types | |
if (req.method != "GET" && | |
req.method != "HEAD" && | |
req.method != "PUT" && | |
req.method != "POST" && | |
req.method != "TRACE" && | |
req.method != "OPTIONS" && | |
req.method != "PATCH" && | |
req.method != "DELETE") { | |
/* Non-RFC2616 or CONNECT which is weird. */ | |
return (pipe); | |
} | |
# Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html) | |
if (req.http.Upgrade ~ "(?i)websocket") { | |
return (pipe); | |
} | |
# Only cache GET or HEAD requests. This makes sure the POST requests are always passed. | |
if (req.method != "GET" && req.method != "HEAD") { | |
return (pass); | |
} | |
# Handle compression correctly. Different browsers send different | |
# "Accept-Encoding" headers, even though they mostly support the same | |
# compression mechanisms. By consolidating compression headers into | |
# a consistent format, we reduce the cache size and get more hits. | |
# @see: http:// varnish.projects.linpro.no/wiki/FAQ/Compression | |
if (req.http.Accept-Encoding) { | |
if (req.http.Accept-Encoding ~ "gzip") { | |
# If the browser supports it, we'll use gzip. | |
set req.http.Accept-Encoding = "gzip"; | |
} | |
else if (req.http.Accept-Encoding ~ "deflate") { | |
# Next, try deflate if it is supported. | |
set req.http.Accept-Encoding = "deflate"; | |
} | |
else { | |
# Unknown algorithm. Remove it and send unencoded. | |
unset req.http.Accept-Encoding; | |
} | |
} | |
# Admin users always miss the cache | |
if (req.url ~ "^/wp-(login|admin)" || | |
req.url ~ "preview=true" || | |
req.http.Cookie ~ "wordpress_logged_in_") { | |
return (pass); | |
} | |
# Remove cookies set by Google Analytics, Universial Analytics or Tag-Manager | |
if (req.http.Cookie) { | |
# Google Analytics (__utmA) | |
set req.http.Cookie = regsuball(req.http.Cookie, | |
"(^|; ) *__utm.=[^;]+;? *", "\1"); | |
# Universial Analytics (_ga or _gat_UA-*) | |
set req.http.Cookie = regsuball(req.http.Cookie, | |
"(^|; ) *_ga[^=]*=[^;]+;? *", "\1"); | |
# Double Click (_dc_gtm) | |
set req.http.Cookie = regsuball(req.http.Cookie, | |
"(^|; ) *_dc_[^=]+=[^;]+;? *", "\1"); | |
if (req.http.Cookie == "") { | |
unset req.http.Cookie; | |
} | |
} | |
# Send Surrogate-Capability headers to announce ESI support to backend | |
set req.http.Surrogate-Capability = "key=ESI/1.0"; | |
# always pass through POST requests and those with basic auth | |
if (req.http.Authorization || req.method == "POST") { | |
return (pass); | |
} | |
# Do not cache these paths | |
if (req.url ~ "^/wp-cron\.php$" || | |
req.url ~ "^/xmlrpc\.php$" || | |
req.url ~ "^/wp-admin/.*$" || | |
req.url ~ "^/wp-includes/.*$" || | |
req.url ~ "\?s=") { | |
return (pass); | |
} | |
if (req.http.Cache-Control ~ "(?i)no-cache") { | |
if (client.ip ~ purge) { | |
# Ignore requests via proxy caches and badly behaved crawlers | |
# like msnbot that send no-cache with every request. | |
if (! (req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) { | |
#set req.hash_always_miss = true; # Doesn't seems to refresh the object in the cache | |
return(purge); # Couple this with restart in vcl_purge and X-Purge header to avoid loops | |
} | |
} | |
} | |
# Large static files are delivered directly to the end-user without | |
# waiting for Varnish to fully read the file first. | |
# Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response() | |
if (req.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") { | |
unset req.http.Cookie; | |
return (hash); | |
} | |
# By ignoring any other cookies, it is now ok to get a page | |
unset req.http.Cookie; | |
return (hash); | |
} | |
sub vcl_pipe { | |
# Called upon entering pipe mode. | |
# In this mode, the request is passed on to the backend, and any further data from both the client | |
# and backend is passed on unaltered until either end closes the connection. Basically, Varnish will | |
# degrade into a simple TCP proxy, shuffling bytes back and forth. For a connection in pipe mode, | |
# no other VCL subroutine will ever get called after vcl_pipe. | |
# Note that only the first request to the backend will have | |
# X-Forwarded-For set. If you use X-Forwarded-For and want to | |
# have it set for all requests, make sure to have: | |
# set bereq.http.connection = "close"; | |
# here. It is not set by default as it might break some broken web | |
# applications, like IIS with NTLM authentication. | |
# set bereq.http.Connection = "Close"; | |
# Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html) | |
if (req.http.upgrade) { | |
set bereq.http.upgrade = req.http.upgrade; | |
} | |
return (pipe); | |
} | |
sub vcl_hash { | |
if(req.http.X-brotli == "true") { | |
hash_data("brotli"); | |
} | |
if (req.http.X-Forwarded-Proto) { | |
hash_data(req.http.X-Forwarded-Proto); | |
} | |
} | |
sub vcl_hit { | |
# Called when a cache lookup is successful. | |
if (obj.ttl + 10s > 0s) { | |
// A pure unadulterated hit, deliver it | |
return (deliver); | |
} | |
if (obj.ttl + obj.grace > 0s) { | |
// Object is in grace, deliver it | |
// Automatically triggers a background fetch | |
return (deliver); | |
} | |
// fetch & deliver once we get the result | |
return (miss); | |
} | |
sub vcl_miss { | |
# Called after a cache lookup if the requested document was not found in the cache. Its purpose | |
# is to decide whether or not to attempt to retrieve the document from the backend, and which | |
# backend to use. | |
return (fetch); | |
} | |
sub vcl_backend_response { | |
# remove some headers we never want to see | |
unset beresp.http.Server; | |
unset beresp.http.X-Powered-By; | |
# Pause ESI request and remove Surrogate-Control header | |
if (beresp.http.Surrogate-Control ~ "ESI/1.0") { | |
unset beresp.http.Surrogate-Control; | |
set beresp.do_esi = true; | |
} | |
if (bereq.http.X-brotli == "true") { | |
set bereq.http.Accept-Encoding = "br"; | |
unset bereq.http.X-brotli; | |
} | |
# Large static files are delivered directly to the end-user without | |
# waiting for Varnish to fully read the file first. | |
# Varnish 4 fully supports Streaming, so use streaming here to avoid locking. | |
if (bereq.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") { | |
unset beresp.http.set-cookie; | |
set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects | |
} | |
// Set grace time | |
set beresp.grace = 3m; | |
# don't cache if nocache header is set | |
if (beresp.http.cache-control ~ "no-cache") { | |
set beresp.uncacheable = true; | |
set beresp.ttl = 120s; | |
return (deliver); | |
} | |
# only cache status ok, 301 or 302 | |
if ( beresp.status != 200 && beresp.status != 301 && beresp.status != 302 ) { | |
set beresp.uncacheable = true; | |
set beresp.ttl = 120s; | |
return (deliver); | |
} | |
# If our backend returns 5xx status this will reset the grace time | |
# set in vcl_recv so that cached content will be served and | |
# the unhealthy backend will not be hammered by requests | |
if (beresp.status == 500 || beresp.status == 503) { | |
set beresp.grace = 60s; | |
return (retry); | |
} | |
# GZip the cached content if possible | |
if (beresp.http.content-type ~ "text") { | |
set beresp.do_gzip = true; | |
} | |
# if nothing above matched it is now ok to cache the response | |
set beresp.ttl = 24h; | |
return (deliver); | |
} | |
sub vcl_deliver { | |
# remove some headers added by varnish | |
unset resp.http.X-Powered-By; | |
unset resp.http.Server; | |
unset resp.http.X-Drupal-Cache; | |
unset resp.http.X-Varnish; | |
unset resp.http.Via; | |
unset resp.http.Link; | |
unset resp.http.X-Generator; | |
if (obj.hits > 0 ) { | |
set resp.http.X-Cache = "HIT:"; | |
set resp.http.X-Cache = regsub( resp.http.X-Cache, "$", obj.hits ); | |
} else { | |
set resp.http.X-Cache = "MISS"; | |
} | |
return (deliver); | |
} | |
sub vcl_purge { | |
# Only handle actual PURGE HTTP methods, everything else is discarded | |
if (req.method != "PURGE") { | |
# restart request | |
set req.http.X-Purge = "Yes"; | |
return(restart); | |
} | |
} | |
sub vcl_synth { | |
if (resp.status == 720) { | |
# We use this special error status 720 to force redirects with 301 (permanent) redirects | |
# To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html")); | |
set resp.http.Location = resp.reason; | |
set resp.status = 301; | |
return (deliver); | |
} elseif (resp.status == 721) { | |
# And we use error status 721 to force redirects with a 302 (temporary) redirect | |
# To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html")); | |
set resp.http.Location = resp.reason; | |
set resp.status = 302; | |
return (deliver); | |
} | |
return (deliver); | |
} | |
sub vcl_fini { | |
# Called when VCL is discarded only after all requests have exited the VCL. | |
# Typically used to clean up VMODs. | |
return (ok); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment