Skip to content

Instantly share code, notes, and snippets.

@rjdp
Created November 23, 2017 16:49
Show Gist options
  • Save rjdp/39c74a5a6784a04322f3431a1120b926 to your computer and use it in GitHub Desktop.
Save rjdp/39c74a5a6784a04322f3431a1120b926 to your computer and use it in GitHub Desktop.
Fairly robust VCL for django sites, can be used with some changes depending on the web App
#
# 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;
import std;
# import digest;
# import directors;
backend default {
.host = "127.0.0.1";
.port = "8080";
.probe = {
#.url = "/"; # short easy way (GET /)
# We prefer to only do a HEAD /
.request =
"HEAD / HTTP/1.1"
"Host: www.example.com"
"Connection: close"
"User-Agent: Varnish Health Probe";
.interval = 5s; # check the health of each backend every 5 seconds
.timeout = 1s; # timing out after 1 second.
.window = 5; # If 3 out of the last 5 polls succeeded the backend is considered healthy, otherwise it will be marked as sick
.threshold = 3;
}
.first_byte_timeout = 300s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 5s; # How long to wait for a backend connection?
.between_bytes_timeout = 2s; # How long to wait between bytes received from our backend?
}
backend examplemedia {
.host = "example.s3.amazonaws.com";
.port = "80";
.probe = {
#.url = "/"; # short easy way (GET /)
# We prefer to only do a HEAD /
.request =
"HEAD /DoNotDelete.txt HTTP/1.1"
"Connection: close"
"User-Agent: Varnish Health Probe";
.interval = 5s; # check the health of each backend every 5 seconds
.timeout = 1s; # timing out after 1 second.
.window = 5; # If 3 out of the last 5 polls succeeded the backend is considered healthy, otherwise it will be marked as sick
.threshold = 3;
}
.first_byte_timeout = 300s; # How long to wait before we receive a first byte from our backend?
.connect_timeout = 5s; # How long to wait for a backend connection?
.between_bytes_timeout = 2s; # How long to wait between bytes received from our backend?
}
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.
# non-www to www redirection
if (req.http.host ~ "^example.com") {
return (synth (750, ""));
}
if (req.url ~ "^/media/") {
set req.backend_hint = examplemedia;
}
if (req.url ~ "^/netdata") {
if (req.url == "/netdata") {
return (synth(301, "/netdata/"));
}
return(pass);
}
if (req.url ~ "^/static" || req.url ~ "^/media" || (req.http.cookie !~ "sessionid" && req.http.cookie !~ "csrftoken")) {
unset req.http.Cookie;
}
if (req.http.upgrade ~ "(?i)websocket") {
return (pipe);
}
if (req.http.Accept-Encoding) {
if (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
# unkown algorithm
unset req.http.Accept-Encoding;
}
}
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
# Remove port
# set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# Sort query parmas in URL have single cahe obj for sematically identical URL
set req.url = std.querysort(req.url);
# Remove ending question mark
if (req.url ~ "\?$") {
set req.url = regsub(req.url, "\?$", "");
}
}
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.
# assuming all static file are being served from /static
if (bereq.url ~ "^/static" || bereq.url ~ "^/media" || (beresp.http.set-cookie !~ "sessionid" && beresp.http.set-cookie !~ "csrftoken")) {
set beresp.grace = 1d;
if (bereq.url ~ "^/static" || bereq.url ~ "^/media") {
set beresp.ttl = 10w;
}
unset beresp.http.set-cookie;
return (deliver);
}
}
sub vcl_hit {
if (obj.ttl >= 0s) {
// A pure unadulterated hit, deliver it
return (deliver);
}
if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) {
// Object is in grace, deliver it
// Automatically triggers a background fetch
return (deliver);
}
// fetch & deliver once we get the result
return (miss);
}
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.
set resp.http.X-Hits = obj.hits;
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
sub vcl_synth {
if (resp.status == 301 || resp.status == 302) {
set resp.http.location = resp.reason;
set resp.reason = "Moved";
return (deliver);
}
if (resp.status == 750) {
set resp.status = 301;
set resp.http.Location = "http://www.example.com" + req.url;
return(deliver);
}
}
sub vcl_pipe {
if (req.http.upgrade) {
set bereq.http.upgrade = req.http.upgrade;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment