Created
May 26, 2018 07:02
-
-
Save danielpotthast/0005ac7f358a3e2524d46792976efb0c to your computer and use it in GitHub Desktop.
Varnish Konfiguration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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