configuration-templates – Blame information for rev 47

Subversion Repositories:
Rev:
Rev Author Line No. Line
2 office 1 vcl 4.0;
16 office 2 ###########################################################################
3 ## Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 ##
4 ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ##
5 ## rights of fair usage, the disclaimer and warranty conditions. ##
6 ###########################################################################
7 ## Derived from the original by Mattias Geniar as a starting template. ##
8 ###########################################################################
2 office 9  
10 import std;
11 import directors;
12  
13 backend server1 { # Define one backend
14 .host = "192.168.0.10"; # IP or Hostname of backend
15 .port = "80"; # Port Apache or whatever is listening
16 .max_connections = 300; # Number of allowed connections
17  
18 .probe = {
19 #.url = "/"; # short easy way (GET /)
20 # We prefer to only do a HEAD /
21 .request =
22 "HEAD / HTTP/1.1"
23 "Host: grimore.org"
24 "Connection: close"
25 "User-Agent: Varnish Health Probe";
26  
27 .interval = 5s; # check the health of each backend every 5 seconds
28 .timeout = 1s; # timing out after 1 second.
29 .window = 5; # If 3 out of the last 5 polls succeeded the backend is considered healthy, otherwise it will be marked as sick
30 .threshold = 3;
31 }
32  
33 .first_byte_timeout = 300s; # How long to wait before we receive a first byte from our backend?
34 .connect_timeout = 5s; # How long to wait for a backend connection?
35 .between_bytes_timeout = 2s; # How long to wait between bytes received from our backend?
36 }
37  
38 acl purge {
39 # ACL we'll use later to allow purges
40 "localhost";
41 "127.0.0.1";
42 /* "::1"; */
43 }
44  
45 /*
46 acl editors {
47 # ACL to honor the "Cache-Control: no-cache" header to force a refresh but only from selected IPs
48 "localhost";
49 "127.0.0.1";
50 "::1";
51 }
52 */
53  
54 sub vcl_init {
55 # Called when VCL is loaded, before any requests pass through it.
56 # Typically used to initialize VMODs.
57  
58 new vdir = directors.round_robin();
59 vdir.add_backend(server1);
60 # vdir.add_backend(server...);
61 # vdir.add_backend(servern);
62 }
63  
64 sub vcl_recv {
47 office 65 ### Conditional routing based on host header requests with subdomain support - split domain.
66 ## Suppose that you have multiple backends (configured at the top of this file) that route to
67 ## diferent backends that also have different websites.
68 ## In that scenario you would want to, say:
69 ## * route example1.tld or www.example1.tld to the server1 (192.168.0.10) backend
70 ## * route example2.tld or www.example2.tld to the server2 (192.168.0.20) backend
71 ##
72 #if (req.http.host ~ "^(.*\.)?example1\.com$") {
73 # set req.backend_hint = server1;
74 # return (hash);
75 #}
76 #if (req.http.host ~ "^(.*\.)?example2\.com$") {
77 # set req.backend_hint = server2;
78 # return (hash);
79 #}
80  
2 office 81 # Called at the beginning of a request, after the complete request has been received and parsed.
82 # Its purpose is to decide whether or not to serve the request, how to do it, and, if applicable,
83 # which backend to use.
84 # also used to modify the request
85  
86 set req.backend_hint = vdir.backend(); # send all traffic to the vdir director
87  
18 office 88 ### Brotli encoding support.
89 if(req.http.Accept-Encoding ~ "br" && req.url !~ "\.(jpg|png|gif|gz|mp3|mov|avi|mpg|mp4|swf|wmf)$") {
90 set req.http.X-brotli = "true";
91 }
92  
2 office 93 # When CloudFlare is in front of varnish, send the real IP address through X-Forwarded-For
94 # otherwise if CloudFlare is not involved, set the X-Forwarded-For to the client IP address.
95 unset req.http.X-Forwarded-For;
96 if (req.http.cf-connecting-ip) {
97 set req.http.X-Forwarded-For = req.http.cf-connecting-ip;
98 } else {
99 set req.http.X-Forwarded-For = client.ip;
100 }
101  
102 # Normalize the header, remove the port (in case you're testing this on various TCP ports)
103 set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
104  
105 # Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
106 unset req.http.proxy;
107  
108 # Normalize the query arguments
109 set req.url = std.querysort(req.url);
110  
111 # Allow purging
112 if (req.method == "PURGE") {
113 if (!client.ip ~ purge) { # purge is the ACL defined at the begining
114 # Not from an allowed IP? Then die with an error.
115 return (synth(405, "This IP is not allowed to send PURGE requests."));
116 }
117 # If you got this stage (and didn't error out above), purge the cached result
118 return (purge);
119 }
120  
121 # Only deal with "normal" types
122 if (req.method != "GET" &&
123 req.method != "HEAD" &&
124 req.method != "PUT" &&
125 req.method != "POST" &&
126 req.method != "TRACE" &&
127 req.method != "OPTIONS" &&
128 req.method != "PATCH" &&
16 office 129 req.method != "DELETE" &&
130 req.method != "PROPFIND" &&
131 req.method != "REPORT") {
2 office 132 /* Non-RFC2616 or CONNECT which is weird. */
133 return (pipe);
134 }
135  
136 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
137 if (req.http.Upgrade ~ "(?i)websocket") {
138 return (pipe);
139 }
140  
141 # Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
142 if (req.method != "GET" && req.method != "HEAD") {
143 return (pass);
144 }
145  
146 # Some generic URL manipulation, useful for all templates that follow
147 # First remove the Google Analytics added parameters, useless for our backend
148 if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
149 set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
150 set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
151 set req.url = regsub(req.url, "\?&", "?");
152 set req.url = regsub(req.url, "\?$", "");
153 }
154  
155 # Strip hash, server doesn't need it.
156 if (req.url ~ "\#") {
157 set req.url = regsub(req.url, "\#.*$", "");
158 }
159  
160 # Strip a trailing ? if it exists
161 if (req.url ~ "\?$") {
162 set req.url = regsub(req.url, "\?$", "");
163 }
164  
165 # Some generic cookie manipulation, useful for all templates that follow
166 # Remove the "has_js" cookie
167 set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
168  
16 office 169 # Remove any CloudFlare cookies
170 set req.http.Cookie = regsuball(req.http.Cookie, "cf_.=[^;]+(; )?", "");
171  
2 office 172 # Remove any Google Analytics based cookies
173 set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
174 set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
175 set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
176 set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
177 set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
178 set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
179  
180 # Remove DoubleClick offensive cookies
181 set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
182  
183 # Remove the Quant Capital cookies (added by some plugin, all __qca)
184 set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
185  
186 # Remove the AddThis cookies
187 set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
188  
189 # Remove a ";" prefix in the cookie if present
190 set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");
191  
192 # Are there cookies left with only spaces or that are empty?
193 if (req.http.cookie ~ "^\s*$") {
194 unset req.http.cookie;
195 }
196  
197 if (req.http.Cache-Control ~ "(?i)no-cache") {
198 #if (req.http.Cache-Control ~ "(?i)no-cache" && client.ip ~ editors) { # create the acl editors if you want to restrict the Ctrl-F5
199 # http://varnish.projects.linpro.no/wiki/VCLExampleEnableForceRefresh
200 # Ignore requests via proxy caches and badly behaved crawlers
201 # like msnbot that send no-cache with every request.
202 if (! (req.http.Via || req.http.User-Agent ~ "(?i)bot" || req.http.X-Purge)) {
203 #set req.hash_always_miss = true; # Doesn't seems to refresh the object in the cache
204 return(purge); # Couple this with restart in vcl_purge and X-Purge header to avoid loops
205 }
206 }
207  
208 # Large static files are delivered directly to the end-user without
209 # waiting for Varnish to fully read the file first.
210 # Varnish 4 fully supports Streaming, so set do_stream in vcl_backend_response()
211 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)(\?.*)?$") {
212 unset req.http.Cookie;
213 return (hash);
214 }
215  
216 # Remove all cookies for static files
217 # 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.
218 # Sure, there's disk I/O, but chances are your OS will already have these files in their buffers (thus memory).
219 # Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
16 office 220 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)(\?.*)?$") {
221 unset req.http.Cookie;
222 return (hash);
223 }
2 office 224  
225 # Send Surrogate-Capability headers to announce ESI support to backend
226 set req.http.Surrogate-Capability = "key=ESI/1.0";
227  
228 if (req.http.Authorization) {
229 # Not cacheable by default
230 return (pass);
231 }
232  
233 return (hash);
234 }
235  
236  
237 sub vcl_pipe {
238 # Called upon entering pipe mode.
239 # In this mode, the request is passed on to the backend, and any further data from both the client
240 # and backend is passed on unaltered until either end closes the connection. Basically, Varnish will
241 # degrade into a simple TCP proxy, shuffling bytes back and forth. For a connection in pipe mode,
242 # no other VCL subroutine will ever get called after vcl_pipe.
243  
20 office 244 ## Note that only the first request to the backend will have
245 ## X-Forwarded-For set. If you use X-Forwarded-For and want to
246 ## have it set for all requests, make sure to have:
247 ## set bereq.http.connection = "close";
248 ## here. It is not set by default as it might break some broken web
249 ## applications, like IIS with NTLM authentication.
2 office 250 # set bereq.http.Connection = "Close";
251  
252 # Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html)
253 if (req.http.upgrade) {
254 set bereq.http.upgrade = req.http.upgrade;
255 }
256  
257 return (pipe);
258 }
259  
260 sub vcl_pass {
261 # Called upon entering pass mode. In this mode, the request is passed on to the backend, and the
262 # backend's response is passed on to the client, but is not entered into the cache. Subsequent
263 # requests submitted over the same client connection are handled normally.
264  
265 # return (pass);
266 }
267  
268 # The data on which the hashing will take place
269 sub vcl_hash {
270 # Called after vcl_recv to create a hash value for the request. This is used as a key
271 # to look up the object in Varnish.
272  
273 hash_data(req.url);
274  
275 if (req.http.host) {
276 hash_data(req.http.host);
277 } else {
278 hash_data(server.ip);
279 }
280  
281 # hash cookies for requests that have them
282 if (req.http.Cookie) {
283 hash_data(req.http.Cookie);
284 }
18 office 285  
286 ### Brotli encoding support.
287 if(req.http.X-brotli == "true") {
288 hash_data("brotli");
289 }
2 office 290 }
291  
292 sub vcl_hit {
293 # Called when a cache lookup is successful.
294  
295 if (obj.ttl >= 0s) {
296 # A pure unadultered hit, deliver it
297 return (deliver);
298 }
299  
300 # https://www.varnish-cache.org/docs/trunk/users-guide/vcl-grace.html
301 # 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.
302 # 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.
303 # if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) {
304 # return (deliver);
305 # } else {
306 # return (fetch);
307 # }
308  
309 # We have no fresh fish. Lets look at the stale ones.
310 if (std.healthy(req.backend_hint)) {
311 # Backend is healthy. Limit age to 10s.
312 if (obj.ttl + 10s > 0s) {
313 #set req.http.grace = "normal(limited)";
314 return (deliver);
315 } else {
316 # No candidate for grace. Fetch a fresh object.
317 return(fetch);
318 }
319 } else {
320 # backend is sick - use full grace
321 if (obj.ttl + obj.grace > 0s) {
322 #set req.http.grace = "full";
323 return (deliver);
324 } else {
325 # no graced object.
326 return (fetch);
327 }
328 }
329  
330 # fetch & deliver once we get the result
331 return (fetch); # Dead code, keep as a safeguard
332 }
333  
334 sub vcl_miss {
335 # Called after a cache lookup if the requested document was not found in the cache. Its purpose
336 # is to decide whether or not to attempt to retrieve the document from the backend, and which
337 # backend to use.
338  
339 return (fetch);
340 }
341  
342 # Handle the HTTP request coming from our backend
343 sub vcl_backend_response {
344 # Called after the response headers has been successfully retrieved from the backend.
345  
346 # Pause ESI request and remove Surrogate-Control header
347 if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
348 unset beresp.http.Surrogate-Control;
349 set beresp.do_esi = true;
17 office 350 set beresp.ttl = 24h; # Set 24h ESI
2 office 351 }
18 office 352  
353 ### Brotli encoding support.
354 if(bereq.http.X-brotli == "true") {
355 set bereq.http.Accept-Encoding = "br";
356 unset bereq.http.X-brotli;
357 }
2 office 358  
16 office 359 ### Set content expiration.
360 ## You may want to disable any expiration on the backend (ie: for Apache, disable mod_expires).
361 # 1 Year
362 if(beresp.http.content-type ~ "(?i)(application/(javascript|x\-javascript))|(text/(javascript|css))|(application/(atom\+xml|rdf\+xml|rss\+xml))") {
363 set beresp.http.Expires = "" + (now + 1y);
364 }
365 # 1 Month
366 if(beresp.http.content-type ~ "(?i)(application/(vnd\.ms\-fontobject|font\-woff|x\-font\-(ttf|woff)))|(audio/ogg)|(font/(eot|opentype|woff))|(image/(bmp|gif|jp2|jpeg|png|svg\+xmlwebp))|(video/(mp4|ogg|webm))") {
367 set beresp.http.Expires = "" + (now + 24w);
368 }
369 # 1 Week
370 if(beresp.http.content-type ~ "(?i)(image/(vnd\.microsoft\.icon|x\-icon))|(application/manifest\+json)|(text/x\-cross\-domain\-policy)") {
371 set beresp.http.Expires = "" + (now + 1w);
372 }
373 # Immediately
19 office 374 # Not exactly "immediately" since we do not want to have to recache on fast reloads - ideally, set this to average page load time.
16 office 375 if(beresp.http.content-type ~ "(?i)(application/(json|ld\+json|schema\+json|vnd\.geo\+jsonxml|x\-web\-app\-manifest\+json))|(text/(xml|cache\-manifest|html))") {
376 set beresp.http.Expires = "" + (now + 3s);
377 }
378  
379 ### GZip content if not already compressed.
380 ## You may want to disable any compression on the backend (ie: for Apache, disable mod_deflate).
381 if(beresp.http.content-type ~ "(?i)(application/(atom\+xml|javascript|json|ld\+json|manifest\+json|rdf\+xml|rss\+xml|schema\+json|vnd\.geo\+json|vnd\.ms\-fontobject|x\-(font\-ttf|javascript|web\-app\-manifest\+json)|xhtml\+xml|xml)|font/(eot|opentype))|(image/(bmp|svg\+xml|vnd\.microsoft\.icon|x\-icon))|(text/(cache\-manifest|css|html|javascript|plain|vcard|vnd\.rim\.location\.xloc|vcalendar|vtt|x\-component|x\-cross\-domain\-policy|xml))") {
382 # Compress object for sending.
383 set beresp.do_gzip = true;
384 }
385  
386 ### Enable cache for all static files
387 ## 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.
388 ## Before you blindly enable this, have a read here: https://ma.ttias.be/stop-caching-static-files/
389 if(beresp.http.content-type ~ "(?i)(application/(java\-vm|javascript|json|msword|pdf|postscript|rtf|vnd\.ms\-(excel|fontobject|powerpoint)|vnd\.oasis\.opendocument\.text|vnd\.openxmlformats\-officedocument\.(presentationml\.presentation|spreadsheetml\.sheet|wordprocessingml\.document)|x\-(7z\-compressed|bzip2|gzip|rar\-compressed|shockwave\-flash|tar)|x\-font\-(bdf|ghostscript|linux\-psf|otf|pcf|snf|ttf|type1|woff)|xz|xml|zip))|(audio/((mpeg|ogg)|(x\-(flac|matroska|ms\-wma|wav))))|(image/((bmp|gif|jp2|jpeg|png|svg\+xml|vnd\.wap\.wbmp|webp|x\-(icon|pict))))|(text/((css|csv|javascript|plain)))|(video/((mp4|quicktime|webm|x\-(flv|matroska|ms\-wmv|msvideo))))") {
2 office 390 unset beresp.http.set-cookie;
391 }
392  
393 # Large static files are delivered directly to the end-user without
394 # waiting for Varnish to fully read the file first.
395 # Varnish 4 fully supports Streaming, so use streaming here to avoid locking.
16 office 396 if (bereq.url ~ "^[^?]*\.(7z|ace|avi|bin|bz2|flac|flv|gz|iso|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|wma|wmv|xz|zip)(\?.*)?$") {
2 office 397 unset beresp.http.set-cookie;
398 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
399 }
400  
401 # Sometimes, a 301 or 302 redirect formed via Apache's mod_rewrite can mess with the HTTP port that is being passed along.
402 # This often happens with simple rewrite rules in a scenario where Varnish runs on :80 and Apache on :8080 on the same box.
403 # A redirect can then often redirect the end-user to a URL on :8080, where it should be :80.
404 # This may need finetuning on your setup.
405 #
406 # To prevent accidental replace, we only filter the 301/302 redirects for now.
407 if (beresp.status == 301 || beresp.status == 302) {
408 set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", "");
409 }
410  
411 # Set 2min cache if unset for static files
412 if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
413 set beresp.ttl = 120s; # Important, you shouldn't rely on this, SET YOUR HEADERS in the backend
414 set beresp.uncacheable = true;
415 return (deliver);
416 }
417  
418 # Don't cache 50x responses
419 if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
420 return (abandon);
421 }
422  
423 # Allow stale content, in case the backend goes down.
424 # make Varnish keep all objects for 6 hours beyond their TTL
425 set beresp.grace = 6h;
426  
427 return (deliver);
428 }
429  
430 # The routine when we deliver the HTTP request to the user
431 # Last chance to modify headers that are sent to the client
432 sub vcl_deliver {
433 # Called before a cached object is delivered to the client.
434  
435 if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
436 set resp.http.X-Cache = "HIT";
437 } else {
438 set resp.http.X-Cache = "MISS";
439 }
440  
441 # Please note that obj.hits behaviour changed in 4.0, now it counts per objecthead, not per object
442 # and obj.hits may not be reset in some cases where bans are in use. See bug 1492 for details.
443 # So take hits with a grain of salt
444 set resp.http.X-Cache-Hits = obj.hits;
445  
18 office 446 ###
447 ## Remove some headers: PHP version
2 office 448 unset resp.http.X-Powered-By;
18 office 449 ## Remove some headers: Apache version & OS
2 office 450 unset resp.http.Server;
451 unset resp.http.X-Drupal-Cache;
452 unset resp.http.X-Varnish;
453 unset resp.http.Via;
454 unset resp.http.Link;
455 unset resp.http.X-Generator;
18 office 456 unset resp.http.X-Powered-By;
2 office 457  
458 return (deliver);
459 }
460  
461 sub vcl_purge {
462 # Only handle actual PURGE HTTP methods, everything else is discarded
463 if (req.method != "PURGE") {
464 # restart request
465 set req.http.X-Purge = "Yes";
466 return(restart);
467 }
468 }
469  
470 sub vcl_synth {
471 if (resp.status == 720) {
472 # We use this special error status 720 to force redirects with 301 (permanent) redirects
473 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
474 set resp.http.Location = resp.reason;
475 set resp.status = 301;
476 return (deliver);
477 } elseif (resp.status == 721) {
478 # And we use error status 721 to force redirects with a 302 (temporary) redirect
479 # To use this, call the following from anywhere in vcl_recv: return (synth(720, "http://host/new.html"));
480 set resp.http.Location = resp.reason;
481 set resp.status = 302;
482 return (deliver);
483 }
484  
485 return (deliver);
486 }
487  
488  
489 sub vcl_fini {
490 # Called when VCL is discarded only after all requests have exited the VCL.
491 # Typically used to clean up VMODs.
492  
493 return (ok);
494 }
495  
496 sub vcl_backend_error {
497 # Called when the backend cannot be reached.
498 # Display an HTML file located at /etc/varnish/500.html
499 set beresp.http.Content-Type = "text/html; charset=utf-8";
500 synthetic(std.fileread("/etc/varnish/500.html"));
501 return (deliver);
502 }