Separate VCL files¶
Having multiple different vhosts in the same Varnish is a very typical use-case, and from Varnish 5.0 it is possible to have a separate VCL files for separate vhosts or any other distinct subset of requests.
Assume that we want to handle varnish.org
with one VCL file
and varnish-cache.org
with another VCL file.
First load the two VCL files:
vcl.load vo_1 /somewhere/vo.vcl
vcl.load vc_1 /somewhere/vc.vcl
These are 100% normal VCL files, as they would look if you ran only that single domain on your varnish instance.
Next we need to point VCL labels to them:
vcl.label l_vo vo_1
vcl.label l_vc vc_1
Next we write the top-level VCL program, which branches out to the other two, depending on the Host: header in the request:
import std;
# We have to have a backend, even if we do not use it
backend default { .host = "127.0.0.1"; }
sub vcl_recv {
# Normalize host header
set req.http.host = std.tolower(req.http.host);
if (req.http.host ~ "\.?varnish\.org$") {
return (vcl(l_vo));
}
if (req.http.host ~ "\.?varnish-cache\.org$") {
return (vcl(l_vc));
}
return (synth(302, "http://varnish-cache.org"));
}
sub vcl_synth {
if (resp.status == 301 || resp.status == 302) {
set resp.http.location = resp.reason;
set resp.reason = "Moved";
return (deliver);
}
}
Finally, we load the top level VCL and make it the active VCL:
vcl.load top_1 /somewhere/top.vcl
vcl.use top_1
If you want to update one of the separated VCLs, you load the new one and change the label to point to it:
vcl.load vo_2 /somewhere/vo.vcl
vcl.label l_vo vo_2
If you want to change the top level VCL, do as you always did:
vcl.load top_2 /somewhere/top.vcl
vcl.use top_2
Details, details, details:¶
All requests always start in the active VCL - the one from
vcl.use
Only VCL labels can be used in
return(vcl(name))
. Without this restriction the top level VCL would have to be reloaded every time one of the separate VCLs were changed.You can only switch VCLs from the active VCL. If you try it from one of the separate VCLs, you will get a 503
You cannot remove VCL labels (with
vcl.discard
) if any VCL containsreturn(vcl(name_of_that_label))
You cannot remove VCLs which have a label attached to them.
This code is tested in testcase c00077
This is a very new feature, it may change
We would very much like feedback how this works for you