https://www.howtoforge.com/how-to-install-and-configure-varnish-with-apache-on-ubuntu-1804/
lagoon drupal varnish docker container+more https://lagoon.readthedocs.io/en/latest/using_lagoon/drupal/services/varnish/
https://www.varnish-software.com/wiki/content/tutorials/drupal/drupal_st...
default.vcl
vcl 4.0;
# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
import std;
import directors; # load the directors
# Define the internal network subnet.
# These are used below to allow internal access to certain files while not
# allowing access from the public internet.
acl internal {
"xxx.xxx.xxx.xxx"/32; # gateway for authors or IP range if no gateway
}
acl purgers {
"xxx.xxx.xxx.xxx"/32; # web serve IP
"xxx.xxx.xxx.xxx"/32; # web serve IP
"xxx.xxx.xxx.xxx"/32; # web serve IP
}
# Default backend definition. Set this to point to your content
# server.
#
backend lb1 {
.host = "examplehostloadbalancer1";
.port = "80";
.first_byte_timeout = 300s;
.probe = {
.url = "/health";
.timeout = 3 s;
.interval = 10s;
.window = 4;
.threshold = 3;
.initial = 3;
}
}
backend lb2 {
.host = "examplehostloadbalancer2";
.port = "80";
.first_byte_timeout = 300s;
.probe = {
.url = "/health";
.timeout = 3 s;
.interval = 10s;
.window = 4;
.threshold = 3;
.initial = 3;
}
}
backend lb3 {
.host = "examplehostloadbalancer3";
.port = "80";
.first_byte_timeout = 300s;
.probe = {
.url = "/health";
.timeout = 3 s;
.interval = 10s;
.window = 4;
.threshold = 3;
.initial = 3;
}
}
sub vcl_init {
new exampleloadbalancer_director = directors.round_robin();
exampleloadbalancer_director.add_backend(lb1);
# exampleloadbalancer_director.add_backend(lb2);#optional if you have a cluster
# exampleloadbalancer_director.add_backend(lb3);#optional if you have a cluster
}
sub vcl_backend_response {
if ( bereq.url ~ "(?i)\.(bz2|css|eot|gif|gz|html?|ico|jpe?g|js|mp3|ogg|otf|pdf|png|rar|svg|swf|tbz|tgz|ttf|woff2?|zip)(\?(itok=)?[a-z0-9_=\.\-]+)?$"
) {
unset beresp.http.set-cookie;
}
# Set ban-lurker friendly custom headers.
set beresp.http.X-Url = bereq.url;
set beresp.http.X-Host = bereq.http.host;
set beresp.ttl=30d;
# 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 = 5m;
}
if (beresp.status == 400) {
set beresp.ttl = 0s;
}
if (bereq.url ~ "views\/ajax") {
unset beresp.http.Cache-Control;
set beresp.http.Cache-Control = "public, max-age=2629800";
}
if (bereq.url ~ "^.*/connect/.*$" ||
bereq.url ~ "^.*/nous-joindre/.*$" ) {
unset beresp.http.Cache-Control;
set beresp.http.Cache-Control = "no-cache, max-age=0";
}
}
sub vcl_backend_fetch {
if (bereq.http.host ~ "dev.hostname.com" || bereq.http.host ~ "prod.hostname.com" ) {
set bereq.http.X-Forwarded-Proto = "https";
}
return (fetch);
}
# Respond to incoming requests.
sub vcl_recv {
# Only allow BAN requests from IP addresses in the 'purge' ACL.
if (req.method == "BAN") {
# Same ACL check as above:
if (!std.ip(regsuball(req.http.X-Forwarded-For, ", xxx\.xxx\.xxx\.xx.", ""), "0.0.0.0") ~ purgers) {
return (synth(403, "Not allowed."));
}
# Logic for the ban, using the Cache-Tags header. For more info
if (req.http.Cache-Tags) {
ban("obj.http.Cache-Tags ~ " + req.http.Cache-Tags);
}
else {
return (synth(403, "Cache-Tags header missing."));
}
# Throw a synthetic page so the request won't go to the backend.
return (synth(200, "Ban added."));
}
# Use anonymous, cached pages if all backends are down.
if (std.ip(regsuball(req.http.X-Forwarded-For, ", xxx\.xxx\.xxx\.xx.", ""), "0.0.0.0") ~ internal) {
#if admin user prefer web1
if (std.healthy(lb1)) {
set req.backend_hint = lb1;
}
else {
if (std.healthy(lb2)) {
set req.backend_hint = lb2;
}
else {
if (std.healthy(lb3)) {
#set req.backend_hint = lb3;
}
}
}
}
else {
set req.backend_hint = exampleloadbalancer_director.backend();
}
set req.url = std.querysort(req.url); # Normalize the query arguments
# Allow the backend to serve up stale content if it is responding slowly.
#set req.grace = 6h;
if (req.restarts == 0) {
set req.http.X-Forwarded-For = regsuball(req.http.X-Forwarded-For, ", xxx\.xxx\.xx\.xx.", "");
}
# 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, "\?$", "");
}
# Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
if (req.method != "GET" && req.method != "HEAD") {
#JJJ Unless it's a an ajax call
if (req.url !~ "views\/ajax") {
return (pass);
}
}
# Do not cache these paths.
if (req.url ~ "^/status\.php$" ||
req.url ~ "^/update\.php$" ||
req.url ~ "^/admin$" ||
req.url ~ "^/admin/.*$" ||
req.url ~ "^/flag/.*$" ||
req.url ~ "^.*/contact-example/.*$" ||
req.url ~ "^.*/connect-example/.*$" ||
req.url ~ "^.*/nous-joindre-example/.*$" ||
req.url ~ "^.*/subscribe-example/.*$" ||
req.url ~ "^.*/abonnement-example/.*$" ||
req.url ~ "^.*/greetings-example/.*$" ||
req.url ~ "^.*/salutations-example/.*$" ||
req.url ~ "^.*/confirmation-example/.*$" ||
req.url ~ "^.*/unsubscribe-example/.*$" ||
req.url ~ "^.*rss-example$" ||
req.url ~ "^/$" ||
req.url ~ "^$" ) {
return (pass);
}
# 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|utm_content|gclid|cx|ie|cof|siteurl)=") {
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
set req.url = regsub(req.url, "\?&", "?");
set req.url = regsub(req.url, "\?$", "");
}
# Always cache the following file types for all users. This list of extensions
# appears twice, once here and again in vcl_fetch so make sure you edit both
# and keep them equal.
if (req.url ~ "(?i)\.(pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
unset req.http.Cookie;
}
# Do not allow outside access to cron.php or install.php.
if (req.url ~ "^/(cron|install)\.php$" && std.ip(regsuball(req.http.X-Forwarded-For, ", xxx\.xxx\.xx\.xx.", ""), "0.0.0.0") !~ internal) {
# Have Varnish throw the error directly.
return(synth(403, "Access denied"));
}
# Do not allow outside access to parallel.live.b.net .
if (req.http.host ~ "parallel.live.b.net" && std.ip(regsuball(req.http.X-Forwarded-For, ", xxx\.xxx\.xx\.xx.", ""), "0.0.0.0") !~ internal) {
# Have Varnish throw the error directly.
return(synth(403, "Access denied"));
}
# Do not allow outside access to querystring with hash=
if (req.url ~ "^.*hash=.*$" && std.ip(regsuball(req.http.X-Forwarded-For, ", xxx\.xxx\.xx\.xx.", ""), "0.0.0.0") !~ internal) {
# Have Varnish throw the error directly.
return(synth(403, "Access denied"));
}
# Do not allow outside access to /admin /user and /services
if (req.url ~ "^(.*/admin/?.*)|(.*/user/?.*)|(.*/services/rest/?.*)|(.*/internal/?.*)$" && std.ip(regsuball(req.http.X-Forwarded-For, ", xxx\.xxx\.xx\.xx.", ""), "0.0.0.0") !~ internal) {
# Have Varnish throw the error directly.
return(synth(403, "Access denied"));
# Use a custom error page that you've defined in Drupal at the path "404".
# set req.url = "/404";
}
# Remove all cookies that Drupal doesn't need to know about. We explicitly
# list the ones that Drupal does need, the SESS and NO_CACHE. If, after
# running this code we find that either of these two cookies remains, we
# will pass as the page cannot be cached.
if (req.http.Cookie) {
# 1. Append a semi-colon to the front of the cookie string.
# 2. Remove all spaces that appear after semi-colons.
# 3. Match the cookies we want to keep, adding the space we removed
# previously back. (\1) is first matching group in the regsuball.
# 4. Remove all other cookies, identifying them by the fact that they have
# no space after the preceding semi-colon.
# 5. Remove all spaces and semi-colons from the beginning and end of the
# cookie string.
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 == "") {
# If there are no remaining cookies, remove the cookie header. If there
# aren't any cookie headers, Varnish's default behavior will be to cache
# the page.
unset req.http.Cookie;
}
else {
# If there is any cookies left (a session or NO_CACHE cookie), do not
# cache the page. Pass it on to Apache directly.
return (pass);
}
}
}
# 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 {
# Called before a cached object is delivered to the client.
# Remove the headers that allow smart bans before sending to client
unset resp.http.x-url;
unset resp.http.x-host;
unset resp.http.Cache-Tags;
if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
# Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object
# and obj.hits may not be reset in some cases where bans are in use. See bug 1492 for details.
# So take hits with a grain of salt
set resp.http.X-Cache-Hits = obj.hits;
# Remove some headers: PHP version
unset resp.http.X-Powered-By;
# Remove some headers: Apache version & OS
unset resp.http.Server;
unset resp.http.X-Drupal-Cache;
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
return (deliver);
}