From f0d2475f74ed4bb16d52fa4678a3a92d93a83c1e Mon Sep 17 00:00:00 2001 From: oddlama Date: Thu, 22 Jun 2023 00:51:45 +0200 Subject: [PATCH] feat: convert all microvms to use nginx --- hosts/common/core/system.nix | 3 +- hosts/ward/microvms/adguardhome/default.nix | 40 +++++++------- .../microvms/adguardhome/secrets/host.pub | 2 +- hosts/ward/microvms/grafana/default.nix | 25 +++++---- hosts/ward/microvms/kanidm/default.nix | 30 ++++++----- hosts/ward/microvms/loki/default.nix | 47 ++++++++++++----- .../loki/secrets/loki-basic-auth-hashes.age | Bin 1169 -> 1148 bytes hosts/ward/microvms/vaultwarden/default.nix | 43 +++++++++------ modules/extra.nix | 49 ------------------ 9 files changed, 114 insertions(+), 125 deletions(-) diff --git a/hosts/common/core/system.nix b/hosts/common/core/system.nix index df6fbcb..2ce9d5d 100644 --- a/hosts/common/core/system.nix +++ b/hosts/common/core/system.nix @@ -376,9 +376,8 @@ file, }: '' echo " -> Aggregating "${lib.escapeShellArg host}":"${lib.escapeShellArg name}"" >&2 - echo -n ${lib.escapeShellArg host}"+"${lib.escapeShellArg name}" " ${decrypt} ${lib.escapeShellArg file} \ - | ${pkgs.caddy}/bin/caddy hash-password --algorithm bcrypt \ + | ${pkgs.apacheHttpd}/bin/htpasswd -niBC 12 ${lib.escapeShellArg host}"+"${lib.escapeShellArg name}" " \ || die "Failure while aggregating caddy basic auth hashes" ''); diff --git a/hosts/ward/microvms/adguardhome/default.nix b/hosts/ward/microvms/adguardhome/default.nix index 02d0bac..6f6aeb4 100644 --- a/hosts/ward/microvms/adguardhome/default.nix +++ b/hosts/ward/microvms/adguardhome/default.nix @@ -6,7 +6,7 @@ ... }: let sentinelCfg = nodes.sentinel.config; - adguardDomain = "adguardhome.${sentinelCfg.repo.secrets.local.personalDomain}"; + adguardhomeDomain = "adguardhome.${sentinelCfg.repo.secrets.local.personalDomain}"; in { imports = [ ../../../../modules/proxy-via-sentinel.nix @@ -22,27 +22,25 @@ in { }; nodes.sentinel = { - proxiedDomains.adguard = adguardDomain; + proxiedDomains.adguard = adguardhomeDomain; - globalConfig = '' - security { - authorization policy mypolicy { - set auth url https://auth.myfiosgateway.com:8443/ - allow roles authp/user - crypto key verify {env.JWT_SHARED_KEY} - } - } - ''; - - services.caddy.virtualHosts.${adguardDomain} = { - useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert adguardDomain; - extraConfig = '' - import common - reverse_proxy { - to http://${config.services.adguardhome.settings.bind_host}:${toString config.services.adguardhome.settings.bind_port} - header_up X-Real-IP {remote_host} - } - ''; + extra.oauth2_proxy.nginx.virtualHosts."${adguardhomeDomain}".allowedGroups = ["adguardhome"]; + services.nginx = { + upstreams.adguardhome = { + servers."${config.services.adguardhome.settings.bind_host}:${toString config.services.adguardhome.settings.bind_port}" = {}; + extraConfig = '' + zone adguardhome 64k; + keepalive 2; + ''; + }; + virtualHosts.${adguardhomeDomain} = { + forceSSL = true; + useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert adguardhomeDomain; + locations."/" = { + proxyPass = "https://adguardhome"; + proxyWebsockets = true; + }; + }; }; }; diff --git a/hosts/ward/microvms/adguardhome/secrets/host.pub b/hosts/ward/microvms/adguardhome/secrets/host.pub index f227506..288bdea 100644 --- a/hosts/ward/microvms/adguardhome/secrets/host.pub +++ b/hosts/ward/microvms/adguardhome/secrets/host.pub @@ -1 +1 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICDDvvF3+KwfoZrPAUAt2HS7y5FM9S5Mr1iRkBUqoXno +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFgqg9aDuyMY+Hmk+++FnoIJRnztJhhj2LfGv4vDhSXG diff --git a/hosts/ward/microvms/grafana/default.nix b/hosts/ward/microvms/grafana/default.nix index 5124e9c..7a1fa23 100644 --- a/hosts/ward/microvms/grafana/default.nix +++ b/hosts/ward/microvms/grafana/default.nix @@ -42,15 +42,22 @@ in { proxiedDomains.grafana = grafanaDomain; - services.caddy.virtualHosts.${grafanaDomain} = { - useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert grafanaDomain; - extraConfig = '' - import common - reverse_proxy { - to http://${config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port} - header_up X-Real-IP {remote_host} - } - ''; + services.nginx = { + upstreams.grafana = { + servers."${config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}" = {}; + extraConfig = '' + zone grafana 64k; + keepalive 2; + ''; + }; + virtualHosts.${grafanaDomain} = { + forceSSL = true; + useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert grafanaDomain; + locations."/" = { + proxyPass = "https://grafana"; + proxyWebsockets = true; + }; + }; }; }; diff --git a/hosts/ward/microvms/kanidm/default.nix b/hosts/ward/microvms/kanidm/default.nix index 29b262a..8652b1a 100644 --- a/hosts/ward/microvms/kanidm/default.nix +++ b/hosts/ward/microvms/kanidm/default.nix @@ -38,18 +38,24 @@ in { nodes.sentinel = { proxiedDomains.kanidm = kanidmDomain; - services.caddy.virtualHosts.${kanidmDomain} = { - useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert kanidmDomain; - extraConfig = '' - import common - reverse_proxy { - to https://${config.services.kanidm.serverSettings.bindaddress} - header_up X-Real-IP {remote_host} - transport http { - tls_insecure_skip_verify - } - } - ''; + services.nginx = { + upstreams.kanidm = { + servers."${config.services.kanidm.serverSettings.bindaddress}" = {}; + extraConfig = '' + zone kanidm 64k; + keepalive 2; + ''; + }; + virtualHosts.${kanidmDomain} = { + forceSSL = true; + useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert kanidmDomain; + locations."/".proxyPass = "https://kanidm"; + # Allow using self-signed certs to satisfy kanidm's requirement + # for TLS connections. (Although this is over wireguard anyway) + extraConfig = '' + proxy_ssl_verify off; + ''; + }; }; }; diff --git a/hosts/ward/microvms/loki/default.nix b/hosts/ward/microvms/loki/default.nix index 38ddbb6..ea64340 100644 --- a/hosts/ward/microvms/loki/default.nix +++ b/hosts/ward/microvms/loki/default.nix @@ -30,22 +30,41 @@ in { # that define passwords (using distributed-config). generator.script = config.age.generators.basic-auth.script; mode = "440"; - group = "caddy"; + group = "nginx"; }; - services.caddy.virtualHosts.${lokiDomain} = { - useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert lokiDomain; - extraConfig = '' - import common - skip_log - basicauth { - import ${sentinelCfg.age.secrets.loki-basic-auth-hashes.path} - } - reverse_proxy { - to http://${config.services.loki.configuration.server.http_listen_address}:${toString config.services.loki.configuration.server.http_listen_port} - header_up X-Real-IP {remote_host} - } - ''; + services.nginx = { + upstreams.loki = { + servers."${config.services.loki.configuration.server.http_listen_address}:${toString config.services.loki.configuration.server.http_listen_port}" = {}; + extraConfig = '' + zone loki 64k; + keepalive 2; + ''; + }; + virtualHosts.${lokiDomain} = { + forceSSL = true; + useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert lokiDomain; + locations."/" = { + proxyPass = "https://loki"; + proxyWebsockets = true; + extraConfig = '' + auth_basic "Authentication required"; + auth_basic_user_file ${sentinelCfg.age.secrets.loki-basic-auth-hashes.path}; + + proxy_read_timeout 1800s; + proxy_connect_timeout 1600s; + + access_log off; + ''; + }; + locations."= /ready" = { + proxyPass = "https://loki"; + extraConfig = '' + auth_basic off; + access_log off; + ''; + }; + }; }; }; diff --git a/hosts/ward/microvms/loki/secrets/loki-basic-auth-hashes.age b/hosts/ward/microvms/loki/secrets/loki-basic-auth-hashes.age index 738a26e150df4d4ee60a65d355235d5abe5a0d87..d45e6635a876e1392704699eadc5a671e46ccfde 100644 GIT binary patch delta 1131 zcmV-x1eE)c3H%6B3UVMt^{Lvw9JT5d0MM^`yUW2oddU0-2QAuQTN`G-=MM79cQ#5WiP)Kb< zO;2oLPj5MTWO@o(Ze%u0V@gs+Qc81IFm`EIPD689S9mjWLvM6tG-+mZadb&XRyAQr zcXtXcJ|ICVQ!FiKa%Ew2Wgs>=V^u0!DLWuVHC|OEZwfd`a4&jwLvt%mb75IWN@8L| zMK&~NXIFYvRDX48dUQoiPj56fY)X1HNGmuBEiEk|NmOolMr~SiRW>+LS6Os!Wo%GX zLN|CvNJeopG-6h4N_tpDZ+A*;Zc8)@@xj3|FK=mOrfWk4ckFB&LihaCk#jt>R_F_i zTvr3ggWk2H>jN3cNddJb%A}lBP#FF0W$_mpq}e=GnG+ zhxK!+pcuI0xU!bzWvotZk!f{=cO5b`K)^9By!GSj(|HbJ_ zy94l|gOCWr3{9{%?Z&VZIv|jd+2+9VaM_~IXl8=5&gKAZI`ou=XJ(J%De=`KGW{LV zv+ZTilz)2(JZd@Al678Ce70J8fcIkx`fuVCq1cJ=+>{fu;aaMGWpB}v`%8#G1$$_-Wxtdef1GXYQFl zph-$|CYb31FC&?|Bspt+S>Kru$j_0qRq!d&*79Q>(u2`!Mdt2 zfQyxHS$XDZ9)Dgxbr7I#wJZAk-0fyxrhhA*)>?xJ4uX%=m4YJAg7m7=Z0#Jft7B?|yYX`c|I+s@a}TD_KQv;Pm};SKtHpeuaG_Xe&W~sX~^Jj84E< zRhN-ILh8pib(pE_`0>F0t;&LSkEAwkympm9p@+!VyD;7)&$m`52yg6lhWM?@Eo4Kj z%9|X(vxQxgvsO8FEvfZrQe0Z4-M~as37E)}GzP29rQg%n7`F_nxoq@FH0FlPBqn5x x0`Kyhz-@FgA1`>^8x3H{-(d8of|pcM54~O;$BQGEg#FWNSe;X-qb1PI5zHa#>7lFjzxwa5!>NV^T&pYDic@a|$g! zAaH4REpRe5HXwL$Q)M_&AVDu|bZ=H9MmJY9bZ==xdM{L3 zQdMM9L^5baYIF*BLrZs4Z(~7lb2LS4NmfxQCdfIRBl8vWlLE(GfYZ2QEzNgR#Qb(S64|| zOi4B}VM$R?L4P(vMNvd%OKxpuD^+Y|Pc%(Z!=|aR!>)I zWKTmxYFA4&cM2^nEg)KESV?bsZZTp)Mo3UAYf?FOc}QAELv&3zPcK?pcSu)8D^5Xn zNN+D;V+wk6DAdiFB*0n6Z&x6sNQSYP9Bvcht9_|Yqf{Df z{oNx=4Aot^p^+r}4%wrSnvtkC~Q9uQasjVn)q}!(H z;zWsB97j8@JhEbMw=h1CL(EN)-p1)PAVQmqS$~Z{h)cXtvYBiA7$M(VYltye`;RiI zUb}+7GA!wC99UX4>&9J-??wm{eNKdaaxx0KZ}~OmWQ|##(zU>2Jhi7#+~4;Ja_S^1 z2=n*Z5k&J4dl(CiC^eOxvpjZ{irx}}%`A6CSTv^QMgq{)15Oj!dNNz@*i!}qIrPDf z{eQkQ*;aiF$;;xdrAWx(ReX=ZazhF#_Ke_ONy&v+Jkn8p_)WlN=Tcpe_AL*C5f>`X>tC-DI9g1O6{+b!;CkBm^&Q?bFz^Z z@EUVzZEvJm$fE2NR9+h~#!|vyA&mN~P>C%Arrkahd1tkjW9Yc`rt`X8t3ug>|9NH% zdfLNo7Uq6V8$C2!Ux(iI4tCf`f04a+larwC2WgT6qb5mVG9!3zjEAfHJd4~TOsUqXJi%~C1VD(k>Dk7KJYXZ-IOC<(CGW{ZZ1`JS8=q4(=pz6m9Mrsa Sl04#2ua4+S6|Tpmct73}3;3`A diff --git a/hosts/ward/microvms/vaultwarden/default.nix b/hosts/ward/microvms/vaultwarden/default.nix index 6815918..4e1e298 100644 --- a/hosts/ward/microvms/vaultwarden/default.nix +++ b/hosts/ward/microvms/vaultwarden/default.nix @@ -33,26 +33,35 @@ in { nodes.sentinel = { proxiedDomains.vaultwarden = vaultwardenDomain; - services.caddy.virtualHosts.${vaultwardenDomain} = { + upstreams.vaultwarden = { + servers."${config.services.vaultwarden.config.rocketAddress}:${toString config.services.vaultwarden.config.rocketPort}" = {}; + extraConfig = '' + zone vaultwarden 64k; + keepalive 2; + ''; + }; + upstreams.vaultwarden-websocket = { + servers."${config.services.vaultwarden.config.websocketAddress}:${toString config.services.vaultwarden.config.websocketPort}" = {}; + extraConfig = '' + zone vaultwarden-websocket 64k; + keepalive 2; + ''; + }; + virtualHosts.${vaultwardenDomain} = { + forceSSL = true; useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert vaultwardenDomain; extraConfig = '' - import common - - reverse_proxy { - to http://${config.services.vaultwarden.config.rocketAddress}:${toString config.services.vaultwarden.config.rocketPort} - header_up X-Real-IP {remote_host} - } - - reverse_proxy /notifications/hub { - to http://${config.services.vaultwarden.config.websocketAddress}:${toString config.services.vaultwarden.config.websocketPort} - header_up X-Real-IP {remote_host} - } - - reverse_proxy /notifications/hub/negotiate { - to http://${config.services.vaultwarden.config.rocketAddress}:${toString config.services.vaultwarden.config.rocketPort} - header_up X-Real-IP {remote_host} - } + client_max_body_size 256M; ''; + locations."/".proxyPass = "http://vaultwarden"; + locations."/notifications/hub" = { + proxyPass = "http://vaultwarden-websocket"; + proxyWebsockets = true; + }; + locations."/notifications/hub/negotiate" = { + proxyPass = "http://vaultwarden"; + proxyWebsockets = true; + }; }; }; diff --git a/modules/extra.nix b/modules/extra.nix index 8464d02..8041604 100644 --- a/modules/extra.nix +++ b/modules/extra.nix @@ -35,36 +35,6 @@ in { individually for each cert by the user or via `security.acme.defaults`. ''; }; - - nginx.proxiedDomains = mkOption { - default = {}; - description = mdDoc "Simplified reverse proxy setup."; - type = types.attrsOf (types.submodule (submod: { - options = { - domain = mkOption { - type = types.str; - description = mdDoc "The public domain for the virtual host."; - }; - - upstream = mkOption { - type = types.str; - description = mdDoc "The upstream server to which requests are forwarded."; - }; - - scheme = mkOption { - type = types.str; - default = "http"; - description = mdDoc "The scheme to use when connecting to upstream."; - }; - - useACMEHost = mkOption { - type = types.str; - default = config.lib.extra.matchingWildcardCert submod.config.domain; - description = mdDoc "The acme host certificate to use for the virtual host."; - }; - }; - })); - }; }; config = { @@ -121,25 +91,6 @@ in { add_header X-Frame-Options "DENY"; add_header X-Content-Type-Options "nosniff"; ''; - - upstreams = - flip mapAttrs config.extra.nginx.proxiedDomains - (name: cfg: { - servers."${cfg.upstream}" = {}; - extraConfig = '' - zone ${name} 64k; - keepalive 2; - ''; - }); - - virtualHosts = - flip mapAttrs' config.extra.nginx.proxiedDomains - (name: cfg: - nameValuePair cfg.domain { - forceSSL = true; - inherit (cfg) useACMEHost; - locations."/".proxyPass = "${cfg.scheme}://${name}"; - }); }; networking.firewall.allowedTCPPorts = optionals config.services.nginx.enable [80 443];