Still a work in progress.

This commit is contained in:
Yaro Kasear 2025-11-29 12:55:11 -06:00
parent 500eb9e859
commit 62899898fe
5 changed files with 42 additions and 75 deletions

8
flake.lock generated
View file

@ -233,16 +233,16 @@
}, },
"nixpkgs_4": { "nixpkgs_4": {
"locked": { "locked": {
"lastModified": 1735563628, "lastModified": 1764316264,
"narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=", "narHash": "sha256-82L+EJU+40+FIdeG4gmUlOF1jeSwlf2AwMarrpdHF6o=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798", "rev": "9a7b80b6f82a71ea04270d7ba11b48855681c4b0",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-24.05", "ref": "nixos-25.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }

View file

@ -2,7 +2,7 @@
description = "Metanix static flake: meta.nix addressing, deploy-rs, disko, nixos-anywhere"; description = "Metanix static flake: meta.nix addressing, deploy-rs, disko, nixos-anywhere";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
deploy-rs.url = "github:serokell/deploy-rs"; deploy-rs.url = "github:serokell/deploy-rs";
disko.url = "github:nix-community/disko"; disko.url = "github:nix-community/disko";
nixos-anywhere.url = "github:numtide/nixos-anywhere"; nixos-anywhere.url = "github:numtide/nixos-anywhere";

View file

@ -47,7 +47,6 @@
deimos = { deimos = {
role = "server"; role = "server";
hw-address = "10:98:36:a0:2c:b2"; hw-address = "10:98:36:a0:2c:b2";
interface = "eno2";
aliases = [ aliases = [
"kasear.net" "kasear.net"
"cloud.kasear.net" "cloud.kasear.net"
@ -115,6 +114,7 @@
phobos = { phobos = {
role = "server"; role = "server";
hw-address = "10:98:36:a9:4a:26"; hw-address = "10:98:36:a9:4a:26";
interface = "eno2";
aliases = [ aliases = [
"pbx.kasear.net" "pbx.kasear.net"
"private.kasear.net" "private.kasear.net"

View file

@ -1,45 +1,34 @@
{ lib, config, ... }: { lib, config, ... }:
let let
inherit (lib) mkOption mkIf types attrValues filterAttrs head; inherit (lib) mkOption mkIf types;
metanix = config.metanix or { }; metanix = config.metanix or { };
# For now, tell Metanix "which host am I?"
thisHostName = config.metanix.thisHost or config.networking.hostName; thisHostName = config.metanix.thisHost or config.networking.hostName;
host = metanix.network.hosts.${thisHostName} or null; hosts = (metanix.network or { }).hosts or { };
host = hosts.${thisHostName} or null;
# Find the subnet this host belongs to by matching IP prefix subnets = (metanix.network or { }).subnets or { };
# VERY SIMPLE: relies on your rigid addressing scheme subnet =
findSubnetForHost = if host != null && host ? subnetKey
ip: then subnets.${host.subnetKey} or null
let else null;
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 = cidrPrefix =
cidr: cidr:
let let
# match "10.1.32.0/19" → [ "19" ]
m = builtins.match ".*/([0-9]+)" cidr; m = builtins.match ".*/([0-9]+)" cidr;
in in
if m == null then 32 else builtins.fromJSON (head m); if m == null then 32 else builtins.fromJSON (builtins.head m);
hostSubnet =
if host == null then null else findSubnetForHost host."ip-address";
prefixLen = prefixLen =
if hostSubnet == null then 32 else cidrPrefix hostSubnet.cidr; if subnet == null then 32 else cidrPrefix subnet.cidr;
unitName =
if host == null then "metanix"
else "10-${host.location}-${host.subnetType}-${host.interface}";
in in
{ {
options.metanix.thisHost = mkOption { options.metanix.thisHost = mkOption {
@ -54,24 +43,16 @@ in
config = mkIf (host != null && host ? interface) { config = mkIf (host != null && host ? interface) {
systemd.network.enable = true; systemd.network.enable = true;
systemd.network.networks."10-metanix-${host.interface}" = { systemd.network.networks.${unitName} = {
matchConfig = { matchConfig.Name = host.interface;
Name = host.interface;
};
# Static address from Metanix
address = [ address = [
"${host."ip-address"}/${toString prefixLen}" "${host."ip-address"}/${toString prefixLen}"
]; ];
# Optional: match MAC if present linkConfig = mkIf (host ? "hw-address") {
linkConfig = lib.mkIf (host ? "hw-address") {
MACAddress = host."hw-address"; MACAddress = host."hw-address";
}; };
# TODO later: gateway & DNS resolution from metanix.network / policy
# gateway = "...";
# dns = [ ... ];
}; };
}; };
} }

View file

@ -2,49 +2,35 @@
let let
system = "x86_64-linux"; system = "x86_64-linux";
# Bring in nixpkgs and lib # Grab nixpkgs lib for convenience
pkgs = import <nixpkgs> { inherit system; }; pkgs = import <nixpkgs> { inherit system; };
lib = pkgs.lib; lib = pkgs.lib;
# Your world + addressing lib # Metanix world + addressing
meta = import ../meta.nix; meta = import ../meta.nix;
addressing = import ../lib/addressing { inherit lib; }; addressing = import ../lib/addressing { inherit lib; };
# NixOS module system library network = addressing.mkNetworkFromSpec meta;
nixosLib = import <nixpkgs/nixos/lib> {
inherit lib;
};
# All standard NixOS modules (as a list) # Fake NixOS config that your module expects
baseModules = import <nixpkgs/nixos/modules/module-list.nix>; config = {
# Evaluate modules as if this were a NixOS system
evalResult = nixosLib.evalModules {
modules =
baseModules
++ [
# Metanix core wiring (meta + addressing)
../modules/metanix/core.nix
# systemd-networkd integration
../modules/metanix/networkd.nix
# Local stub: "this machine is phobos"
{
networking.hostName = "phobos"; networking.hostName = "phobos";
metanix.thisHost = "phobos"; metanix = {
} thisHost = "phobos";
]; inherit network;
# Args passed to all modules: { lib, pkgs, system, meta, addressing, modulesPath, ... }
specialArgs = {
inherit lib pkgs system meta addressing;
modulesPath = builtins.toString <nixpkgs/nixos/modules>;
}; };
}; };
# Call the networkd module directly as a function
networkdModule = import ../modules/metanix/networkd.nix {
inherit lib config;
};
in in
{ {
systemdNetwork = evalResult.config.systemd.network; # Raw Metanix view
metanixHost = evalResult.config.metanix.network.hosts.phobos; metanixHost = network.hosts.phobos;
metanixSubnet = evalResult.config.metanix.network.subnets."home-main"; metanixSubnet = network.subnets."home-main";
# What the module actually emits
systemdNetwork = networkdModule.config.systemd.network;
} }