Skip to content
Back to top

# Separate VCL files

Having multiple different vhosts in the same Vinyl Cache is a very typical use-case, and from Varnish Cache 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 `code.vinyl-cache.org` with one VCL file and `vinyl-cache.org` with another VCL file.

First load the two VCL files:

    vcl.load code_1 /somewhere/code.vcl
    vcl.load vinyl_1 /somewhere/vinyl.vcl

These are 100% normal VCL files, as they would look if you ran only that single domain on your Vinyl Cache instance.

Next we need to point VCL labels to them:

    vcl.label l_code code_1
    vcl.label l_vinyl vinyl_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
        call vcl_req_host;

        if (req.http.host == "code.vinyl-cache.org") {
            return (vcl(l_code));
        }
        if (req.http.host ~ "\.?vinyl-cache\.org$") {
            return (vcl(l_vinyl));
        }
        return (synth(302, "http://vinyl-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 code_2 /somewhere/code.vcl
    vcl.label l_code code_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 contains `return(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