public
Created — forked from bmarini/default.vcl.pl

A good varnish config for a Rails app

  • Download Gist
default.vcl.pl
Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
# https://www.varnish-cache.org/docs/2.1/tutorial/vcl.html
# https://www.varnish-cache.org/trac/wiki/VCLExamples
 
# Summary
# 1. Varnish will poll the backend at /health_check to make sure it is
# healthy. If the backend goes down, varnish will server stale content
# from the cache for up to 1 hour.
# 2. Varnish will pass X-Forwarded-For headers through to the backend
# 3. Varnish will remove cookies from urls that match static content file
# extensions (jpg, gif, ...)
# 4. Varnish will normalize the Accept-Encoding header
# 5. Varnish will respect the Cache-Control header, even when a Set-Cookie
# header accompanies it from the backend. For example,
# `Cache-Control: no-cache` will not get stored in Varnish and
# `Cache-Control: max-age=600` will.
# 6. Varnish will add a X-Varnish-Cache header to aid in debugging
 
backend default {
.host = "127.0.0.1";
.port = "8080";
 
# https://www.varnish-cache.org/trac/wiki/BackendPolling
.probe = {
.url = "/health_check";
.timeout = 2 s;
.interval = 1s;
.window = 10;
.threshold = 8;
}
}
 
# NOTE: vcl_recv is called at the beginning of a request, after the complete
# request has been received and parsed. Its purpose is to decide whether or not
# to serve the request, how to do it, and, if applicable, which backend to use.
sub vcl_recv {
# If the backend is healthy, only accept objects that are 30 seconds old,
# but if the backend is sick, accept objects that are up to an hour old.
# https://www.varnish-cache.org/trac/wiki/VCLExampleGrace
if (req.backend.healthy) {
set req.grace = 30s;
} else {
set req.grace = 1h;
}
 
# Normalize Accept-Encoding to prevent duplicates in the cache
# https://www.varnish-cache.org/trac/wiki/VCLExampleNormalizeAcceptEncoding
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
remove req.http.Accept-Encoding;
}
}
 
# This rule is to insert the client's ip address into the request header
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For ", " client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
 
# Force lookup if the request is a no-cache request from the client
# IE - shift-reload causes cache refresh - We may not want this in
# production but useful during initial deployment and testing
if (req.http.Cache-Control ~ "no-cache") {
purge_url(req.url);
}
 
# Don't cache POST, PUT, or DELETE requests
if (req.request == "POST" || req.request == "PUT" || req.request == "DELETE") {
return(pass);
}
 
# Strip cookies from static content
if (req.request == "GET" && req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
unset req.http.cookie;
}
 
# We will try to retrieve every request from the cache. There will be no
# intelligence on the varnish side to determine whether to look or not look
# at the cache.
return(lookup);
}
 
sub vcl_pipe {
# Note that only the first request to the backend will have
# X-Forwarded-For set. If you use X-Forwarded-For and want to
# have it set for all requests, make sure to have:
# set bereq.http.connection = "close";
# here. It is not set by default as it might break some broken web
# applications, like IIS with NTLM authentication.
set bereq.http.connection = "close";
return(pipe);
}
 
# NOTE: vcl_fetch is called after a document has been successfully retrieved
# from the backend. Normal tasks her are to alter the response headers, trigger
# ESI processing, try alternate backend servers in case the request failed.
sub vcl_fetch {
# Keep objects 1 hour in cache past their expiry time. This allows varnish
# to server stale content if the backend is sick.
set beresp.grace = 1h;
 
# If header specifies "no-cache", don't cache.
if (
beresp.http.Pragma ~ "no-cache" ||
beresp.http.Cache-Control ~ "no-cache" ||
beresp.http.Cache-Control ~ "private"
) {
return(pass);
}
 
# If header specifies "max-age", remove any cookie and deliver into the cache.
# The idea here is to trust the backend. If the backend set a max-age in
# the Cache-Control header, then the response should be cached even if there
# is a Set-Cookie header. The cleaner way to handle this is the not set a
# Set-Cookie header in the backend, but unfortunately Rails always sets one.
if (beresp.http.Cache-Control ~ "max-age") {
unset beresp.http.Set-Cookie;
return(deliver);
}
 
# Do not deliver into cache otherwise.
return(pass);
}
 
sub vcl_deliver {
# The below provides custom headers to indicate whether the response came from
# varnish cache or directly from the app.
if (obj.hits > 0) {
set resp.http.X-Varnish-Cache = "HIT";
} else {
set resp.http.X-Varnish-Cache = "MISS";
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.