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);
    # }