From 4a4b369136a7bbd9b2a90460e17c5fd56cc0a0d7 Mon Sep 17 00:00:00 2001 From: Yaro Kasear Date: Sat, 29 Nov 2025 11:21:10 -0600 Subject: [PATCH] Some work to do with systemd-networkd. Still nowhere near enough to create an actual config. --- flake.nix | 3 +- lib/addressing/default.nix | 11 ++- meta.nix | 1 + .../{metanix-core.nix => metanix/core.nix} | 0 modules/metanix/networkd.nix | 77 +++++++++++++++++++ 5 files changed, 90 insertions(+), 2 deletions(-) rename modules/{metanix-core.nix => metanix/core.nix} (100%) create mode 100644 modules/metanix/networkd.nix diff --git a/flake.nix b/flake.nix index f883cba..e358b78 100644 --- a/flake.nix +++ b/flake.nix @@ -45,7 +45,8 @@ modules = (sysCfg.modules or [ ]) ++ [ - ./modules/metanix-core.nix + ./modules/metanix/core.nix + ./modules/metanix/networkd.nix # Disko wiring if present (if sysCfg ? diskoConfig then diff --git a/lib/addressing/default.nix b/lib/addressing/default.nix index 4e580a3..445da81 100644 --- a/lib/addressing/default.nix +++ b/lib/addressing/default.nix @@ -331,6 +331,11 @@ let { ip-address = ip; inherit hostname fqdn; + + # New context fields: + location = locationName; + subnetType = typeName; + subnetKey = "${locationName}-${typeName}"; } // optionalAttrs (hostCfg ? hw-address) { inherit (hostCfg) hw-address; @@ -341,7 +346,11 @@ let // optionalAttrs (hostCfg ? aliases) { inherit (hostCfg) aliases; } - )) + // optionalAttrs (hostCfg ? interface) { + inherit (hostCfg) interface; + } + ) + ) hostNames)) subnets) locations; diff --git a/meta.nix b/meta.nix index 66bb70d..403c6fa 100644 --- a/meta.nix +++ b/meta.nix @@ -47,6 +47,7 @@ deimos = { role = "server"; hw-address = "10:98:36:a0:2c:b2"; + interface = "eno2"; aliases = [ "kasear.net" "cloud.kasear.net" diff --git a/modules/metanix-core.nix b/modules/metanix/core.nix similarity index 100% rename from modules/metanix-core.nix rename to modules/metanix/core.nix diff --git a/modules/metanix/networkd.nix b/modules/metanix/networkd.nix new file mode 100644 index 0000000..451096a --- /dev/null +++ b/modules/metanix/networkd.nix @@ -0,0 +1,77 @@ +{ lib, config, ... }: + +let + inherit (lib) mkOption mkIf types attrValues filterAttrs head; + + metanix = config.metanix or { }; + + # For now, tell Metanix "which host am I?" + thisHostName = config.metanix.thisHost or config.networking.hostName; + + host = metanix.network.hosts.${thisHostName} or null; + + # Find the subnet this host belongs to by matching IP prefix + # VERY SIMPLE: relies on your rigid addressing scheme + findSubnetForHost = + ip: + let + subnets = metanix.network.subnets or { }; + matches = + filterAttrs + (_: s: lib.strings.hasPrefix (lib.strings.concatStringsSep "." (lib.take 3 (lib.splitString "." s.cidr))) + (lib.strings.concatStringsSep "." (lib.take 3 (lib.splitString "." ip)))) + subnets; + in + if matches == { } + then null + else head (attrValues matches); + + cidrPrefix = + cidr: + let + # match "10.1.32.0/19" → [ "19" ] + m = builtins.match ".*/([0-9]+)" cidr; + in + if m == null then 32 else builtins.fromJSON (head m); + + hostSubnet = + if host == null then null else findSubnetForHost host."ip-address"; + + prefixLen = + if hostSubnet == null then 32 else cidrPrefix hostSubnet.cidr; + +in +{ + options.metanix.thisHost = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Logical Metanix host name for this machine. + Used to look up IP/interface in metanix.network.hosts. + ''; + }; + + config = mkIf (host != null && host ? interface) { + systemd.network.enable = true; + + systemd.network.networks."10-metanix-${host.interface}" = { + matchConfig = { + Name = host.interface; + }; + + # Static address from Metanix + address = [ + "${host."ip-address"}/${toString prefixLen}" + ]; + + # Optional: match MAC if present + linkConfig = lib.mkIf (host ? "hw-address") { + MACAddress = host."hw-address"; + }; + + # TODO later: gateway & DNS resolution from metanix.network / policy + # gateway = "..."; + # dns = [ ... ]; + }; + }; +}