diff --git a/modules/nixos/nginx/listen.nix b/modules/nixos/nginx/listen.nix new file mode 100644 index 00000000..8308bd1e --- /dev/null +++ b/modules/nixos/nginx/listen.nix @@ -0,0 +1,71 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.modules) mkIf mkDefault mkOptionDefault mkForce mkOverride; + inherit (lib.attrsets) mapAttrsToList filterAttrs removeAttrs; + inherit (lib.lists) concatMap; + mkAlmostOptionDefault = mkOverride 1250; + inherit (config.services) nginx; + extraListenAttrs = [ "enable" ]; + listenModule = { config, virtualHost, ... }: { + options = with lib.types; { + enable = mkEnableOption "this port" // { + default = true; + }; + ssl = mkOption { + type = bool; + default = false; + }; + port = mkOption { + type = nullOr port; + }; + }; + config = { + enable = mkIf (config.ssl && !virtualHost.ssl.enable) (mkForce false); + _module.freeformType = with lib.types; attrsOf (oneOf [ + str (listOf str) (nullOr port) bool + ]); + port = mkOptionDefault ( + if config.ssl then nginx.defaultSSLListenPort else nginx.defaultHTTPListenPort + ); + }; + }; + hostModule = { config, ... }: let + cfg = config.listenPorts; + enabledPorts = filterAttrs (_: port: port.enable) cfg; + in { + options = with lib.types; { + listenPorts = mkOption { + type = attrsOf (submoduleWith { + modules = [ listenModule ]; + specialArgs = { + virtualHost = config; + }; + }); + default = { }; + }; + }; + + config = { + listen = let + addresses = if config.listenAddresses != [ ] then config.listenAddresses else nginx.defaultListenAddresses; + in mkIf (cfg != { }) (mkAlmostOptionDefault ( + concatMap (addr: mapAttrsToList (_: listen: { + addr = mkDefault addr; + } // removeAttrs listen extraListenAttrs) enabledPorts) addresses + )); + }; + }; +in { + options = with lib.types; { + services.nginx.virtualHosts = mkOption { + type = attrsOf (submoduleWith { + modules = [ hostModule ]; + shorthandOnlyDefinesConfig = true; + }); + }; + }; +} diff --git a/modules/nixos/nginx/local.nix b/modules/nixos/nginx/local.nix index 75f672f1..e5cb871d 100644 --- a/modules/nixos/nginx/local.nix +++ b/modules/nixos/nginx/local.nix @@ -62,7 +62,7 @@ enable = mkOptionDefault virtualHost.local.enable; denyGlobal = mkOptionDefault virtualHost.local.denyGlobal; trusted = mkOptionDefault virtualHost.local.trusted; - emitDenyGlobal = virtualHost.local.emitDenyGlobal; + emitDenyGlobal = config.local.denyGlobal && !virtualHost.local.emitDenyGlobal; }; }; hostModule = {config, ...}: { diff --git a/modules/nixos/nginx/name.nix b/modules/nixos/nginx/name.nix new file mode 100644 index 00000000..05603122 --- /dev/null +++ b/modules/nixos/nginx/name.nix @@ -0,0 +1,69 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption; + inherit (lib.modules) mkIf mkDefault mkOptionDefault; + inherit (lib.strings) optionalString; + inherit (config.services) tailscale; + inherit (config) networking; + hostModule = {config, ...}: let + cfg = config.name; + in { + options = with lib.types; { + name = { + shortServer = mkOption { + type = nullOr str; + default = null; + }; + qualifier = mkOption { + type = nullOr str; + }; + includeLocal = mkOption { + type = bool; + default = false; + }; + includeTailscale = mkOption { + type = bool; + }; + }; + allServerNames = mkOption { + type = listOf str; + }; + }; + + config = { + name = { + qualifier = mkOptionDefault ( + if config.local.enable then "local" + else null + ); + includeTailscale = mkOptionDefault ( + config.local.enable && tailscale.enable && cfg.qualifier != "tail" + ); + }; + serverName = mkIf (cfg.shortServer != null) (mkDefault ( + cfg.shortServer + + optionalString (cfg.qualifier != null) ".${cfg.qualifier}" + + ".${networking.domain}" + )); + serverAliases = mkIf (cfg.shortServer != null) (mkDefault [ + (mkIf cfg.includeLocal "${cfg.shortServer}.local.${networking.domain}") + (mkIf cfg.includeTailscale "${cfg.shortServer}.tail.${networking.domain}") + ]); + allServerNames = mkOptionDefault ( + [ config.serverName ] ++ config.serverAliases + ); + }; + }; +in { + options = with lib.types; { + services.nginx.virtualHosts = mkOption { + type = attrsOf (submoduleWith { + modules = [hostModule]; + shorthandOnlyDefinesConfig = true; + }); + }; + }; +} diff --git a/modules/nixos/nginx/proxied.nix b/modules/nixos/nginx/proxied.nix new file mode 100644 index 00000000..07697afa --- /dev/null +++ b/modules/nixos/nginx/proxied.nix @@ -0,0 +1,204 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.modules) mkIf mkMerge mkBefore mkAfter mkOrder mkDefault mkOptionDefault mkOverride; + inherit (lib.strings) optionalString splitString match; + inherit (lib.attrsets) attrValues; + inherit (lib.lists) length head /*optional*/ any; + inherit (lib.trivial) mapNullable; + #inherit (config) networking; + inherit (config.services) nginx; + mkAlmostAfter = mkOrder 1250; + mkAlmostOptionDefault = mkOverride 1250; + schemeForUrl = url: let + parts = splitString ":" url; + in if length parts == 1 then null else head parts; + pathForUrl = url: let + parts = match ''[^:]+://[^/]+(.*)'' url; + in if parts == null then null else head parts; + hostForUrl = url: let + parts = match ''[^:]+://([^/]+).*'' url; + in if parts == null then null else head parts; + xHeadersDefaults = '' + set $x_scheme $scheme; + set $x_forwarded_for $remote_addr; + set $x_remote_addr $remote_addr; + set $x_forwarded_host $host; + set $x_forwarded_server $host; + set $x_host $host; + set $x_referer $http_referer; + set $x_proxy_host $x_host; + ''; + xHeadersProxied = '' + set $x_forwarded_for $proxy_add_x_forwarded_for; + if ($http_x_forwarded_proto) { + set $x_scheme $http_x_forwarded_proto; + } + if ($http_x_real_ip) { + set $x_remote_addr $http_x_real_ip; + } + if ($http_x_forwarded_host) { + set $x_forwarded_host $http_x_forwarded_host; + } + if ($http_x_forwarded_server) { + set $x_forwarded_server $http_x_forwarded_server; + } + if ($x_referer ~ "^https?://([^/]*)/(.*)$") { + set $x_referer_host $1; + set $x_referer_path $2; + } + ''; + locationModule = { config, virtualHost, ... }: let + cfg = config.proxied; + in { + options = with lib.types; { + proxied = { + enable = mkOption { + type = enum [ false true "cloudflared" ]; + default = false; + }; + enabled = mkOption { + type = bool; + readOnly = true; + }; + xvars.enable = mkEnableOption "$x_variables"; + redirectScheme = mkEnableOption "redirect to X-Forwarded-Proto" // { + default = cfg.enabled; + }; + rewriteReferer = mkEnableOption "rewrite Referer header" // { + default = cfg.enabled; + }; + }; + proxy = { + enabled = mkOption { + type = bool; + readOnly = true; + }; + scheme = mkOption { + type = nullOr str; + }; + path = mkOption { + type = nullOr str; + }; + host = mkOption { + type = nullOr str; + }; + headers.enableRecommended = mkOption { + type = enum [ true false "nixpkgs" ]; + }; + }; + force = mkEnableOption "redirect to SSL"; + }; + config = let + emitVars = cfg.enabled && !virtualHost.proxied.enabled; + emitRedirectScheme = config.proxy.enabled && cfg.redirectScheme; + emitRefererRewrite = config.proxy.enabled && cfg.rewriteReferer; + emitHeaders = config.proxy.enabled && config.proxy.headers.enableRecommended == true; + in { + proxied = { + enabled = mkOptionDefault (virtualHost.proxied.enabled || cfg.enable != false); + xvars.enable = mkIf (cfg.enabled || emitRedirectScheme || emitHeaders) true; + }; + proxy = { + enabled = mkOptionDefault (config.proxyPass != null); + headers.enableRecommended = mkOptionDefault ( + if !virtualHost.recommendedProxySettings then false + else if cfg.enabled then true + else "nixpkgs" + ); + scheme = mkOptionDefault ( + mapNullable schemeForUrl config.proxyPass + ); + path = mkOptionDefault ( + mapNullable pathForUrl config.proxyPass + ); + host = mkOptionDefault ( + mapNullable hostForUrl config.proxyPass + ); + }; + recommendedProxySettings = mkMerge [ + (mkAlmostOptionDefault (config.proxy.headers.enableRecommended == "nixpkgs")) + ]; + extraConfig = mkMerge [ + (mkIf emitVars ( + mkBefore xHeadersProxied + )) + (mkIf emitRedirectScheme '' + proxy_redirect ${config.proxy.scheme}://$host/ $x_scheme://$host/; + '') + (mkIf emitRefererRewrite '' + if ($x_referer_host = $host) { + set $x_referer "${config.proxy.scheme}://${config.proxy.host}/$x_referer_path"; + } + '') + (mkIf emitHeaders (mkAlmostAfter '' + if ($x_proxy_host = "") { + set $x_proxy_host $proxy_host; + } + if ($x_proxy_host = "") { + set $x_proxy_host ${config.proxy.host}; + } + proxy_set_header Host $x_proxy_host; + proxy_set_header Referer $x_referer; + proxy_set_header X-Real-IP $x_remote_addr; + proxy_set_header X-Forwarded-For $x_forwarded_for; + proxy_set_header X-Forwarded-Proto $x_scheme; + proxy_set_header X-Forwarded-Host $x_forwarded_host; + proxy_set_header X-Forwarded-Server $x_forwarded_server; + '')) + ]; + }; + }; + hostModule = { config, ... }: let + cfg = config.proxied; + in { + options = with lib.types; { + proxied = { + enable = mkOption { + type = enum [ false true "cloudflared" ]; + default = false; + }; + enabled = mkOption { + type = bool; + default = cfg.enable != false; + }; + xvars.enable = mkEnableOption "$x_variables" // { + default = cfg.enabled; + }; + }; + recommendedProxySettings = mkOption { + type = bool; + default = nginx.recommendedProxySettings; + }; + locations = mkOption { + type = attrsOf (submoduleWith { + modules = [ locationModule ]; + shorthandOnlyDefinesConfig = true; + }); + }; + }; + + config = { + proxied = { + xvars.enable = mkIf (any (loc: loc.proxied.xvars.enable) (attrValues config.locations)) true; + }; + local.denyGlobal = mkIf (cfg.enable == "cloudflared") (mkDefault true); + extraConfig = mkIf cfg.xvars.enable (mkBefore '' + ${xHeadersDefaults} + ${optionalString cfg.enabled xHeadersProxied} + ''); + }; + }; +in { + options = with lib.types; { + services.nginx.virtualHosts = mkOption { + type = attrsOf (submoduleWith { + modules = [ hostModule ]; + shorthandOnlyDefinesConfig = true; + }); + }; + }; +} diff --git a/modules/nixos/nginx/ssl.nix b/modules/nixos/nginx/ssl.nix new file mode 100644 index 00000000..e396b82b --- /dev/null +++ b/modules/nixos/nginx/ssl.nix @@ -0,0 +1,92 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.modules) mkIf mkDefault mkOptionDefault mkOverride; + mkAlmostOptionDefault = mkOverride 1250; + forceRedirectConfig = virtualHost: '' + if ($x_scheme = http) { + return ${toString virtualHost.redirectCode} https://$host$request_uri; + } + ''; + locationModule = { config, virtualHost, ... }: let + cfg = config.ssl; + emitForce = cfg.force && !virtualHost.ssl.forced; + in { + options.ssl = { + force = mkEnableOption "redirect to SSL"; + }; + config = { + proxied.xvars.enable = mkIf emitForce true; + extraConfig = mkIf emitForce (forceRedirectConfig virtualHost); + }; + }; + hostModule = { config, name, ... }: let + cfg = config.ssl; + emitForce = cfg.forced && config.proxied.enabled; + in { + options = with lib.types; { + ssl = { + enable = mkOption { + type = bool; + }; + force = mkOption { + # TODO: "force-nonlocal"? exceptions for tailscale? + type = enum [ false true "only" "reject" ]; + default = false; + }; + forced = mkOption { + type = bool; + readOnly = true; + }; + cert = { + name = mkOption { + type = nullOr str; + default = null; + }; + keyPath = mkOption { + type = nullOr path; + default = null; + }; + path = mkOption { + type = nullOr path; + default = null; + }; + }; + }; + locations = mkOption { + type = attrsOf (submoduleWith { + modules = [ locationModule ]; + shorthandOnlyDefinesConfig = true; + }); + }; + }; + config = { + ssl = { + enable = mkOptionDefault (cfg.cert.name != null || cfg.cert.keyPath != null); + forced = mkOptionDefault (cfg.force != false && cfg.force != "reject"); + }; + addSSL = mkIf (cfg.enable && (cfg.force == false || emitForce)) (mkDefault true); + forceSSL = mkIf (cfg.enable && cfg.force == true && !emitForce) (mkDefault true); + onlySSL = mkIf (cfg.enable && cfg.force == "only" && !emitForce) (mkDefault true); + rejectSSL = mkIf (cfg.force == "reject") (mkDefault true); + useACMEHost = mkAlmostOptionDefault cfg.cert.name; + sslCertificate = mkIf (cfg.cert.path != null) (mkAlmostOptionDefault cfg.cert.path); + sslCertificateKey = mkIf (cfg.cert.keyPath != null) (mkAlmostOptionDefault cfg.cert.keyPath); + + proxied.xvars.enable = mkIf emitForce true; + extraConfig = mkIf emitForce (forceRedirectConfig config); + }; + }; +in { + options = with lib.types; { + services.nginx.virtualHosts = mkOption { + type = attrsOf (submoduleWith { + modules = [ hostModule ]; + shorthandOnlyDefinesConfig = true; + }); + }; + }; +} diff --git a/modules/nixos/nginx/vouch.nix b/modules/nixos/nginx/vouch.nix index 70be6ff9..dfc32aab 100644 --- a/modules/nixos/nginx/vouch.nix +++ b/modules/nixos/nginx/vouch.nix @@ -6,11 +6,123 @@ inherit (lib.options) mkOption mkEnableOption; inherit (lib.modules) mkIf mkMerge mkBefore mkDefault; inherit (config) networking; - inherit (config.services) vouch-proxy tailscale; - vouchModule = {config, ...}: { + inherit (config.services) vouch-proxy nginx tailscale; + inherit (nginx) vouch; + locationModule = {config, virtualHost, ...}: { + options.vouch = with lib.types; { + requireAuth = mkEnableOption "require auth to access this location"; + }; + config = mkIf config.vouch.requireAuth { + proxied.xvars.enable = true; + extraConfig = assert virtualHost.vouch.enable; mkMerge [ + '' + add_header Access-Control-Allow-Origin ${vouch.url}; + add_header Access-Control-Allow-Origin ${vouch.authUrl}; + '' + (mkIf (vouch.localSso.enable && config.local.enable) '' + add_header Access-Control-Allow-Origin ${vouch.localUrl}; + '') + (mkIf (vouch.localSso.enable && config.local.enable && tailscale.enable) '' + add_header Access-Control-Allow-Origin $x_scheme://${vouch.tailDomain}; + '') + '' + proxy_set_header X-Vouch-User $auth_resp_x_vouch_user; + '' + ]; + }; + }; + hostModule = {config, ...}: let + cfg = config.vouch; + in { options = with lib.types; { + locations = mkOption { + type = attrsOf (submodule locationModule); + }; vouch = { enable = mkEnableOption "vouch auth proxy"; + requireAuth = mkEnableOption "require auth to access this host" // { + default = true; + }; + errorLocation = mkOption { + type = str; + default = "@error401"; + }; + authRequestLocation = mkOption { + type = str; + default = "/validate"; + }; + authRequestDirective = mkOption { + type = lines; + default = '' + auth_request ${cfg.authRequestLocation}; + ''; + }; + }; + }; + config = { + extraConfig = mkIf (cfg.enable && cfg.requireAuth) '' + ${cfg.authRequestDirective} + error_page 401 = ${cfg.errorLocation}; + ''; + locations = mkIf cfg.enable { + "/" = mkIf cfg.requireAuth { + vouch.requireAuth = true; + }; + ${cfg.errorLocation} = { + proxied.xvars.enable = true; + extraConfig = let + localVouchUrl = '' + if ($x_forwarded_host ~ "\.local\.${networking.domain}$") { + set $vouch_url ${vouch.localUrl}; + } + ''; + tailVouchUrl = '' + if ($x_forwarded_host ~ "\.tail\.${networking.domain}$") { + set $vouch_url $x_scheme://${vouch.tailDomain}; + } + ''; + in + mkMerge [ + (mkBefore '' + set $vouch_url ${vouch.url}; + '') + (mkIf (vouch.localSso.enable && config.local.enable or false) localVouchUrl) + (mkIf (vouch.localSso.enable && config.local.enable or false && tailscale.enable) tailVouchUrl) + '' + return 302 $vouch_url/login?url=$x_scheme://$x_forwarded_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err; + '' + ]; + }; + ${cfg.authRequestLocation} = { + proxyPass = "${vouch.proxyOrigin}/validate"; + proxy.headers.enableRecommended = true; + extraConfig = let + # nginx-proxied vouch must use X-Forwarded-Host, but vanilla vouch requires Host + vouchProxyHost = if vouch.doubleProxy + then "''" + else "$x_forwarded_host"; + in '' + set $x_proxy_host ${vouchProxyHost}; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user; + auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt; + auth_request_set $auth_resp_err $upstream_http_x_vouch_err; + auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount; + ''; + }; + }; + }; + }; +in { + options = with lib.types; { + services.nginx = { + vouch = { + enable = mkEnableOption "vouch auth proxy"; + localSso = { + # NOTE: this won't work without multiple vouch-proxy instances with different auth urls... + enable = mkEnableOption "lan-local auth"; + }; proxyOrigin = mkOption { type = str; default = "https://login.local.${networking.domain}"; @@ -35,117 +147,32 @@ type = str; default = "login.tail.${networking.domain}"; }; - authRequestDirective = mkOption { - type = lines; - default = '' - auth_request /validate; - ''; - }; + }; + virtualHosts = mkOption { + type = attrsOf (submodule hostModule); }; }; - config = mkMerge [ + }; + config.services.nginx = { + vouch = mkMerge [ { - vouch = mkIf vouch-proxy.enable { - proxyOrigin = let - inherit (vouch-proxy.settings.vouch) listen port; - host = - if listen == "0.0.0.0" || listen == "[::]" - then "localhost" - else listen; - in - mkDefault "http://${host}:${toString port}"; - authUrl = mkDefault vouch-proxy.authUrl; - url = mkDefault vouch-proxy.url; - doubleProxy = mkDefault false; - }; - } - { - vouch.proxyOrigin = mkIf (tailscale.enable && !vouch-proxy.enable) ( - mkDefault - "http://login.tail.${networking.domain}" + proxyOrigin = mkIf (tailscale.enable && !vouch-proxy.enable) ( + mkDefault "http://login.tail.${networking.domain}" ); } - (mkIf config.vouch.enable { - extraConfig = '' - ${config.vouch.authRequestDirective} - error_page 401 = @error401; - ''; - locations = { - "/" = { - extraConfig = mkMerge [ - '' - add_header Access-Control-Allow-Origin ${config.vouch.url}; - add_header Access-Control-Allow-Origin ${config.vouch.authUrl}; - '' - (mkIf config.local.enable '' - add_header Access-Control-Allow-Origin ${config.vouch.localUrl}; - '') - (mkIf (config.local.enable && tailscale.enable) '' - add_header Access-Control-Allow-Origin $scheme://${config.vouch.tailDomain}; - '') - '' - proxy_set_header X-Vouch-User $auth_resp_x_vouch_user; - '' - ]; - }; - "@error401" = { - extraConfig = let - localVouchUrl = '' - if ($http_host ~ "\.local\.${networking.domain}$") { - set $vouch_url ${config.vouch.localUrl}; - } - ''; - tailVouchUrl = '' - if ($http_host ~ "\.tail\.${networking.domain}$") { - set $vouch_url $vouch_scheme://${config.vouch.tailDomain}; - } - ''; - in - mkMerge [ - (mkBefore '' - set $vouch_url ${config.vouch.url}; - set $vouch_scheme $scheme; - '') - (mkIf config.local.trusted (mkBefore '' - if ($http_x_forwarded_proto) { - set $vouch_scheme $http_x_forwarded_proto; - } - '')) - (mkIf (config.local.enable or false) localVouchUrl) - (mkIf (config.local.enable or false && tailscale.enable) tailVouchUrl) - '' - return 302 $vouch_url/login?url=$vouch_scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err; - '' - ]; - }; - "/validate" = { - recommendedProxySettings = false; - proxyPass = "${config.vouch.proxyOrigin}/validate"; - extraConfig = mkMerge [ - (mkIf (!config.vouch.doubleProxy) '' - proxy_set_header Host $host; - '') - (mkIf config.vouch.doubleProxy '' - proxy_set_header X-Host $host; - '') - '' - proxy_pass_request_body off; - proxy_set_header Content-Length ""; - auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user; - auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt; - auth_request_set $auth_resp_err $upstream_http_x_vouch_err; - auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount; - '' - ]; - }; - }; + (mkIf vouch-proxy.enable { + proxyOrigin = let + inherit (vouch-proxy.settings.vouch) listen port; + host = + if listen == "0.0.0.0" || listen == "[::]" + then "localhost" + else listen; + in + mkDefault "http://${host}:${toString port}"; + authUrl = mkDefault vouch-proxy.authUrl; + url = mkDefault vouch-proxy.url; + doubleProxy = mkDefault false; }) ]; }; -in { - options = with lib.types; { - services.nginx.virtualHosts = mkOption { - type = attrsOf (submodule vouchModule); - }; - }; } diff --git a/modules/nixos/nginx/websocket.nix b/modules/nixos/nginx/websocket.nix index bad992cf..47625a68 100644 --- a/modules/nixos/nginx/websocket.nix +++ b/modules/nixos/nginx/websocket.nix @@ -7,7 +7,6 @@ }; config = mkIf config.proxy.websocket.enable { extraConfig = '' - proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; ''; diff --git a/nixos/access/bazarr.nix b/nixos/access/bazarr.nix deleted file mode 100644 index 49734cb2..00000000 --- a/nixos/access/bazarr.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - config, - lib, -}: let - inherit (lib.modules) mkIf mkDefault mkOptionDefault; - cfg = config.services.bazarr; - access = config.services.nginx.access.bazarr; - proxyPass = mkDefault "https://${access.host}:${toString access.port}"; - locations = { - "/" = { - inherit proxyPass; - }; - }; -in { - options.services.nginx.access.bazarr = with lib.types; { - host = mkOption { - type = str; - }; - domain = mkOption { - type = str; - default = "bazarr.${config.networking.domain}"; - }; - port = mkOption { - type = port; - }; - }; - config.services.nginx = { - access.bazarr = mkIf cfg.enable { - host = mkOptionDefault "localhost"; - port = mkOptionDefault cfg.listenPort; - }; - virtualHosts = { - ${access.domain} = { - inherit locations; - }; - }; - }; -} diff --git a/nixos/access/gensokyo.nix b/nixos/access/gensokyo.nix index 505d2f3f..5f87503c 100644 --- a/nixos/access/gensokyo.nix +++ b/nixos/access/gensokyo.nix @@ -7,7 +7,8 @@ }: let inherit (lib.modules) mkDefault; in { - services.nginx.virtualHosts.${config.networking.domain} = { + services.nginx.virtualHosts.gensokyoZone = { + serverName = config.networking.domain; locations = { "/" = { root = inputs.website.packages.${pkgs.system}.gensokyoZone; diff --git a/nixos/access/home-assistant.nix b/nixos/access/home-assistant.nix index fdb7fd7b..b6ab6fbb 100644 --- a/nixos/access/home-assistant.nix +++ b/nixos/access/home-assistant.nix @@ -3,20 +3,29 @@ lib, ... }: let - inherit (lib.modules) mkIf mkDefault; - inherit (config.services) home-assistant tailscale; - proxyPass = "http://localhost:${toString home-assistant.config.http.server_port}/"; + inherit (lib.modules) mkIf mkMerge mkDefault; + inherit (config.services) home-assistant nginx; + name.shortServer = mkDefault "home"; + listenPorts = { + http = { }; + https.ssl = true; + hass = mkIf (!home-assistant.enable) { port = mkDefault home-assistant.config.http.server_port; }; + }; in { - services.nginx.virtualHosts."home.local.${config.networking.domain}" = mkIf home-assistant.enable { - local.enable = mkDefault true; - locations."/" = { - inherit proxyPass; - }; - }; - services.nginx.virtualHosts."home.tail.${config.networking.domain}" = mkIf (home-assistant.enable && tailscale.enable) { - local.enable = mkDefault true; - locations."/" = { - inherit proxyPass; + config.services.nginx.virtualHosts = { + home-assistant = { + inherit name listenPorts; + locations."/".proxyPass = mkIf home-assistant.enable (mkDefault + "http://localhost:${toString home-assistant.config.http.server_port}" + ); + }; + home-assistant'local = { + inherit name listenPorts; + local.enable = mkDefault true; + locations."/".proxyPass = mkIf home-assistant.enable (mkDefault + nginx.virtualHosts.home-assistant.locations."/".proxyPass + ); }; }; + config.networking.firewall.allowedTCPPorts = [ home-assistant.config.http.server_port ]; } diff --git a/nixos/access/jackett.nix b/nixos/access/jackett.nix deleted file mode 100644 index d285ee27..00000000 --- a/nixos/access/jackett.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - config, - lib, -}: let - inherit (lib.modules) mkIf mkDefault mkOptionDefault; - cfg = config.services.jackett; - access = config.services.nginx.access.jackett; - proxyPass = mkDefault "https://${access.host}:${toString access.port}"; - locations = { - "/" = { - inherit proxyPass; - }; - }; -in { - options.services.nginx.access.jackett = with lib.types; { - host = mkOption { - type = str; - }; - domain = mkOption { - type = str; - default = "jackett.${config.networking.domain}"; - }; - port = mkOption { - type = port; - default = cfg.port; - }; - }; - config.services.nginx = { - access.jackett = mkIf cfg.enable { - host = mkOptionDefault "localhost"; - }; - virtualHosts = { - ${access.domain} = { - inherit locations; - }; - }; - }; -} diff --git a/nixos/access/keycloak.nix b/nixos/access/keycloak.nix new file mode 100644 index 00000000..648cead1 --- /dev/null +++ b/nixos/access/keycloak.nix @@ -0,0 +1,54 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption; + inherit (lib.modules) mkIf mkDefault; + cfg = config.services.keycloak; + inherit (config) networking; + inherit (config.services) nginx; + access = nginx.access.keycloak; + locations = { + "/" = { + proxyPass = mkDefault access.url; + }; + }; +in { + options.services.nginx.access.keycloak = with lib.types; { + host = mkOption { + type = str; + default = "keycloak.local.${networking.domain}"; + }; + url = mkOption { + type = str; + default = "https://${access.host}"; + }; + }; + config.services.nginx = { + access.keycloak = mkIf cfg.enable { + host = mkDefault "localhost"; + url = mkDefault (if cfg.sslCertificate != null then "https://${access.host}" else "http://${access.host}"); + }; + virtualHosts = { + keycloak = { + name.shortServer = mkDefault "sso"; + ssl.force = mkDefault true; + inherit locations; + }; + keycloak'local = { + name.shortServer = mkDefault "sso"; + ssl.force = mkDefault true; + local.enable = true; + inherit locations; + extraConfig = mkIf nginx.vouch.localSso.enable '' + set $vouch_local_url ${nginx.vouch.localUrl}; + if ($x_forwarded_host ~ "\.tail\.${networking.domain}$") { + set $vouch_local_url $x_scheme://${nginx.vouch.tailDomain}; + } + proxy_redirect ${nginx.vouch.url}/ $vouch_local_url/; + ''; + }; + }; + }; +} diff --git a/nixos/access/kitchencam.nix b/nixos/access/kitchencam.nix index 206cfb95..a3537890 100644 --- a/nixos/access/kitchencam.nix +++ b/nixos/access/kitchencam.nix @@ -27,18 +27,6 @@ in { type = str; default = "http://${access.host}:${toString access.streamPort}"; }; - domain = mkOption { - type = str; - default = "kitchen.${config.networking.domain}"; - }; - localDomain = mkOption { - type = str; - default = "kitchen.local.${config.networking.domain}"; - }; - tailDomain = mkOption { - type = str; - default = "kitchen.tail.${config.networking.domain}"; - }; useACMEHost = mkOption { type = nullOr str; default = null; @@ -46,7 +34,6 @@ in { }; config.services.nginx = { virtualHosts = let - addSSL = access.useACMEHost != null || virtualHosts.${access.domain}.addSSL || virtualHosts.${access.domain}.forceSSL; extraConfig = '' proxy_redirect off; proxy_buffering off; @@ -64,47 +51,22 @@ in { inherit extraConfig; }; }; - streamListen = {config, ...}: { - listen = - concatMap (addr: [ - (mkIf config.addSSL { - inherit addr; - port = nginx.defaultSSLListenPort; - ssl = true; - }) - { - inherit addr; - port = nginx.defaultHTTPListenPort; - } - { - inherit addr; - port = access.streamPort; - } - ]) - nginx.defaultListenAddresses; + listenPorts = { + http = { }; + https.ssl = true; + stream.port = mkDefault access.streamPort; }; + name.shortServer = mkDefault "kitchen"; + kTLS = mkDefault true; in { - ${access.domain} = mkMerge [ - { - vouch.enable = true; - kTLS = mkDefault true; - inherit (access) useACMEHost; - addSSL = mkDefault (access.useACMEHost != null); - inherit locations; - } - streamListen - ]; - ${access.localDomain} = mkMerge [ - { - serverAliases = mkIf config.services.tailscale.enable [access.tailDomain]; - inherit (virtualHosts.${access.domain}) useACMEHost; - addSSL = mkDefault addSSL; - kTLS = mkDefault true; - local.enable = true; - inherit locations; - } - streamListen - ]; + kitchencam = { + inherit name locations listenPorts kTLS; + vouch.enable = true; + }; + kitchencam'local = { + inherit name locations listenPorts kTLS; + local.enable = true; + }; }; }; config.networking.firewall.allowedTCPPorts = [ diff --git a/nixos/access/nextcloud.nix b/nixos/access/nextcloud.nix deleted file mode 100644 index c868bd1b..00000000 --- a/nixos/access/nextcloud.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ - config, - lib, - meta, - ... -}: -with lib; { - services.nginx.virtualHosts."cloud.${config.networking.domain}" = { - locations = { - "/".proxyPass = meta.tailnet.yukari.ppp 4 80 "nextcloud/"; - }; - }; -} diff --git a/nixos/access/ombi.nix b/nixos/access/ombi.nix deleted file mode 100644 index 9df495a2..00000000 --- a/nixos/access/ombi.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - config, - lib, -}: let - inherit (lib.modules) mkIf mkDefault mkOptionDefault; - cfg = config.services.ombi; - access = config.services.nginx.access.ombi; - proxyPass = mkDefault "https://${access.host}:${toString access.port}"; - locations = { - "/" = { - inherit proxyPass; - }; - }; -in { - options.services.nginx.access.ombi = with lib.types; { - host = mkOption { - type = str; - }; - domain = mkOption { - type = str; - default = "ombi.${config.networking.domain}"; - }; - port = mkOption { - type = port; - }; - }; - config.services.nginx = { - access.ombi = mkIf cfg.enable { - host = mkOptionDefault "localhost"; - port = mkOptionDefault cfg.port; - }; - virtualHosts = { - ${access.domain} = { - inherit locations; - }; - }; - }; -} diff --git a/nixos/access/plex.nix b/nixos/access/plex.nix index dc0d9788..b2a8e5ac 100644 --- a/nixos/access/plex.nix +++ b/nixos/access/plex.nix @@ -13,14 +13,6 @@ in { url = mkOption { type = str; }; - domain = mkOption { - type = str; - default = "plex.${config.networking.domain}"; - }; - localDomain = mkOption { - type = str; - default = "plex.local.${config.networking.domain}"; - }; externalPort = mkOption { type = nullOr port; default = null; @@ -51,33 +43,25 @@ in { proxy_redirect off; proxy_buffering off; ''; - location = { + locations."/" = { proxy.websocket.enable = true; proxyPass = access.url; }; + name.shortServer = mkDefault "plex"; + kTLS = mkDefault true; in { - ${access.domain} = { - locations."/" = location; - kTLS = mkDefault true; - inherit extraConfig; + plex = { + inherit name locations extraConfig kTLS; }; - ${access.localDomain} = { + plex'local = { + inherit name locations extraConfig kTLS; local.enable = true; - locations."/" = location; - kTLS = mkDefault true; - inherit extraConfig; }; plex-external = mkIf (access.externalPort != null) { - serverName = mkDefault access.domain; + serverName = mkDefault "plex.${config.networking.domain}"; default = mkDefault true; - listen = - map (addr: { - inherit addr; - port = access.externalPort; - }) - nginx.defaultListenAddresses; - locations."/" = location; - inherit extraConfig; + listenPorts.external.port = access.externalPort; + inherit extraConfig locations; }; }; }; diff --git a/nixos/access/radarr.nix b/nixos/access/radarr.nix deleted file mode 100644 index 5bf865c0..00000000 --- a/nixos/access/radarr.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - config, - lib, -}: let - inherit (lib.modules) mkIf mkDefault mkOptionDefault; - cfg = config.services.radarr; - access = config.services.nginx.access.radarr; - proxyPass = mkDefault "https://${access.host}:${toString access.port}"; - locations = { - "/" = { - inherit proxyPass; - }; - }; -in { - options.services.nginx.access.radarr = with lib.types; { - host = mkOption { - type = str; - }; - domain = mkOption { - type = str; - default = "radarr.${config.networking.domain}"; - }; - port = mkOption { - type = port; - default = cfg.port; - }; - }; - config.services.nginx = { - access.radarr = mkIf cfg.enable { - host = mkOptionDefault "localhost"; - }; - virtualHosts = { - ${access.domain} = { - inherit locations; - }; - }; - }; -} diff --git a/nixos/access/sonarr.nix b/nixos/access/sonarr.nix deleted file mode 100644 index fbb0012d..00000000 --- a/nixos/access/sonarr.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - config, - lib, -}: let - inherit (lib.modules) mkIf mkDefault mkOptionDefault; - cfg = config.services.sonarr; - access = config.services.nginx.access.sonarr; - proxyPass = mkDefault "https://${access.host}:${toString access.port}"; - locations = { - "/" = { - inherit proxyPass; - }; - }; -in { - options.services.nginx.access.sonarr = with lib.types; { - host = mkOption { - type = str; - }; - domain = mkOption { - type = str; - default = "sonarr.${config.networking.domain}"; - }; - port = mkOption { - type = port; - default = cfg.port; - }; - }; - config.services.nginx = { - access.sonarr = mkIf cfg.enable { - host = mkOptionDefault "localhost"; - }; - virtualHosts = { - ${access.domain} = { - inherit locations; - }; - }; - }; -} diff --git a/nixos/access/tautulli.nix b/nixos/access/tautulli.nix deleted file mode 100644 index 11a33da3..00000000 --- a/nixos/access/tautulli.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - config, - lib, -}: let - inherit (lib.modules) mkIf mkDefault mkOptionDefault; - cfg = config.services.tautulli; - access = config.services.nginx.access.tautulli; - proxyPass = mkDefault "https://${access.host}:${toString access.port}"; - locations = { - "/" = { - inherit proxyPass; - }; - }; -in { - options.services.nginx.access.tautulli = with lib.types; { - host = mkOption { - type = str; - }; - domain = mkOption { - type = str; - default = "tautulli.${config.networking.domain}"; - }; - port = mkOption { - type = port; - }; - }; - config.services.nginx = { - access.tautulli = mkIf cfg.enable { - host = mkOptionDefault "localhost"; - port = mkOptionDefault cfg.port; - }; - virtualHosts = { - ${access.domain} = { - inherit locations; - }; - }; - }; -} diff --git a/nixos/access/vouch.nix b/nixos/access/vouch.nix index 35e9c3a3..57959be9 100644 --- a/nixos/access/vouch.nix +++ b/nixos/access/vouch.nix @@ -14,22 +14,6 @@ in { url = mkOption { type = str; }; - domain = mkOption { - type = str; - default = "login.${networking.domain}"; - }; - localDomain = mkOption { - type = str; - default = "login.local.${networking.domain}"; - }; - tailDomain = mkOption { - type = str; - default = "login.tail.${networking.domain}"; - }; - useACMEHost = mkOption { - type = nullOr str; - default = null; - }; }; config.services.nginx = { access.vouch = mkIf cfg.enable { @@ -51,42 +35,52 @@ in { ''; }; "/validate" = {config, ...}: { + proxied.enable = true; proxyPass = mkDefault (access.url + "/validate"); - recommendedProxySettings = mkDefault false; - extraConfig = - if config.local.trusted - then '' - if ($http_x_host = ''') { - set $http_x_host $host; - } - proxy_set_header Host $http_x_host; - '' - else '' - proxy_set_header Host $host; - ''; + proxy.headers.enableRecommended = true; + local.denyGlobal = true; + extraConfig = '' + set $x_proxy_host $x_forwarded_host; + ''; }; }; - localLocations = kanidmDomain: { - "/".extraConfig = '' - proxy_redirect $scheme://sso.${networking.domain}/ $scheme://${kanidmDomain}/; - ''; + localLocations = kanidmDomain: mkIf nginx.vouch.localSso.enable { + "/" = { + proxied.xvars.enable = true; + extraConfig = '' + proxy_redirect https://sso.${networking.domain}/ $x_scheme://${kanidmDomain}/; + ''; + }; }; + name.shortServer = mkDefault "login"; in { - ${access.localDomain} = mkIf (access.useACMEHost != null) { - local.enable = true; - locations = mkMerge [ - locations - ]; - useACMEHost = mkDefault access.useACMEHost; - forceSSL = true; + vouch = { + inherit name locations; + ssl.force = true; }; - ${access.tailDomain} = mkIf tailscale.enable { + vouch'local = { + name = { + inherit (name) shortServer; + qualifier = mkDefault "local"; + includeTailscale = false; + }; + local.enable = true; + ssl.force = true; + locations = mkMerge [ + locations + (localLocations "sso.local.${networking.domain}") + ]; + }; + vouch'tail = mkIf tailscale.enable { + name = { + inherit (name) shortServer; + qualifier = mkDefault "tail"; + }; local.enable = true; locations = mkMerge [ locations + (localLocations "sso.tail.${networking.domain}") ]; - useACMEHost = mkDefault access.useACMEHost; - addSSL = mkIf (access.useACMEHost != null) (mkDefault true); }; }; }; diff --git a/nixos/access/zigbee2mqtt.nix b/nixos/access/zigbee2mqtt.nix index 305bb75a..0d73c8f3 100644 --- a/nixos/access/zigbee2mqtt.nix +++ b/nixos/access/zigbee2mqtt.nix @@ -7,47 +7,35 @@ inherit (lib.modules) mkIf mkDefault mkOptionDefault; cfg = config.services.zigbee2mqtt; access = config.services.nginx.access.zigbee2mqtt; - location = { + locations."/" = { proxy.websocket.enable = true; proxyPass = mkDefault "http://${access.host}:${toString access.port}"; }; + name.shortServer = mkDefault "z2m"; in { options.services.nginx.access.zigbee2mqtt = with lib.types; { host = mkOption { type = str; }; - domain = mkOption { - type = str; - }; - localDomain = mkOption { - type = str; - default = "z2m.local.${config.networking.domain}"; - }; - tailDomain = mkOption { - type = str; - default = "z2m.tail.${config.networking.domain}"; - }; port = mkOption { type = port; }; }; config.services.nginx = { access.zigbee2mqtt = mkIf cfg.enable { - domain = mkOptionDefault cfg.domain; host = mkOptionDefault "localhost"; port = mkIf (cfg.settings ? frontend.port) ( mkOptionDefault cfg.settings.frontend.port ); }; virtualHosts = { - ${access.domain} = { + zigbee2mqtt = { + inherit name locations; vouch.enable = true; - locations."/" = location; }; - ${access.localDomain} = { - serverAliases = mkIf config.services.tailscale.enable [access.tailDomain]; + zigbee2mqtt'local = { + inherit name locations; local.enable = true; - locations."/" = location; }; }; }; diff --git a/nixos/keycloak.nix b/nixos/keycloak.nix index 17ba5e23..5c1a703c 100644 --- a/nixos/keycloak.nix +++ b/nixos/keycloak.nix @@ -43,6 +43,7 @@ in { settings = { hostname = mkDefault hostname; proxy = mkDefault (if cfg.sslCertificate != null then "reencrypt" else "edge"); + proxy-headers = mkDefault "xforwarded"; }; sslCertificate = mkDefault "${cert}/fullchain.pem"; diff --git a/nixos/secrets/vouch.yaml b/nixos/secrets/vouch.yaml index 28f3f58c..4dd0fcb5 100644 --- a/nixos/secrets/vouch.yaml +++ b/nixos/secrets/vouch.yaml @@ -1,4 +1,4 @@ -vouch-client-secret: ENC[AES256_GCM,data:RWGjoC+L0FilUipBgvCy5t1bJEzDM8THc/m6RjwSPs9qPqfQCbSQWt/XXtQMR0VJ,iv:PJREZcXjLf3JVU4W5jD/6ruoaCIUV5TRocrmb1PjQeE=,tag:ZgKi+rI4ok7aIB3TOCXFKg==,type:str] +vouch-client-secret: ENC[AES256_GCM,data:gmCOrC3FDSUw/V1FZywiq0MWgKTK7j2ojb/fZahFS4g=,iv:D6UfdfeRaqzEhK9yVsc0TfIfQ/EBzWdtzLt/vUKPR8I=,tag:EZ+XHvi0gnhvJ6s1d6KviA==,type:str] vouch-jwt: ENC[AES256_GCM,data:7G1/pzEmR7NM7eFb2wED4HR/A00TNdBjBs/OdziDgIuPttqp4AeLRnJ0UhRps5taEx2cTH0U5GyCR/A9ef9hfA==,iv:ugOuH35frzoT6lX9UTJjzoTm2OTCqS3sNJGq8TfViEY=,tag:jvv4DkLwMB9ytefpGpIqPQ==,type:str] sops: shamir_threshold: 1 @@ -70,8 +70,8 @@ sops: RkQvakRmdjB3ME1rbnNTWjVDQU5QSmcKi1KhB8zpSLlaCgSelaEYdtOGHFLlc+Z3 hagYdJqojaOYbTGVBkWAYK0Zfh++1/QbDYJH6ySjDC8mFFCqEdSuYQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-01-16T19:11:11Z" - mac: ENC[AES256_GCM,data:1J3dCx5ptr2ah2LbvoP/rcUzPlzm3wZvpWLffIvh7PriNJ6vx2xj5fFK9s2AhIunxAaef0KJLzwzcfNwxEkJO3M6QSf0UUw3wopah1W3ZKLE2H/Z8bNncaNzSuh6QODbYShSG2yK4HmQApd8R9NfKlAHsDno+aRhuh7OYM7CaLI=,iv:KzMfJDJOqYm2epLM6Epd44aRoU7uJcusCl6m6/+cDtQ=,tag:tQ8MQ1NWey4E1dFu2YnOQw==,type:str] + lastmodified: "2024-03-20T00:39:56Z" + mac: ENC[AES256_GCM,data:JY2ttbttavS4RqYEFf95BkiPrK1r4r6hXnoQMCqtoQmBhSbUF9X5gvxZuqBFF7as9KgwiWHXFJ6S0FccmDDcBA/QoGxI4IJoR4nEIp7Y/YHTY6Ni0vZfO27yAtGmnViXadOeVyFChVN6GjRnxLp/FaBdXxtjSH8x4sQqf/2VWCw=,iv:/pnWEOcclzw0xcpL6lwErJLOBE9tBk1pOZZe3ew20TM=,tag:WNWiSG7Buve8YxJb1XxFwg==,type:str] pgp: - created_at: "2024-03-19T02:39:12Z" enc: |- diff --git a/systems/hakurei/nixos.nix b/systems/hakurei/nixos.nix index 96eed1dd..08374916 100644 --- a/systems/hakurei/nixos.nix +++ b/systems/hakurei/nixos.nix @@ -11,6 +11,7 @@ tei = access.nixosFor "tei"; inherit (mediabox.services) plex; inherit (keycloak.services) vouch-proxy; + inherit (tei.services) home-assistant; inherit (config.services) nginx tailscale; in { imports = let @@ -31,11 +32,13 @@ in { nixos.access.nginx nixos.access.global nixos.access.gensokyo + nixos.access.keycloak nixos.access.vouch nixos.access.freeipa nixos.access.freepbx nixos.access.unifi nixos.access.kitchencam + nixos.access.home-assistant nixos.access.proxmox nixos.access.plex nixos.access.invidious @@ -61,14 +64,31 @@ in { }; security.acme.certs = let - inherit (nginx) access; + inherit (nginx) access virtualHosts; in { - ${access.vouch.localDomain} = { + keycloak = { inherit (nginx) group; + domain = virtualHosts.keycloak.serverName; extraDomainNames = mkMerge [ - (mkIf tailscale.enable [ - access.vouch.tailDomain - ]) + virtualHosts.keycloak.serverAliases + virtualHosts.keycloak'local.allServerNames + ]; + }; + home-assistant = { + inherit (nginx) group; + domain = virtualHosts.home-assistant.serverName; + extraDomainNames = mkMerge [ + virtualHosts.home-assistant.serverAliases + virtualHosts.home-assistant'local.allServerNames + ]; + }; + vouch = { + inherit (nginx) group; + domain = virtualHosts.vouch.serverName; + extraDomainNames = mkMerge [ + virtualHosts.vouch.serverAliases + virtualHosts.vouch'local.allServerNames + (mkIf tailscale.enable virtualHosts.vouch'tail.allServerNames) ]; }; ${access.unifi.domain} = { @@ -116,19 +136,20 @@ in { ]) ]; }; - ${access.plex.domain} = { - inherit (nginx) group; - extraDomainNames = [access.plex.localDomain]; - }; - ${access.kitchencam.domain} = { + plex = { inherit (nginx) group; + domain = virtualHosts.plex.serverName; extraDomainNames = mkMerge [ - [ - access.kitchencam.localDomain - ] - (mkIf tailscale.enable [ - access.kitchencam.tailDomain - ]) + virtualHosts.plex.serverAliases + virtualHosts.plex'local.allServerNames + ]; + }; + kitchencam = { + inherit (nginx) group; + domain = virtualHosts.kitchencam.serverName; + extraDomainNames = mkMerge [ + virtualHosts.kitchencam.serverAliases + virtualHosts.kitchencam'local.allServerNames ]; }; ${access.invidious.domain} = { @@ -153,7 +174,6 @@ in { }; access.vouch = assert vouch-proxy.enable; { url = "http://${keycloak.lib.access.hostnameForNetwork.local}:${toString vouch-proxy.settings.vouch.port}"; - useACMEHost = access.vouch.localDomain; }; access.unifi = { host = tei.lib.access.hostnameForNetwork.local; @@ -169,24 +189,40 @@ in { }; access.kitchencam = { streamPort = 41081; - useACMEHost = access.kitchencam.domain; }; access.invidious = { url = "http://${mediabox.lib.access.hostnameForNetwork.local}:${toString mediabox.services.invidious.port}"; }; virtualHosts = { + gensokyoZone.proxied.enable = "cloudflared"; + keycloak = { + # we're not the real sso record-holder, so don't respond globally.. + local.denyGlobal = true; + ssl.cert.name = "keycloak"; + }; + keycloak'local.ssl.cert.name = "keycloak"; + vouch.ssl.cert.name = "vouch"; + vouch'local.ssl.cert.name = "vouch"; + vouch'tail = mkIf tailscale.enable { + ssl.cert.name = "vouch"; + }; + home-assistant = { + # not the real hass record-holder, so don't respond globally.. + local.denyGlobal = true; + ssl.cert.name = "home-assistant"; + locations."/".proxyPass = "http://${tei.lib.access.hostnameForNetwork.tail}:${toString home-assistant.config.http.server_port}"; + }; + home-assistant'local.ssl.cert.name = "home-assistant"; ${access.freepbx.domain} = { local.enable = true; }; ${access.proxmox.domain} = { useACMEHost = access.proxmox.domain; }; - ${access.plex.domain} = { - addSSL = true; - useACMEHost = access.plex.domain; - }; - ${access.kitchencam.domain} = { - }; + plex.ssl.cert.name = "plex"; + plex'local.ssl.cert.name = "plex"; + kitchencam.ssl.cert.name = "kitchencam"; + kitchencam'local.ssl.cert.name = "kitchencam"; ${access.invidious.domain} = { useACMEHost = access.invidious.domain; forceSSL = true; diff --git a/systems/keycloak/nixos.nix b/systems/keycloak/nixos.nix index 9f297c72..76b01d82 100644 --- a/systems/keycloak/nixos.nix +++ b/systems/keycloak/nixos.nix @@ -17,18 +17,20 @@ tunnels.${tunnelId} = { default = "http_status:404"; credentialsFile = config.sops.secrets.cloudflared-tunnel-keycloak.path; - ingress = { - ${keycloak.settings.hostname} = assert keycloak.enable; let - scheme = if keycloak.sslCertificate != null then "https" else "http"; - port = keycloak.settings."${scheme}-port"; - in { - service = "${scheme}://localhost:${toString port}"; - originRequest.${if scheme == "https" then "noTLSVerify" else null} = true; + ingress = let + keycloakHost = if keycloak.settings.hostname != null then keycloak.settings.hostname else "sso.${config.networking.domain}"; + keyCloakScheme = if keycloak.sslCertificate != null then "https" else "http"; + keycloakPort = keycloak.settings."${keyCloakScheme}-port"; + in { + ${keycloakHost} = assert keycloak.enable; { + service = "${keyCloakScheme}://localhost:${toString keycloakPort}"; + originRequest.${if keyCloakScheme == "https" then "noTLSVerify" else null} = true; }; ${vouch-proxy.domain}.service = assert vouch-proxy.enable; "http://localhost:${toString vouch-proxy.settings.vouch.port}"; }; }; }; + sops.secrets.cloudflared-tunnel-keycloak = { owner = config.services.cloudflared.user; }; diff --git a/systems/reisen/setup.sh b/systems/reisen/setup.sh index e469bbdf..73c6f1af 100644 --- a/systems/reisen/setup.sh +++ b/systems/reisen/setup.sh @@ -153,9 +153,9 @@ chmod 0755 /rpool/caches/plex/tautulli/cache mkshared hass 100286 100286 0700 mkshared kanidm 100994 100993 0700 mkshared mosquitto 100246 100246 0700 -mkshared plex 100193 100193 0755 +mkshared plex 100193 100193 0750 mkshared postgresql 100071 100071 0750 -mkshared unifi 100990 100990 0755 +mkshared unifi 100990 100990 0750 mkshared zigbee2mqtt 100317 100317 0700 ln -sf /lib/systemd/system/auth-rpcgss-module.service /etc/systemd/system/ diff --git a/systems/tei/nixos.nix b/systems/tei/nixos.nix index 4690dac4..0a1c334a 100644 --- a/systems/tei/nixos.nix +++ b/systems/tei/nixos.nix @@ -17,7 +17,6 @@ in { nixos.postgres nixos.nginx nixos.access.zigbee2mqtt - nixos.access.home-assistant nixos.access.unifi nixos.unifi nixos.mosquitto @@ -27,13 +26,9 @@ in { ./cloudflared.nix ]; - services.nginx = let - inherit (config.services.nginx) access; - in { + services.nginx = { virtualHosts = { - ${access.zigbee2mqtt.domain} = { - local.denyGlobal = true; - }; + zigbee2mqtt.proxied.enable = "cloudflared"; }; }; diff --git a/tf/cloudflare_records.tf b/tf/cloudflare_records.tf index 955bea8e..82ddc006 100644 --- a/tf/cloudflare_records.tf +++ b/tf/cloudflare_records.tf @@ -19,12 +19,14 @@ module "hakurei_system_records" { "prox", "id", "login", + "sso", "ldap", "freeipa", "unifi", "pbx", "smb", "kitchen", + "home", "yt", ] global_subdomains = [ @@ -87,7 +89,6 @@ module "tewi_system_records" { local_subdomains = [ "mqtt", "z2m", - "home", "postgresql", ] }