This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Varnish

To properly configure Varnish with Drupal you should ensure the following configuration is your default.vcl file.

Note: Some customizations might be necessary depending on your individual requirements.

vcl 4.0;

import std;
import directors;

backend nginx {
  .host = "hostname-nginx";
  .host_header = "hostname-nginx";
  .port = "80";
}

sub vcl_init {
  new backends = directors.round_robin();
  backends.add_backend(nginx);
}

sub vcl_recv {
  set req.http.X-Forwarded-Host = req.http.Host;
  if (!req.http.X-Forwarded-Proto) {
    set req.http.X-Forwarded-Proto = "http";
  }

  # Answer healthcheck
  if (req.url == "/_healthcheck" || req.url == "/healthcheck.txt") {
    return (synth(700, "HEALTHCHECK"));
  }
  set req.backend_hint = backends.backend();

  # Answer healthcheck
  if (req.url == "/_healthcheck" || req.url == "/healthcheck.txt") {
    return (synth(700, "HEALTHCHECK"));
  }
  set req.backend_hint = backends.backend();

  # Always cache certain file types
  # Remove cookies that Drupal doesn't care about
  if (req.url ~ "(?i)\.(asc|dat|tgz|png|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
    unset req.http.Cookie;
  } else if (req.http.Cookie) {
    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]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
    set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
    set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
    if (req.http.Cookie == "") {
        unset req.http.Cookie;
    } else {
        return (pass);
    }
  }
  # If POST, PUT or DELETE, then don't cache
  if (req.method == "POST" || req.method == "PUT" || req.method == "DELETE") {
    return (pass);
  }
  # Happens before we check if we have this in cache already.
  #
  # Typically you clean up the request here, removing cookies you don't need,
  # rewriting the request, etc.
  return (hash);
  #return (pass);
}

sub vcl_backend_fetch {
  # NEW
  set bereq.http.Host = "hostname-nginx";

  # Don't add 127.0.0.1 to X-Forwarded-For
  set bereq.http.X-Forwarded-For = regsub(bereq.http.X-Forwarded-For, "(, )?127\.0\.0\.1$", "");
}

sub vcl_backend_response {
  if (beresp.http.Location) {
    set beresp.http.Location = regsub(
      beresp.http.Location,
      "^https?://[^/]+/",
      bereq.http.X-Forwarded-Proto + "://" + bereq.http.X-Forwarded-Host + "/"
    );
  }
  # Only cache select response codes
  if (beresp.status == 200 || beresp.status == 203 || beresp.status == 204 || beresp.status == 206 || beresp.status == 300 || beresp.status == 301 || beresp.status == 404 || beresp.status == 405 || beresp.status == 410 || beresp.status == 414 || beresp.status == 501) {
    # Cache for 5 minutes
    set beresp.ttl = 5m;
    set beresp.grace = 12h;
    set beresp.keep = 24h;
  } else {
    set beresp.ttl = 0s;
  }
}

sub vcl_deliver {
  # Remove identifying information
  unset resp.http.Server;
  unset resp.http.X-Powered-By;
  unset resp.http.X-Varnish;
  unset resp.http.Via;

  # Comment these for easier Drupal cache tag debugging in development.
  unset resp.http.Cache-Tags;
  unset resp.http.X-Drupal-Cache-Contexts;

  # Add Content-Security-Policy
  # set resp.http.Content-Security-Policy = "default-src 'self' *.example.ca *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca https://fonts.googleapis.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca  *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net data:; font-src 'self' *.example.ca https://fonts.gstatic.com";

  # Add CORS Headers
  # if (req.http.Origin ~ "(?i)\.example\.ca$") {
  #   if (req.url ~ "\.(ttd|woff|woff2)(\?.*)?$") {
  #     set resp.http.Access-Control-Allow-Origin = "*";
  #     set resp.http.Access-Control-Allow-Methods = "GET";
  #   }
  # }

  # Add X-Frame-Options
  if (req.url ~ "^/livechat" || req.url ~ "^/(en/|fr/)?entity-browser/") {
    set resp.http.X-Frame-Options = "SAMEORIGIN";
  } else {
    set resp.http.X-Frame-Options = "DENY";
  }

  set resp.http.X-Content-Type-Options = "nosniff";
  set resp.http.X-XSS-Protection = "1; mode=block";

  # Happens when we have all the pieces we need, and are about to send the
  # response to the client.
  #
  # You can do accounting or modifying the final object here.
  if (obj.hits > 0) {
    set resp.http.X-Cache = "HIT";
  } else {
    set resp.http.X-Cache = "MISS";
  }
  # Handle errors
  if ( (resp.status >= 500 && resp.status <= 599)
    || resp.status == 400
    || resp.status == 401
    || resp.status == 403
    || resp.status == 404) {
    return (synth(resp.status));
  }
}

sub vcl_synth {
  # Remove identifying information
  unset resp.http.Server;
  unset resp.http.X-Powered-By;
  unset resp.http.X-Varnish;
  unset resp.http.Via;

  # Add Content-Security-Policy
  # set resp.http.Content-Security-Policy = "default-src 'self' *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca data:;";
  # set resp.http.X-Content-Type-Options = "nosniff";
  # set resp.http.X-Frame-Options = "DENY";
  # set resp.http.X-XSS-Protection = "1; mode=block";

  # if (resp.status >= 500 && resp.status <= 599) {
  #   set resp.http.Content-Type = "text/html; charset=utf-8";
  #   synthetic(std.fileread("/data/configuration/varnish/errors/503.html"));
  #   return (deliver);
  # } elseif (resp.status == 400) { # 400 - Bad Request
  #   set resp.http.Content-Type = "text/html; charset=utf-8";
  #   synthetic(std.fileread("/data/configuration/varnish/errors/400.html"));
  #   return (deliver);
  # } elseif (resp.status == 401) { # 401 - Unauthorized
  #   set resp.http.Content-Type = "text/html; charset=utf-8";
  #   synthetic(std.fileread("/data/configuration/varnish/errors/401.html"));
  #   return (deliver);
  # } elseif (resp.status == 403) { # 403 - Forbidden
  #   set resp.http.Content-Type = "text/html; charset=utf-8";
  #   synthetic(std.fileread("/data/configuration/varnish/errors/403.html"));
  #   return (deliver);
  # } elseif (resp.status == 404) { # 404 - Not Found
  #   set resp.http.Content-Type = "text/html; charset=utf-8";
  #   synthetic(std.fileread("/data/configuration/varnish/errors/404.html"));
  #   return (deliver);
  # } else
  if (resp.status == 700) { # Respond to healthcheck
    set resp.status = 200;
    set resp.http.Content-Type = "text/plain";
    synthetic ( {"OK"} );
    return (deliver);
  }
}

##
# ERROR HANDLING
##
# sub vcl_backend_error {
#   set beresp.http.Content-Type = "text/html; charset=utf-8";
#   synthetic(std.fileread("/data/configuration/varnish/errors/503.html"));
#   return (deliver);
# }