Created
August 17, 2018 08:16
-
-
Save slivorezka/438db1c15a49463e7b6d1d1316caa581 to your computer and use it in GitHub Desktop.
Drupal 8 Varnish
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
# | |
# This is an example VCL file for Varnish. | |
# | |
# It does not do anything by default, delegating control to the | |
# builtin VCL. The builtin VCL is called when there is no explicit | |
# return statement. | |
# | |
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/ | |
# and https://www.varnish-cache.org/trac/wiki/VCLExamples for more examples. | |
# Marker to tell the VCL compiler that this VCL has been adapted to the | |
# new 4.0 format. | |
vcl 4.0; | |
# Default backend definition. Set this to point to your content server. | |
backend default { | |
.host = "127.0.0.1"; | |
.port = "8080"; | |
.max_connections = 250; | |
.connect_timeout = 300s; | |
.first_byte_timeout = 300s; | |
.between_bytes_timeout = 300s; | |
} | |
acl purge { | |
"127.0.0.1"; | |
} | |
acl internal { | |
"127.0.0.1"; | |
# For remote access, add your IP address here. | |
# Ex: 162.xxx.xx.xx | |
} | |
sub vcl_recv { | |
# Happens before we check if we have this in cache already. | |
# | |
# Typically you clean up the request here, removing cookies you don't need, | |
# rewriting the request, etc. | |
# Return (pass) instructs Varnish not to cache the request | |
# when the condition is met. | |
# Force look-up if request is a no-cache request. | |
if (req.http.Cache-Control ~ "no-cache") { | |
return (pass); | |
} | |
# Disallow outside access to cron.php or install.php | |
if (req.url ~ "^/(cron|install|update)\.php$" && !client.ip ~ internal) { | |
# Either let Varnish throw the error directly error 404 "Page not found."; | |
# Or, use a custom error page that you've defined in Drupal at the path "404". | |
# set req.url = "/404"; | |
return (synth(404, "Not Found.")); | |
} | |
# Add an X-Forwarded-For header with the client IP address. | |
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; | |
} | |
} | |
## Method ## | |
if (req.method == "URIBAN") { | |
ban("req.http.host == " + req.http.host + " && req.url == " + req.url); | |
# Throw a synthetic page so the request won't go to the backend. | |
return (synth(200, "Ban added.")); | |
} | |
# Check the incoming request type is "PURGE", not "GET" or "POST". | |
if (req.method == "PURGE") { | |
# Check if the IP is allowed. | |
if (!client.ip ~ purge) { | |
# Return error code 405 (Forbidden) when not. | |
return (synth(405, "Not allowed.")); | |
} | |
return (purge); | |
} | |
# Only allow BAN requests from IP addresses in the 'purge' ACL. | |
if (req.method == "BAN") { | |
# Same ACL check as above: | |
if (!client.ip ~ purge) { | |
return (synth(403, "Not allowed.")); | |
} | |
# Clean cache by Cache-Tags heder. | |
if (req.http.Cache-Tags) { | |
ban("obj.http.Cache-Tags ~ " + req.http.Cache-Tags); | |
} | |
else { | |
return (synth(403, "Cache-Tags header missing.")); | |
} | |
# Logic for banning everything | |
return (synth(200, "Ban added.")); | |
} | |
# Only cache GET and HEAD requests (pass through POST requests). | |
if (req.method != "GET" && req.method != "HEAD") { | |
return (pass); | |
} | |
## ADMIN PAGES ## | |
# Here we filter out all URLs containing Drupal administrative sections | |
if (req.url ~ "^/status\.php$" || req.url ~ "^/update\.php$" || req.url ~ "^/admin$" || req.url ~ "^/admin/.*$" || req.url ~ "^/user$" || req.url ~ "^/user/.*$" || req.url ~ "^/flag/.*$" || req.url ~ "^.*/ajax/.*$" || req.url ~ "^/system/files/.*$") { | |
return (pass); | |
} | |
## BACKUP AND MIGRATE MODULE ## | |
# Backup and Migrate is a very popular Drupal module that needs to be excluded | |
# It won't work with Varnish | |
if (req.url ~ "^/admin/content/backup_migrate/export") { | |
return (pipe); | |
} | |
## COOKIES ## | |
# Remove cookies for stylesheets, scripts, and images used throughout the site. | |
# Removing cookies will allow Varnish to cache those files. | |
if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|svg|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") { | |
# Stop processing further for those file types. This way, we ensure to have | |
# X-Varnish-Cache HIT for those requests. | |
unset req.http.Cookie; | |
} | |
# Remove all cookies that are not necessary for Drupal to work properly. | |
# Since it would be cumbersome to REMOVE certain cookies, we specify | |
# which ones are of interest to us, and remove all others. In this particular | |
# case we leave SESS, SSESS and NO_CACHE cookies used by Drupal's administrative | |
# interface. Cookies in cookie header are delimited with ";", so when there are | |
# many cookies, the header looks like "Cookie1=value1; Cookie2=value2; Cookie3..." | |
# and so on. That allows us to work with ";" to split cookies into individual | |
# ones. | |
# | |
# The method for filtering unnecessary cookies has been adopted from: | |
# https://fourkitchens.atlassian.net/wiki/display/TECH/Configure+Varnish+3+for+Drupal+7 | |
if (req.http.Cookie) { | |
# 1. We add ; to the beginning of cookie header | |
set req.http.Cookie = ";" + req.http.Cookie; | |
# 2. We remove spaces following each occurence of ";". After this operation | |
# all cookies are delimited with no spaces. | |
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); | |
# 3. We replace ";" INTO "; " (adding the space we have previously removed) in cookies | |
# named SESS..., SSESS... and NO_CACHE. After this operation those cookies will be | |
# easy to differentiate from the others, because those will be the only one with space | |
# after ";" | |
set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1="); | |
# 4. We remove all cookies with no space after ";", so basically we remove all cookies other | |
# than those above. | |
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); | |
# 5. We strip leading and trailing whitespace and semicolons. | |
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); | |
# If there are no cookies after our striping procedure, we remove the header altogether, | |
# thus allowing Varnish to cache this page | |
if (req.http.Cookie == "") { | |
unset req.http.Cookie; | |
} | |
# if any of our cookies of interest are still there, we disable caching and pass the request | |
# straight to Apache and Drupal | |
else { | |
return (pass); | |
} | |
} | |
} | |
sub vcl_backend_response { | |
# Happens after we have read the response headers from the backend. | |
# | |
# Here you clean the response headers, removing silly Set-Cookie headers | |
# and other mistakes your backend does. | |
# Set ban-lurker friendly custom headers. | |
set beresp.http.X-Url = bereq.url; | |
set beresp.http.X-Host = bereq.http.host; | |
# Cache 404s, 301s, at 500s with a short lifetime to protect the backend. | |
if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) { | |
set beresp.ttl = 10m; | |
} | |
# Remove cookies for stylesheets, scripts and images used throughout the site. | |
# Removing cookies will allow Varnish to cache those files. It is uncommon for | |
# static files to contain cookies, but it is possible for files generated | |
# dynamically by Drupal. Those cookies are unnecessary, but could prevent files | |
# from being cached. | |
if (bereq.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|svg|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") { | |
unset beresp.http.set-cookie; | |
} | |
# Allow items to remain in cache up to 6 hours past their cache expiration. | |
set beresp.grace = 6h; | |
} | |
sub vcl_deliver { | |
# Happens when we have all the pieces we need, and are about to send the | |
# response to the client. | |
# | |
# You can do accounting or modifying the final object here. | |
# Remove ban-lurker friendly custom headers when delivering to client. | |
unset resp.http.X-Url; | |
unset resp.http.X-Host; | |
unset resp.http.Cache-Tags; | |
# Reject use cache on the client. | |
if (resp.http.Content-Type ~ "text/html") { | |
set resp.http.Cache-Control = "private, no-cache"; | |
} | |
if (obj.hits > 0) { | |
set resp.http.X-Varnish-Cache = "HIT"; | |
} | |
else { | |
set resp.http.X-Varnish-Cache = "MISS"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment