Varnish 3.x Configuration

Last updated on
16 August 2016

Backends


In the main section of your VCL

backend default {
.host = "127.0.0.1";
.port = "8080";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}

backend sitea {
.host = "xxx.xx.xxx.103";
.port = "8080";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}

backend siteb {
.host = "xxx.xx.xxx.104";
.port = "8080";
.connect_timeout = 600s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
.max_connections = 800;
}

And in sub vcl_recv:

  # Use different backend for each site served through the proxy. Again, 
  # this is not needed if you're running a single site on a server.
  if (req.http.host ~ "sitea.com$") {
    set req.backend = sitea;
  }
  else if (req.http.host ~ "siteb.com$") {
    set req.backend = siteb;
  }
  # Use the default backend for all other requests
  else {
    set req.backend = default;
  }
  
  # Get rid of progress.js query params 
  if (req.url ~ "^/misc/progress\.js\?[0-9]+$") { 
    set req.url = "/misc/progress.js";
  } 
  
  # Pipe these paths directly to Apache for streaming.
  if (req.url ~ "^/admin/content/backup_migrate/export") { 
    return (pipe);
  } 
  
#  If global redirect is on
#  if (req.url ~ "node\?page=[0-9]+$") {
#    set req.url = regsub(req.url, "node(\?page=[0-9]+$)", "\1");
#    return (lookup);
#  }
  
  # Do not cache these paths.
  if (req.url ~ "^/status\.php$" ||
    req.url ~ "^/update\.php" ||
    req.url ~ "^/install\.php" ||
    req.url ~ "^/admin" ||
    req.url ~ "^/admin/.*$" || 
    req.url ~ "^/system/files.*$" ||
    req.url ~ "^/user" ||
    req.url ~ "^/user/.*$" || 
    req.url ~ "^/users/.*$" ||
    req.url ~ "^/info/.*$" ||
    req.url ~ "^/flag/.*$" ||
    req.url ~ "^.*/ajax/.*$" || 
    req.url ~ "^.*/ahah/.*$") {
    return (pass);
  }
  
  # Disallow outside access to cron.php or install.php
  if (req.url ~ "^/(cron|install)\.php$" && !client.ip ~ internal) {
    # Either let Varnish throw the error directly,
    error 404 "Page not found.";
    # Or, use a custom error page that you've defined in Drupal at the path "404". 
    # set req.url = "/404"; 
  }
  
  # Always cache the following file types for all users.
  if (req.url ~ "(?i)\.(png|gif|jpeg|jpg|ico|swf|css|js|html|htm)(\?[a-z0-9]+)?$") {
    unset req.http.Cookie;
  }

  # Remove all cookies that Drupal doesn't need to know about. ANY remaining
  # cookie will cause the request to pass-through to Apache. For the most part
  # we always set the NO_CACHE cookie after any POST request, disabling the
  # Varnish cache temporarily. The session cookie allows all authenticated users
  # to pass through as long as they're logged in.
  # @see http://drupal.stackexchange.com/questions/53467
  #
  # 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.
  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, ";(S{1,2}ESS[a-z0-9]+|NO_CACHE)=", "; \1=");
    set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
    set req.http.Cookie = regsuball(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.
    if (req.http.Cookie == "") {
      unset req.http.Cookie;
    }
    
    # If there are any cookies left (a session or NO_CACHE cookie), do not
    # cache the page; pass it on to Apache directly.
    else {
      return (pass);
    }
  }
  

Purge


near top, right after backend section:

acl internal{
  "localhost";
  "127.0.0.1";
}

in vcl_recv section:

  # Check the incoming request type is "PURGE", not "GET" or "POST"
  if (req.request == "PURGE") {
    # Check if the ip coresponds with the acl purge
    if (!client.ip ~ internal) {
    # Return error code 405 (Forbidden) when not
      error 405 "Not allowed.";
    }
    return (lookup);
  }

and two new sections at end:

sub vcl_hit {
  if (req.request == "PURGE") {
    purge;
    error 200 "Purged.";
  }
}

sub vcl_miss {
  if (req.request == "PURGE") {
    purge;
    error 200 "Purged.";
  }
}