Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner Author

commented Feb 19, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.