2

I have been following a tutorial on setting up haproxy and varnish. (Link) However, the tutorial was written years ago. I have been trying to change the V3 varnish config and have come across a problem in this part:

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

        return (deliver);
}

The set obj.ttl = 0s; is outdated. It gives this error when starting the service:

Stopping Varnish Cache:                                    [FAILED]
Starting Varnish Cache: Error:

Variable 'obj.ttl' is read only.
At: ('input' Line 46 Pos 21)

Someone said beresp.ttl should be used instead, but it isn't supported in method vcl_hit:

Message from VCC-compiler:
'beresp.ttl': cannot be set in method 'vcl_hit'.
At: ('input' Line 95 Pos 21)
                set beresp.ttl = 0s;

--------------------##########-------

Running VCC-compiler failed, exited with 2
VCL compilation failed

Can anyone suggest a solution for it?

Here's what I have changed so far in the varnish config:

vcl 4.0;
backend apache2_static {
        .host = "127.0.0.1";
        .port = "3001";
        .connect_timeout = 3s;
        .first_byte_timeout = 10s;
        .between_bytes_timeout = 5s;
        .probe = {
                .url = "/haproxycheck";
                .expected_response = 200;
                .timeout = 1s;
                .interval = 3s;
                .window = 2;
                .threshold = 2;
                .initial = 2;
        }
}

acl purge {
        "localhost";
}

sub vcl_recv {
### Default options

        # Health Checking
        if (req.url == "/varnishcheck") {
                return (synth(751, "health check OK!"));
        }

        # Set default backend
        set req.backend_hint = apache2_static;

        # grace period (stale content delivery while revalidating)
        #
        # This is now handled in vcl_hit.
        #
        # set req.grace = 30s;

        # Purge request
        if (req.method == "PURGE") {
                if (!client.ip ~ purge) {
                        return (synth(405, "Not allowed."));
                }
                return (hash);
        }

        # Accept-Encoding header clean-up
        if (req.http.Accept-Encoding) {
                # use gzip when possible, otherwise use deflate
                if (req.http.Accept-Encoding ~ "gzip") {
                        set req.http.Accept-Encoding = "gzip";
                } elsif (req.http.Accept-Encoding ~ "deflate") {
                        set req.http.Accept-Encoding = "deflate";
                } else {
                        # unknown algorithm, remove accept-encoding header
                        unset req.http.Accept-Encoding;
                }

                # Microsoft Internet Explorer 6 is well know to be buggy with compression and css / js
                if (req.url ~ ".(css|js)" && req.http.User-Agent ~ "MSIE 6") {
                        unset req.http.Accept-Encoding;
                }
        }

### Per host/application configuration
        # apache2_static
        # Stale content delivery
        # Cookie ignored in these static pages
        unset req.http.cookie;

### Common options
         # Static objects are first looked up in the cache
        if (req.url ~ "\.(gif|jpg|jpeg|swf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") {
                return (hash);
        }

        # if we arrive here, we look for the object in the cache
        return (hash);
}

sub vcl_hash {
        hash_data(req.url);
        if (req.http.host) {
                hash_data(req.http.host);
        } else {
                hash_data(server.ip);
        }
        return (lookup);
}

sub vcl_hit {
        # Purge
        if (req.method == "PURGE") {
                set obj.ttl = 0s;
                return (synth(200, "Purged."));
        }

        return (deliver);
}

sub vcl_miss {
        # Purge
        if (req.method == "PURGE") {
                return (synth(404, "Not in cache."));
        }

        return (fetch);
}

sub vcl_backend_response {
        # Stale content delivery
        set beresp.grace = 1d;

        # Hide Server information
        unset beresp.http.Server;

        # Store compressed objects in memory
        # They would be uncompressed on the fly by Varnish if the client doesn't support compression
        if (beresp.http.content-type ~ "(text|application)") {
                set beresp.do_gzip = true;
        }

        # remove any cookie on static or pseudo-static objects
        unset beresp.http.set-cookie;

        return (deliver);
}

sub vcl_deliver {
        unset resp.http.via;
        unset resp.http.x-varnish;

        # could be useful to know if the object was in cache or not
        if (obj.hits > 0) {
                set resp.http.X-Cache = "HIT";
        } else {
                set resp.http.X-Cache = "MISS";
        }

        return (deliver);
}

sub vcl_backend_error {
        # Health check
        if (beresp.status == 751) {
                set beresp.status = 200;
                return (deliver);
        }
}

sub vcl_synth {
        # Health check
        if (resp.status == 751) {
                set resp.status = 200;
                return (deliver);
        }
}
RedGiant
  • 4,444
  • 11
  • 59
  • 146
  • 2
    You might want to read https://www.varnish-software.com/book/4.0/chapters/Cache_Invalidation.html#http-purge – Ronald Dec 15 '15 at 07:01
  • Working link as of 2022: https://book.varnish-software.com/4.0/chapters/Cache_Invalidation.html – Nitrodist Jan 31 '22 at 15:59

2 Answers2

4

The "purge part" should only be in vcl_recv and removed from vcl_hit & vcl_miss.

You also have to alter it in vcl_recv.

sub vcl_recv {
### Default options

    # Health Checking
    if (req.url == "/varnishcheck") {
            return (synth(751, "health check OK!"));
    }

    # Set default backend
    set req.backend_hint = apache2_static;

    # grace period (stale content delivery while revalidating)
    #
    # This is now handled in vcl_hit.
    #
    # set req.grace = 30s;

    # Purge request
    if (req.method == "PURGE") {
            if (!client.ip ~ purge) {
                    return (synth(405, "Not allowed."));
            }
            return (purge);
    }

    # Accept-Encoding header clean-up
    if (req.http.Accept-Encoding) {
            # use gzip when possible, otherwise use deflate
            if (req.http.Accept-Encoding ~ "gzip") {
                    set req.http.Accept-Encoding = "gzip";
            } elsif (req.http.Accept-Encoding ~ "deflate") {
                    set req.http.Accept-Encoding = "deflate";
            } else {
                    # unknown algorithm, remove accept-encoding header
                    unset req.http.Accept-Encoding;
            }

            # Microsoft Internet Explorer 6 is well know to be buggy with compression and css / js
            if (req.url ~ ".(css|js)" && req.http.User-Agent ~ "MSIE 6") {
                    unset req.http.Accept-Encoding;
            }
    }

### Per host/application configuration
    # apache2_static
    # Stale content delivery
    # Cookie ignored in these static pages
    unset req.http.cookie;

### Common options
     # Static objects are first looked up in the cache
    if (req.url ~ "\.(gif|jpg|jpeg|swf|css|js|flv|mp3|mp4|pdf|ico|png)(\?.*|)$") {
            return (hash);
    }

    # if we arrive here, we look for the object in the cache
    return (hash);
}

The vcl_hit method

sub vcl_hit {
    return (deliver);
}

The vcl_miss method

sub vcl_miss {
    return (fetch);
}
Jacob Rastad
  • 1,153
  • 10
  • 24
1

vcl_hit() and vcl_miss() are unfortunately no longer on the PURGE code path for Varnish 4. I have always successfully used it with Varnish 3 to report on cache invalidation. I asked the people at Varnish Software why it was removed and they only they said was that it is not accurate because you could have different variants for an obj in the cache. I do not agree with their decision as it would still be useful to verify that the variant you wanted to purge was in fact purged.

In the other answer provided, I would just remove vcl_hit() and vcl_miss() and let the default handler run, since you are not adding any additional conditions.

Ray Jennings
  • 336
  • 2
  • 10