diff options
author | Kristian Lyngstol <kly@kly.no> | 2019-02-04 21:12:50 +0100 |
---|---|---|
committer | Kristian Lyngstol <kly@kly.no> | 2019-02-04 21:12:50 +0100 |
commit | 27929d995bad0b9123aec4773a3801587a2f671d (patch) | |
tree | 2cda4e52660cfd7def396f5150d9db6ca7b7e60e /extras | |
parent | 68d31e02b28487cb5dd552c68efd10b4973f4169 (diff) |
VCL/Varnish: Rewrite/order varnish VCL
Diffstat (limited to 'extras')
-rw-r--r-- | extras/misc/varnish.vcl | 169 |
1 files changed, 126 insertions, 43 deletions
diff --git a/extras/misc/varnish.vcl b/extras/misc/varnish.vcl index 271211b..c47c3e6 100644 --- a/extras/misc/varnish.vcl +++ b/extras/misc/varnish.vcl @@ -1,37 +1,96 @@ # vim: ts=8:expandtab:sw=4:softtabstop=4 +# VCL for Gondul - also requires auth.vcl (see further down) +# Also uses hitch and acmetool for ssl vcl 4.0; -include "/opt/gondul/data/varnish-auth.vcl"; +import std; +# API - apache backend default { - .host = "gondul-front"; - .port = "80"; + .host = "::1"; + .port = "8080"; } -backend graphite { - .host = "gondul-graphite"; - .port = "80"; - .first_byte_timeout = 3s; - .between_bytes_timeout = 3s; - .connect_timeout = 1s; - .max_connections = 20; +# Templating engine +backend templating { + .host = "::1"; + .port = "8081"; } -backend templating { - .host = "gondul-templating"; - .port = "8080"; +# Definitely not influx +backend influx { + .host = "::1"; + .port = "8086"; } -backend grafana { - .host = "gondul-grafana"; - .port = "3000"; +# For certbot +# WTF... isn't this apache? Apparently acmetool listens on port 402 +backend acmetool { + .host = "::1"; + .port = "402"; } +# White-list localhost - PLEASE make sure this is actually smart +acl white { + "::1"; + "127.0.0.0"/8; + #"172.16.0.0"/12; + #"192.168.0.0"/16; + #"10.0.0.0"/8; +} + +# vcl_recv is "prep-processing of requests sub vcl_recv { + # Handle certbot by passing /.well-known to acmetool + if (req.url ~ "^/.well-known/acme-challenge/") { + set req.backend_hint = acmetool; + return(pass); + } + + # Redirect to https - note that this does NOT happen for + # "whitelisted" stuff - e.g., templating engine. + if (std.port(local.ip) == 80 && client.ip !~ white) { + set req.http.x-redir = "https://" + req.http.host + req.url; + return(synth(301)); + } + + # Basic authentication .... + # We include the following from /etc/varnish/auth.vcl, to keep passwords + # out of default vcl: + # req.http.Authorization != "Basic AAAA" + # + # where AAAA is the result of: + # echo -n user:password | base64. + # Example: + # kly@jade:~$ echo -n tech:rules | base64 + # dGVjaDpydWxlcw== + # # cat /etc/varnish/auth.vcl + # req.http.Authorization != "Basic dGVjaDpydWxlcw==" + if (client.ip !~ white && + include "/etc/varnish/auth.vcl";) { + return(synth(401)); + } else { + unset req.http.Authorization; + set req.http.X-Webauth-User = "admin"; + } + + if (req.url ~ "^/api/templates") { + set req.url = regsub(req.url,"^/api/templates",""); + set req.backend_hint = templating; + } + + if (req.url ~ "^/query") { + set req.backend_hint = influx; + } + + # More human-typable URL if (req.url ~ "^/where" || req.url ~ "^/location") { - set req.url = "/api/public/location"; + set req.url = "/api/public/location"; } + + # Fairly standard filtering. Default VCL will do "pipe", which is + # pointless for us. if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && @@ -43,60 +102,84 @@ sub vcl_recv { return (synth(418,"LOLOLOL")); } - if (req.url ~ "^/render" || req.url ~ "^/metric") { - set req.backend_hint = graphite; - } - if (req.url ~ "^/grafana") { - set req.url = regsub(req.url, "^/grafana",""); - set req.backend_hint = grafana; - return (pass); - } - if (req.url ~ "^/api/templates") { - set req.url = regsub(req.url, "/api/templates", ""); - set req.backend_hint = templating; - } - + # We can only cache GET/HEAD requests. if (req.method != "GET" && req.method != "HEAD") { - /* We only deal with GET and HEAD by default */ return (pass); } - # Brukes ikke. Cookies er for nubs. + # We don't use cookies - so get rid of them so we don't mess up the cache + # by accident. unset req.http.Cookie; - # Tvinges gjennom for å cache med authorization-skrot. + # Force hash, since we want to cache with Authorization headers return (hash); } - -# Rosa magi +# vcl_hash runs right after vcl_recv, and determines what +# is "unique", e.g., what's part of the hash key. We simply +# add the Authorization header, allowing caching of authenticated +# content. +# NOTE: We do NOT run "return" so it will fall back to the default +# vcl builtin, which will add ip/host and URL as you'd expect. sub vcl_hash { - # Wheee. Legg til authorization-headeren i hashen. hash_data(req.http.authorization); } -# Mauve magi. Hva nå enn det er. -# Dette er WIP - Skal flyttes til backend +# vcl_synth is run for "synthetic messages": responses generated internally +# from Varnish, typically error messages or "return (synth...)" +sub vcl_synth { + if (resp.status == 401) { + set resp.http.WWW-Authenticate = {"Basic realm="WHAT .... is your favorite color?""}; + } + + # Second part of redirect-logic + if (resp.status == 301) { + set resp.http.Location = req.http.x-redir; + return (deliver); + } +} + +# vcl_backend_response is run when we have a reply from a backend, +# allowing us to massage the backend response. We wish to do as little +# as possible here to keep things transparent. sub vcl_backend_response { + # Expose the URL used for debug purposes and future + # cache invalidation. set beresp.http.x-url = bereq.url; + + # If the backend response supplies the "x-ban" HTTP response + # header, then invalidate based on it. This is used for for + # invalidating e.g. switch-management if a switch is added, or the oplog. if (beresp.http.x-ban) { ban("obj.http.x-url ~ " + beresp.http.x-ban); } - if (bereq.url ~ "/render") { - # Graphite claims "no-cache", which is dumb. - # Let's blindly cache for 5+10s. Which is 10000 times better. + + # Force gzip on text-based content so we don't have to + # rely on Apache. + if (beresp.http.content-type ~ "text") { + set beresp.do_gzip = true; + } + + # Do some hand-crafting for influx. Should probably be + # improved... e.g.: with checking error codes. + if (bereq.url ~ "/query") { set beresp.http.Cache-Control = "max-age=5"; unset beresp.http.Pragma; set beresp.uncacheable = false; set beresp.grace = 10s; set beresp.ttl = 5s; } + + # Wait, nvm, we catch non-200 here and make them actually cacheable for 5 + # seconds - we don't want to nuke a backend just because it has ...issues. if (beresp.status != 200) { set beresp.uncacheable = false; set beresp.ttl = 5s; } - if (bereq.url ~ "\.(html|css|js)") { - # Mainly for ease of development + # So for html/css/js there really is no sensible blackend to set + # smart TTL, so we hard-code it to 10s. 10s can be a bit annoying + # for development, but works. + if (bereq.url ~ "\.(html|css|js)" || bereq.url ~ "^/[^/.]*") { set beresp.ttl = 10s; } } |