Created
February 6, 2012 19:28
-
-
Save kimlindholm/1754248 to your computer and use it in GitHub Desktop.
Varnish configuration example
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
# 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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
From presentation Improving Site Response Time, Part 3 - Varnish Configuration Step by Step