-
-
Save sjelfull/a2d0f7f753478141cfc3 to your computer and use it in GitHub Desktop.
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
# Varnish 4.0 file for our Craft CMS projects | |
# Based on https://github.com/mattiasgeniar/varnish-4.0-configuration-templates/blob/master/default.vcl | |
# | |
# This is still work in progress, comments appreciated. | |
vcl 4.0; | |
# Default backend definition. Set this to point to your content server. | |
backend default { | |
.host = "127.0.0.1"; | |
.port = "80"; | |
} | |
acl purge { | |
# Only allow purges coming from localhost | |
"127.0.0.1"; | |
"localhost"; | |
} | |
# Handle the HTTP request received by the client | |
sub vcl_recv { | |
if (req.restarts == 0) { | |
if (req.http.X-Forwarded-For) { | |
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; | |
} else { | |
set req.http.X-Forwarded-For = client.ip; | |
} | |
} | |
# 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]+", ""); | |
# Exclude Craft admin URL and other url's that shouldn't be cached by Varnish. | |
# If you want to exclude asset folders, upload directories, etc, do it here. | |
if (req.url ~ "(\/admin|p=admin)(.*)" || | |
req.url ~ "^/search(.*)" | |
) { | |
return(pass); | |
} | |
# Allow purging | |
if (req.method == "PURGE") { | |
if (!client.ip ~ purge) { | |
# Not from an allowed IP? Then die with an error. | |
return (synth(405, "This IP is not allowed to send PURGE requests.")); | |
} | |
# If you got this stage (and didn't error out above), purge the cached result | |
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); | |
} | |
# Only cache GET or HEAD requests. This makes sure the POST requests are always passed. | |
if (req.method != "GET" && req.method != "HEAD") { | |
return (pass); | |
} | |
# Configure grace period, in case the backend goes down. This allows otherwise "outdated" | |
# cache entries to still be served to the user, because the backend is unavailable to refresh them. | |
# This may not be desireable for you, but showing a Varnish Guru Meditation error probably isn't either. | |
#set req.grace = 15s; | |
#if (std.healthy(req.backend)) { | |
# set req.grace = 30s; | |
#} else { | |
# unset req.http.Cookie; | |
# set req.grace = 6h; | |
#} | |
# Some generic URL manipulation, useful for all templates that follow | |
# First remove the Google Analytics added parameters, useless for our backend | |
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=") { | |
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", ""); | |
set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?"); | |
set req.url = regsub(req.url, "\?&", "?"); | |
set req.url = regsub(req.url, "\?$", ""); | |
} | |
# Strip hash, server doesn't need it. | |
if (req.url ~ "\#") { | |
set req.url = regsub(req.url, "\#.*$", ""); | |
} | |
# Strip a trailing ? if it exists | |
if (req.url ~ "\?$") { | |
set req.url = regsub(req.url, "\?$", ""); | |
} | |
# Normalize Accept-Encoding header | |
# straight from the manual: https://www.varnish-cache.org/docs/3.0/tutorial/vary.html | |
if (req.http.Accept-Encoding) { | |
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") { | |
# No point in compressing these | |
unset req.http.Accept-Encoding; | |
} elsif (req.http.Accept-Encoding ~ "gzip") { | |
set req.http.Accept-Encoding = "gzip"; | |
} elsif (req.http.Accept-Encoding ~ "deflate") { | |
set req.http.Accept-Encoding = "deflate"; | |
} else { | |
# unkown algorithm | |
unset req.http.Accept-Encoding; | |
} | |
} | |
# Normalize Accept-Language | |
# I don't need it, our site is only in one language | |
if (req.http.Accept-Language) { | |
unset req.http.Accept-Language; | |
} | |
# Large static files should be piped, so they are delivered directly to the end-user without | |
# waiting for Varnish to fully read the file first. | |
if (req.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip)(\?.*)?$") { | |
unset req.http.Cookie; | |
return (pipe); | |
} | |
# Remove all cookies for static files | |
# A valid discussion could be held on this line: do you really need to cache static files that don't cause load? Only if you have memory left. | |
# Sure, there's disk I/O, but chances are your OS will already have these files in their buffers (thus memory). | |
# Before you blindly enable this, have a read here: http://mattiasgeniar.be/2012/11/28/stop-caching-static-files/ | |
if (req.url ~ "^[^?]*\.(bmp|bz2|css|doc|eot|flv|gif|gz|ico|jpeg|jpg|js|less|pdf|png|rtf|swf|txt|woff|xml)(\?.*)?$") { | |
unset req.http.Cookie; | |
return (hash); | |
} | |
# Remove ALL cookies | |
# A bit heavy handed, but I don’t need ‘em. | |
# If I decide to not cache static files, move this into else in previous conditional | |
unset req.http.Cookie; | |
# Send Surrogate-Capability headers to announce ESI support to backend | |
set req.http.Surrogate-Capability = "key=ESI/1.0"; | |
if (req.http.Authorization) { | |
# Not cacheable by default | |
return (pass); | |
} | |
return (hash); | |
} | |
sub 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"; | |
return (pipe); | |
} | |
sub vcl_pass { | |
# return (pass); | |
} | |
# The data on which the hashing will take place | |
sub vcl_hash { | |
hash_data(req.url); | |
if (req.http.host) { | |
hash_data(req.http.host); | |
} else { | |
hash_data(server.ip); | |
} | |
# hash cookies for requests that have them | |
if (req.http.Cookie) { | |
hash_data(req.http.Cookie); | |
} | |
} | |
sub vcl_hit { | |
return (deliver); | |
} | |
sub vcl_miss { | |
return (fetch); | |
} | |
# Handle the HTTP request coming from our backend | |
sub vcl_backend_response { | |
# 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; | |
} | |
# Enable cache for all static files | |
# The same argument as the static caches from above: monitor your cache size, if you get data nuked out of it, consider giving up the static file cache. | |
# Before you blindly enable this, have a read here: http://mattiasgeniar.be/2012/11/28/stop-caching-static-files/ | |
#if (bereq.url ~ "^[^?]*\.(bmp|bz2|css|doc|eot|flv|gif|gz|ico|jpeg|jpg|js|less|mp[34]|pdf|png|rar|rtf|swf|tar|tgz|txt|wav|woff|xml|zip)(\?.*)?$") { | |
# unset beresp.http.set-cookie; | |
#} | |
# Removes Crafts Set-Cookie on everything except admin and other selected urls | |
if (!(bereq.url ~ "(\/admin|p=admin)(.*)" || | |
bereq.url ~ "^/search(.*)" | |
)) { | |
unset beresp.http.set-cookie; | |
} | |
# Set 2min cache if unset for static files | |
if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") { | |
set beresp.ttl = 120s; | |
set beresp.uncacheable = true; | |
return (deliver); | |
} | |
# Allow stale content, in case the backend goes down. | |
set beresp.grace = 1h; | |
return (deliver); | |
} | |
# The routine when we deliver the HTTP request to the user | |
# Last chance to modify headers that are sent to the client | |
sub vcl_deliver { | |
if (obj.hits > 0) { | |
set resp.http.X-Cache = "cached"; | |
} else { | |
set resp.http.x-Cache = "uncached"; | |
} | |
# Remove some headers: PHP version | |
unset resp.http.X-Powered-By; | |
# Remove some headers: Apache/nginx version & OS | |
unset resp.http.Server; | |
unset resp.http.X-Varnish; | |
unset resp.http.Via; | |
unset resp.http.Link; | |
# Set some headers just for fun :P | |
set resp.http.X-Domain-Juice-By = "vaersaagod.no"; | |
return (deliver); | |
} | |
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: error 720 "http://host/new.html" | |
set resp.status = 301; | |
set resp.http.Location = resp.reason; | |
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: error 720 "http://host/new.html" | |
set resp.status = 302; | |
set resp.http.Location = resp.reason; | |
return (deliver); | |
} | |
return (deliver); | |
} | |
sub vcl_init { | |
return (ok); | |
} | |
sub vcl_fini { | |
return (ok); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment