From 647b20b9343541e3eb3ff411a54f2e86ee659470 Mon Sep 17 00:00:00 2001 From: alexion Date: Sat, 29 Aug 2026 17:05:43 -0400 Subject: [PATCH] refactor(flake): split assembly by concept --- flake/default.nix | 92 +++++++++++---------------------- flake/{guests.nix => guest.nix} | 32 +++++------- flake/host.nix | 46 +++++++++++++++++ flake/module.nix | 5 ++ guests/actualbudget.nix | 4 +- guests/copyparty.nix | 4 +- guests/nesting-sample.nix | 4 +- guests/reverse-proxy.nix | 4 +- guests/sample.nix | 4 +- lib/default.nix | 9 ++++ lib/files.nix | 22 ++++++++ lib/network.nix | 12 +++++ modules/default.nix | 4 +- modules/network/vlans.nix | 4 +- 14 files changed, 149 insertions(+), 97 deletions(-) rename flake/{guests.nix => guest.nix} (94%) create mode 100644 flake/host.nix create mode 100644 flake/module.nix create mode 100644 lib/default.nix create mode 100644 lib/files.nix create mode 100644 lib/network.nix diff --git a/flake/default.nix b/flake/default.nix index 7127139..359dab8 100644 --- a/flake/default.nix +++ b/flake/default.nix @@ -4,93 +4,59 @@ self, }: let + # TODO: refactor the registry code registryAssembly = import ./registry.nix { inherit lib self; }; - collectNixFiles = - dir: - lib.flatten ( - lib.mapAttrsToList ( - name: type: - let - path = dir + "/${name}"; - in - if type == "directory" then - collectNixFiles path - else if type == "regular" && lib.hasSuffix ".nix" name then - [ path ] - else - [ ] - ) (builtins.readDir dir) - ); + util = import ../lib { inherit lib; }; + mkModules = import ./module.nix { inherit util; }; - moduleFiles = collectNixFiles (self + "/modules"); - guestFiles = collectNixFiles (self + "/guests"); + modules = mkModules { + root = self + "/modules"; + }; + + #---------------------------------------------------------- + guestFiles = util.collectNixFiles (self + "/guests"); collectedRegistry = registryAssembly.collect { hosts = self.nixosConfigurations; }; specialArgs = { inherit - dotfiles + flake inputs self ; registry = collectedRegistry; }; - bridgeName = id: "br-vlan${toString id}"; + flake = { + inherit (hosts) mkHosts; + inherit (guests) mkGuest; - dotfiles = { - inherit (guests) guest; - - lib = { - inherit bridgeName; - inherit (guests) deriveMac; - }; + inherit util; }; - guests = import ./guests.nix { + guests = import ./guest.nix { inherit inputs lib self specialArgs - bridgeName - moduleFiles registryAssembly + util ; + repositoryModules = modules; }; - mkHost = - { - hostName, - system ? "x86_64-linux", - }: - inputs.nixpkgs.lib.nixosSystem { - inherit system specialArgs; - modules = - moduleFiles - ++ guestFiles - ++ [ - inputs.chaotic.nixosModules.default - inputs.disko.nixosModules.disko - inputs.sops-nix.nixosModules.sops - inputs.stylix.nixosModules.stylix - registryAssembly.module - (self + "/hosts/${hostName}") - { - networking.hostName = hostName; - modules.host.enable = true; - } - ]; - }; - - mkHosts = - hostsDir: - let - hostNames = lib.attrNames (lib.filterAttrs (_name: type: type == "directory") (builtins.readDir hostsDir)); - in - lib.genAttrs hostNames (hostName: mkHost { inherit hostName; }); + hosts = import ./host.nix { + inherit + inputs + lib + self + specialArgs + guestFiles + registryAssembly + ; + repositoryModules = modules; + }; in -{ - inherit mkHosts; -} +flake diff --git a/flake/guests.nix b/flake/guest.nix similarity index 94% rename from flake/guests.nix rename to flake/guest.nix index 33ab552..3f4d8d8 100644 --- a/flake/guests.nix +++ b/flake/guest.nix @@ -3,22 +3,12 @@ lib, self, specialArgs, - bridgeName, - moduleFiles, + repositoryModules, registryAssembly, + util, }: let - inherit (lib) escapeShellArg mapAttrsToList; - - deriveMac = - name: - let - hash = builtins.hashString "sha256" name; - octet = i: builtins.substring (i * 2) 2 hash; - in - lib.concatStringsSep ":" ([ "02" ] ++ map octet [ 0 1 2 3 4 ]); - - guest = + mkGuest = { name, interior ? { }, @@ -59,13 +49,13 @@ let createdMounts = lib.filterAttrs (_guestPath: m: m.create != null) cfg.mounts; mountCreateScript = lib.concatStringsSep "\n" ( - mapAttrsToList ( + lib.mapAttrsToList ( _guestPath: m: let create = m.create; in '' - ${config.system.path}/bin/install -d -o ${escapeShellArg (toString create.owner)} -g ${escapeShellArg create.group} -m ${escapeShellArg create.mode} ${escapeShellArg m.hostPath} + ${config.system.path}/bin/install -d -o ${lib.escapeShellArg (toString create.owner)} -g ${lib.escapeShellArg create.group} -m ${lib.escapeShellArg create.mode} ${lib.escapeShellArg m.hostPath} '' ) createdMounts ); @@ -113,7 +103,7 @@ let }; mac = lib.mkOption { type = lib.types.str; - default = deriveMac name; + default = util.deriveMac name; defaultText = lib.literalMD "a stable address derived from the guest's namespace path"; example = "bc:24:11:00:00:01"; description = '' @@ -316,7 +306,7 @@ let } (lib.mkIf networked ( let - bridgeDevice = "sys-subsystem-net-devices-${lib.replaceStrings [ "-" ] [ "\\x2d" ] (bridgeName cfg.vlan)}.device"; + bridgeDevice = "sys-subsystem-net-devices-${lib.replaceStrings [ "-" ] [ "\\x2d" ] (util.bridgeName cfg.vlan)}.device"; in { after = [ bridgeDevice ]; @@ -329,7 +319,7 @@ let containers.${machineName} = lib.mkIf (cfg.backend == "container") { autoStart = cfg.autoStart; privateNetwork = lib.mkDefault true; - hostBridge = lib.mkIf networked (bridgeName cfg.vlan); + hostBridge = lib.mkIf networked (util.bridgeName cfg.vlan); privateUsers = lib.mkDefault "no"; additionalCapabilities = lib.optionals cfg.nesting [ "CAP_NET_ADMIN" ]; allowedDevices = lib.optionals cfg.nesting [ @@ -349,7 +339,9 @@ let config = { imports = - moduleFiles + [ + repositoryModules + ] ++ [ registryAssembly.module inputs.sops-nix.nixosModules.sops @@ -366,5 +358,5 @@ let }; in { - inherit deriveMac guest; + inherit mkGuest; } diff --git a/flake/host.nix b/flake/host.nix new file mode 100644 index 0000000..0b7c889 --- /dev/null +++ b/flake/host.nix @@ -0,0 +1,46 @@ +{ + inputs, + lib, + self, + specialArgs, + repositoryModules, + guestFiles, + registryAssembly, +}: +let + mkHost = + { + hostName, + system ? "x86_64-linux", + }: + inputs.nixpkgs.lib.nixosSystem { + inherit system specialArgs; + modules = + [ + repositoryModules + ] + ++ guestFiles + ++ [ + inputs.chaotic.nixosModules.default + inputs.disko.nixosModules.disko + inputs.sops-nix.nixosModules.sops + inputs.stylix.nixosModules.stylix + registryAssembly.module + (self + "/hosts/${hostName}") + { + networking.hostName = hostName; + modules.host.enable = true; + } + ]; + }; + + mkHosts = + hostsDir: + let + hostNames = lib.attrNames (lib.filterAttrs (_name: type: type == "directory") (builtins.readDir hostsDir)); + in + lib.genAttrs hostNames (hostName: mkHost { inherit hostName; }); +in +{ + inherit mkHosts; +} diff --git a/flake/module.nix b/flake/module.nix new file mode 100644 index 0000000..5c38e3e --- /dev/null +++ b/flake/module.nix @@ -0,0 +1,5 @@ +{ util }: +{ root }: +{ + imports = util.collectNixFiles root; +} diff --git a/guests/actualbudget.nix b/guests/actualbudget.nix index c4f5aac..fbfb352 100644 --- a/guests/actualbudget.nix +++ b/guests/actualbudget.nix @@ -1,7 +1,7 @@ { config, lib, - dotfiles, + flake, ... }: let @@ -10,7 +10,7 @@ let in { imports = [ - (dotfiles.guest { + (flake.mkGuest { name = "actualbudget"; interior = { modules.services.actualbudget = { diff --git a/guests/copyparty.nix b/guests/copyparty.nix index 161cdc8..5f73fd9 100644 --- a/guests/copyparty.nix +++ b/guests/copyparty.nix @@ -1,7 +1,7 @@ { config, lib, - dotfiles, + flake, ... }: let @@ -35,7 +35,7 @@ let in { imports = [ - (dotfiles.guest { + (flake.mkGuest { name = "copyparty"; interior = { modules.services.copyparty = { diff --git a/guests/nesting-sample.nix b/guests/nesting-sample.nix index 12a1e27..5ecd5c5 100644 --- a/guests/nesting-sample.nix +++ b/guests/nesting-sample.nix @@ -1,7 +1,7 @@ -args@{ dotfiles, ... }: +args@{ flake, ... }: # A sample guest whose interior runs an OCI container on Podman. # The image is pulled at runtime, so the guest builds with no build-time fetch. -dotfiles.guest { +flake.mkGuest { name = "nesting-sample"; interior = { virtualisation.oci-containers.containers.hello = { diff --git a/guests/reverse-proxy.nix b/guests/reverse-proxy.nix index 090081a..b71d316 100644 --- a/guests/reverse-proxy.nix +++ b/guests/reverse-proxy.nix @@ -1,7 +1,7 @@ { config, lib, - dotfiles, + flake, ... }: let @@ -9,7 +9,7 @@ let in { imports = [ - (dotfiles.guest { + (flake.mkGuest { name = "reverse-proxy"; interior = { modules.services.reverse-proxy.enable = true; diff --git a/guests/sample.nix b/guests/sample.nix index 1e0fab9..7651aa2 100644 --- a/guests/sample.nix +++ b/guests/sample.nix @@ -1,5 +1,5 @@ -args@{ dotfiles, ... }: +args@{ flake, ... }: # The tracer-bullet guest: the thinnest complete path from discovery to a # running nested container. Its interior is just the guest-base — the baseline # toolset and SSH access — so it proves the concept without carrying a service. -dotfiles.guest { name = "sample"; } args +flake.mkGuest { name = "sample"; } args diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..9c535ce --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,9 @@ +{ lib }: +let + files = import ./files.nix { inherit lib; }; + network = import ./network.nix { inherit lib; }; +in +{ + inherit (files) collectNixFiles; + inherit (network) bridgeName deriveMac; +} diff --git a/lib/files.nix b/lib/files.nix new file mode 100644 index 0000000..daecfdd --- /dev/null +++ b/lib/files.nix @@ -0,0 +1,22 @@ +{ lib }: +let + collectNixFiles = + dir: + lib.flatten ( + lib.mapAttrsToList ( + name: type: + let + path = dir + "/${name}"; + in + if type == "directory" then + collectNixFiles path + else if type == "regular" && lib.hasSuffix ".nix" name then + [ path ] + else + [ ] + ) (builtins.readDir dir) + ); +in +{ + inherit collectNixFiles; +} diff --git a/lib/network.nix b/lib/network.nix new file mode 100644 index 0000000..f8524f1 --- /dev/null +++ b/lib/network.nix @@ -0,0 +1,12 @@ +{ lib }: +{ + bridgeName = id: "br-vlan${toString id}"; + + deriveMac = + name: + let + hash = builtins.hashString "sha256" name; + octet = i: builtins.substring (i * 2) 2 hash; + in + lib.concatStringsSep ":" ([ "02" ] ++ map octet [ 0 1 2 3 4 ]); +} diff --git a/modules/default.nix b/modules/default.nix index e4cba84..ca7f6bc 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,7 +1,7 @@ { config, lib, - dotfiles, + flake, pkgs, inputs, ... @@ -64,7 +64,7 @@ in useGlobalPkgs = true; useUserPackages = true; extraSpecialArgs = { - inherit dotfiles inputs; + inherit flake inputs; }; users.${user.name} = { home.username = user.name; diff --git a/modules/network/vlans.nix b/modules/network/vlans.nix index dd2fb9a..dc4124c 100644 --- a/modules/network/vlans.nix +++ b/modules/network/vlans.nix @@ -1,14 +1,14 @@ { config, lib, - dotfiles, + flake, ... }: # The host networking foundation: per-VLAN bridges over a tagged trunk. let cfg = config.modules.network.vlans; - inherit (dotfiles.lib) bridgeName; + inherit (flake.util) bridgeName; vlanName = id: "${cfg.trunk}.${toString id}"; in