mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 20:39:18 -08:00
feat(exports): service access
This commit is contained in:
parent
91918b8061
commit
871b1c5b2d
69 changed files with 1317 additions and 509 deletions
|
|
@ -8,10 +8,12 @@
|
|||
}: let
|
||||
inherit (inputs.self) nixosConfigurations;
|
||||
inherit (inputs.self.lib) systems;
|
||||
inherit (inputs.self.lib.lib) domain;
|
||||
inherit (inputs.self.lib.lib) domain mkAddress6;
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
inherit (lib.attrsets) mapAttrs attrValues;
|
||||
inherit (lib.lists) findSingle;
|
||||
inherit (lib.trivial) mapNullable;
|
||||
cfg = config.access;
|
||||
systemConfig = config;
|
||||
systemAccess = access;
|
||||
|
|
@ -42,20 +44,29 @@
|
|||
config = {
|
||||
networking.access = {
|
||||
moduleArgAttrs = let
|
||||
mkGetAddressFor = addressForAttr: hostName: network: let
|
||||
mkGetAddressFor = nameAllowed: addressForAttr: hostName: network: let
|
||||
forSystem = access.systemFor hostName;
|
||||
err = throw "no lan interface found between ${config.networking.hostName} and ${hostName}";
|
||||
err = throw "no interface found between ${config.networking.hostName} -> ${hostName}@${network}";
|
||||
fallback = if nameAllowed
|
||||
then lib.warn "getAddressFor hostname fallback for ${config.networking.hostName} -> ${hostName}@${network}" (access.getHostnameFor hostName network)
|
||||
else err;
|
||||
local = forSystem.access.${addressForAttr}.local or forSystem.access.address4ForNetwork.local or fallback;
|
||||
int = forSystem.access.${addressForAttr}.int or forSystem.access.address4ForNetwork.int or fallback;
|
||||
tail = forSystem.access.${addressForAttr}.tail or fallback;
|
||||
in {
|
||||
lan =
|
||||
if has'Int then forSystem.access.${addressForAttr}.int or forSystem.access.${addressForAttr}.local or err
|
||||
else if has'Local then forSystem.access.${addressForAttr}.local or err
|
||||
else err;
|
||||
${if has'Local then "local" else null} = forSystem.access.${addressForAttr}.local or err;
|
||||
${if has'Int then "int" else null} = forSystem.access.${addressForAttr}.int or err;
|
||||
${if has'Tail then "tail" else null} = forSystem.access.${addressForAttr}.tail or err;
|
||||
}.${network} or err;
|
||||
if hostName == system.name then forSystem.access.${addressForAttr}.localhost
|
||||
else if has'Int then int
|
||||
else if has'Local then local
|
||||
else fallback;
|
||||
${if has'Local then "local" else null} = local;
|
||||
${if has'Int then "int" else null} = int;
|
||||
${if has'Tail then "tail" else null} = tail;
|
||||
}.${network} or fallback;
|
||||
in {
|
||||
inherit (systemAccess) hostnameForNetwork address4ForNetwork address6ForNetwork;
|
||||
inherit (systemAccess)
|
||||
hostnameForNetwork address4ForNetwork address6ForNetwork
|
||||
systemForService systemForServiceId;
|
||||
addressForNetwork = systemAccess.${addressForAttr};
|
||||
systemFor = hostName:
|
||||
if hostName == config.networking.hostName
|
||||
|
|
@ -73,21 +84,39 @@
|
|||
if hostName == config.networking.hostName
|
||||
then config
|
||||
else systemAccess.nixosForOrNull hostName;
|
||||
getAddressFor = mkGetAddressFor addressForAttr;
|
||||
getAddress4For = mkGetAddressFor "address4ForNetwork";
|
||||
getAddress6For = mkGetAddressFor "address6ForNetwork";
|
||||
getAddressFor = mkGetAddressFor true addressForAttr;
|
||||
getAddress4For = mkGetAddressFor false "address4ForNetwork";
|
||||
getAddress6For = mkGetAddressFor false "address6ForNetwork";
|
||||
getHostnameFor = hostName: network: let
|
||||
forSystem = access.systemFor hostName;
|
||||
err = throw "no ${network} interface found between ${config.networking.hostName} and ${hostName}";
|
||||
in {
|
||||
lan =
|
||||
if has'Int then forSystem.access.hostnameForNetwork.int or forSystem.access.hostnameForNetwork.local or err
|
||||
if hostName == system.name then forSystem.access.hostnameForNetwork.localhost
|
||||
else if has'Int then forSystem.access.hostnameForNetwork.int or forSystem.access.hostnameForNetwork.local or err
|
||||
else if has'Local then forSystem.access.hostnameForNetwork.local or err
|
||||
else err;
|
||||
${if has'Local then "local" else null} = forSystem.access.hostnameForNetwork.local or err;
|
||||
${if has'Int then "int" else null} = forSystem.access.hostnameForNetwork.int or err;
|
||||
${if has'Tail then "tail" else null} = forSystem.access.hostnameForNetwork.tail or err;
|
||||
}.${network} or err;
|
||||
proxyUrlFor = {
|
||||
system ? if serviceId != null then access.systemForServiceId serviceId else access.systemForService serviceName,
|
||||
serviceName ? mapNullable (serviceId: (findSingle (s: s.id == serviceId) null null (attrValues system.exports.services)).name) serviceId,
|
||||
serviceId ? null,
|
||||
service ? system.exports.services.${serviceName},
|
||||
portName ? "default",
|
||||
network ? "lan",
|
||||
scheme ? null,
|
||||
}: let
|
||||
port = service.ports.${portName};
|
||||
scheme' = if scheme == null then port.protocol else scheme;
|
||||
port' = if !port.enable
|
||||
then throw "${system.name}.exports.services.${service.name}.ports.${portName} isn't enabled"
|
||||
else ":${toString port.port}";
|
||||
host = access.getAddressFor system.name network;
|
||||
url = "${scheme'}://${mkAddress6 host}${port'}";
|
||||
in assert service.enable; url;
|
||||
};
|
||||
};
|
||||
networking.tempAddresses = mkIf cfg.global.enable (
|
||||
|
|
@ -110,7 +139,6 @@ in {
|
|||
type = str;
|
||||
default = domain;
|
||||
};
|
||||
tailscale.enable = mkEnableOption "tailscale access";
|
||||
global.enable = mkEnableOption "globally routeable";
|
||||
hostnameForNetwork = mkOption {
|
||||
type = attrsOf str;
|
||||
|
|
@ -143,6 +171,7 @@ in {
|
|||
hostnameForNetwork = mkMerge [
|
||||
(mapAttrs (_: mapNetworkFqdn) config.network.networks)
|
||||
{
|
||||
localhost = mkOptionDefault "localhost";
|
||||
lan = mkMerge [
|
||||
(mapNetwork' mkDefault "fqdn" int)
|
||||
(mapNetworkFqdn local)
|
||||
|
|
@ -153,6 +182,7 @@ in {
|
|||
address4ForNetwork = mkMerge [
|
||||
(mapAttrs (_: mapNetwork4) config.network.networks)
|
||||
{
|
||||
localhost = mkOptionDefault "127.0.0.1";
|
||||
lan = mkMerge [
|
||||
(mapNetwork' mkDefault "address4" int)
|
||||
(mapNetwork4 local)
|
||||
|
|
@ -162,6 +192,7 @@ in {
|
|||
address6ForNetwork = mkMerge [
|
||||
(mapAttrs (_: mapNetwork6) config.network.networks)
|
||||
{
|
||||
localhost = mkOptionDefault "::1";
|
||||
lan = mkMerge [
|
||||
(mapNetwork' mkDefault "address6" int)
|
||||
(mapNetwork6 local)
|
||||
|
|
@ -176,6 +207,16 @@ in {
|
|||
systemForOrNull = hostName: systems.${hostName}.config or null;
|
||||
nixosFor = hostName: nixosConfigurations.${hostName}.config or (access.systemFor hostName).built.config;
|
||||
nixosForOrNull = hostName: nixosConfigurations.${hostName}.config or (access.systemForOrNull hostName).built.config or null;
|
||||
systemForService = service: let
|
||||
hasService = system: system.config.exports.services.${service}.enable;
|
||||
notFound = throw "no system found serving ${service}";
|
||||
multiple = throw "multiple systems found serving ${service}";
|
||||
in (findSingle hasService notFound multiple (attrValues systems)).config;
|
||||
systemForServiceId = serviceId: let
|
||||
hasService = system: findSingle (service: service.id == serviceId && service.enable) null multiple (attrValues system.config.exports.services) != null;
|
||||
notFound = throw "no system found serving ${serviceId}";
|
||||
multiple = throw "multiple systems found serving ${serviceId}";
|
||||
in (findSingle hasService notFound multiple (attrValues systems)).config;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
22
modules/system/exports/dnsmasq.nix
Normal file
22
modules/system/exports/dnsmasq.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.dnsmasq = { config, ... }: {
|
||||
id = mkAlmostOptionDefault "dns";
|
||||
nixos = {
|
||||
serviceAttr = "dnsmasq";
|
||||
};
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 53;
|
||||
transport = "udp";
|
||||
};
|
||||
tcp = {
|
||||
port = config.ports.default.port;
|
||||
transport = "tcp";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
48
modules/system/exports/exports.nix
Normal file
48
modules/system/exports/exports.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
config,
|
||||
name,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
cfg = config.exports;
|
||||
systemConfig = config;
|
||||
exportModule = {
|
||||
config,
|
||||
name,
|
||||
...
|
||||
}: {
|
||||
options = with lib.types; {
|
||||
enable = mkEnableOption "exported service";
|
||||
name = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
serviceName = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
id = mkOption {
|
||||
type = str;
|
||||
default = cfg.services.${config.serviceName}.id/* or config.name*/;
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.exports = with lib.types; {
|
||||
exports = mkOption {
|
||||
type = attrsOf (submoduleWith {
|
||||
modules = [exportModule];
|
||||
specialArgs = {
|
||||
machine = name;
|
||||
inherit systemConfig;
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
_module.args.exports = cfg;
|
||||
};
|
||||
}
|
||||
18
modules/system/exports/freeipa.nix
Normal file
18
modules/system/exports/freeipa.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.freeipa = {
|
||||
id = mkAlmostOptionDefault "freeipa";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 443;
|
||||
protocol = "https";
|
||||
};
|
||||
redirect = {
|
||||
port = 80;
|
||||
protocol = "http";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
34
modules/system/exports/freepbx.nix
Normal file
34
modules/system/exports/freepbx.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.freepbx = {
|
||||
id = mkAlmostOptionDefault "pbx";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
http = {
|
||||
port = 80;
|
||||
protocol = "http";
|
||||
};
|
||||
https = {
|
||||
port = 443;
|
||||
protocol = "https";
|
||||
};
|
||||
ucp = {
|
||||
port = 8001;
|
||||
protocol = "http";
|
||||
};
|
||||
ucp-ssl = {
|
||||
port = 8003;
|
||||
protocol = "https";
|
||||
};
|
||||
asterisk = {
|
||||
port = 8088;
|
||||
protocol = "http";
|
||||
};
|
||||
asterisk-ssl = {
|
||||
port = 8089;
|
||||
protocol = "https";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
45
modules/system/exports/home-assistant.nix
Normal file
45
modules/system/exports/home-assistant.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
inherit (lib.lists) all imap0;
|
||||
inherit (lib.trivial) id;
|
||||
in {
|
||||
config.exports.services.home-assistant = { config, ... }: let
|
||||
mkAssertion = f: nixosConfig: let
|
||||
cfg = nixosConfig.services.home-assistant;
|
||||
in f nixosConfig cfg;
|
||||
assertPort = nixosConfig: cfg: {
|
||||
assertion = config.ports.default.port == cfg.config.http.server_port;
|
||||
message = "port mismatch";
|
||||
};
|
||||
assertHomekitPort = let
|
||||
portName = i: "homekit${toString i}";
|
||||
mkAssertPort = i: homekit: config.ports.${portName i}.port or null == homekit.port;
|
||||
in nixosConfig: cfg: {
|
||||
assertion = all id (imap0 mkAssertPort cfg.config.homekit);
|
||||
message = "homekit port mismatch";
|
||||
};
|
||||
in {
|
||||
id = mkAlmostOptionDefault "home";
|
||||
nixos = {
|
||||
serviceAttr = "home-assistant";
|
||||
assertions = mkIf config.enable [
|
||||
(mkAssertion assertPort)
|
||||
(mkAssertion assertHomekitPort)
|
||||
];
|
||||
};
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 8123;
|
||||
protocol = "http";
|
||||
};
|
||||
homekit0 = {
|
||||
port = 21063;
|
||||
transport = "tcp";
|
||||
};
|
||||
# TODO: cast udp port range 32768 to 60999
|
||||
};
|
||||
};
|
||||
}
|
||||
21
modules/system/exports/invidious.nix
Normal file
21
modules/system/exports/invidious.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.modules) mkIf;
|
||||
in {
|
||||
config.exports.services.invidious = { config, ... }: {
|
||||
id = mkAlmostOptionDefault "yt";
|
||||
nixos = {
|
||||
serviceAttr = "invidious";
|
||||
assertions = mkIf config.enable [
|
||||
(nixosConfig: {
|
||||
assertion = config.ports.default.port == nixosConfig.services.invidious.port;
|
||||
message = "port mismatch";
|
||||
})
|
||||
];
|
||||
};
|
||||
ports.default = mapAlmostOptionDefaults {
|
||||
port = 3000;
|
||||
protocol = "http";
|
||||
};
|
||||
};
|
||||
}
|
||||
35
modules/system/exports/kerberos.nix
Normal file
35
modules/system/exports/kerberos.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.kerberos = { config, ... }: {
|
||||
id = "krb5";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 88;
|
||||
transport = "tcp";
|
||||
};
|
||||
udp = {
|
||||
port = config.ports.default.port;
|
||||
transport = "udp";
|
||||
};
|
||||
kadmin = {
|
||||
port = 749;
|
||||
transport = "tcp";
|
||||
};
|
||||
kpasswd = {
|
||||
port = 464;
|
||||
transport = "tcp";
|
||||
};
|
||||
kpasswd-udp = {
|
||||
port = config.ports.kpasswd.port;
|
||||
transport = "udp";
|
||||
};
|
||||
ticket4 = {
|
||||
enable = false;
|
||||
port = 4444;
|
||||
transport = "udp";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
37
modules/system/exports/keycloak.nix
Normal file
37
modules/system/exports/keycloak.nix
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.keycloak = { config, ... }: {
|
||||
id = mkAlmostOptionDefault "sso";
|
||||
nixos = {
|
||||
serviceAttr = "keycloak";
|
||||
assertions = let
|
||||
mkAssertion = f: nixosConfig: let
|
||||
cfg = nixosConfig.services.keycloak;
|
||||
in f nixosConfig cfg;
|
||||
in mkIf config.enable [
|
||||
(mkAssertion (nixosConfig: cfg: {
|
||||
assertion = config.ports.${cfg.protocol}.port == cfg.port;
|
||||
message = "port mismatch";
|
||||
}))
|
||||
(mkAssertion (nixosConfig: cfg: {
|
||||
assertion = config.ports.${cfg.protocol}.enable;
|
||||
message = "port enable mismatch";
|
||||
}))
|
||||
];
|
||||
};
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
http = {
|
||||
enable = !config.ports.https.enable;
|
||||
port = 8080;
|
||||
protocol = "http";
|
||||
};
|
||||
https = {
|
||||
port = 8443;
|
||||
protocol = "https";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
19
modules/system/exports/ldap.nix
Normal file
19
modules/system/exports/ldap.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.ldap = { config, ... }: {
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 389;
|
||||
transport = "tcp";
|
||||
};
|
||||
ssl = {
|
||||
port = 636;
|
||||
ssl = true;
|
||||
listen = "wan";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
38
modules/system/exports/mosquitto.nix
Normal file
38
modules/system/exports/mosquitto.nix
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
inherit (lib.lists) all imap0;
|
||||
inherit (lib.trivial) id;
|
||||
in {
|
||||
config.exports.services.mosquitto = { config, ... }: {
|
||||
id = mkAlmostOptionDefault "mqtt";
|
||||
nixos = {
|
||||
serviceAttr = "mosquitto";
|
||||
assertions = mkIf config.enable [
|
||||
(nixosConfig: let
|
||||
cfg = nixosConfig.services.mosquitto;
|
||||
portName = i:
|
||||
if i == 0 then "default"
|
||||
else "listener${toString i}";
|
||||
mkAssertPort = i: listener: config.ports.${portName i}.port or null == listener.port;
|
||||
in {
|
||||
assertion = all id (imap0 mkAssertPort cfg.listeners);
|
||||
message = "port mismatch";
|
||||
})
|
||||
];
|
||||
};
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 1883;
|
||||
transport = "tcp";
|
||||
};
|
||||
ssl = {
|
||||
enable = false;
|
||||
port = 8883;
|
||||
ssl = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
18
modules/system/exports/motion.nix
Normal file
18
modules/system/exports/motion.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.motion = { config, ... }: {
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 8080;
|
||||
protocol = "http";
|
||||
};
|
||||
stream = {
|
||||
port = 8081;
|
||||
protocol = "http";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
77
modules/system/exports/nfs.nix
Normal file
77
modules/system/exports/nfs.nix
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.nfs = { config, ... }: let
|
||||
mkAssertion = f: nixosConfig: let
|
||||
cfg = nixosConfig.services.nfs;
|
||||
in f nixosConfig cfg;
|
||||
mkAssertionPort = portName: mkAssertion (nixosConfig: cfg: let
|
||||
portAttr = "${portName}Port";
|
||||
in {
|
||||
assertion = mkAssertPort config.ports.${portName} cfg.server.${portAttr};
|
||||
message = "${portAttr} mismatch";
|
||||
});
|
||||
mkAssertPort = port: cfgPort: let
|
||||
cmpPort = if port.enable then port.port else null;
|
||||
in cfgPort == cmpPort;
|
||||
in {
|
||||
nixos = {
|
||||
serviceAttrPath = [ "services" "nfs" "server" ];
|
||||
assertions = mkIf config.enable [
|
||||
(mkAssertionPort "statd")
|
||||
(mkAssertionPort "lockd")
|
||||
(mkAssertionPort "mountd")
|
||||
(mkAssertion (nixosConfig: cfg: {
|
||||
assertion = nixosConfig.services.rpcbind.enable == config.ports.rpcbind.enable;
|
||||
message = "rpcbind enable mismatch";
|
||||
}))
|
||||
];
|
||||
};
|
||||
# TODO: expose over wan
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 2049;
|
||||
transport = "tcp";
|
||||
};
|
||||
udp = {
|
||||
port = config.ports.default.port;
|
||||
transport = "udp";
|
||||
};
|
||||
rpcbind = {
|
||||
port = 111;
|
||||
transport = "tcp";
|
||||
};
|
||||
rpcbind-udp = {
|
||||
port = config.ports.rpcbind.port;
|
||||
transport = "udp";
|
||||
};
|
||||
statd = {
|
||||
port = 4000;
|
||||
transport = "tcp";
|
||||
};
|
||||
statd-udp = {
|
||||
port = config.ports.statd.port;
|
||||
transport = "udp";
|
||||
};
|
||||
lockd = {
|
||||
port = 4001;
|
||||
transport = "tcp";
|
||||
};
|
||||
lockd-udp = {
|
||||
port = config.ports.lockd.port;
|
||||
transport = "udp";
|
||||
};
|
||||
mountd = {
|
||||
port = 4002;
|
||||
transport = "tcp";
|
||||
};
|
||||
mountd-udp = {
|
||||
port = config.ports.mountd.port;
|
||||
transport = "udp";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
43
modules/system/exports/plex.nix
Normal file
43
modules/system/exports/plex.nix
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.plex = {
|
||||
nixos.serviceAttr = "plex";
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
default = {
|
||||
port = 32400;
|
||||
protocol = "http";
|
||||
};
|
||||
roku = {
|
||||
port = 8324;
|
||||
transport = "tcp";
|
||||
};
|
||||
dlna-tcp = {
|
||||
port = 32469;
|
||||
transport = "tcp";
|
||||
};
|
||||
dlna-udp = {
|
||||
port = 1900;
|
||||
transport = "udp";
|
||||
};
|
||||
gdm0 = {
|
||||
port = 32410;
|
||||
transport = "udp";
|
||||
};
|
||||
gdm1 = {
|
||||
port = 32412;
|
||||
transport = "udp";
|
||||
};
|
||||
gdm2 = {
|
||||
port = 32413;
|
||||
transport = "udp";
|
||||
};
|
||||
gdm3 = {
|
||||
port = 32414;
|
||||
transport = "udp";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
27
modules/system/exports/postgresql.nix
Normal file
27
modules/system/exports/postgresql.nix
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults;
|
||||
inherit (lib.modules) mkIf;
|
||||
in {
|
||||
config.exports.services.postgresql = { config, ... }: let
|
||||
mkAssertion = f: nixosConfig: let
|
||||
cfg = nixosConfig.services.postgresql;
|
||||
in f nixosConfig cfg;
|
||||
in {
|
||||
nixos = {
|
||||
assertions = mkIf config.enable [
|
||||
(mkAssertion (nixosConfig: cfg: {
|
||||
assertion = config.ports.default.port == cfg.settings.port;
|
||||
message = "port mismatch";
|
||||
}))
|
||||
(mkAssertion (nixosConfig: cfg: {
|
||||
assertion = config.ports.default.enable == cfg.enableTCPIP;
|
||||
message = "enableTCPIP mismatch";
|
||||
}))
|
||||
];
|
||||
};
|
||||
ports.default = mapAlmostOptionDefaults {
|
||||
port = 5432;
|
||||
transport = "tcp";
|
||||
};
|
||||
};
|
||||
}
|
||||
12
modules/system/exports/prox.nix
Normal file
12
modules/system/exports/prox.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
in {
|
||||
config.exports.services.proxmox = { config, ... }: {
|
||||
id = mkAlmostOptionDefault "prox";
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports.default = mapAlmostOptionDefaults {
|
||||
port = 8006;
|
||||
protocol = "https";
|
||||
};
|
||||
};
|
||||
}
|
||||
29
modules/system/exports/samba.nix
Normal file
29
modules/system/exports/samba.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.samba = {
|
||||
id = mkAlmostOptionDefault "smb";
|
||||
nixos.serviceAttr = "samba";
|
||||
# TODO: expose over wan
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
port0 = {
|
||||
port = 137;
|
||||
transport = "udp";
|
||||
};
|
||||
port1 = {
|
||||
port = 138;
|
||||
transport = "udp";
|
||||
};
|
||||
port2 = {
|
||||
port = 139;
|
||||
transport = "tcp";
|
||||
};
|
||||
default = {
|
||||
port = 445;
|
||||
transport = "tcp";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
155
modules/system/exports/services.nix
Normal file
155
modules/system/exports/services.nix
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
{
|
||||
config,
|
||||
name,
|
||||
lib,
|
||||
gensokyo-zone,
|
||||
...
|
||||
}: let
|
||||
inherit (gensokyo-zone.lib) mkAlmostOptionDefault;
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrsToList getAttrFromPath;
|
||||
inherit (lib.trivial) mapNullable;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
systemConfig = config;
|
||||
portModule = {config, service, ...}: {
|
||||
options = with lib.types; {
|
||||
enable =
|
||||
mkEnableOption "port"
|
||||
// {
|
||||
default = true;
|
||||
};
|
||||
listen = mkOption {
|
||||
type = enum ["wan" "lan" "int" "localhost"];
|
||||
};
|
||||
protocol = mkOption {
|
||||
type = nullOr (enum ["http" "https"]);
|
||||
default = null;
|
||||
};
|
||||
transport = mkOption {
|
||||
type = enum ["tcp" "udp" "unix"];
|
||||
};
|
||||
path = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
description = "unix socket path";
|
||||
};
|
||||
ssl = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
port = mkOption {
|
||||
type = nullOr int;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
transport = mkMerge [
|
||||
(mkIf (config.protocol == "http" || config.protocol == "https") (mkOptionDefault "tcp"))
|
||||
(mkIf config.ssl (mkOptionDefault "tcp"))
|
||||
];
|
||||
ssl = mkIf (config.protocol == "https") (
|
||||
mkAlmostOptionDefault true
|
||||
);
|
||||
listen = mkOptionDefault service.defaults.port.listen;
|
||||
};
|
||||
};
|
||||
serviceModule = {
|
||||
config,
|
||||
name,
|
||||
...
|
||||
}: {
|
||||
options = with lib.types; {
|
||||
enable = mkEnableOption "hosted service";
|
||||
name = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
id = mkOption {
|
||||
type = str;
|
||||
default = config.name;
|
||||
};
|
||||
ports = mkOption {
|
||||
type = attrsOf (submoduleWith {
|
||||
modules = [portModule];
|
||||
specialArgs = {
|
||||
service = config;
|
||||
};
|
||||
});
|
||||
};
|
||||
nixos = {
|
||||
serviceAttr = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
};
|
||||
serviceAttrPath = mkOption {
|
||||
type = nullOr (listOf str);
|
||||
};
|
||||
assertions = mkOption {
|
||||
type = listOf (functionTo attrs);
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
defaults = {
|
||||
port = {
|
||||
listen = mkOption {
|
||||
type = str;
|
||||
default = "int";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
nixos = {
|
||||
serviceAttrPath = mkOptionDefault (
|
||||
mapNullable (serviceAttr: ["services" config.nixos.serviceAttr]) config.nixos.serviceAttr
|
||||
);
|
||||
assertions = let
|
||||
serviceConfig = getAttrFromPath config.nixos.serviceAttrPath;
|
||||
mkAssertion = f: nixosConfig: let
|
||||
cfg = serviceConfig nixosConfig;
|
||||
in f nixosConfig cfg;
|
||||
enableAssertion = nixosConfig: cfg: {
|
||||
assertion = (! cfg ? enable) || (config.enable == cfg.enable);
|
||||
message = "enable == nixosConfig.${concatStringsSep "." config.nixos.serviceAttrPath}.enable";
|
||||
};
|
||||
in [
|
||||
(mkIf (config.nixos.serviceAttrPath != null) (
|
||||
mkAssertion enableAssertion
|
||||
))
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
nixosModule = {config, system, ...}: let
|
||||
mapAssertion = service: a: let
|
||||
res = a config;
|
||||
in res // {
|
||||
message = "system.exports.${service.name}: " + res.message or "assertion failed";
|
||||
};
|
||||
assertions = mapAttrsToList (_: service: map (mapAssertion service) service.nixos.assertions) system.exports.services;
|
||||
in {
|
||||
config = {
|
||||
assertions = mkMerge assertions;
|
||||
# TODO: export ports via firewall according to enable/listen/etc
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.exports = with lib.types; {
|
||||
services = mkOption {
|
||||
type = attrsOf (submoduleWith {
|
||||
modules = [serviceModule];
|
||||
specialArgs = {
|
||||
machine = name;
|
||||
inherit systemConfig;
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
modules = mkIf (config.type == "NixOS") [
|
||||
nixosModule
|
||||
];
|
||||
};
|
||||
}
|
||||
7
modules/system/exports/tailscale.nix
Normal file
7
modules/system/exports/tailscale.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{...}: {
|
||||
config.exports.services.tailscale = {
|
||||
id = "tail";
|
||||
nixos.serviceAttr = "tailscale";
|
||||
ports = {};
|
||||
};
|
||||
}
|
||||
47
modules/system/exports/unifi.nix
Normal file
47
modules/system/exports/unifi.nix
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.attrsets) mapAttrs;
|
||||
in {
|
||||
config.exports.services.unifi = { config, ... }: {
|
||||
nixos.serviceAttr = "unifi";
|
||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||
ports = mapAttrs (_: mapAlmostOptionDefaults) {
|
||||
management = {
|
||||
# remote login
|
||||
port = 8443;
|
||||
protocol = "https";
|
||||
listen = "int";
|
||||
};
|
||||
uap = {
|
||||
# UAP to inform controller
|
||||
port = 8080;
|
||||
transport = "tcp";
|
||||
};
|
||||
portal = {
|
||||
# HTTP portal redirect, if guest portal is enabled
|
||||
port = 8880;
|
||||
protocol = "http";
|
||||
};
|
||||
portal-secure = {
|
||||
# HTTPS portal redirect
|
||||
port = 8843;
|
||||
protocol = "https";
|
||||
};
|
||||
speedtest = {
|
||||
# UniFi mobile speed test
|
||||
port = 6789;
|
||||
transport = "tcp";
|
||||
};
|
||||
stun = {
|
||||
port = 3478;
|
||||
transport = "udp";
|
||||
listen = "wan";
|
||||
};
|
||||
discovery = {
|
||||
# device discovery
|
||||
port = 10001;
|
||||
transport = "udp";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
22
modules/system/exports/vouch.nix
Normal file
22
modules/system/exports/vouch.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.modules) mkIf;
|
||||
in {
|
||||
config.exports.services.vouch-proxy = { config, ... }: {
|
||||
id = mkAlmostOptionDefault "login";
|
||||
defaults.port.listen = mkAlmostOptionDefault "localhost";
|
||||
nixos = {
|
||||
serviceAttr = "vouch-proxy";
|
||||
assertions = mkIf config.enable [
|
||||
(nixosConfig: {
|
||||
assertion = config.ports.default.port == nixosConfig.services.vouch-proxy.settings.vouch.port;
|
||||
message = "port mismatch";
|
||||
})
|
||||
];
|
||||
};
|
||||
ports.default = mapAlmostOptionDefaults {
|
||||
port = 30746;
|
||||
protocol = "http";
|
||||
};
|
||||
};
|
||||
}
|
||||
21
modules/system/exports/zigbee2mqtt.nix
Normal file
21
modules/system/exports/zigbee2mqtt.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{lib, gensokyo-zone, ...}: let
|
||||
inherit (gensokyo-zone.lib) mapAlmostOptionDefaults mkAlmostOptionDefault;
|
||||
inherit (lib.modules) mkIf;
|
||||
in {
|
||||
config.exports.services.zigbee2mqtt = { config, ... }: {
|
||||
id = mkAlmostOptionDefault "z2m";
|
||||
nixos = {
|
||||
serviceAttr = "zigbee2mqtt";
|
||||
assertions = mkIf config.enable [
|
||||
(nixosConfig: {
|
||||
assertion = config.ports.default.port == nixosConfig.services.zigbee2mqtt.settings.frontend.port;
|
||||
message = "port mismatch";
|
||||
})
|
||||
];
|
||||
};
|
||||
ports.default = mapAlmostOptionDefaults {
|
||||
port = 8072;
|
||||
protocol = "http";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -15,6 +15,11 @@ in {
|
|||
inherit (lib.types) str listOf attrs unspecified enum;
|
||||
inherit (lib.options) mkOption;
|
||||
in {
|
||||
name = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
readOnly = true;
|
||||
};
|
||||
arch = mkOption {
|
||||
description = "Processor architecture of the host";
|
||||
type = str;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue