refactor(nginx): ssl module

This commit is contained in:
arcnmx 2024-03-05 15:42:36 -08:00
parent 69c014b24e
commit a7e35fbc88
28 changed files with 794 additions and 546 deletions

View file

@ -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;
});
};
};
}

View file

@ -62,7 +62,7 @@
enable = mkOptionDefault virtualHost.local.enable; enable = mkOptionDefault virtualHost.local.enable;
denyGlobal = mkOptionDefault virtualHost.local.denyGlobal; denyGlobal = mkOptionDefault virtualHost.local.denyGlobal;
trusted = mkOptionDefault virtualHost.local.trusted; trusted = mkOptionDefault virtualHost.local.trusted;
emitDenyGlobal = virtualHost.local.emitDenyGlobal; emitDenyGlobal = config.local.denyGlobal && !virtualHost.local.emitDenyGlobal;
}; };
}; };
hostModule = {config, ...}: { hostModule = {config, ...}: {

View file

@ -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;
});
};
};
}

View file

@ -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;
});
};
};
}

View file

@ -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;
});
};
};
}

View file

@ -6,11 +6,123 @@
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkDefault; inherit (lib.modules) mkIf mkMerge mkBefore mkDefault;
inherit (config) networking; inherit (config) networking;
inherit (config.services) vouch-proxy tailscale; inherit (config.services) vouch-proxy nginx tailscale;
vouchModule = {config, ...}: { 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; { options = with lib.types; {
locations = mkOption {
type = attrsOf (submodule locationModule);
};
vouch = { vouch = {
enable = mkEnableOption "vouch auth proxy"; 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 { proxyOrigin = mkOption {
type = str; type = str;
default = "https://login.local.${networking.domain}"; default = "https://login.local.${networking.domain}";
@ -35,117 +147,32 @@
type = str; type = str;
default = "login.tail.${networking.domain}"; default = "login.tail.${networking.domain}";
}; };
authRequestDirective = mkOption { };
type = lines; virtualHosts = mkOption {
default = '' type = attrsOf (submodule hostModule);
auth_request /validate;
'';
};
}; };
}; };
config = mkMerge [ };
config.services.nginx = {
vouch = mkMerge [
{ {
vouch = mkIf vouch-proxy.enable { proxyOrigin = mkIf (tailscale.enable && !vouch-proxy.enable) (
proxyOrigin = let mkDefault "http://login.tail.${networking.domain}"
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}"
); );
} }
(mkIf config.vouch.enable { (mkIf vouch-proxy.enable {
extraConfig = '' proxyOrigin = let
${config.vouch.authRequestDirective} inherit (vouch-proxy.settings.vouch) listen port;
error_page 401 = @error401; host =
''; if listen == "0.0.0.0" || listen == "[::]"
locations = { then "localhost"
"/" = { else listen;
extraConfig = mkMerge [ in
'' mkDefault "http://${host}:${toString port}";
add_header Access-Control-Allow-Origin ${config.vouch.url}; authUrl = mkDefault vouch-proxy.authUrl;
add_header Access-Control-Allow-Origin ${config.vouch.authUrl}; url = mkDefault vouch-proxy.url;
'' doubleProxy = mkDefault false;
(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;
''
];
};
};
}) })
]; ];
}; };
in {
options = with lib.types; {
services.nginx.virtualHosts = mkOption {
type = attrsOf (submodule vouchModule);
};
};
} }

View file

@ -7,7 +7,6 @@
}; };
config = mkIf config.proxy.websocket.enable { config = mkIf config.proxy.websocket.enable {
extraConfig = '' extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
''; '';

View file

@ -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;
};
};
};
}

View file

@ -7,7 +7,8 @@
}: let }: let
inherit (lib.modules) mkDefault; inherit (lib.modules) mkDefault;
in { in {
services.nginx.virtualHosts.${config.networking.domain} = { services.nginx.virtualHosts.gensokyoZone = {
serverName = config.networking.domain;
locations = { locations = {
"/" = { "/" = {
root = inputs.website.packages.${pkgs.system}.gensokyoZone; root = inputs.website.packages.${pkgs.system}.gensokyoZone;

View file

@ -3,20 +3,29 @@
lib, lib,
... ...
}: let }: let
inherit (lib.modules) mkIf mkDefault; inherit (lib.modules) mkIf mkMerge mkDefault;
inherit (config.services) home-assistant tailscale; inherit (config.services) home-assistant nginx;
proxyPass = "http://localhost:${toString home-assistant.config.http.server_port}/"; name.shortServer = mkDefault "home";
listenPorts = {
http = { };
https.ssl = true;
hass = mkIf (!home-assistant.enable) { port = mkDefault home-assistant.config.http.server_port; };
};
in { in {
services.nginx.virtualHosts."home.local.${config.networking.domain}" = mkIf home-assistant.enable { config.services.nginx.virtualHosts = {
local.enable = mkDefault true; home-assistant = {
locations."/" = { inherit name listenPorts;
inherit proxyPass; locations."/".proxyPass = mkIf home-assistant.enable (mkDefault
}; "http://localhost:${toString home-assistant.config.http.server_port}"
}; );
services.nginx.virtualHosts."home.tail.${config.networking.domain}" = mkIf (home-assistant.enable && tailscale.enable) { };
local.enable = mkDefault true; home-assistant'local = {
locations."/" = { inherit name listenPorts;
inherit proxyPass; 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 ];
} }

View file

@ -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;
};
};
};
}

54
nixos/access/keycloak.nix Normal file
View file

@ -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/;
'';
};
};
};
}

View file

@ -27,18 +27,6 @@ in {
type = str; type = str;
default = "http://${access.host}:${toString access.streamPort}"; 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 { useACMEHost = mkOption {
type = nullOr str; type = nullOr str;
default = null; default = null;
@ -46,7 +34,6 @@ in {
}; };
config.services.nginx = { config.services.nginx = {
virtualHosts = let virtualHosts = let
addSSL = access.useACMEHost != null || virtualHosts.${access.domain}.addSSL || virtualHosts.${access.domain}.forceSSL;
extraConfig = '' extraConfig = ''
proxy_redirect off; proxy_redirect off;
proxy_buffering off; proxy_buffering off;
@ -64,47 +51,22 @@ in {
inherit extraConfig; inherit extraConfig;
}; };
}; };
streamListen = {config, ...}: { listenPorts = {
listen = http = { };
concatMap (addr: [ https.ssl = true;
(mkIf config.addSSL { stream.port = mkDefault access.streamPort;
inherit addr;
port = nginx.defaultSSLListenPort;
ssl = true;
})
{
inherit addr;
port = nginx.defaultHTTPListenPort;
}
{
inherit addr;
port = access.streamPort;
}
])
nginx.defaultListenAddresses;
}; };
name.shortServer = mkDefault "kitchen";
kTLS = mkDefault true;
in { in {
${access.domain} = mkMerge [ kitchencam = {
{ inherit name locations listenPorts kTLS;
vouch.enable = true; vouch.enable = true;
kTLS = mkDefault true; };
inherit (access) useACMEHost; kitchencam'local = {
addSSL = mkDefault (access.useACMEHost != null); inherit name locations listenPorts kTLS;
inherit locations; local.enable = true;
} };
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
];
}; };
}; };
config.networking.firewall.allowedTCPPorts = [ config.networking.firewall.allowedTCPPorts = [

View file

@ -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/";
};
};
}

View file

@ -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;
};
};
};
}

View file

@ -13,14 +13,6 @@ in {
url = mkOption { url = mkOption {
type = str; type = str;
}; };
domain = mkOption {
type = str;
default = "plex.${config.networking.domain}";
};
localDomain = mkOption {
type = str;
default = "plex.local.${config.networking.domain}";
};
externalPort = mkOption { externalPort = mkOption {
type = nullOr port; type = nullOr port;
default = null; default = null;
@ -51,33 +43,25 @@ in {
proxy_redirect off; proxy_redirect off;
proxy_buffering off; proxy_buffering off;
''; '';
location = { locations."/" = {
proxy.websocket.enable = true; proxy.websocket.enable = true;
proxyPass = access.url; proxyPass = access.url;
}; };
name.shortServer = mkDefault "plex";
kTLS = mkDefault true;
in { in {
${access.domain} = { plex = {
locations."/" = location; inherit name locations extraConfig kTLS;
kTLS = mkDefault true;
inherit extraConfig;
}; };
${access.localDomain} = { plex'local = {
inherit name locations extraConfig kTLS;
local.enable = true; local.enable = true;
locations."/" = location;
kTLS = mkDefault true;
inherit extraConfig;
}; };
plex-external = mkIf (access.externalPort != null) { plex-external = mkIf (access.externalPort != null) {
serverName = mkDefault access.domain; serverName = mkDefault "plex.${config.networking.domain}";
default = mkDefault true; default = mkDefault true;
listen = listenPorts.external.port = access.externalPort;
map (addr: { inherit extraConfig locations;
inherit addr;
port = access.externalPort;
})
nginx.defaultListenAddresses;
locations."/" = location;
inherit extraConfig;
}; };
}; };
}; };

View file

@ -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;
};
};
};
}

View file

@ -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;
};
};
};
}

View file

@ -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;
};
};
};
}

View file

