configuration-templates – Blame information for rev 2

Subversion Repositories:
Rev:
Rev Author Line No. Line
2 office 1 vcl 4.0;
2 # Optimized Varnish VCL for load balancing and caching.
3 # original: https://github.com/mattiasgeniar/varnish-4.0-configuration-templates/blob/master/default.vcl
4 # modified: Wizardry and Steamworks (http://grimore.org)
5  
6 import std;
7 import directors;
8  
9 backend server1 { # Define one backend
10 .host = "192.168.0.10"; # IP or Hostname of backend
11 .port = "80"; # Port Apache or whatever is listening
12 .max_connections = 300; # Number of allowed connections
13  
14 .probe = {
15 #.url = "/"; # short easy way (GET /)
16 # We prefer to only do a HEAD /
17 .request =
18 "HEAD / HTTP/1.1"
19 "Host: grimore.org"
20 "Connection: close"
21 "User-Agent: Varnish Health Probe";
22  
23 .interval = 5s; # check the health of each backend every 5 seconds
24 .timeout = 1s; # timing out after 1 second.
25 .window = 5; # If 3 out of the last 5 polls succeeded the backend is considered healthy, otherwise it will be marked as sick
26 .threshold = 3;
27 }
28  
29 .first_byte_timeout = 300s; # How long to wait before we receive a first byte from our backend?
30 .connect_timeout = 5s; # How long to wait for a backend connection?
31 .between_bytes_timeout = 2s; # How long to wait between bytes received from our backend?
32 }
33  
34 acl purge {
35 # ACL we'll use later to allow purges
36 "localhost";
37 "127.0.0.1";
38 /* "::1"; */
39 }
40  
41 /*
42 acl editors {
43 # ACL to honor the "Cache-Control: no-cache" header to force a refresh but only from selected IPs
44 "localhost";
45 "127.0.0.1";
46 "::1";
47 }
48 */
49  
50 sub vcl_init {
51 # Called when VCL is loaded, before any requests pass through it.
52 # Typically used to initialize VMODs.
53  
54 new vdir = directors.round_robin();
55 vdir.add_backend(server1);
56 # vdir.add_backend(server...);
57 # vdir.add_backend(servern);
58 }
59  
60 sub vcl_recv {
61 # Called at the beginning of a request, after the complete request has been received and parsed.
62 # Its purpose is to decide whether or not to serve the request, how to do it, and, if applicable,
63 # which backend to use.
64 # also used to modify the request
65  
66 set req.backend_hint = vdir.backend(); # send all traffic to the vdir director
67  
68 # When CloudFlare is in front of varnish, send the real IP address through X-Forwarded-For
69 # otherwise if CloudFlare is not involved, set the X-Forwarded-For to the client IP address.
70 unset req.http.X-Forwarded-For;
71 if (req.http.cf-connecting-ip) {
72 set req.http.X-Forwarded-For = req.http.cf-connecting-ip;
73 } else {
74 set req.http.X-Forwarded-For = client.ip;
75 }
76  
77 # Normalize the header, remove the port (in case you're testing this on various TCP ports)
78 set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
79  
80 # Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
81 unset req.http.proxy;
82  
83 # Normalize the query arguments
84 set req.url = std.querysort(req.url);
85  
86 # Allow purging
87 if (req.method == "PURGE") {
88 if (!client.ip ~ purge) { # purge is the ACL defined at the begining
89 # Not from an allowed IP? Then die with an error.
90 return (synth(405, "This IP is not allowed to send PURGE requests."));
91 }
92 # If you got this stage (and didn't error out above), purge the cached result
93 return (purge);
94 }
95  
96 # Only deal with "normal" types
97 if (req.method != "GET" &&
98 req.method != "HEAD" &&
99 req.method != "PUT" &&
100 req.method != "POST" &&
101 req.method != "TRACE" &&
102 req.method != "OPTIONS" &&
103 req.method != "PATCH" &&
104 req.method != "DELETE") {
105 /* Non-RFC2616 or CONNECT which is weird. */
106 return (pipe);
107 }
108  
109 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
110 if (req.http.Upgrade ~ "(?i)websocket") {
111 return (pipe);
112 }
113  
114 # Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
115 if (req.method != "GET" && req.method != "HEAD") {
116 return (pass);
117 }
118  
119 # Some generic URL manipulation, useful for all templates that follow
120 # First remove the Google Analytics added parameters, useless for our backend
121 if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
122 set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
123 set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
124 set req.url = regsub(req.url, "\?&", "?");
125 set req.url = regsub(req.url, "\?$", "");
126 }
127  
128 # Strip hash, server doesn't need it.
129 if (req.url ~ "\#") {
130 set req.url = regsub(req.url, "\#.*$", "");
131 }
132  
133 # Strip a trailing ? if it exists
134 if (req.url ~ "\?$") {
135 set req.url = regsub(req.url, "\?$", "");
136 }
137  
138 # Some generic cookie manipulation, useful for all templates that follow
139 # Remove the "has_js" cookie
140 set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
141  
142 # Remove any Google Analytics based cookies
143 set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
144 set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
145 set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
146 set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
147 set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
148 set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
149  
150 # Remove DoubleClick offensive cookies
151 set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
152  
153 # Remove the Quant Capital cookies (added by some plugin, all __qca)
154 set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
155  
156 # Remove the AddThis cookies
157 set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
158  
159 # Remove a ";" prefix in the cookie if present
160 set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");
161  
162 # Are there cookies left with only spaces or that are empty?
163 if (req.http.cookie ~ "^\s*$") {
164 unset req.http.cookie;
165 }
166  
167 if (req.http.Cache-Control ~ "(?i)no-cache") {
168 #if (req.http.Cache-Control ~ "(?i)no-cache" && client.ip ~ editors) { # create the acl editors if you want to restrict the Ctrl-F5
169 # http://varnish.projects.linpro.no/wiki/VCLExampleEnableForceRefresh
170 # Ignore requests via proxy caches and badly behaved crawlers
171 # like msnbot that send no-cache with every request.
172 if (! (req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) {
173 #set req.hash_always_miss = true; # Doesn't seems to refresh the object in the cache
174 return(purge); # Couple this with restart in vcl_purge and X-Purge header to avoid loops
175 }
176 }
177  
178 # Large static files are delivered directly to the end-user without
179 # waiting for Varnish to fully read the file first.
180 # Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response()
181 if (req.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
182 unset req.http.Cookie;
183 return (hash);
184 }
185  
186 # Remove all cookies for static files
187 # A valid discussion could be held on this line: do you really need to cache static files that don't cause load? Only if you have memory left.
188 # Sure, there's disk I/O, but chances are your OS will already have these files in their buffers (thus memory).
189 # Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
190 # if (req.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
191 # unset req.http.Cookie;
192 # return (hash);
193 # }
194  
195 # Send Surrogate-Capability headers to announce ESI support to backend
196 set req.http.Surrogate-Capability = "key=ESI/1.0";
197  
198 if (req.http.Authorization) {
199 # Not cacheable by default
200 return (pass);
201 }
202  
203 return (hash);
204 }
205  
206  
207 sub vcl_pipe {
208 # Called upon entering pipe mode.
209 # In this mode, the request is passed on to the backend, and any further data from both the client
210 # and backend is passed on unaltered until either end closes the connection. Basically, Varnish will
211 # degrade into a simple TCP proxy, shuffling bytes back and forth. For a connection in pipe mode,
212 # no other VCL subroutine will ever get called after vcl_pipe.
213  
214 # Note that only the first request to the backend will have
215 # X-Forwarded-For set. If you use X-Forwarded-For and want to
216 # have it set for all requests, make sure to have:
217 # set bereq.http.connection = "close";
218 # here. It is not set by default as it might break some broken web
219 # applications, like IIS with NTLM authentication.
220  
221 # set bereq.http.Connection = "Close";
222  
223 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
224 if (req.http.upgrade) {
225 set bereq.http.upgrade = req.http.upgrade;
226 }
227  
228 return (pipe);
229 }
230  
231 sub vcl_pass {
232 # Called upon entering pass mode. In this mode, the request is passed on to the backend, and the
233 # backend's response is passed on to the client, but is not entered into the cache. Subsequent
234 # requests submitted over the same client connection are handled normally.
235  
236 # return (pass);
237 }
238  
239 # The data on which the hashing will take place
240 sub vcl_hash {
241 # Called after vcl_recv to create a hash value for the request. This is used as a key
242 # to look up the object in Varnish.
243  
244 hash_data(req.url);
245  
246 if (req.http.host) {
247 hash_data(req.http.host);
248 } else {
249 hash_data(server.ip);
250 }
251  
252 # hash cookies for requests that have them
253 if (req.http.Cookie) {
254 hash_data(req.http.Cookie);
255 }
256 }
257  
258 sub vcl_hit {
259 # Called when a cache lookup is successful.
260  
261 if (obj.ttl >= 0s) {
262 # A pure unadultered hit, deliver it
263 return (deliver);
264 }
265  
266 # https://www.varnish-cache.org/docs/trunk/users-guide/vcl-grace.html
267 # When several clients are requesting the same page Varnish will send one request to the backend and place the others on hold while fetching one copy from the backend. In some products this is called request coalescing and Varnish does this automatically.
268 # If you are serving thousands of hits per second the queue of waiting requests can get huge. There are two potential problems - one is a thundering herd problem - suddenly releasing a thousand threads to serve content might send the load sky high. Secondly - nobody likes to wait. To deal with this we can instruct Varnish to keep the objects in cache beyond their TTL and to serve the waiting requests somewhat stale content.
269  
270 # if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) {
271 # return (deliver);
272 # } else {
273 # return (fetch);
274 # }
275  
276 # We have no fresh fish. Lets look at the stale ones.
277 if (std.healthy(req.backend_hint)) {
278 # Backend is healthy. Limit age to 10s.
279 if (obj.ttl + 10s > 0s) {
280 #set req.http.grace = "normal(limited)";
281 return (deliver);
282 } else {
283 # No candidate for grace. Fetch a fresh object.
284 return(fetch);
285 }
286 } else {
287 # backend is sick - use full grace
288 if (obj.ttl + obj.grace > 0s) {
289 #set req.http.grace = "full";
290 return (deliver);
291 } else {
292 # no graced object.
293 return (fetch);
294 }
295 }
296  
297 # fetch & deliver once we get the result
298 return (fetch); # Dead code, keep as a safeguard
299 }
300  
301 sub vcl_miss {
302 # Called after a cache lookup if the requested document was not found in the cache. Its purpose
303 # is to decide whether or not to attempt to retrieve the document from the backend, and which
304 # backend to use.
305  
306 return (fetch);
307 }
308  
309 # Handle the HTTP request coming from our backend
310 sub vcl_backend_response {
311 # Called after the response headers has been successfully retrieved from the backend.
312  
313 # Pause ESI request and remove Surrogate-Control header
314 if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
315 unset beresp.http.Surrogate-Control;
316 set beresp.do_esi = true;
317 }
318  
319 # Enable cache for all static files
320 # The same argument as the static caches from above: monitor your cache size, if you get data nuked out of it, consider giving up the static file cache.
321 # Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
322 if (bereq.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
323 unset beresp.http.set-cookie;
324 }
325  
326 # Large static files are delivered directly to the end-user without
327 # waiting for Varnish to fully read the file first.
328 # Varnish 4 fully supports Streaming, so use streaming here to avoid locking.
329 if (bereq.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
330 unset beresp.http.set-cookie;
331 set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects
332 }
333  
334 # Sometimes, a 301 or 302 redirect formed via Apache's mod_rewrite can mess with the HTTP port that is being passed along.
335 # This often happens with simple rewrite rules in a scenario where Varnish runs on :80 and Apache on :8080 on the same box.
336 # A redirect can then often redirect the end-user to a URL on :8080, where it should be :80.
337 # This may need finetuning on your setup.
338 #
339 # To prevent accidental replace, we only filter the 301/302 redirects for now.
340 if (beresp.status == 301 || beresp.status == 302) {
341 set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", "");
342 }
343  
344 # Set 2min cache if unset for static files
345 if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
346 set beresp.ttl = 120s; # Important, you shouldn't rely on this, SET YOUR HEADERS in the backend
347 set beresp.uncacheable = true;
348 return (deliver);
349 }
350  
351 # Don't cache 50x responses
352 if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
353 return (abandon);
354 }
355  
356 # Allow stale content, in case the backend goes down.
357 # make Varnish keep all objects for 6 hours beyond their TTL
358 set beresp.grace = 6h;
359  
360 return (deliver);
361 }
362  
363 # The routine when we deliver the HTTP request to the user
364 # Last chance to modify headers that are sent to the client
365 sub vcl_deliver {
366 # Called before a cached object is delivered to the client.
367  
368 if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
369 set resp.http.X-Cache = "HIT";
370 } else {
371 set resp.http.X-Cache = "MISS";
372 }
373  
374 # Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object
375 # and obj.hits may not be reset in some cases where bans are in use. See bug 1492 for details.
376 # So take hits with a grain of salt
377 set resp.http.X-Cache-Hits = obj.hits;
378  
379 # Remove some headers: PHP version
380 unset resp.http.X-Powered-By;
381  
382 # Remove some headers: Apache version & OS
383 unset resp.http.Server;
384 unset resp.http.X-Drupal-Cache;
385 unset resp.http.X-Varnish;
386 unset resp.http.Via;
387 unset resp.http.Link;
388 unset resp.http.X-Generator;
389  
390 return (deliver);
391 }
392  
393 sub vcl_purge {
394 # Only handle actual PURGE HTTP methods, everything else is discarded
395 if (req.method != "PURGE") {
396 # restart request
397 set req.http.X-Purge = "Yes";
398 return(restart);
399 }
400 }
401  
402 sub vcl_synth {
403 if (resp.status == 720) {
404 # We use this special error status 720 to force redirects with 301 (permanent) redirects
405 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
406 set resp.http.Location = resp.reason;
407 set resp.status = 301;
408 return (deliver);
409 } elseif (resp.status == 721) {
410 # And we use error status 721 to force redirects with a 302 (temporary) redirect
411 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
412 set resp.http.Location = resp.reason;
413 set resp.status = 302;
414 return (deliver);
415 }
416  
417 return (deliver);
418 }
419  
420  
421 sub vcl_fini {
422 # Called when VCL is discarded only after all requests have exited the VCL.
423 # Typically used to clean up VMODs.
424  
425 return (ok);
426 }
427  
428 sub vcl_backend_error {
429 # Called when the backend cannot be reached.
430 # Display an HTML file located at /etc/varnish/500.html
431 set beresp.http.Content-Type = "text/html; charset=utf-8";
432 synthetic(std.fileread("/etc/varnish/500.html"));
433 return (deliver);
434 }