Hero Image

Varnish VCL Configuration on Arch Linux

Varnish VCL Configuration on Arch Linux

Complete example VCL with common patterns

vcl 4.1;

import std;

# Backend servers
backend web1 {
    .host = "192.168.1.10";
    .port = "8080";
    .probe = {
        .url = "/health";
        .timeout = 5s;
        .interval = 10s;
        .window = 5;
        .threshold = 3;
    }
}

backend web2 {
    .host = "192.168.1.11";
    .port = "8080";
    .probe = {
        .url = "/health";
        .timeout = 5s;
        .interval = 10s;
    }
}

# Load balancing director
sub vcl_init {
    new lb = directors.round_robin();
    lb.add_backend(web1);
    lb.add_backend(web2);
}

sub vcl_recv {
    # Use load balancer
    set req.backend_hint = lb.backend();

    # Normalize Accept-Encoding
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
            unset req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "br") {
            set req.http.Accept-Encoding = "br";
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } else {
            unset req.http.Accept-Encoding;
        }
    }

    # Don't cache POST/PUT/DELETE
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    # Don't cache authenticated requests
    if (req.http.Authorization) {
        return (pass);
    }

    # Strip session cookies for static files
    if (req.url ~ "\.(css|js|png|jpg|gif|ico|svg|woff2?)$") {
        unset req.http.Cookie;
        return (hash);
    }
}

sub vcl_hash {
    hash_data(req.url);
    hash_data(req.http.host);
}

sub vcl_backend_response {
    # Grace: serve stale if backend is slow
    set beresp.grace = 30s;

    # Cache static files
    if (bereq.url ~ "\.(css|js|png|jpg|gif|ico|woff2?)$") {
        unset beresp.http.Set-Cookie;
        set beresp.ttl = 7d;
    }

    # Don't cache server errors
    if (beresp.status >= 500) {
        set beresp.ttl = 0s;
        set beresp.uncacheable = true;
        return (deliver);
    }
}

sub vcl_deliver {
    # Add cache hit/miss header for debugging
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
        set resp.http.X-Cache-Hits = obj.hits;
    } else {
        set resp.http.X-Cache = "MISS";
    }
    unset resp.http.X-Varnish;
    unset resp.http.Via;
}

Purge cached objects

varnishadm "ban req.http.host == example.com && req.url ~ /blog"
# Or with HTTP PURGE method (add to vcl_recv):
if (req.method == "PURGE") {
    if (!client.ip ~ purge_acl) {
        return (synth(405, "Not allowed"));
    }
    return (purge);
}