To properly configure Varnish with Drupal you should ensure the following configuration is your default.vcl
file.
Note: Some customizations might be necessary depending on your individual requirements.
vcl 4.0;
import std;
import directors;
backend nginx {
.host = "hostname-nginx";
.host_header = "hostname-nginx";
.port = "80";
}
sub vcl_init {
new backends = directors.round_robin();
backends.add_backend(nginx);
}
sub vcl_recv {
set req.http.X-Forwarded-Host = req.http.Host;
if (!req.http.X-Forwarded-Proto) {
set req.http.X-Forwarded-Proto = "http";
}
# Answer healthcheck
if (req.url == "/_healthcheck" || req.url == "/healthcheck.txt") {
return (synth(700, "HEALTHCHECK"));
}
set req.backend_hint = backends.backend();
# Answer healthcheck
if (req.url == "/_healthcheck" || req.url == "/healthcheck.txt") {
return (synth(700, "HEALTHCHECK"));
}
set req.backend_hint = backends.backend();
# Always cache certain file types
# Remove cookies that Drupal doesn't care about
if (req.url ~ "(?i)\.(asc|dat|tgz|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
unset req.http.Cookie;
} else if (req.http.Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.Cookie == "") {
unset req.http.Cookie;
} else {
return (pass);
}
}
# If POST, PUT or DELETE, then don't cache
if (req.method == "POST" || req.method == "PUT" || req.method == "DELETE") {
return (pass);
}
# 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 (hash);
#return (pass);
}
sub vcl_backend_fetch {
# NEW
set bereq.http.Host = "hostname-nginx";
# Don't add 127.0.0.1 to X-Forwarded-For
set bereq.http.X-Forwarded-For = regsub(bereq.http.X-Forwarded-For, "(, )?127\.0\.0\.1$", "");
}
sub vcl_backend_response {
if (beresp.http.Location) {
set beresp.http.Location = regsub(
beresp.http.Location,
"^https?://[^/]+/",
bereq.http.X-Forwarded-Proto + "://" + bereq.http.X-Forwarded-Host + "/"
);
}
# Only cache select response codes
if (beresp.status == 200 || beresp.status == 203 || beresp.status == 204 || beresp.status == 206 || beresp.status == 300 || beresp.status == 301 || beresp.status == 404 || beresp.status == 405 || beresp.status == 410 || beresp.status == 414 || beresp.status == 501) {
# Cache for 5 minutes
set beresp.ttl = 5m;
set beresp.grace = 12h;
set beresp.keep = 24h;
} else {
set beresp.ttl = 0s;
}
}
sub vcl_deliver {
# Remove identifying information
unset resp.http.Server;
unset resp.http.X-Powered-By;
unset resp.http.X-Varnish;
unset resp.http.Via;
# Comment these for easier Drupal cache tag debugging in development.
unset resp.http.Cache-Tags;
unset resp.http.X-Drupal-Cache-Contexts;
# Add Content-Security-Policy
# set resp.http.Content-Security-Policy = "default-src 'self' *.example.ca *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca https://fonts.googleapis.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net data:; font-src 'self' *.example.ca https://fonts.gstatic.com";
# Add CORS Headers
# if (req.http.Origin ~ "(?i)\.example\.ca$") {
# if (req.url ~ "\.(ttd|woff|woff2)(\?.*)?$") {
# set resp.http.Access-Control-Allow-Origin = "*";
# set resp.http.Access-Control-Allow-Methods = "GET";
# }
# }
# Add X-Frame-Options
if (req.url ~ "^/livechat" || req.url ~ "^/(en/|fr/)?entity-browser/") {
set resp.http.X-Frame-Options = "SAMEORIGIN";
} else {
set resp.http.X-Frame-Options = "DENY";
}
set resp.http.X-Content-Type-Options = "nosniff";
set resp.http.X-XSS-Protection = "1; mode=block";
# 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.
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
# Handle errors
if ( (resp.status >= 500 && resp.status <= 599)
|| resp.status == 400
|| resp.status == 401
|| resp.status == 403
|| resp.status == 404) {
return (synth(resp.status));
}
}
sub vcl_synth {
# Remove identifying information
unset resp.http.Server;
unset resp.http.X-Powered-By;
unset resp.http.X-Varnish;
unset resp.http.Via;
# Add Content-Security-Policy
# set resp.http.Content-Security-Policy = "default-src 'self' *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca data:;";
# set resp.http.X-Content-Type-Options = "nosniff";
# set resp.http.X-Frame-Options = "DENY";
# set resp.http.X-XSS-Protection = "1; mode=block";
# if (resp.status >= 500 && resp.status <= 599) {
# set resp.http.Content-Type = "text/html; charset=utf-8";
# synthetic(std.fileread("/data/configuration/varnish/errors/503.html"));
# return (deliver);
# } elseif (resp.status == 400) { # 400 - Bad Request
# set resp.http.Content-Type = "text/html; charset=utf-8";
# synthetic(std.fileread("/data/configuration/varnish/errors/400.html"));
# return (deliver);
# } elseif (resp.status == 401) { # 401 - Unauthorized
# set resp.http.Content-Type = "text/html; charset=utf-8";
# synthetic(std.fileread("/data/configuration/varnish/errors/401.html"));
# return (deliver);
# } elseif (resp.status == 403) { # 403 - Forbidden
# set resp.http.Content-Type = "text/html; charset=utf-8";
# synthetic(std.fileread("/data/configuration/varnish/errors/403.html"));
# return (deliver);
# } elseif (resp.status == 404) { # 404 - Not Found
# set resp.http.Content-Type = "text/html; charset=utf-8";
# synthetic(std.fileread("/data/configuration/varnish/errors/404.html"));
# return (deliver);
# } else
if (resp.status == 700) { # Respond to healthcheck
set resp.status = 200;
set resp.http.Content-Type = "text/plain";
synthetic ( {"OK"} );
return (deliver);
}
}
##
# ERROR HANDLING
##
# sub vcl_backend_error {
# set beresp.http.Content-Type = "text/html; charset=utf-8";
# synthetic(std.fileread("/data/configuration/varnish/errors/503.html"));
# return (deliver);
# }