@ -14,22 +14,6 @@ in {
url = mkOption { url = mkOption {
type = str; 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 = { config.services.nginx = {
access.vouch = mkIf cfg.enable { access.vouch = mkIf cfg.enable {
@ -51,42 +35,52 @@ in {
''; '';
}; };
"/validate" = {config, ...}: { "/validate" = {config, ...}: {
proxied.enable = true;
proxyPass = mkDefault (access.url + "/validate"); proxyPass = mkDefault (access.url + "/validate");
recommendedProxySettings = mkDefault false; proxy.headers.enableRecommended = true;
extraConfig = local.denyGlobal = true;
if config.local.trusted extraConfig = ''
then '' set $x_proxy_host $x_forwarded_host;
if ($http_x_host = ''') { '';
set $http_x_host $host;
}
proxy_set_header Host $http_x_host;
''
else ''
proxy_set_header Host $host;
'';
}; };
}; };
localLocations = kanidmDomain: { localLocations = kanidmDomain: mkIf nginx.vouch.localSso.enable {
"/".extraConfig = '' "/" = {
proxy_redirect $scheme://sso.${networking.domain}/ $scheme://${kanidmDomain}/; proxied.xvars.enable = true;
''; extraConfig = ''
proxy_redirect https://sso.${networking.domain}/ $x_scheme://${kanidmDomain}/;
'';
};
}; };
name.shortServer = mkDefault "login";
in { in {
${access.localDomain} = mkIf (access.useACMEHost != null) { vouch = {
local.enable = true; inherit name locations;
locations = mkMerge [ ssl.force = true;
locations
];
useACMEHost = mkDefault access.useACMEHost;
forceSSL = 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; local.enable = true;
locations = mkMerge [ locations = mkMerge [
locations locations
(localLocations "sso.tail.${networking.domain}")
]; ];
useACMEHost = mkDefault access.useACMEHost;
addSSL = mkIf (access.useACMEHost != null) (mkDefault true);
}; };
}; };
}; };

View file

@ -7,47 +7,35 @@
inherit (lib.modules) mkIf mkDefault mkOptionDefault; inherit (lib.modules) mkIf mkDefault mkOptionDefault;
cfg = config.services.zigbee2mqtt; cfg = config.services.zigbee2mqtt;
access = config.services.nginx.access.zigbee2mqtt; access = config.services.nginx.access.zigbee2mqtt;
location = { locations."/" = {
proxy.websocket.enable = true; proxy.websocket.enable = true;
proxyPass = mkDefault "http://${access.host}:${toString access.port}"; proxyPass = mkDefault "http://${access.host}:${toString access.port}";
}; };
name.shortServer = mkDefault "z2m";
in { in {
options.services.nginx.access.zigbee2mqtt = with lib.types; { options.services.nginx.access.zigbee2mqtt = with lib.types; {
host = mkOption { host = mkOption {
type = str; 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 { port = mkOption {
type = port; type = port;
}; };
}; };
config.services.nginx = { config.services.nginx = {
access.zigbee2mqtt = mkIf cfg.enable { access.zigbee2mqtt = mkIf cfg.enable {
domain = mkOptionDefault cfg.domain;
host = mkOptionDefault "localhost"; host = mkOptionDefault "localhost";
port = mkIf (cfg.settings ? frontend.port) ( port = mkIf (cfg.settings ? frontend.port) (
mkOptionDefault cfg.settings.frontend.port mkOptionDefault cfg.settings.frontend.port
); );
}; };
virtualHosts = { virtualHosts = {
${access.domain} = { zigbee2mqtt = {
inherit name locations;
vouch.enable = true; vouch.enable = true;
locations."/" = location;
}; };
${access.localDomain} = { zigbee2mqtt'local = {
serverAliases = mkIf config.services.tailscale.enable [access.tailDomain]; inherit name locations;
local.enable = true; local.enable = true;
locations."/" = location;
}; };
}; };
}; };

View file

@ -43,6 +43,7 @@ in {
settings = { settings = {
hostname = mkDefault hostname; hostname = mkDefault hostname;
proxy = mkDefault (if cfg.sslCertificate != null then "reencrypt" else "edge"); proxy = mkDefault (if cfg.sslCertificate != null then "reencrypt" else "edge");
proxy-headers = mkDefault "xforwarded";
}; };
sslCertificate = mkDefault "${cert}/fullchain.pem"; sslCertificate = mkDefault "${cert}/fullchain.pem";

View file

@ -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] vouch-jwt: ENC[AES256_GCM,data:7G1/pzEmR7NM7eFb2wED4HR/A00TNdBjBs/OdziDgIuPttqp4AeLRnJ0UhRps5taEx2cTH0U5GyCR/A9ef9hfA==,iv:ugOuH35frzoT6lX9UTJjzoTm2OTCqS3sNJGq8TfViEY=,tag:jvv4DkLwMB9ytefpGpIqPQ==,type:str]
sops: sops:
shamir_threshold: 1 shamir_threshold: 1
@ -70,8 +70,8 @@ sops:
RkQvakRmdjB3ME1rbnNTWjVDQU5QSmcKi1KhB8zpSLlaCgSelaEYdtOGHFLlc+Z3 RkQvakRmdjB3ME1rbnNTWjVDQU5QSmcKi1KhB8zpSLlaCgSelaEYdtOGHFLlc+Z3
hagYdJqojaOYbTGVBkWAYK0Zfh++1/QbDYJH6ySjDC8mFFCqEdSuYQ== hagYdJqojaOYbTGVBkWAYK0Zfh++1/QbDYJH6ySjDC8mFFCqEdSuYQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-01-16T19:11:11Z" lastmodified: "2024-03-20T00:39:56Z"
mac: ENC[AES256_GCM,data:1J3dCx5ptr2ah2LbvoP/rcUzPlzm3wZvpWLffIvh7PriNJ6vx2xj5fFK9s2AhIunxAaef0KJLzwzcfNwxEkJO3M6QSf0UUw3wopah1W3ZKLE2H/Z8bNncaNzSuh6QODbYShSG2yK4HmQApd8R9NfKlAHsDno+aRhuh7OYM7CaLI=,iv:KzMfJDJOqYm2epLM6Epd44aRoU7uJcusCl6m6/+cDtQ=,tag:tQ8MQ1NWey4E1dFu2YnOQw==,type:str] mac: ENC[AES256_GCM,data:JY2ttbttavS4RqYEFf95BkiPrK1r4r6hXnoQMCqtoQmBhSbUF9X5gvxZuqBFF7as9KgwiWHXFJ6S0FccmDDcBA/QoGxI4IJoR4nEIp7Y/YHTY6Ni0vZfO27yAtGmnViXadOeVyFChVN6GjRnxLp/FaBdXxtjSH8x4sQqf/2VWCw=,iv:/pnWEOcclzw0xcpL6lwErJLOBE9tBk1pOZZe3ew20TM=,tag:WNWiSG7Buve8YxJb1XxFwg==,type:str]
pgp: pgp:
- created_at: "2024-03-19T02:39:12Z" - created_at: "2024-03-19T02:39:12Z"
enc: |- enc: |-

View file

@ -11,6 +11,7 @@
tei = access.nixosFor "tei"; tei = access.nixosFor "tei";
inherit (mediabox.services) plex; inherit (mediabox.services) plex;
inherit (keycloak.services) vouch-proxy; inherit (keycloak.services) vouch-proxy;
inherit (tei.services) home-assistant;
inherit (config.services) nginx tailscale; inherit (config.services) nginx tailscale;
in { in {
imports = let imports = let
@ -31,11 +32,13 @@ in {
nixos.access.nginx nixos.access.nginx
nixos.access.global nixos.access.global
nixos.access.gensokyo nixos.access.gensokyo
nixos.access.keycloak
nixos.access.vouch nixos.access.vouch
nixos.access.freeipa nixos.access.freeipa
nixos.access.freepbx nixos.access.freepbx
nixos.access.unifi nixos.access.unifi
nixos.access.kitchencam nixos.access.kitchencam
nixos.access.home-assistant
nixos.access.proxmox nixos.access.proxmox
nixos.access.plex nixos.access.plex
nixos.access.invidious nixos.access.invidious
@ -61,14 +64,31 @@ in {
}; };
security.acme.certs = let security.acme.certs = let
inherit (nginx) access; inherit (nginx) access virtualHosts;
in { in {
${access.vouch.localDomain} = { keycloak = {
inherit (nginx) group; inherit (nginx) group;
domain = virtualHosts.keycloak.serverName;
extraDomainNames = mkMerge [ extraDomainNames = mkMerge [
(mkIf tailscale.enable [ virtualHosts.keycloak.serverAliases
access.vouch.tailDomain 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} = { ${access.unifi.domain} = {
@ -116,19 +136,20 @@ in {
]) ])
]; ];
}; };
${access.plex.domain} = { plex = {
inherit (nginx) group;
extraDomainNames = [access.plex.localDomain];
};
${access.kitchencam.domain} = {
inherit (nginx) group; inherit (nginx) group;
domain = virtualHosts.plex.serverName;
extraDomainNames = mkMerge [ extraDomainNames = mkMerge [
[ virtualHosts.plex.serverAliases
access.kitchencam.localDomain virtualHosts.plex'local.allServerNames
] ];
(mkIf tailscale.enable [ };
access.kitchencam.tailDomain kitchencam = {
]) inherit (nginx) group;
domain = virtualHosts.kitchencam.serverName;
extraDomainNames = mkMerge [
virtualHosts.kitchencam.serverAliases
virtualHosts.kitchencam'local.allServerNames
]; ];
}; };
${access.invidious.domain} = { ${access.invidious.domain} = {
@ -153,7 +174,6 @@ in {
}; };
access.vouch = assert vouch-proxy.enable; { access.vouch = assert vouch-proxy.enable; {
url = "http://${keycloak.lib.access.hostnameForNetwork.local}:${toString vouch-proxy.settings.vouch.port}"; url = "http://${keycloak.lib.access.hostnameForNetwork.local}:${toString vouch-proxy.settings.vouch.port}";
useACMEHost = access.vouch.localDomain;
}; };
access.unifi = { access.unifi = {
host = tei.lib.access.hostnameForNetwork.local; host = tei.lib.access.hostnameForNetwork.local;
@ -169,24 +189,40 @@ in {
}; };
access.kitchencam = { access.kitchencam = {
streamPort = 41081; streamPort = 41081;
useACMEHost = access.kitchencam.domain;
}; };
access.invidious = { access.invidious = {
url = "http://${mediabox.lib.access.hostnameForNetwork.local}:${toString mediabox.services.invidious.port}"; url = "http://${mediabox.lib.access.hostnameForNetwork.local}:${toString mediabox.services.invidious.port}";
}; };
virtualHosts = { 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} = { ${access.freepbx.domain} = {
local.enable = true; local.enable = true;
}; };
${access.proxmox.domain} = { ${access.proxmox.domain} = {
useACMEHost = access.proxmox.domain; useACMEHost = access.proxmox.domain;
}; };
${access.plex.domain} = { plex.ssl.cert.name = "plex";
addSSL = true; plex'local.ssl.cert.name = "plex";
useACMEHost = access.plex.domain; kitchencam.ssl.cert.name = "kitchencam";
}; kitchencam'local.ssl.cert.name = "kitchencam";
${access.kitchencam.domain} = {
};
${access.invidious.domain} = { ${access.invidious.domain} = {
useACMEHost = access.invidious.domain; useACMEHost = access.invidious.domain;
forceSSL = true; forceSSL = true;

View file

@ -17,18 +17,20 @@
tunnels.${tunnelId} = { tunnels.${tunnelId} = {
default = "http_status:404"; default = "http_status:404";
credentialsFile = config.sops.secrets.cloudflared-tunnel-keycloak.path; credentialsFile = config.sops.secrets.cloudflared-tunnel-keycloak.path;
ingress = { ingress = let
${keycloak.settings.hostname} = assert keycloak.enable; let keycloakHost = if keycloak.settings.hostname != null then keycloak.settings.hostname else "sso.${config.networking.domain}";
scheme = if keycloak.sslCertificate != null then "https" else "http"; keyCloakScheme = if keycloak.sslCertificate != null then "https" else "http";
port = keycloak.settings."${scheme}-port"; keycloakPort = keycloak.settings."${keyCloakScheme}-port";
in { in {
service = "${scheme}://localhost:${toString port}"; ${keycloakHost} = assert keycloak.enable; {
originRequest.${if scheme == "https" then "noTLSVerify" else null} = true; 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}"; ${vouch-proxy.domain}.service = assert vouch-proxy.enable; "http://localhost:${toString vouch-proxy.settings.vouch.port}";
}; };
}; };
}; };
sops.secrets.cloudflared-tunnel-keycloak = { sops.secrets.cloudflared-tunnel-keycloak = {
owner = config.services.cloudflared.user; owner = config.services.cloudflared.user;
}; };

View file

@ -153,9 +153,9 @@ chmod 0755 /rpool/caches/plex/tautulli/cache
mkshared hass 100286 100286 0700 mkshared hass 100286 100286 0700
mkshared kanidm 100994 100993 0700 mkshared kanidm 100994 100993 0700
mkshared mosquitto 100246 100246 0700 mkshared mosquitto 100246 100246 0700
mkshared plex 100193 100193 0755 mkshared plex 100193 100193 0750
mkshared postgresql 100071 100071 0750 mkshared postgresql 100071 100071 0750
mkshared unifi 100990 100990 0755 mkshared unifi 100990 100990 0750
mkshared zigbee2mqtt 100317 100317 0700 mkshared zigbee2mqtt 100317 100317 0700
ln -sf /lib/systemd/system/auth-rpcgss-module.service /etc/systemd/system/ ln -sf /lib/systemd/system/auth-rpcgss-module.service /etc/systemd/system/

View file

@ -17,7 +17,6 @@ in {
nixos.postgres nixos.postgres
nixos.nginx nixos.nginx
nixos.access.zigbee2mqtt nixos.access.zigbee2mqtt
nixos.access.home-assistant
nixos.access.unifi nixos.access.unifi
nixos.unifi nixos.unifi
nixos.mosquitto nixos.mosquitto
@ -27,13 +26,9 @@ in {
./cloudflared.nix ./cloudflared.nix
]; ];
services.nginx = let services.nginx = {
inherit (config.services.nginx) access;
in {
virtualHosts = { virtualHosts = {
${access.zigbee2mqtt.domain} = { zigbee2mqtt.proxied.enable = "cloudflared";
local.denyGlobal = true;
};
}; };
}; };

View file

@ -19,12 +19,14 @@ module "hakurei_system_records" {
"prox", "prox",
"id", "id",
"login", "login",
"sso",
"ldap", "ldap",
"freeipa", "freeipa",
"unifi", "unifi",
"pbx", "pbx",
"smb", "smb",
"kitchen", "kitchen",
"home",
"yt", "yt",
] ]
global_subdomains = [ global_subdomains = [
@ -87,7 +89,6 @@ module "tewi_system_records" {
local_subdomains = [ local_subdomains = [
"mqtt", "mqtt",
"z2m", "z2m",
"home",
"postgresql", "postgresql",
] ]
} }