Skip to content

Instantly share code, notes, and snippets.

@robertsosinski
Created August 29, 2011 22:53
Show Gist options
  • Save robertsosinski/1179635 to your computer and use it in GitHub Desktop.
Save robertsosinski/1179635 to your computer and use it in GitHub Desktop.
A Varnish config for Rails
backend default {
.host = "127.0.0.1";
.port = "3000";
}
acl admin {
"127.0.0.1";
}
sub vcl_recv {
set req.backend = default;
# unset cookie for static assets
if (req.url ~ "^/assets/") {
unset req.http.Cookie;
}
# pass on any requests that varnish should not handle
if (req.request != "HEAD" && req.request != "GET" &&
req.request != "PURGE" && req.request != "BAN") {
return (pass);
}
# pass requests to the backend if they have a no-cache header or cookie
if (req.http.X-Varnish-No-Cache == "true" || (req.http.Cookie && req.http.Cookie ~ "X-Varnish-No-Cache=true")) {
return (pass);
}
# enable purging via the "PURGE" http verb
if (req.request == "PURGE" && !client.ip ~ admin) {
error 401 "Unauthorized";
}
# enable banning via the "BAN" http verb and "X-Varnish-Ban" header
# e.g. ban all .png images and have varnish fetch from the backend.
# "X-Varnish-Ban: req.http.host == example.com && req.url ~ \.png$"
if (req.request == "BAN") {
if (!client.ip ~ admin) {
error 401 "Unauthorized";
}
else {
if (req.http.X-Varnish-Ban) {
ban(req.http.X-Varnish-Ban);
error 200 "Banned";
}
else {
error 412 "No Ban Specified";
}
}
}
return (lookup);
}
sub vcl_hit {
# remove object from cache if purge request finds it
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged";
}
}
sub vcl_miss {
# raise error if purge request does not find anything
if (req.request == "PURGE") {
error 404 "Not In Cache";
}
}
sub vcl_fetch {
# store static assets in varnish for a month, set max age for a day, and strip cookies from the response
if (req.request == "GET" && req.url ~ "^/assets/") {
set beresp.ttl = 1m;
set beresp.http.Cache-Control = "public, max-age=86400";
unset beresp.http.Set-Cookie;
}
# process edge-side-includes only if the server requires
if (beresp.http.X-Varnish-Esi == "true") {
set beresp.do_esi = true;
}
# set the time-to-live for the object by using "X-Varnish-Ttl" header
# using c as we must typecast the string header value to a ttl object
if (beresp.http.X-Varnish-Ttl) {
C{
char *ttl;
// first char in third param is length of header plus colon in octal
ttl = VRT_GetHdr(sp, HDR_BERESP, "\016X-VARNISH-TTL:");
VRT_l_beresp_ttl(sp, atoi(ttl));
}C
}
# if the response has no ttl or is a 302 redirect, prevent varnish from performing request coalescing for 10 minutes
if (beresp.ttl <= 0s || beresp.status == 302) {
set beresp.ttl = 10m;
return (hit_for_pass);
}
return (deliver);
}
sub vcl_error {
set obj.http.Content-Type = "text/html; charset=utf-8";
set obj.http.Retry-After = "5";
synthetic {"
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>"} + obj.status + " " + obj.response + {"</title>
</head>
<body>
<h1>"} + obj.status + " " + obj.response + {"</h1>
<p>"} + obj.response + {"</p>
<p>XID: "} + req.xid + {"</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
"};
return (deliver);
}
# Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be
# appended to your code.
#
# sub vcl_recv {
# 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;
# }
# }
# if (req.request != "GET" &&
# req.request != "HEAD" &&
# req.request != "PUT" &&
# req.request != "POST" &&
# req.request != "TRACE" &&
# req.request != "OPTIONS" &&
# req.request != "DELETE") {
# # Non-RFC2616 or CONNECT which is weird.
# return (pipe);
# }
# if (req.request != "GET" && req.request != "HEAD") {
# /* We only deal with GET and HEAD by default */
# return (pass);
# }
# if (req.http.Authorization || req.http.Cookie) {
# /* Not cacheable by default */
# return (pass);
# }
# 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.
# return (pipe);
# }
#
# sub vcl_pass {
# return (pass);
# }
#
# sub vcl_hash {
# hash_data(req.url);
# if (req.http.host) {
# hash_data(req.http.host);
# }
# else {
# hash_data(server.ip);
# }
# return (hash);
# }
#
# sub vcl_hit {
# return (deliver);
# }
#
# sub vcl_miss {
# return (fetch);
# }
#
# sub vcl_fetch {
# if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
# # Mark as "Hit-For-Pass" for the next 2 minutes
# set beresp.ttl = 120 s;
# return (hit_for_pass);
# }
# return (deliver);
# }
#
# sub vcl_deliver {
# return (deliver);
# }
#
# sub vcl_error {
# set obj.http.Content-Type = "text/html; charset=utf-8";
# set obj.http.Retry-After = "5";
# synthetic {"
# <?xml version="1.0" encoding="utf-8"?>
# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
# "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# <html>
# <head>
# <title>"} + obj.status + " " + obj.response + {"</title>
# </head>
# <body>
# <h1>Error "} + obj.status + " " + obj.response + {"</h1>
# <p>"} + obj.response + {"</p>
# <h3>Guru Meditation:</h3>
# <p>XID: "} + req.xid + {"</p>
# <hr>
# <p>Varnish cache server</p>
# </body>
# </html>
# "};
# return (deliver);
# }
#
# sub vcl_init {
# return (ok);
# }
#
# sub vcl_fini {
# return (ok);
# }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment