Skip to content

Instantly share code, notes, and snippets.

@reuhno
Last active November 9, 2022 14:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reuhno/0502663c466571211c479fa0bec9a5b1 to your computer and use it in GitHub Desktop.
Save reuhno/0502663c466571211c479fa0bec9a5b1 to your computer and use it in GitHub Desktop.
Config Varnish Infomaniak - Reuhno.fr
#
# 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 http://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;
import std;
import directors;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.80";
.port = "80";
.connect_timeout = 5s;
.first_byte_timeout = 60s;
.between_bytes_timeout = 60s;
}
acl local {
"localhost";
"127.0.0.1";
"127.0.0.80";
"::1";
"195.15.xxx.xxx";
"2001:1600:3:19:xxxx:xxxx:xxxx:xxxx";
"193.248.xxx.xxx";
}
sub vcl_synth {
if (resp.status == 750) {
set resp.status = 301;
set resp.http.Location = req.http.x-Redir-Url;
return(deliver);
}
}
sub vcl_recv {
# Remove query string added automatically by Facebook and others services
# these pages are identical even if the query string parameters are differents
if (req.url ~ "(\?|&)(fbclid|gclid|utm_[a-z]+)=") {
set req.url = regsuball(req.url, "(fbclid|gclid|utm_[a-z]+)=[-_A-z0-9+()%.]+&?", "");
set req.url = regsub(req.url, "[?|&]+$", "");
}
# Remove empty query string parameters
# e.g.: www.example.com/index.html?
if (req.url ~ "\?$") {
set req.url = regsub(req.url, "\?$", "");
}
# Remove port number from host header
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# Sorts query string parameters alphabetically for cache normalization purposes
set req.url = std.querysort(req.url);
# Remove the proxy header to mitigate the httpoxy vulnerability
# See https://httpoxy.org/
unset req.http.proxy;
if (req.method == "PURGE" || req.method == "BAN") {
# If the IP isn't a match, we can't flush cache.
if (!client.ip ~ local) {
return (synth(405, "This IP is not allowed to send PURGE requests."));
}
# If we're trying to regex, then we need to use the ban calls:
if (req.http.X-Purge-Method == "regex") {
ban("obj.http.x-url ~ " + req.url + " && obj.http.x-host ~ " + req.http.host);
return (synth(200, "Purged"));
}
# Backported catch for exact cache flush calls:
if (req.http.X-Purge-Method == "exact") {
ban("obj.http.x-url == " + req.url + " && obj.http.X-Req-Host == " + req.http.host);
return (synth(200, "Purged"));
}
# Otherwise, we strip the query params and flush as is:
set req.url = regsub(req.url, "\?.*$", "");
return (purge);
}
else{
if ( req.http.X-Forwarded-Proto !~ "(?i)https" ) {
set req.http.x-Redir-Url = "https://" + req.http.host + req.url;
return ( synth( 750 ));
}
}
# Only handle relevant HTTP request methods
if (
req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "PATCH" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE"
) {
return (pipe);
}
# Only cache GET and HEAD requests
if (req.method != "GET" && req.method != "HEAD") {
set req.http.X-Cacheable = "NO:REQUEST-METHOD";
return(pass);
}
# Mark static files with the X-Static-File header, and remove any cookies
# X-Static-File is also used in vcl_backend_response to identify static files
if (req.url ~ "^[^?]*\.(7z|avi|avif|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|json|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|ogg|ogm|opus|otf|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
set req.http.X-Static-File = "true";
unset req.http.Cookie;
return(hash);
}
# No caching of special URLs, logged in users and some plugins
if (
req.http.Cookie ~ "wordpress_(?!test_)[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+|woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_[a-zA-Z0-9]+|wordpress_logged_in_|comment_author|PHPSESSID|wp-resetpass-[a-zA-Z0-9]" ||
req.http.Authorization ||
req.url ~ "add_to_cart" ||
req.url ~ "edd_action" ||
req.url ~ "nocache" ||
req.url ~ "no_cache" ||
req.url ~ "^/addons" ||
req.url ~ "^/bb-admin" ||
req.url ~ "^/bb-login.php" ||
req.url ~ "^/bb-reset-password.php" ||
req.url ~ "^/cart" ||
req.url ~ "^/checkout" ||
req.url ~ "^/control.php" ||
req.url ~ "^/login" ||
req.url ~ "^/logout" ||
req.url ~ "^/lost-password" ||
req.url ~ "^/my-account" ||
req.url ~ "^/product" ||
req.url ~ "^/register" ||
req.url ~ "^/register.php" ||
req.url ~ "^/server-status" ||
req.url ~ "^/signin" ||
req.url ~ "^/signup" ||
req.url ~ "^/stats" ||
req.url ~ "^/wc-api" ||
req.url ~ "^/wp-admin" ||
req.url ~ "^/wp-comments-post.php" ||
req.url ~ "^/wp-cron.php" ||
req.url ~ "^/wp-login.php" ||
req.url ~ "^/wp-activate.php" ||
req.url ~ "^/wp-mail.php" ||
req.url ~ "^/wp-login.php" ||
req.url ~ "add-to-cart=" ||
req.url ~ "wc-api=" ||
req.url ~ "^/preview=" ||
req.url ~ "preview=" ||
req.url ~ "^/\.well-known/acme-challenge/"
) {
set req.http.X-Cacheable = "NO:Logged in/Got Sessions";
if(req.http.X-Requested-With == "XMLHttpRequest") {
set req.http.X-Cacheable = "NO:Ajax";
}
return(pass);
}
# Remove any cookies left
unset req.http.Cookie;
return(hash);
}
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.
# Inject URL & Host header into the object for asynchronous banning purposes
set beresp.http.x-url = bereq.url;
set beresp.http.x-host = bereq.http.host;
# Define grace
# https://varnish-cache.org/docs/trunk/users-guide/vcl-grace.html
# no keep - the grace should be enough for 304 candidates
set beresp.grace = 4h;
# cache only successfully responses
# you can set 404 to be cached, but if your site generate temporarily 404 errors (for eg. when Wp Rocket Async CSS & Elementor are generating css file, it could be longer than expected and 404 should'not be must not be cached or it will remain inaccessible until the next flush)
if (beresp.status != 200 && beresp.status != 410 && beresp.status != 301 && beresp.status != 302 && beresp.status != 304 && beresp.status != 307) {
set beresp.http.X-Cacheable = "NO:UNCACHEABLE";
set beresp.ttl = 10s;
set beresp.uncacheable = true;
}
else
{
# If we dont get a Cache-Control header from the backend
# we default to 1h cache for all objects
if (!beresp.http.Cache-Control) {
set beresp.ttl = 1h;
set beresp.http.X-Cacheable = "YES:Forced";
}
# If the file is marked as static we cache it for 1 day
if (bereq.http.X-Static-File == "true") {
unset beresp.http.Set-Cookie;
set beresp.http.X-Cacheable = "YES:Forced";
set beresp.ttl = 1d;
}
# Remove the Set-Cookie header when a specific Wordfence cookie is set
if (beresp.http.Set-Cookie ~ "wfvt_|wordfence_verifiedHuman") {
unset beresp.http.Set-Cookie;
}
if (beresp.http.Set-Cookie) {
set beresp.http.X-Cacheable = "NO:Got Cookies";
} elseif(beresp.http.Cache-Control ~ "private") {
if(beresp.http.Cache-Control ~ "public" && bereq.http.X-Static-File == "true" ) {
set beresp.http.Cache-Control = regsub(beresp.http.Cache-Control, "private,", "");
set beresp.http.Cache-Control = regsub(beresp.http.Cache-Control, "private", "");
set beresp.http.X-Cacheable = "YES";
}
elseif(bereq.http.X-Static-File == "true" && (beresp.http.Content-type ~ "image\/webp" || beresp.http.Content-type ~ "image\/avif") )
{
set beresp.http.Cache-Control = regsub(beresp.http.Cache-Control, "private,", "");
set beresp.http.Cache-Control = regsub(beresp.http.Cache-Control, "private", "");
set beresp.http.X-Cacheable = "YES";
}
else{
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
}
}
}
}
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.
# Debug header
if(req.http.X-Cacheable) {
set resp.http.X-Cacheable = req.http.X-Cacheable;
} elseif(obj.uncacheable) {
if(!resp.http.X-Cacheable) {
set resp.http.X-Cacheable = "NO:UNCACHEABLE";
}
} elseif(!resp.http.X-Cacheable) {
set resp.http.X-Cacheable = "YES";
}
# End Debug Header
if (resp.http.X-Varnish ~ "[0-9]+ +[0-9]+") {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
#unset resp.http.X-Cacheable
# Cleanup of headers
unset resp.http.x-url;
unset resp.http.x-host;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment