Regular purging in Varnish is done based on the URL and removes all variations. If you only want to remove specific objects for one of the cache variations (mobile vs desktop), you'll need to use banning.
Here's an official banning tutorial: https://www.varnish-software.com/developers/tutorials/ban/
The VCL code
If we use your VCL code as the basis, here's the complete VCL including the banning logic:
vcl 4.1;
backend default {
.port = "8000";
}
acl purge {
"localhost";
"192.168.55.0"/24;
}
include "devicedetect.vcl";
sub vcl_recv {
call devicedetect;
if(req.http.X-UA-Device ~ "^(mobile|tablet)\-.+$") {
set req.http.X-UA-Device = "mobile";
} else {
set req.http.X-UA-Device = "desktop";
}
}
sub vcl_recv {
if (req.method == "BAN") {
if (!client.ip ~ purge) {
return (synth(405));
}
if (!req.http.x-invalidate-pattern) {
if(!req.http.x-invalidate-ua-device) {
return (purge);
}
ban("obj.http.x-url == " + req.url
+ " && obj.http.x-host == " + req.http.host
+ " && obj.http.x-ua-device == " + req.http.x-invalidate-ua-device);
return (synth(200,"Ban added"));
}
if(!req.http.x-invalidate-ua-device) {
ban("obj.http.x-url ~ " + req.http.x-invalidate-pattern
+ " && obj.http.x-host == " + req.http.host);
return (synth(200,"Ban added"));
}
ban("obj.http.x-url ~ " + req.http.x-invalidate-pattern
+ " && obj.http.x-host == " + req.http.host
+ " && obj.http.x-ua-device == " + req.http.x-invalidate-ua-device);
return (synth(200,"Ban added"));
}
}
sub vcl_backend_response {
set beresp.http.x-url = bereq.url;
set beresp.http.x-host = bereq.http.host;
set beresp.http.x-ua-device = bereq.http.X-UA-Device;
}
sub vcl_deliver {
unset resp.http.x-url;
unset resp.http.x-host;
unset resp.http.x-ua-device;
}
sub vcl_hash {
hash_data(req.http.X-UA-Device);
}
How to run
Here are a couple of examples of how to execute the bans.
1. Invalidate a page for both mobile and desktop
The following command will remove the /my-page
page from the cache for the domain.ext
domain. This will remove both the mobile and the desktop version:
curl -XBAN http://domain.ext/my-page
2. Invalidate a page for the mobile version of the website
The following command will remove the /my-page
page from the cache for the domain.ext
domain, but only for the mobile version:
curl -XBAN -H "x-invalidate-ua-device: mobile" http://domain.ext/my-page
3. Invalidate a page for the mobile version of the website
The following command will remove the /my-page
page from the cache for the domain.ext
domain, but only for the desktop version:
curl -XBAN -H "x-invalidate-ua-device: desktop" http://domain.ext/my-page
4. Invalidate multiple pages for both the mobile and the desktop version
The following command will remove all pages from the cache that start with /my-*
for the domain.ext
domain. Both for the mobile and desktop version of the website
curl -XBAN -H "x-invalidate-pattern: /my-" http://domain.ext/my-page
5. Invalidate multiple pages for the mobile website
The following command will remove all pages from the cache that start with /my-*
for the domain.ext
domain, but only for the mobile version of the website:
curl -XBAN -H "x-invalidate-pattern: /my-" -H "x-invalidate-ua-device: mobile" http://domain.ext/my-page
6. Invalidate multiple pages for the desktop website
The following command will remove all pages from the cache that start with /my-*
for the domain.ext
domain, but only for the desktop version of the website:
curl -XBAN -H "x-invalidate-pattern: /my-" -H "x-invalidate-ua-device: desktop" http://domain.ext/my-page
Further customizations
The VCL code assumes that the 192.168.55.0/24
IP range will be used to invalidate the cache remotely. Please make sure the right IP addresses, hostnames and CIDRs are part of the purge
ACL.
The ban executions were done using the domain.ext
domain name. Please use the right hostname to invalidate your cache.
If the hostname you're using to invalidate (e.g. "localhost") is not that hostname with which the objects are stored in the cache, please assign an explicit Host
header to your invalidation calls.
Here's an example where the ban call is done locally, but the Host
header to match is domain.ext
:
curl -XBAN -H "Host: domain.ext" -H "x-invalidate-pattern: /my-" -H "x-invalidate-ua-device: desktop" http://localhost/my-page
Bypassing the cache for desktop users
To answer your second question, here's how you bypass the cache for the desktop website:
sub vcl_recv {
if(req.http.X-UA-Device == "desktop") {
return(pass);
}
}
This small snippet of VCL code can be added to your existing one. In one of the earlier vcl_recv
definitions the X-UA-Device
header is set, which can be reused here.