title: Upgrading varnish config. obj.ttl and beresp.ttl in vcl_hit aren't working
body: <p>I have been following a tutorial on setting up haproxy and varnish.  (<a href="http://blog.haproxy.com/2012/08/25/haproxy-varnish-and-the-single-hostname-website/" rel="nofollow">Link</a>) 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:</p>
  
  <pre><code>sub vcl_hit {
          # Purge
          if (req.request == "PURGE") {
                  set obj.ttl = 0s;
                  error 200 "Purged.";
          }
  
          return (deliver);
  }
  </code></pre>
  
  <p>The <code>set obj.ttl = 0s;</code> is outdated. It gives this error when starting the service:</p>
  
  <pre><code>Stopping Varnish Cache:                                    [FAILED]
  Starting Varnish Cache: Error:
  
  Variable 'obj.ttl' is read only.
  At: ('input' Line 46 Pos 21)
  </code></pre>
  
  <p>Someone said <code>beresp.ttl</code> should be used instead, but it isn't supported in method <code>vcl_hit</code>:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Can anyone suggest a solution for it?</p>
  
  <p>Here's what I have changed so far in the varnish config:</p>
  
  <pre><code>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)" &amp;&amp; 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 &gt; 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);
          }
  }
  </code></pre>