VCL(7)

NAME
VCL - Varnish Configuration Language

DESCRIPTION
The VCL language is a small domain-specific language designed to be used to define request handling and document caching policies for the Varnish HTTP accelerator.

When a new configuration is loaded, the varnishd management process translates the VCL code to C and compiles it to a shared object which is then dynamically linked into the server process.

  Syntax
The VCL syntax is very simple, and deliberately similar to C and Perl. Blocks are delimited by curly braces, statements end with semicolons, and comments may be written as in C, C++ or Perl according to your own preferences.

In addition to the C-like assignment (=), comparison (==) and boolean (!, && and ||) operators, VCL supports regular expression and ACL matching using the ~ operator.

Unlike C and Perl, the backslash (\) character has no special meaning in strings in VCL, so it can be freely used in regular expressions without doubling.

Assignments are introduced with the set keyword. There are no user-defined variables; values can only be assigned to variables attached to backend, request or document objects. Most of these are typed, and the values assigned to them must have a compatible unit suffix.

VCL has if tests, but no loops.

The contents of another VCL file may be inserted at any point in the code by using the include keyword followed by the name of the other file as a quoted string.

  Backend declarations
A backend declaration creates and initializes a named backend object:

    backend www {
        set backend.host = "www.example.com";
        set backend.port = "http";
    }

The backend object can later be used to select a backend at request time:

    if (req.http.host ~ "^(www.)?example.com$") {
        set req.backend = www;
    }

  ACLs
An ACL declaration creates and initializes a named access control list which can later be used to match client addresses:

    acl local {
        "locahost";         /* myself */
        "10.0.0.1"/8;       /* and everyone on the local network */
        ! "10.0.0.23";      /* except for the dialin router */
    }

If an ACL entry specifies a host name which Varnish is unable to resolve, it will match any address it is compared to. Consequently, if it is preceded by a negation mark, it will reject any address it is compared to, which may not be what you intended. If the entry is enclosed in parentheses, however, it will simply be ignored.

To match an IP address against an ACL, simply use the match operator:

    if (client.ip ~ local) {
        pipe;
    }

  Functions
The following built-in functions are available:

regsub(str, regex, sub)
    Returns a copy of str with all occurrences of the regular expression regex replaced with sub. Within sub, $0 (which can also be spelled &) is replaced with the entire matched string, and $n is replaced with the contents of subgroup n in the matched string.

purge_url(regex)
    Purge all objects in cache whose URLs match regex.

  Subroutines
A subroutine is used to group code for legibility or reusability:

    sub pipe_if_local {
        if (client.ip ~ local) {
            pipe;
        }
    }

Subroutines in VCL do not take arguments, nor do they return values.

If multiple subroutines with the same name are defined, they are concatenated in the order in which the appear in the source.

To call a subroutine, use the call keyword followed by the subroutine's name:

    call pipe_if_local;

There are a number of special subroutines which hook into the Varnish workflow. These subroutines may inspect and manipulate HTTP headers and various other aspects of each request, and to a certain extent decide how the request should be handled. Each subroutine terminates by calling one of a small number of keywords which indicates the desired outcome.

vcl_recv
    Called at the beginning of a request, after the complete request has been received and parsed. Its purpose is to decide whether or not to serve the request, how to do it, and, if applicable, which backend to use.

    The vcl_recv subroutine may terminate with one of the following keywords:

    error code [reason]
        Return the specified error code to the client and abandon the request.

    pass
        Switch to pass mode. Control will eventually pass to vcl_pass.

    pipe
        Switch to pipe mode. Control will eventually pass to vcl_pipe.

    lookup
        Look up the requested object in the cache. Control will eventually pass to vcl_hit or vcl_miss, depending on whether the object is in the cache.

vcl_pipe
    Called upon entering pipe mode. In this mode, the request is passed on to the backend, and any further data from either client or backend is passed on unaltered until either end closes the connection.

    The vcl_pipe subroutine may terminate with one of the following keywords:

    error code [reason]
        Return the specified error code to the client and abandon the request.

    pipe
        Proceed with pipe mode.

