-
-
Save ethier/3899035 to your computer and use it in GitHub Desktop.
A good varnish config for a Rails app
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
# 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"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment