From c3a62715827c52354fea2759837a2862f3f40a8c Mon Sep 17 00:00:00 2001 From: alexion Date: Mon, 5 Oct 2026 00:08:36 -0400 Subject: [PATCH] refactor(nixos): model route protocols explicitly --- configs/nixos/hosts/pikachu/default.nix | 12 ++++-- configs/nixos/modules/services/homepage.nix | 6 +-- .../nixos/modules/services/reverse-proxy.nix | 10 +++-- configs/nixos/registry/route.nix | 41 ++++++++++++------- docs/TODO.md | 9 ++-- 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/configs/nixos/hosts/pikachu/default.nix b/configs/nixos/hosts/pikachu/default.nix index d999722..1febafc 100644 --- a/configs/nixos/hosts/pikachu/default.nix +++ b/configs/nixos/hosts/pikachu/default.nix @@ -78,7 +78,8 @@ enable = true; route = { domain = "valheim.alexion.dev"; - udp.ports = [ + protocol = "udp"; + ports = [ config.guests.valheim.port (config.guests.valheim.port + 1) ]; @@ -101,7 +102,8 @@ enable = true; route = { domain = "palworld.alexion.dev"; - udp.ports = [ config.guests.palworld.port ]; + protocol = "udp"; + ports = [ config.guests.palworld.port ]; }; }; }; @@ -116,6 +118,7 @@ enable = true; route = { domain = "budget.alexion.dev"; + protocol = "https"; port = 5006; }; }; @@ -132,6 +135,7 @@ enable = true; route = { domain = "music.alexion.dev"; + protocol = "https"; port = 4533; }; }; @@ -152,7 +156,8 @@ enable = true; route = { domain = "home"; - http.port = 8082; + protocol = "http"; + port = 8082; }; }; }; @@ -167,6 +172,7 @@ enable = true; route = { domain = "files.alexion.dev"; + protocol = "https"; port = 3923; }; trustedSources = [ "${registry.address.${config.networking.hostName}."reverse-proxy"}/32" ]; diff --git a/configs/nixos/modules/services/homepage.nix b/configs/nixos/modules/services/homepage.nix index fa7bbb9..7604b6e 100644 --- a/configs/nixos/modules/services/homepage.nix +++ b/configs/nixos/modules/services/homepage.nix @@ -71,12 +71,12 @@ let if item.homepage.href != null then item.homepage.href else if (item.composite.route or null) != null then - if item.composite.route.port != null then + if item.composite.route.protocol == "https" then "https://${item.composite.route.domain}" - else if item.composite.route.http.port != null then + else if item.composite.route.protocol == "http" then "http://${item.composite.route.domain}" else - throw "${mkRegistryPath "homepage" item.host item.entry} needs href or a matching TCP route entry" + throw "${mkRegistryPath "homepage" item.host item.entry} needs href or a matching HTTP route entry" else throw "${mkRegistryPath "homepage" item.host item.entry} needs href or a matching route entry"; diff --git a/configs/nixos/modules/services/reverse-proxy.nix b/configs/nixos/modules/services/reverse-proxy.nix index c925641..321ee8f 100644 --- a/configs/nixos/modules/services/reverse-proxy.nix +++ b/configs/nixos/modules/services/reverse-proxy.nix @@ -11,7 +11,9 @@ let lib.mapAttrsToList ( host: routes: lib.concatLists ( - lib.mapAttrsToList (entry: route: map (mkUdpStream host entry) route.udp.ports) routes + lib.mapAttrsToList ( + entry: route: lib.optionals (route.protocol == "udp") (map (mkUdpStream host entry) route.ports) + ) routes ) ) registry.route ); @@ -75,7 +77,7 @@ let lib.mapAttrsToList ( host: routes: lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "https") ( - lib.filterAttrs (_entry: route: route.port != null) routes + lib.filterAttrs (_entry: route: route.protocol == "https") routes ) ) registry.route ); @@ -89,7 +91,7 @@ let or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}"); compositeEntry = registry.join host entry; inherit (compositeEntry) route; - port = if isHttp then route.http.port else route.port; + inherit (route) port; in { inherit host entry; @@ -108,7 +110,7 @@ let lib.mapAttrsToList ( host: routes: lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "http") ( - lib.filterAttrs (_entry: route: route.http.port != null) routes + lib.filterAttrs (_entry: route: route.protocol == "http") routes ) ) registry.route ); diff --git a/configs/nixos/registry/route.nix b/configs/nixos/registry/route.nix index fc69b87..653ae31 100644 --- a/configs/nixos/registry/route.nix +++ b/configs/nixos/registry/route.nix @@ -9,14 +9,25 @@ assertion = entries: util.registry.predicates.uniqueValue (entry: entry.value) ( - lib.concatMap (entry: map (port: entry // { value = port; }) entry.value.udp.ports) entries + lib.concatMap (entry: map (port: entry // { value = port; }) entry.value.ports) entries ); message = "Route UDP ports must be unique."; } { assertion = - entries: lib.all (entry: entry.value.port == null || entry.value.http.port == null) entries; - message = "Route entries must not set both port and http.port."; + entries: + lib.all (entry: entry.value.port != null && entry.value.ports == [ ]) ( + lib.filter (entry: entry.value.protocol != "udp") entries + ); + message = "HTTP and HTTPS routes must set port and not ports."; + } + { + assertion = + entries: + lib.all (entry: entry.value.port == null && entry.value.ports != [ ]) ( + lib.filter (entry: entry.value.protocol == "udp") entries + ); + message = "UDP routes must set ports and not port."; } ]; @@ -25,31 +36,33 @@ domain = lib.mkOption { type = lib.types.str; example = "files.alexion.dev"; - description = "Domain served by this route entry."; + description = "Public domain for this route."; + }; + + protocol = lib.mkOption { + type = lib.types.enum [ + "http" + "https" + "udp" + ]; + description = "Public protocol for this route."; }; port = lib.mkOption { type = lib.types.nullOr lib.types.port; default = null; example = 3923; - description = "HTTPS backend TCP port served by the matching address registry entry."; + description = "HTTP backend port for an HTTP or HTTPS route."; }; - http.port = lib.mkOption { - type = lib.types.nullOr lib.types.port; - default = null; - example = 8082; - description = "HTTP backend TCP port served by the matching address registry entry."; - }; - - udp.ports = lib.mkOption { + ports = lib.mkOption { type = lib.types.listOf lib.types.port; default = [ ]; example = [ 2456 2457 ]; - description = "UDP ports served by the matching address registry entry."; + description = "UDP ports for a UDP route."; }; }; }; diff --git a/docs/TODO.md b/docs/TODO.md index 446ca76..2631aaf 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -130,11 +130,10 @@ Review Nix files in entrypoint order: - [x] `src/dotfiles/util.nix` - [x] `src/dotfiles/registry.nix` - [x] `src/dotfiles/registry/schema.nix` -- [ ] `src/dotfiles/registry/validation.nix` -- [ ] `configs/nixos/registry/address.nix` -- [ ] `configs/nixos/registry/env-var.nix` -- [ ] `configs/nixos/registry/homepage.nix` -- [ ] `configs/nixos/registry/route.nix` +- [x] `src/dotfiles/registry/validation.nix` +- [x] `configs/nixos/registry/address.nix` +- [>] `configs/nixos/registry/homepage.nix` +- [x] `configs/nixos/registry/route.nix` - [ ] `configs/nixos/registry/shell-shortcut.nix` - [ ] `configs/nixos/registry/stable-uid.nix` - [ ] `src/dotfiles/modules.nix`