vcl_pass
    Called upon entering pass mode. In this mode, the request is passed on to the backend, and the backend's response is passed on to the client, but is not entered into the cache. Subsequent requests submitted over the same client connection are handled normally.

    The vcl_pass subroutine may terminate with one of the following keywords:

    error code [reason]
        Return the specified error code to the client and abandon the request.

    pass
        Proceed with pass mode.

vcl_hash
    Currently not used. The vcl_hash subroutine may terminate with one of the following keywords:

    hash
        Proceed.

vcl_hit
    Called after a cache lookup if the requested document was found in the cache.

    The vcl_hit subroutine may terminate with one of the following keywords:

    error code [reason]
        Return the specified error code to the client and abandon the request.

    pass
        Switch to pass mode. Control will eventually pass to vcl_pass.

    deliver
        Deliver the cached object to the client. Control will eventually pass to vcl_deliver.

vcl_miss
    Called after a cache lookup if the requested document was not found in the cache. Its purpose is to decide whether or not to attempt to retrieve the document from the backend, and which backend to use.

    The vcl_miss subroutine may terminate with one of the following keywords:

    error code [reason]
        Return the specified error code to the client and abandon the request.

    pass
        Switch to pass mode. Control will eventually pass to vcl_pass.

    fetch
        Retrieve the requested object from the backend. Control will eventually pass to vcl_fetch.

vcl_fetch
    Called after a document has been successfully retrieved from the backend.

    The vcl_fetch subroutine may terminate with one of the following keywords:

    error code [reason]
        Return the specified error code to the client and abandon the request.

    pass
        Switch to pass mode. Control will eventually pass to vcl_pass.

    insert
        Insert the object into the cache, then deliver it to the client. Control will eventually pass to vcl_deliver.

vcl_deliver
    Called before a cached object is delivered to the client.

    The vcl_deliver subroutine may terminate with one of the following keywords:

    error code [reason]
        Return the specified error code to the client and abandon the request.

    deliver
        Deliver the object to the client.

vcl_timeout
    Called by the reaper thread shortly before a cached document reaches its expiry time.

    The vcl_timeout subroutine may terminate with one of the following keywords:

    fetch
        Request a fresh copy of the object from the backend.

    discard
        Discard the object.

vcl_discard
    Called by the reaper thread when a cached document is about to be discarded, either because it has expired or because space is running low.

    The vcl_discard subroutine may terminate with one of the following keywords:

    discard
        Discard the object.

    keep
        Keep the object in cache.

If one of these subroutines is left undefined or terminates without reaching a handling decision, control will be handed over to the builtin default. See the EXAMPLES section for a listing of the default code.

  Variables
Although subroutines take no arguments, the necessary information is made available to the handler subroutines through global variables.

The following variables are always available:

now The current time, in seconds since the epoch.

The following variables are available in backend declarations:

backend.host
    Host name or IP address of a backend.

backend.port
    Service name or port number of a backend.

The following variables are available while processing a request:

client.ip
    The client's IP address.

server.ip
    The IP address of the socket on which the client connection was received.

req.request
    The request type (e.g. "GET", "HEAD").

req.url
    The requested URL.

req.proto
    The HTTP protocol version used by the client.

req.backend
    The backend to use to service the request.

req.http.header
    The corresponding HTTP header.

The following variables are available while preparing a backend request (either for a cache miss or for pass or pipe mode):

bereq.request
    The request type (e.g. "GET", "HEAD").

bereq.url
    The requested URL.

bereq.proto
    The HTTP protocol version used to talk to the server.

bereq.http.header
    The corresponding HTTP header.

The following variables are available after the requested object has been retrieved from cache or from the backend:

obj.proto
    The HTTP protocol version used when the object was retrieved.

obj.status
    The HTTP status code returned by the server.

obj.response
    The HTTP status message returned by the server.

obj.valid
    True if the request resulted in a valid HTTP response.

obj.cacheable
    True if the request resulted in a cacheable response. A response is considered cacheable if it is valid (see above), the HTTP status code is 200, 203, 300, 301, 302, 404 or 410 and it has a non-zero time-to-live when Expires and Cache-Control headers are taken into account.

