feat(nginx): enable option for vhost/location

This commit is contained in:
arcnmx 2024-03-21 11:25:31 -07:00
parent a6fced79d5
commit 8f227a1bc5
7 changed files with 116 additions and 31 deletions

View file

@ -0,0 +1,47 @@
{
lib,
...
}: let
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkOverride;
mkExtraForce = mkOverride 25;
locationModule = { config, virtualHost, ... }: {
options = with lib.types; {
enable = mkEnableOption "enable location" // {
default = true;
};
};
config = mkIf (!virtualHost.enable || !config.enable) {
extraConfig = mkExtraForce "deny all;";
};
};
hostModule = { config, ... }: {
options = with lib.types; {
enable = mkEnableOption "enable server" // {
default = true;
};
locations = mkOption {
type = attrsOf (submoduleWith {
modules = [ locationModule ];
shorthandOnlyDefinesConfig = true;
});
};
};
config = mkIf (!config.enable) {
default = mkExtraForce false;
extraConfig = mkExtraForce ''
deny all;
'';
};
};
in {
options = with lib.types; {
services.nginx.virtualHosts = mkOption {
type = attrsOf (submoduleWith {
modules = [ hostModule ];
shorthandOnlyDefinesConfig = true;
});
};
};
}

View file

@ -4,17 +4,26 @@
... ...
}: let }: let
inherit (lib.options) mkOption mkEnableOption; inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkDefault mkOptionDefault mkForce mkOverride; inherit (lib.modules) mkIf mkMerge mkOptionDefault mkForce mkOverride mkRenamedOptionModule;
inherit (lib.attrsets) mapAttrsToList filterAttrs removeAttrs; inherit (lib.attrsets) attrValues mapAttrs mapAttrsToList;
inherit (lib.lists) concatMap; inherit (lib.lists) filter concatMap;
mkAlmostOptionDefault = mkOverride 1250; mkAlmostOptionDefault = mkOverride 1250;
inherit (config.services) nginx; inherit (config.services) nginx;
extraListenAttrs = [ "enable" ];
listenModule = { config, virtualHost, ... }: { listenModule = { config, virtualHost, ... }: {
options = with lib.types; { options = with lib.types; {
enable = mkEnableOption "this port" // { enable = mkEnableOption "this port" // {
default = true; default = true;
}; };
addr = mkOption {
type = nullOr str;
default = null;
description = "shorthand to override config.addresses";
};
addresses = mkOption {
type = listOf str;
description = "applies to all listen addresses unless set";
defaultText = "virtualHost.listenAddresses'";
};
ssl = mkOption { ssl = mkOption {
type = bool; type = bool;
default = false; default = false;
@ -22,23 +31,42 @@
port = mkOption { port = mkOption {
type = nullOr port; type = nullOr port;
}; };
extraParameters = mkOption {
type = listOf str;
default = [ ];
};
proxyProtocol = mkOption {
type = bool;
default = false;
};
}; };
config = { config = {
enable = mkIf (config.ssl && !virtualHost.ssl.enable) (mkForce false); enable = mkIf (config.ssl && !virtualHost.ssl.enable) (mkForce false);
_module.freeformType = with lib.types; attrsOf (oneOf [
str (listOf str) (nullOr port) bool
]);
port = mkOptionDefault ( port = mkOptionDefault (
if config.ssl then nginx.defaultSSLListenPort else nginx.defaultHTTPListenPort if config.ssl then nginx.defaultSSLListenPort else nginx.defaultHTTPListenPort
); );
addresses = mkMerge [
(mkOptionDefault virtualHost.listenAddresses')
(mkIf (config.addr != null) (mkAlmostOptionDefault [ config.addr ]))
];
}; };
}; };
hostModule = { config, ... }: let hostModule = { config, ... }: let
cfg = config.listenPorts; cfg = attrValues config.listen';
enabledPorts = filterAttrs (_: port: port.enable) cfg; enabledCfg = filter (port: port.enable) cfg;
mkListen = listen: addr: let
listenAttrs = {
inherit addr;
inherit (listen) port ssl extraParameters proxyProtocol;
};
in mapAttrs (_: mkAlmostOptionDefault) listenAttrs;
mkListens = listen: map (mkListen listen) listen.addresses;
in { in {
imports = [
(mkRenamedOptionModule [ "listenPorts" ] [ "listen'" ])
];
options = with lib.types; { options = with lib.types; {
listenPorts = mkOption { listen' = mkOption {
type = attrsOf (submoduleWith { type = attrsOf (submoduleWith {
modules = [ listenModule ]; modules = [ listenModule ];
specialArgs = { specialArgs = {
@ -47,15 +75,19 @@
}); });
default = { }; default = { };
}; };
listenAddresses' = mkOption {
type = listOf str;
description = "listenAddresses or defaultListenAddresses if empty";
};
}; };
config = { config = {
listen = let enable = mkIf (cfg != [ ] && enabledCfg == [ ]) (mkForce false);
addresses = if config.listenAddresses != [ ] then config.listenAddresses else nginx.defaultListenAddresses; listenAddresses' = mkOptionDefault (
in mkIf (cfg != { }) (mkAlmostOptionDefault ( if config.listenAddresses != [ ] then config.listenAddresses else nginx.defaultListenAddresses
concatMap (addr: mapAttrsToList (_: listen: { );
addr = mkDefault addr; listen = mkIf (cfg != { }) (mkAlmostOptionDefault (
} // removeAttrs listen extraListenAttrs) enabledPorts) addresses concatMap (mkListens) enabledCfg
)); ));
}; };
}; };

View file

@ -9,12 +9,16 @@
listenPorts = { listenPorts = {
http = { }; http = { };
https.ssl = true; https.ssl = true;
hass = mkIf (!home-assistant.enable) { port = mkDefault home-assistant.config.http.server_port; }; hass = {
enable = !home-assistant.enable;
port = mkDefault home-assistant.config.http.server_port;
extraParameters = [ "default_server" ];
};
}; };
in { in {
config.services.nginx.virtualHosts = { config.services.nginx.virtualHosts = {
home-assistant = { home-assistant = {
inherit name listenPorts; inherit name;
locations."/" = { locations."/" = {
proxy = { proxy = {
websocket.enable = true; websocket.enable = true;
@ -33,7 +37,7 @@ in {
websocket.enable = true; websocket.enable = true;
headers.enableRecommended = true; headers.enableRecommended = true;
}; };
proxyPass = mkIf (!home-assistant.enable) (mkDefault proxyPass = (mkDefault
nginx.virtualHosts.home-assistant.locations."/".proxyPass nginx.virtualHosts.home-assistant.locations."/".proxyPass
); );
}; };

View file

@ -52,17 +52,20 @@ in {
in { in {
plex = { plex = {
inherit name locations extraConfig kTLS; inherit name locations extraConfig kTLS;
listenPorts = {
http = { };
https.ssl = true;
external = {
enable = mkDefault (access.externalPort != null);
port = mkDefault access.externalPort;
extraParameters = [ "default_server" ];
};
};
}; };
plex'local = { plex'local = {
inherit name locations extraConfig kTLS; inherit name locations extraConfig kTLS;
local.enable = true; local.enable = true;
}; };
plex-external = mkIf (access.externalPort != null) {
serverName = mkDefault "plex.${config.networking.domain}";
default = mkDefault true;
listenPorts.external.port = access.externalPort;
inherit extraConfig locations;
};
}; };
}; };
config.networking.firewall.allowedTCPPorts = mkIf (access.externalPort != null) [ config.networking.firewall.allowedTCPPorts = mkIf (access.externalPort != null) [

View file

@ -43,9 +43,9 @@ in {
listenPorts.management = { listenPorts.management = {
port = access.managementPort; port = access.managementPort;
ssl = true; ssl = true;
extraParameters = [ "default_server" ];
}; };
ssl.force = true; ssl.force = true;
default = mkDefault true;
inherit name locations extraConfig kTLS; inherit name locations extraConfig kTLS;
}; };
unifi = { unifi = {

View file

@ -71,7 +71,8 @@ in {
(localLocations "sso.local.${networking.domain}") (localLocations "sso.local.${networking.domain}")
]; ];
}; };
vouch'tail = mkIf tailscale.enable { vouch'tail = {
enable = mkDefault tailscale.enable;
name = { name = {
inherit (name) shortServer; inherit (name) shortServer;
qualifier = mkDefault "tail"; qualifier = mkDefault "tail";

View file

@ -106,7 +106,7 @@ in {
extraDomainNames = mkMerge [ extraDomainNames = mkMerge [
virtualHosts.vouch.serverAliases virtualHosts.vouch.serverAliases
virtualHosts.vouch'local.allServerNames virtualHosts.vouch'local.allServerNames
(mkIf tailscale.enable virtualHosts.vouch'tail.allServerNames) (mkIf virtualHosts.vouch'tail.enable virtualHosts.vouch'tail.allServerNames)
]; ];
}; };
unifi = { unifi = {
@ -219,9 +219,7 @@ in {
keycloak'local.ssl.cert.name = "keycloak"; keycloak'local.ssl.cert.name = "keycloak";
vouch.ssl.cert.name = "vouch"; vouch.ssl.cert.name = "vouch";
vouch'local.ssl.cert.name = "vouch"; vouch'local.ssl.cert.name = "vouch";
vouch'tail = mkIf tailscale.enable { vouch'tail.ssl.cert.name = "vouch";
ssl.cert.name = "vouch";
};
unifi = { unifi = {
# we're not the real unifi record-holder, so don't respond globally.. # we're not the real unifi record-holder, so don't respond globally..
local.denyGlobal = true; local.denyGlobal = true;