Skip to content

Instantly share code, notes, and snippets.

@chinthakagodawita
Last active January 3, 2016 13:09
Show Gist options
  • Save chinthakagodawita/8467303 to your computer and use it in GitHub Desktop.
Save chinthakagodawita/8467303 to your computer and use it in GitHub Desktop.
Nginx config for a Drupal installation with Varnish.
# Demonz default Varnish config.
#
# Modified from:
# https://fourkitchens.atlassian.net/wiki/display/TECH/Configure+Varnish+3+for+Drupal+7
#
# Default backend definition. Set this to point to your content
# server.
backend default {
.host = "MYSERVER";
.port = "80";
}
sub vcl_recv {
# Set exact request client IP for authentication purposes.
if (req.http.X-Forwarded-Proto == "https") {
set req.http.X-Auth-IP = req.http.X-Real-IP;
}
else {
set req.http.X-Auth-IP = client.ip;
}
# 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 ~ "^/update\.php$" ||
req.url ~ "^/cron\.php$" ||
req.url ~ "^/admin$" ||
req.url ~ "^/admin/.*$" ||
req.url ~ "^/flag/.*$" ||
req.url ~ "^/batch.*$" ||
req.url ~ "^/batch/.*$" ||
req.url ~ "^.*/ajax/.*$" ||
req.url ~ "^/admin/build/features" ||
req.url ~ "^.*/ahah/.*$") {
return (pass);
}
# Always cache the following file types for all users. This list of extensions
# appears twice, once here and again in vcl_fetch so make sure you edit both
# and keep them equal.
if (req.url ~ "(?i)\.(nrg|docx|xslx|pptx|zip|bmp|rtf|iso|mp3|wav|mp4|avi|pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
unset req.http.Cookie;
}
# Remove all cookies that Drupal doesn't need to know about. We explicitly
# list the ones that Drupal does need, the SESS and NO_CACHE. If, after
# running this code we find that either of these two cookies remains, we
# will pass as the page cannot be cached.
if (req.http.Cookie) {
# 1. Append a semi-colon to the front of the cookie string.
# 2. Remove all spaces that appear after semi-colons.
# 3. Match the cookies we want to keep, adding the space we removed
# previously back. (\1) is first matching group in the regsuball.
# 4. Remove all other cookies, identifying them by the fact that they have
# no space after the preceding semi-colon.
# 5. Remove all spaces and semi-colons from the beginning and end of the
# cookie string.
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|has_js|session_api_available|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|__utma_a2a|has_js|amfID|session_api_available|highContrast)=[^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
# Remove has_js and Google Analytics __* cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
if (req.http.Cookie == "") {
# If there are no remaining cookies, remove the cookie header. If there
# aren't any cookie headers, Varnish's default behavior will be to cache
# the page.
unset req.http.Cookie;
}
else {
# If there is any cookies left (a session or NO_CACHE cookie), do not
# cache the page. Pass it on to Apache directly.
return (pass);
}
}
# Authorization has already been checked in NGINX, removing the attribute here
# to avoid missing varnish cash.
if (req.http.Authorization) {
unset req.http.Authorization;
}
}
sub vcl_hash {
if (req.http.hash-input) {
hash_data(req.http.hash-input);
}
# Add the fact that we may be on HTTPS to the cache hash.
if (req.http.X-Forwarded-Proto) {
hash_data(req.http.X-Forwarded-Proto);
}
}
# Code determining what to do when serving items from the Apache servers.
# beresp == Back-end response from the web server.
sub vcl_fetch {
# We need this to cache 404s, 301s, 500s. Otherwise, depending on backend but
# definitely in Drupal's case these responses are not cacheable by default.
if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
set beresp.ttl = 10m;
}
# Don't allow static files to set cookies.
# (?i) denotes case insensitive in PCRE (perl compatible regular expressions).
# This list of extensions appears twice, once here and again in vcl_recv so
# make sure you edit both and keep them equal.
if (req.url ~ "(?i)\.(nrg|docx|xslx|pptx|zip|bmp|rtf|iso|mp3|wav|mp4|avi|pdf|asc|dat|txt|doc|xls|ppt|tgz|csv|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
unset beresp.http.set-cookie;
}
# Allow items to be stale if needed.
set beresp.grace = 6h;
# Support ban lurker in the Drupal varnish module.
set beresp.http.x-url = req.url;
set beresp.http.x-host = req.http.host;
# Uncomment in order to debug cookie issues.
# set beresp.http.X-Varnish-Cookie-Debug = "Cleaned request cookie: " + req.http.Cookie;
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Varnish-Cache = "HIT";
}
else {
set resp.http.X-Varnish-Cache = "MISS";
}
}
sub vcl_error {
set obj.http.Content-Type = "text/html; charset=utf-8";
set obj.http.Retry-After = "5";
synthetic {"
<!-- Add your custom error page here -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Server under maintenance | MY SITE</title>
<meta name="viewport" content="width=device-width">
<!-- Use inline CSS -->
<style type="text/css">
</style>
</head>
<body>
<div class="centering">
<div class="logo">
<!-- Use base64-encoded images or images hosted off-site (e.g. Amazon S3). -->
<a href="http://mysite/" title="MY SITE">
<img alt="" src="data:image/png;{BASE64LOGOIMAGE}" style="max-width:100%;" alt="MY SITE"/>
</a>
</div><!-- logo -->
<h1 class="intro">The server is currently down for maintenance.</h1>
<div id="comingsoon">
<p>We are running some routine maintenance on the server so please check back soon,<br />if we are not back in 30 minutes, please contact us.</p>
<p><b>Phone number</b> {PHONE NUMBER}<br></p>
</div>
</div><!-- centering -->
</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);
# }
# Demonz default nginx config.
# HTTPS server
server {
listen 443;
server_tokens off;
ssl on;
# Update these to match your certificate locations.
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_trusted_certificate /etc/nginx/ssl/bundle.crt;
# Enable OCSP stapling to reduce First-Byte-Time.
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AES:RSA+3DES:!ADH:!AECDH:!MD5:!DSS;
ssl_prefer_server_ciphers on;
# Update this to match your maximum POST/upload size.
client_max_body_size 128M;
location @proxy {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
# Update this to point to your Varnish/HTTP server
proxy_pass http://127.0.0.1:80;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Front-End-Https on;
# Enable HSTS
add_header Strict-Transport-Security max-age=157680000;
# By default we don't want to redirect this request
proxy_redirect off;
# Force timeouts if one of the backends has died
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
location / {
try_files $uri @proxy;
}
# Allow long expires for static assets.
location ~* \.(js|css|woff|eot|svg|ttf|otf|png|jpg|jpeg|gif|ico)$ {
expires max;
try_files $uri @proxy;
}
# Advagg support.
location ~* files/advagg_(?:css|js)/ {
gzip_static on;
access_log off;
expires max;
add_header ETag "";
add_header Cache-Control "max-age=290304000, no-transform, public";
try_files $uri @proxy;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment