14

I'm looking for a way to clear the cache for all domains and all URLs in Varnish.

Currently, I would need to issue individual commands for each URLs, for example:

curl -X PURGE http://example.com/url1
curl -X PURGE http://example.com/url1
curl -X PURGE http://subdomain.example.com/
curl -X PURGE http://subdomain.example.com/url1
// etc.

While I'm looking for a way to do something like

curl -X PURGE http://example.com/*

And that would clear all URLs under example.com, but also all URLs in sub-domains of example.com, basically all the URLs managed by Varnish.

Any idea how to achieve this?

This is my current VCL file:

vcl 4.0;

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

sub vcl_recv {
    # Command to clear the cache
    # curl -X PURGE http://example.com
    if (req.method == "PURGE") {
        return (purge);
    }
}
laurent
  • 88,262
  • 77
  • 290
  • 428
  • 1
    Did you try to use banning? This may be exactly what you want. http://book.varnish-software.com/4.0/chapters/Cache_Invalidation.html#banning – Rastislav Kassak Aug 11 '16 at 09:20

4 Answers4

17

With Varnish 4.0 I ended up implementing it with the ban command:

sub vcl_recv {
    # ...

    # Command to clear complete cache for all URLs and all sub-domains
    # curl -X XCGFULLBAN http://example.com
    if (req.method == "XCGFULLBAN") {
        ban("req.http.host ~ .*");
        return (synth(200, "Full cache cleared"));
    }

    # ...
}
laurent
  • 88,262
  • 77
  • 290
  • 428
  • 1
    Not need to write VCL to submit a ban. In any case, the way to go should be creating a ban lurker friendly. See https://varnish-cache.org/docs/trunk/users-guide/purging.html#bans for details. – Carlos Abalde May 25 '18 at 14:38
  • While this works, it's not very efficient for caches with a large number of objects. I'd suggest future readers check out Joshua DeWald's answer below, which is lurker friendly and thereby a bit easier on Varnish to process. – Spikes Jan 04 '19 at 22:42
17

Well, I suggest just restart varnish. It will purge all of the files because varnish keeps cache into memory.

Run: sudo /etc/init.d/varnish restart

Paulo Victor
  • 3,814
  • 2
  • 26
  • 29
6

Assuming no change of URL or internal cache key, for a full flush the simplest approach would be to restart Varnish, as it maintains its cache in memory.

If doing a quick restart is not acceptable, the BAN suggested by Rastislav is a great approach. It will need to stay active as long your longest TTL, so if you frequently need a full flush, the BAN list will be pretty much permanent as the ban lurker (which sweeps for BANs which no longer are relevant) may always think that your BAN is useful

So in your case, your VCL would be:

# Highly recommend that you set up an ACL for IPs that are allowed
# to make the BAN call
acl acl_ban {
    "localhost";
    "1.2.3.4"/32;
}

sub vcl_recv {
   if (client.ip ~ acl_ban && req.method == "BAN") {
      ban("req.http.host == " + req.http.host);
      # Throw a synthetic page so the request won't go to the backend.
      return(synth(200, "Ban added"));
   }
}

However as noted by Carlos in the comments, this will actually create a lazy invalidation (and so only removed at request time). If you want to have the objects actually get purged by the background ban lurker every so often, you can instead do:

# Highly recommend that you set up an ACL for IPs that are allowed
# to make the BAN call
acl acl_ban {
    "localhost";
    "1.2.3.4"/32;
}

sub vcl_recv {
   if (client.ip ~ acl_ban && req.method == "BAN") {
      # see below for why this is obj. rather than req.
      ban("obj.http.host == " + req.http.host);
      # Throw a synthetic page so the request won't go to the backend.
      return(synth(200, "Ban added"));
   }
}

sub vcl_backend_response {
   # add any portions of the request that would want to be able
   # to BAN on. Doing it in vcl_backend_response means that it
   # will make it into the storage object
   set beresp.http.host = bereq.http.host;
}

sub vcl_deliver {
   # Unless you want the header to actually show in the response,
   # clear them here. So they will be part of the stored object
   # but otherwise invisible
   unset beresp.http.host;
}

Then to do the flush:

curl -X BAN http://example.com;
Joshua DeWald
  • 3,079
  • 20
  • 16
  • 2
    That's right, but beware that the ban you're creating in ``vcl_recv`` is not lurker friendly. It will be ignored by the ban lurker. That's not critical in some cases, but if your bans are going to match a lot of objects in the storage, you should avoid lazy invalidations and allow the ban lurker to purge objects. Creating lurker friendly bans requires a few more lines of VCL. Please check https://www.varnish-cache.org/docs/trunk/users-guide/purging.html#bans for details. – Carlos Abalde Aug 12 '16 at 07:15
  • 1
    That's a great note! I'll modify the answer with that in mind. – Joshua DeWald Aug 12 '16 at 07:24
  • 1
    Message from VCC-compiler: varnish-dev | 'beresp.http.host': cannot be unset in method 'vcl_deliver'. varnish-dev | At: ('/etc/varnish/conf.d/varnish.vcl' Line 195 Pos 10) varnish-dev | unset beresp.http.host; – benh57 Jan 28 '22 at 03:51
  • @benh57 I suspect my answer is no longer a good one with newer versions of Varnish :/ – Joshua DeWald Apr 22 '22 at 16:07
4

Purge all Varnish cache from command line (invalidate all the cache):

varnishadm "ban.url ."  # Matches all URLs

Note: Command is purge.url in Varnish 2.x.

We can also ban by a hostname:

varnishadm "ban req.http.host == xxx.com"
Ashwin
  • 450
  • 1
  • 6
  • 17