feat(nixos): add UDP route ingress

This commit is contained in:
2026-09-10 08:43:17 -04:00
parent 88762118b9
commit 1c043c7239
4 changed files with 78 additions and 11 deletions

View File

@@ -64,7 +64,17 @@
pools.pikachu = { };
};
registry.address.pikachu.self = "10.23.10.102";
registry.address.pikachu = {
self = "10.23.10.102";
valheim = "10.23.10.102";
};
registry.route.pikachu.valheim = {
domain = "valheim.alexion.dev";
udp.ports = [
config.modules.services.games.valheim.port
(config.modules.services.games.valheim.port + 1)
];
};
modules.services.games.valheim = {
enable = true;

View File

@@ -30,7 +30,9 @@ let
generatedVirtualHostList = lib.concatLists (
lib.mapAttrsToList (
host: routes:
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry) routes
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry) (
lib.filterAttrs (_entry: route: route.port != null) routes
)
) registry.route
);
@@ -59,6 +61,55 @@ let
throw (builtins.head duplicateDomainMessages)
else
lib.listToAttrs generatedVirtualHostList;
mkUdpStream = host: entry: port:
let
compositeEntry = registry.join host entry;
address = compositeEntry.address or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
in
{
inherit host entry port address;
};
generatedUdpStreams = lib.concatLists (
lib.mapAttrsToList (
host: routes:
lib.concatLists (
lib.mapAttrsToList (entry: route: map (mkUdpStream host entry) route.udp.ports) routes
)
) registry.route
);
udpStreamsByPort = lib.foldl' (
acc: stream:
acc
// {
${toString stream.port} = (acc.${toString stream.port} or [ ]) ++ [ stream ];
}
) { } generatedUdpStreams;
duplicateUdpPortMessages = lib.concatLists (
lib.mapAttrsToList (
port: streams:
if lib.length streams > 1 then
[
"duplicate UDP route port ${port} in ${lib.concatMapStringsSep " and " (stream: mkRegistryPath "route" stream.host stream.entry) streams}"
]
else
[ ]
) udpStreamsByPort
);
generatedStreamConfig =
if duplicateUdpPortMessages != [ ] then
throw (builtins.head duplicateUdpPortMessages)
else
lib.concatMapStringsSep "\n" (stream: ''
server {
listen ${toString stream.port} udp;
proxy_pass ${stream.address}:${toString stream.port};
}
'') generatedUdpStreams;
in
{
options.modules.services.reverse-proxy = {
@@ -70,6 +121,7 @@ in
80
443
];
networking.firewall.allowedUDPPorts = map (stream: stream.port) generatedUdpStreams;
security.acme = {
acceptTerms = true;
@@ -89,6 +141,7 @@ in
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
streamConfig = lib.mkIf (generatedUdpStreams != [ ]) generatedStreamConfig;
virtualHosts = generatedVirtualHosts;
};
};

View File

@@ -1,11 +1,4 @@
{ lib, ... }:
{
type = lib.types.str;
checks = [
{
assertion = lib.registry.predicates.uniqueValue (entry: entry.value);
message = "Address registry values must be unique.";
}
];
}

View File

@@ -12,14 +12,25 @@
domain = lib.mkOption {
type = lib.types.str;
example = "files.alexion.dev";
description = "Public domain served by this reverse-proxy route entry.";
description = "Public domain served by this route entry.";
};
port = lib.mkOption {
type = lib.types.ints.between 1 65535;
type = lib.types.nullOr lib.types.port;
default = null;
example = 3923;
description = "Backend TCP port served by the matching address registry entry.";
};
udp.ports = lib.mkOption {
type = lib.types.listOf lib.types.port;
default = [ ];
example = [
2456
2457
];
description = "UDP ports served by the matching address registry entry.";
};
};
};
}