Skip to end of metadata
Go to start of metadata

Drupal

  • Setup the Drupal site on admin/config/development/performance. Set your cache lifetimes.
  • Set the reverse proxy settings found in settings.php.

default.vcl (Varnish 3 only)

# This is a basic VCL configuration file for varnish.  See the vcl(7)
# man page for details on VCL syntax and semantics.
#

# TODO: Update internal subnet ACL and security.

# Define the internal network subnet.
# These are used below to allow internal access to certain files while not
# allowing access from the public internet.
# acl internal {
#  "192.10.0.0"/24;
# }

# Default backend definition.  Set this to point to your content
# server.
#
backend default {
  .host = "127.0.0.1";
  .port = "8080";
}

# Respond to incoming requests.
sub vcl_recv {
  # 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;

  # Pipe these paths directly to Apache for streaming.
  #if (req.url ~ "^/admin/content/backup_migrate/export") {
  #  return (pipe);
  #}

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

  # Do not cache these paths.
  if (req.url ~ "^/status\.php$" ||
      req.url ~ "^/update\.php$" ||
      req.url ~ "^/admin$" ||
      req.url ~ "^/admin/.*$" ||
      req.url ~ "^/flag/.*$" ||
      req.url ~ "^.*/ajax/.*$" ||
      req.url ~ "^.*/ahah/.*$") {
       return (pass);
  }

  # Do not allow outside access to cron.php or install.php.
  #if (req.url ~ "^/(cron|install)\.php$" && !client.ip ~ internal) {
    # Have Varnish throw the error directly.
  #  error 404 "Page not found.";
    # 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. 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)\.(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]+|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 == "") {
      # 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);
    }
  }
}

# Set a header to track a cache HIT/MISS.
sub vcl_deliver {
  if (obj.hits > 0) {
    set resp.http.X-Varnish-Cache = "HIT";
  }
  else {
    set resp.http.X-Varnish-Cache = "MISS";
  }
}

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

