Skip to content

Instantly share code, notes, and snippets.

@kimlindholm
Created February 6, 2012 19:28
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save kimlindholm/1754248 to your computer and use it in GitHub Desktop.
Save kimlindholm/1754248 to your computer and use it in GitHub Desktop.
Varnish configuration example
# VCL configuration file for Varnish
# Define which IP addresses or hosts have access to files that are
# blocked from the public internet
acl internal {
"localhost";
}
# Define origin servers
backend web { .host = "1.2.3.4"; .port = "80"; }
backend web_ssl { .host = "1.2.3.4"; .port = "443"; }
# Uncomment to support Munin graphs
# backend monitoring { .host = "127.0.0.1"; .port = "8081"; }
# Uncomment to include Security.VCL module
# @see: https://github.com/comotion/security.vcl
# include "/etc/varnish/security/main.vcl";
# Respond to incoming requests
sub vcl_recv {
# Uncomment to support Munin graphs. Access is granted if visitor is coming
# from a whitelisted IP address and secret token is provided.
# e.g. http://www.example.com/munin?your-secret-token
# if (req.url ~ "^/munin" && client.ip ~ internal
# && (req.url ~ "\?your-secret-token"
# || req.http.referer ~ "(www\.)?example\.com")) {
# set req.backend = monitoring;
# return (pipe);
# }
# Uncomment to have New Relic track queue times
# C{
# #include </etc/varnish/newrelic.h>
# }C
# Handle HTTPS connection
if (server.port == 443) {
set req.backend = web_ssl;
} else {
set req.backend = web;
}
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;
}
}
# Normalize requests sent via curls -X mode and LWP
if (req.url ~ "^http://") {
set req.url = regsub(req.url, "http://[^/]*", "");
}
# Normalize hostname to avoid double caching
set req.http.host = regsub(req.http.host,
"^example\.com$", "www.example.com");
# Uncomment to support shared hosting when testing through staging server
# set req.http.host = regsub(req.http.host, "^cache\.example\.com$",
# "www.example.com");
# Use anonymous, cached pages if all backends are down
if (!req.backend.healthy) {
unset req.http.Cookie;
}
# Allow the backend to serve up stale content if it is responding slowly
set req.grace = 6h;
# Do not cache these paths
if (req.url ~ "^/status\.php$" ||
req.url ~ "^/administrator") {
return (pass);
}
# Do not cache authenticated sessions
if (req.http.Cookie && req.http.Cookie ~ "authtoken=") {
return (pipe);
}
# Do not allow outside access to configuration.php
if (req.url ~ "^/configuration\.php$" && !client.ip ~ internal) {
# Have Varnish throw the error directly
# error 404 "Page not found.";
# Use a custom error page
set req.url = "/";
}
# Allow purge only from internal users
if (req.request == "PURGE") {
if (!client.ip ~ internal) {
error 405 "Not allowed.";
}
return (lookup);
}
# Handle compression correctly. Different browsers send different
# "Accept-Encoding" headers, even though they mostly all support the same
# compression mechanisms. By consolidating these compression headers into
# a consistent format, we can reduce the size of the cache and get more hits.
# @see: http:// varnish.projects.linpro.no/wiki/FAQ/Compression
if (req.http.Accept-Encoding) {
if (req.http.Accept-Encoding ~ "gzip") {
# If the browser supports it, we'll use gzip.
set req.http.Accept-Encoding = "gzip";
} else if (req.http.Accept-Encoding ~ "deflate") {
# Next, try deflate if it is supported.
set req.http.Accept-Encoding = "deflate";
} else {
# Unknown algorithm. Remove it and send unencoded.
unset req.http.Accept-Encoding;
}
}
# Always cache the following file types for all users
if (req.url ~
"(?i)\.(png|gif|jpeg|jpg|ico|swf|pdf|txt|css|js|html|htm|gz|xml)(\?[a-z0-9]+)?$") {
unset req.http.Cookie;
}
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") {
return (pass);
}
# We cache requests with cookies too (e.g. Google Analytics)
# Original: if (req.http.Authenticate || req.http.Authorization
# || req.http.Cookie) {
if (req.http.Authenticate || req.http.Authorization) {
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);
# }
# Determine the cache key when storing/retrieving a cached page
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
# Don't include cookie in hash
# if (req.http.Cookie) {
# hash_data(req.http.Cookie);
# }
return (hash);
}
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged.";
}
if (obj.ttl <= 0s) {
return (pass);
}
return (deliver);
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
return (fetch);
}
# Called when the requested object has been retrieved from the backend, or the
# request to the backend has failed; "beresp" stands for back-end response
sub vcl_fetch {
# Don't allow static files to set cookies
if (req.url ~
"(?i)\.(png|gif|jpeg|jpg|ico|swf|pdf|txt|css|js|html|htm|gz|xml)(\?[a-z0-9]+)?$") {
unset beresp.http.Set-cookie;
}
# Allow items to be stale if needed
set beresp.grace = 6h;
if (beresp.ttl <= 0s) {
set beresp.http.X-Cacheable = "NO:Not Cacheable";
return (hit_for_pass);
} else if (req.http.Cookie ~"(UserID|_session)") {
# Don't cache content for logged in users
set beresp.http.X-Cacheable = "NO:Got Session";
return (hit_for_pass);
} else if (beresp.http.Cache-Control ~ "private") {
# Respect the Cache-Control=private header from the backend
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
return (hit_for_pass);
} else if (beresp.ttl < 1s) {
# Extend the lifetime of the object artificially
set beresp.ttl = 300s;
set beresp.grace = 300s;
set beresp.http.X-Cacheable = "YES:Forced";
} else {
# Varnish determined the object was cacheable
set beresp.http.X-Cacheable = "YES";
# Uncomment to have Varnish cache objects longer than the clients do.
# Cache must be purged manually when the site changes, so don't use with
# frequently changing content - comments, visitor counters etc.
# @see: https://www.varnish-cache.org/trac/wiki/VCLExampleLongerCaching
# unset beresp.http.expires;
# set beresp.ttl = 1w;
# set beresp.http.magicmarker = "1";
}
return (deliver);
}
sub vcl_deliver {
# Uncomment to add hostname to headers
# set resp.http.X-Served-By = server.hostname;
# Identify which Varnish handled the request
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT from Tokyo";
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS from Tokyo";
}
# Remove version number sometimes set by CMS
if (resp.http.X-Content-Encoded-By) {
unset resp.http.X-Content-Encoded-By;
}
if (resp.http.magicmarker) {
# Remove the magic marker, see vcl_fetch
unset resp.http.magicmarker;
# By definition we have a fresh object
set resp.http.Age = "0";
}
return (deliver);
}
sub vcl_error {
# Redirect to some other URL in case of root page failure
# if (req.url ~ "^/?$") {
# set obj.status = 302;
# set obj.http.Location = "http://backup.example.com/";
# }
# Otherwise redirect to root, which will likely be in the cache
set obj.http.Content-Type = "text/html; charset=utf-8";
synthetic {"
<html>
<head>
<title>Page Unavailable</title>
<style>
body { background: #efefef; text-align: center; color: white;
font-family: Trebuchet MS, sans-serif; }
#page { width: 500px; margin: 100px auto 0; padding: 30px; background: #888888;
border-radius: 14px; -moz-border-radius: 14px; -webkit-border-radius: 14px; border: 0 }
a, a:link, a:visited { color: #cccccc; }
.error { color: #222222; }
</style>
</head>
<body onload="setTimeout(function() { window.location = '/' }, 3000)">
<div id="page">
<h1 class="title">Page Unavailable</h1>
<p>The page you requested is temporarily unavailable.</p>
<p>We're redirecting you to the <a href="/">homepage</a> in 3 seconds.</p>
<div class="error">(Error "} + obj.status + " " + obj.response + {")</div>
</div>
</body>
</html>
"};
return (deliver);
}
@kimlindholm
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment