0

I have a simple PHP index file website that changes color if refreshed on port 8080, but correctly shows the cached version of the page with the same color thanks to the following default.vcl:

    vcl 4.0;

    # This is where your content lives. Adjust it to point at your web server.

    backend default {
        .host = "xx.xx.xx.xx";
        .port = "8080";
    }

    # The only thing stopping Varnish from caching properly by default in most
# cases is the presence of cookies. Strip them, and voila, cache works.
sub vcl_recv {
    # We leave cookies for content under "/user".
        if (req.url !~ "^/user") {
                unset req.http.cookie;
        }
}

# That's all you need, but you might want to start adjusting cache duration
# too! You can do that by emitting "Cache-Control: s-maxage=123" from your
# backend server, telling Varnish to cache for 123 seconds. That requires 0
# configuration, but the following snippet removes "s-maxage" from the
# response before it is sent to the client, so as not to confuse other
# proxy servers between you and the client.
sub strip_smaxage {
        # Remove white space
        set beresp.http.cache-control = regsuball(beresp.http.cache-control, " ","");
        # strip s-maxage - Varnish has already used it
        set beresp.http.cache-control = regsub(beresp.http.cache-control, "s-maxage=[0-9]+\b","");
        # Strip extra commas
        set beresp.http.cache-control = regsub(beresp.http.cache-control, "(^,|,$|,,)", "");
}

# This just calls the above function at the appropriate time.
sub vcl_backend_response {
        call strip_smaxage;
}

# You can read more about control Varnish through headers at
# https://varnishfoo.info/chapter-2.html

However, I need to host a Drupal website on the same server, so I replaced the default.vcl file with the following content:

vcl 4.0;

backend default {
    .host = "xx.xx.xx.xx";
    .port = "8080";
}

acl purge {
  "localhost";
  "127.0.0.1";
}

sub vcl_recv {


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

# Do not cache these paths.
  if (req.url ~ "^/status\.php$" ||
      req.url ~ "^/update\.php" ||
      req.url ~ "^/install\.php" ||
      req.url ~ "^/apc\.php$" ||
      req.url ~ "^/admin" ||
      req.url ~ "^/admin/.*$" ||
      req.url ~ "^/user" ||
      req.url ~ "^/user/.*$" ||
      req.url ~ "^/users/.*$" ||
      req.url ~ "^/info/.*$" ||
      req.url ~ "^/flag/.*$" ||
      req.url ~ "^.*/ajax/.*$" ||
      req.url ~ "^.*/ahah/.*$" ||
      req.url ~ "^/system/files/.*$") {

    return (pass);
  }

 # Always cache the following file types for all users. This list of extensions
  # appears twice, once here and again in vcl_backend_response 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);
    }
  }


}

and it works perfectly well for caching the Drupal site, but breaks the other "regular" website, because it starts changing colors on every page refresh on both ports 80 (Varnish cached) and 8080 (Apache) versions.

What should be the right content for the default.vcl file to cover both Drupal and non-Drupal websites?

Nick
  • 205
  • 1
  • 9
  • You might want to look [here](https://www.getpagespeed.com/server-setup/varnish/varnish-virtual-hosts) for a way to combine different websites' VCL in a single Varnish instance. Otherwise it's just easier to setup multiple Varnish master services each having its own `default.vcl` – Danila Vershinin Feb 22 '19 at 11:39
  • That's a really nice article, however I'd appreciate specific example solution of the given above two configuration files. Because the post mainly discusses how to separate the `sub vcl_recv` sections and following it didn't work for me, because in my case I believe sub sections other that `vcl_recv` are conflicting. – Nick Feb 22 '19 at 20:06

1 Answers1

0

Trying different combinations I've found that just incorporating if (req.http.host == "non-drupal-site.com") { into sub vcl_recv section of the second (Drupal) configuration file like so:

sub vcl_recv {

 if (req.http.host == "non-drupal-site.com") {
        if (req.url !~ "^/user") {
                unset req.http.cookie;
        }
    }

works ok and gives the desired effect: Drupal pages are cached correctly, but also the colors of the simple website are cached intact.

Nick
  • 205
  • 1
  • 9