Last active
November 9, 2022 14:55
-
-
Save reuhno/0502663c466571211c479fa0bec9a5b1 to your computer and use it in GitHub Desktop.
Config Varnish Infomaniak - Reuhno.fr
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 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