From 959a9f98aebb5bda1cd97f6be7ac0fe4a0d8b8a0 Mon Sep 17 00:00:00 2001 From: alexion Date: Tue, 25 Aug 2026 22:10:09 -0400 Subject: [PATCH] feat(registry): validate unique addresses and routes --- flake.nix | 127 ++++++++++++++++++++++++------------------- lib/registry.nix | 29 +++++++++- registry/address.nix | 5 ++ registry/route.nix | 5 ++ 4 files changed, 109 insertions(+), 57 deletions(-) diff --git a/flake.nix b/flake.nix index 4f02d49..49f56e3 100644 --- a/flake.nix +++ b/flake.nix @@ -403,6 +403,38 @@ touch $out ''; + address-registry-duplicate-value-fails = + let + alpha = lib.nixosSystem { + system = "x86_64-linux"; + specialArgs.my = self.lib; + modules = [ + self.lib.registry.module + { + registry.address.alpha.self = "10.23.50.146"; + system.stateVersion = "26.11"; + } + ]; + }; + beta = lib.nixosSystem { + system = "x86_64-linux"; + specialArgs.my = self.lib; + modules = [ + self.lib.registry.module + { + registry.address.beta.self = "10.23.50.146"; + system.stateVersion = "26.11"; + } + ]; + }; + registry = self.lib.registry.collect { hosts = { inherit alpha beta; }; }; + result = builtins.tryEval (builtins.deepSeq registry.address true); + in + pkgs.runCommand "address-registry-duplicate-value-fails-check" { } '' + ${lib.optionalString result.success "exit 1"} + touch $out + ''; + ssh-targets-use-address-registry = let neogaiaConfig = self.nixosConfigurations.neogaia.config; @@ -434,7 +466,7 @@ modules = [ self.lib.registry.module { - registry.address.routeHost.app = "10.23.20.126"; + registry.address.routeHost.app = "10.23.20.127"; registry.route.routeHost.app = { domain = "worker.alexion.dev"; port = 3923; @@ -472,7 +504,7 @@ registry.route ? routeHost && registry.route.routeHost ? app && registry.route.pikachu ? actualbudget - && vhosts."worker.alexion.dev".locations."/".proxyPass == "http://10.23.20.126:3923" + && vhosts."worker.alexion.dev".locations."/".proxyPass == "http://10.23.20.127:3923" && vhosts."budget.alexion.dev".locations."/".proxyPass == "http://10.23.20.42:5006" && vhosts."files.alexion.dev".locations."/".proxyPass == "http://10.23.20.126:3923" ) @@ -481,6 +513,44 @@ touch $out ''; + route-registry-duplicate-domain-fails = + let + alpha = lib.nixosSystem { + system = "x86_64-linux"; + specialArgs.my = self.lib; + modules = [ + self.lib.registry.module + { + registry.route.alpha.app = { + domain = "files.alexion.dev"; + port = 3923; + }; + system.stateVersion = "26.11"; + } + ]; + }; + beta = lib.nixosSystem { + system = "x86_64-linux"; + specialArgs.my = self.lib; + modules = [ + self.lib.registry.module + { + registry.route.beta.app = { + domain = "files.alexion.dev"; + port = 3923; + }; + system.stateVersion = "26.11"; + } + ]; + }; + registry = self.lib.registry.collect { hosts = { inherit alpha beta; }; }; + result = builtins.tryEval (builtins.deepSeq registry.route true); + in + pkgs.runCommand "route-registry-duplicate-domain-fails-check" { } '' + ${lib.optionalString result.success "exit 1"} + touch $out + ''; + reverse-proxy-address-backends = let workerHost = @@ -603,59 +673,6 @@ touch $out ''; - reverse-proxy-duplicate-domain-fails = - let - pikachu = lib.nixosSystem { - system = "x86_64-linux"; - specialArgs.my = self.lib; - modules = [ - self.lib.registry.module - { - registry.address.pikachu.copyparty = "10.23.20.126"; - registry.route.pikachu.copyparty = { - domain = "files.alexion.dev"; - port = 3923; - }; - system.stateVersion = "26.11"; - } - ]; - }; - raichu = lib.nixosSystem { - system = "x86_64-linux"; - specialArgs.my = self.lib; - modules = [ - self.lib.registry.module - { - registry.address.raichu.files = "10.23.20.10"; - registry.route.raichu.files = { - domain = "files.alexion.dev"; - port = 3923; - }; - system.stateVersion = "26.11"; - } - ]; - }; - registry = self.lib.registry.collect { hosts = { inherit pikachu raichu; }; }; - testConfig = lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - my = self.lib; - inherit registry; - }; - modules = [ - ./modules/reverse-proxy.nix - { - modules.reverse-proxy.enable = true; - system.stateVersion = "26.11"; - } - ]; - }; - result = builtins.tryEval (builtins.deepSeq testConfig.config.services.nginx.virtualHosts true); - in - pkgs.runCommand "reverse-proxy-duplicate-domain-fails-check" { } '' - ${lib.optionalString result.success "exit 1"} - touch $out - ''; }; }; } diff --git a/lib/registry.nix b/lib/registry.nix index 2c00390..760a7ae 100644 --- a/lib/registry.nix +++ b/lib/registry.nix @@ -16,6 +16,7 @@ let nameValuePair removeSuffix types + unique ; assertionType = types.submodule { @@ -36,6 +37,30 @@ let }; }; + validators = { + uniqueValue = + { + value, + message, + }: + entries: + let + values = map value entries; + in + [ + { + assertion = builtins.length (unique values) == builtins.length values; + inherit message; + } + ]; + }; + + registryLib = lib // { + registry = (lib.registry or { }) // { + inherit validators; + }; + }; + registryDefinitionModule = { options = { type = mkOption { @@ -76,7 +101,7 @@ let mkRegistry = path: let evaluated = lib.evalModules { - specialArgs = { inherit lib; }; + specialArgs.lib = registryLib; modules = [ registryDefinitionModule path @@ -189,7 +214,7 @@ let }; in { - inherit definitions; + inherit definitions validators; module = { options.registry = mapAttrs (_name: registry: registryOption registry) definitions; diff --git a/registry/address.nix b/registry/address.nix index 8a6fd91..f8d7630 100644 --- a/registry/address.nix +++ b/registry/address.nix @@ -1,4 +1,9 @@ { lib, ... }: { type = lib.types.str; + + validate = lib.registry.validators.uniqueValue { + value = entry: entry.value; + message = "Address registry values must be unique."; + }; } diff --git a/registry/route.nix b/registry/route.nix index a07f9dc..ffa12c9 100644 --- a/registry/route.nix +++ b/registry/route.nix @@ -1,5 +1,10 @@ { lib, ... }: { + validate = lib.registry.validators.uniqueValue { + value = entry: entry.value.domain; + message = "Route domains must be unique."; + }; + type = lib.types.submodule { options = { domain = lib.mkOption {