# In the event of an error, show friendlier messages.
sub vcl_error {
  # Redirect to some other URL in the case of a homepage failure.
  #if (req.url ~ "^/?$") {
  #  set obj.status = 302;
  #  set obj.http.Location = "http://backup.example.com/";
  #}

  # Otherwise redirect to the homepage, 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: #303030; text-align: center; color: white; }
    #page { border: 1px solid #CCC; width: 500px; margin: 100px auto 0; padding: 30px; background: #323232; }
    a, a:link, a:visited { color: #CCC; }
    .error { color: #222; }
  </style>
</head>
<body onload="setTimeout(function() { window.location = '/' }, 5000)">
  <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 5 seconds.</p>
    <div class="error">(Error "} + obj.status + " " + obj.response + {")</div>
  </div>
</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);
# }
  • No labels

26 Comments

  1. Anonymous

    Might be a Varnish version thing but I found I couldn't use;

    set req.http.Cookie = ";" + req.http.Cookie;

    and had to change it to this instead;

    set req.http.Cookie = ";" req.http.Cookie;

    (and the same for the one around div class "error")

    1. Yes, that's because you're still using Varnish 2. I've updated the page titles to better reflect that this is Varnish 3. All the changes between the two versions are here:

       

      https://www.varnish-cache.org/docs/3.0/installation/upgrade.html

  2. Anonymous

    Mark,

    I've installed default varnish and changed default.vcl as per your post.

    Varnish is up and running.

    I also installed varnish module and amended settings.php as per module's README.txt instructions.

    I also setup cache lifetimes on admin/config/development/performance

    On varnish module's settings page it says 'Varnish is running' however I do not get any Varnish headers to indicate that pages are served by it.

    Am I missing something?

  3. You sure you're hitting the right port? Varnish needs to be configured to listen on port 80, and then use Apache as a backend on 8080.

     

  4. Anonymous

    Error 503 Service Unavailable

    Service Unavailable

    Guru Meditation:

    XID: 53417928


    Varnish cache server

    why is this?

    1. Anonymous

      I had the server down, but still when navigating into the admin/config/development/varnish, I get

      The Varnish control terminal is not responding at 127.0.0.1 on port 8080 although I have started varnish sudo varnishd -a 127.0.0.1:8080 -b 127.0.0.1:80 -s file,/tmp,500M

      I can still navigate the site using localhost:8080

      1. Anonymous

        The control terminal's port shouldn't be the same as the port varnish is listening for traffic on.

        6082 is the default.

        Your application also needs to use varnish's secret key to exchange information with the control terminal.

        You can copy the key from /etc/varnish/secret and update the Varnish secret in the varnish module's configuration page in your site.

  5. Anonymous

    Thanks for quick reply.

    I am using port 80 in apache and listening varnish on 8080 though I can't find the secret file or /etc/varnish directory.

    I did $ find / -name 'secret' 2>/dev/null

    And found nothing. Perhaps this is because I have installed varnish from macports.

    1. Anonymous

      The secret should be in /etc/varnish unless macports places the varnish global config folders elsewhere.

  6. Anonymous

    any examples of vcl for ESI?

    http://drupal.org/project/esi

  7. Anonymous

    can you include (post) apache configuration as well?

  8. Anonymous

    Hello Mark, 

    I use the default.vcl you provided but my problem is I cannot login. Some cookie problem. 

    Ubuntu 12.04 / Apache2 / Varnish3 / Varnish module 7.x beta

  9. Could you give more information? Exactly what happens? What are the headers sent from the server? How are they different to the headers from Apache? ... etc

  10. Anonymous

    These are the response headers when I click "login" : http://paste.ubuntu.com/1294314/ . I can actually login if I point my port to :8080 (directly apache, not varnish) . My varnish defaults are (only the following, nothing else) :

    START=yes
    DAEMON_OPTS="-a :80 \
    -T localhost:6082 \
    -f /etc/varnish/default.vcl \
    -S /etc/varnish/secret \
    -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,128M"

    1. Anonymous

      These are the response headers from a succesful login on :8080 .. http://paste.ubuntu.com/1294319/ there's quite some difference....

      1. Anonymous

        Actually the Varnish module says it cannot connect to Varnish  (localhost:6082) and one observation; If I login via :8080 , and then go back to :80, the cookie remains and I am able to surf /admin on :80... As soon as I delete all browser cookies of course, I'm locked-out .. 

  11. Anonymous

    Thanks for this the VCL works for me. It solves my problem regarding not caching logged-in users.

  12. Anonymous

    Thank you mark! This works with me. I blog about this too and link this page:

    http://miss-hana.com/varnish-3-on-nginx-for-drupal-7/

  13. Anonymous

    In order for me to get this working with the latest git version of Varnish, I had to rename "vcl_fetch" "vcl_backend_response", and I had to change "req.url" to "bereq.url" in the same event handler.

  14. Anonymous

    I am unable to restart varnish after using this vcl. Is there anything i can do to get some error messages? I am using varnish 3

  15. Anonymous

    Unable to restart, was my bad. So this vcl works.

     

    Now only have to figure out why my cache headers always have miss...

  16. Anonymous

    I can not start varnish when use this

  17. Anonymous

    Thanks for the file.  I have tried example files without succesfully caching content in varnish.  This one did the trick.

  18. Anonymous

    Not Woking for me....

    Please help...

    Unable to start Varnish Service...

    1. Anonymous

      Make sure apache is not running on the same port.

  19. Anonymous

    I'm struggling with this, I can contact mysite on mysite.com:8080 and varnish starts ok.

    When I run varnishlog and access the site the first error is "FetchError   c no backend connection" I have two network address on internal and on external and apache is configured to listen *:8080

    I have tried setting my backend to both internal and external IP, internal IP, localhost, 127.0.0.1 and the site domain name. 

    internal IP 10.179.73.78

    external IP 95.138.172.219

    domain cycletyre.com (this currently does not resolve to the above IP addres as this is a new server, I have a manual entry in the host file against the external IP)

    backend default {
      .host = "cycletyre.com";
      .port = "8080";
    }

    DAEMON_OPTS="-a :80 \

                 -T localhost:6082 \

                 -f /etc/varnish/default.vcl \

                 -S /etc/varnish/secret \

                 -s malloc,128m"

     

    Apache ports.conf has "listen *:8080" and all virtual hosts are set to the same *:8080

    Any help would be appreciated.

    Cheers  Dan