obj.ttl
    The object's remaining time to live, in seconds.

obj.lastuse
    The approximate time elapsed since the object was last requests, in seconds.

The following variables are available while preparing a response to the client:

resp.proto
    The HTTP protocol version to use for the response.

resp.status
    The HTTP status code that will be returned.

resp.response
    The HTTP status message that will be returned.

resp.http.header
    The corresponding HTTP header.

Values may be assigned to variables using the set keyword:

    sub vcl_recv {
        # Normalize the Host: header
        if (req.http.host ~ "^(www.)?example.com$") {
            set req.http.host = "www.example.com";
        }
    }

HTTP headers can be removed entirely using the remove keyword:

    sub vcl_fetch {
        # Don't cache cookies
        remove obj.http.Set-Cookie;
    }

EXAMPLES
The following code is the equivalent of the default configuration with the backend address set to "backend.example.com" and no backend port specified.

    backend default {
        set backend.host = "backend.example.com";
        set backend.port = "http";
    }

    sub vcl_recv {
        if (req.request != "GET" && req.request != "HEAD") {
            pipe;
        }
        if (req.http.Expect) {
            pipe;
        }
        if (req.http.Authenticate || req.http.Cookie) {
            pass;
        }
        lookup;
    }

    sub vcl_pipe {
        pipe;
    }

    sub vcl_pass {
        pass;
    }

    sub vcl_hash {
        set req.hash += req.url;
        set req.hash += req.http.host;
        hash;
    }

    sub vcl_hit {
        if (!obj.cacheable) {
            pass;
        }
        deliver;
    }

    sub vcl_miss {
        fetch;
    }

    sub vcl_fetch {
        if (!obj.valid) {
            error;
        }
        if (!obj.cacheable) {
            pass;
        }
        if (obj.http.Set-Cookie) {
            pass;
        }
        insert;
    }

    sub vcl_deliver {
        deliver;
    }

    sub vcl_timeout {
        discard;
    }

    sub vcl_discard {
        discard;
    }

The following example shows how to support multiple sites running on separate backends in the same Varnish instance, by selecting backends based on the request URL.

    backend www {
        set backend.host = "www.example.com";
        set backend.port = "80";
    }

    backend images {
        set backend.host = "images.example.com";
        set backend.port = "80";
    }

    sub vcl_recv {
        if (req.http.host ~ "^(www.)?example.com$") {
            set req.http.host = "www.example.com";
            set req.backend = www;
        } elsif (req.http.host ~ "^images.example.com$") {
            set req.backend = images;
        } else {
            error 404 "Unknown virtual host";
        }
    }

The following snippet demonstrates how to force a minimum TTL for all documents. Note that this is not the same as setting the default_ttl run-time parameter, as that only affects document for which the backend did not specify a TTL.

    sub vcl_fetch {
        if (obj.ttl < 120s) {
            set obj.ttl = 120s;
        }
    }

The following snippet demonstrates how to force Varnish to cache documents even when cookies are present.

    sub vcl_recv {
        if (req.request == "GET" && req.http.cookie) {
            lookup;
        }
    }

    sub vcl_fetch {
        if (obj.http.Set-Cookie) {
            insert;
        }
    }

The following code implements the HTTP PURGE method as used by Squid for object invalidation:

    acl purge {
            "localhost";
            "10.0.0.1"/8;
    }

    sub vcl_recv {
        if (req.request == "PURGE") {
            if (!client.ip ~ purge) {
                error 405 "Not allowed.";
            }
            lookup;
        }
    }

    sub vcl_hit {
        if (req.request == "PURGE") {
            set obj.ttl = 0s;
            error 200 "Purged.";
        }
    }

    sub vcl_miss {
        if (req.request == "PURGE") {
            error 404 "Not in cache.";
        }
    }

SEE ALSO
varnishd(1)

HISTORY
The VCL language was developed by Poul-Henning Kamp <phk@phk.freebsd.dk> in cooperation with Verdens Gang AS and Linpro AS. This manual page was written by Dag-Erling Smørgrav <des@linpro.no>.