refactor(flake): move assembly code out of lib

This commit is contained in:
2026-08-29 17:05:43 -04:00
parent abac67afb4
commit 1ba3bdf8d6
12 changed files with 46 additions and 53 deletions

View File

@@ -66,7 +66,7 @@ One flake builds every machine I own.
- Guest modules are host-agnostic wiring, while host files own deployment-specific service configuration such as served volumes and host paths. - Guest modules are host-agnostic wiring, while host files own deployment-specific service configuration such as served volumes and host paths.
For example, `guests/copyparty.nix` should expose options and translate them into guest mounts/service settings, while `hosts/pikachu/default.nix` chooses `/inbox`, `/media`, and their backing paths. For example, `guests/copyparty.nix` should expose options and translate them into guest mounts/service settings, while `hosts/pikachu/default.nix` chooses `/inbox`, `/media`, and their backing paths.
Guest addresses and routes are host-level configuration because a guest module can be used on multiple hosts. Guest addresses and routes are host-level configuration because a guest module can be used on multiple hosts.
- `self.lib.registry.collect { hosts = self.nixosConfigurations; }` reads only top-level host `config.registry` declarations. - The registry collector reads only top-level host `config.registry` declarations.
Registry declarations inside guest interiors live under `config.containers.<guest>.config.registry`. Registry declarations inside guest interiors live under `config.containers.<guest>.config.registry`.
The collected registry does not include those guest-interior declarations. The collected registry does not include those guest-interior declarations.
Publish guest values from host-side code, or extend the collector to recurse into guests. Publish guest values from host-side code, or extend the collector to recurse into guests.

View File

@@ -76,14 +76,11 @@
{ self, nixpkgs, ... }@inputs: { self, nixpkgs, ... }@inputs:
let let
inherit (nixpkgs) lib; inherit (nixpkgs) lib;
my = import ./lib { inherit lib inputs self; }; flake = import ./flake { inherit lib inputs self; };
in in
{ {
# Helper functions for discovering and building hosts.
lib = my;
# Every host under hosts/ is discovered and built. # Every host under hosts/ is discovered and built.
nixosConfigurations = my.mkHosts (self + "/hosts"); nixosConfigurations = flake.mkHosts (self + "/hosts");
# A project shell for agent-local resources that should travel with this # A project shell for agent-local resources that should travel with this
# checkout rather than the operator's global profile. # checkout rather than the operator's global profile.

View File

@@ -4,28 +4,19 @@
self, self,
}: }:
let let
inherit (lib) registryAssembly = import ./registry.nix { inherit lib self; };
attrNames
filterAttrs
genAttrs
flatten
hasSuffix
mapAttrsToList
;
registry = import ./registry.nix { inherit lib self; };
collectNixFiles = collectNixFiles =
dir: dir:
flatten ( lib.flatten (
mapAttrsToList ( lib.mapAttrsToList (
name: type: name: type:
let let
path = dir + "/${name}"; path = dir + "/${name}";
in in
if type == "directory" then if type == "directory" then
collectNixFiles path collectNixFiles path
else if type == "regular" && hasSuffix ".nix" name then else if type == "regular" && lib.hasSuffix ".nix" name then
[ path ] [ path ]
else else
[ ] [ ]
@@ -35,14 +26,28 @@ let
moduleFiles = collectNixFiles (self + "/modules"); moduleFiles = collectNixFiles (self + "/modules");
guestFiles = collectNixFiles (self + "/guests"); guestFiles = collectNixFiles (self + "/guests");
collectedRegistry = registryAssembly.collect { hosts = self.nixosConfigurations; };
specialArgs = { specialArgs = {
inherit inputs self; inherit
my = self.lib; dotfiles
registry = self.lib.registry.collect { hosts = self.nixosConfigurations; }; inputs
self
;
registry = collectedRegistry;
}; };
bridgeName = id: "br-vlan${toString id}"; bridgeName = id: "br-vlan${toString id}";
dotfiles = {
inherit (guests) guest;
lib = {
inherit bridgeName;
inherit (guests) deriveMac;
};
};
guests = import ./guests.nix { guests = import ./guests.nix {
inherit inherit
inputs inputs
@@ -51,7 +56,7 @@ let
specialArgs specialArgs
bridgeName bridgeName
moduleFiles moduleFiles
registry registryAssembly
; ;
}; };
@@ -70,7 +75,7 @@ let
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
inputs.stylix.nixosModules.stylix inputs.stylix.nixosModules.stylix
registry.module registryAssembly.module
(self + "/hosts/${hostName}") (self + "/hosts/${hostName}")
{ {
networking.hostName = hostName; networking.hostName = hostName;
@@ -82,19 +87,10 @@ let
mkHosts = mkHosts =
hostsDir: hostsDir:
let let
hostNames = attrNames (filterAttrs (_name: type: type == "directory") (builtins.readDir hostsDir)); hostNames = lib.attrNames (lib.filterAttrs (_name: type: type == "directory") (builtins.readDir hostsDir));
in in
genAttrs hostNames (hostName: mkHost { inherit hostName; }); lib.genAttrs hostNames (hostName: mkHost { inherit hostName; });
in in
{ {
inherit inherit mkHosts;
collectNixFiles
mkHost
mkHosts
bridgeName
registry
;
inherit (guests) deriveMac guest;
} }

View File

@@ -5,7 +5,7 @@
specialArgs, specialArgs,
bridgeName, bridgeName,
moduleFiles, moduleFiles,
registry, registryAssembly,
}: }:
let let
inherit (lib) escapeShellArg mapAttrsToList; inherit (lib) escapeShellArg mapAttrsToList;
@@ -136,7 +136,7 @@ let
enable = lib.mkEnableOption "a reverse-proxy route for this guest"; enable = lib.mkEnableOption "a reverse-proxy route for this guest";
route = lib.mkOption { route = lib.mkOption {
type = self.lib.registry.definitions.route.type; type = registryAssembly.definitions.route.type;
description = "Route registry entry published for this guest."; description = "Route registry entry published for this guest.";
}; };
}; };
@@ -351,7 +351,7 @@ let
imports = imports =
moduleFiles moduleFiles
++ [ ++ [
registry.module registryAssembly.module
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
inputs.stylix.nixosModules.stylix inputs.stylix.nixosModules.stylix
{ {

View File

@@ -1,7 +1,7 @@
{ {
config, config,
lib, lib,
my, dotfiles,
... ...
}: }:
let let
@@ -10,7 +10,7 @@ let
in in
{ {
imports = [ imports = [
(my.guest { (dotfiles.guest {
name = "actualbudget"; name = "actualbudget";
interior = { interior = {
modules.services.actualbudget = { modules.services.actualbudget = {

View File

@@ -1,7 +1,7 @@
{ {
config, config,
lib, lib,
my, dotfiles,
... ...
}: }:
let let
@@ -35,7 +35,7 @@ let
in in
{ {
imports = [ imports = [
(my.guest { (dotfiles.guest {
name = "copyparty"; name = "copyparty";
interior = { interior = {
modules.services.copyparty = { modules.services.copyparty = {

View File

@@ -1,7 +1,7 @@
args@{ my, ... }: args@{ dotfiles, ... }:
# A sample guest whose interior runs an OCI container on Podman. # 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. # The image is pulled at runtime, so the guest builds with no build-time fetch.
my.guest { dotfiles.guest {
name = "nesting-sample"; name = "nesting-sample";
interior = { interior = {
virtualisation.oci-containers.containers.hello = { virtualisation.oci-containers.containers.hello = {

View File

@@ -1,7 +1,7 @@
{ {
config, config,
lib, lib,
my, dotfiles,
... ...
}: }:
let let
@@ -9,7 +9,7 @@ let
in in
{ {
imports = [ imports = [
(my.guest { (dotfiles.guest {
name = "reverse-proxy"; name = "reverse-proxy";
interior = { interior = {
modules.services.reverse-proxy.enable = true; modules.services.reverse-proxy.enable = true;

View File

@@ -1,5 +1,5 @@
args@{ my, ... }: args@{ dotfiles, ... }:
# The tracer-bullet guest: the thinnest complete path from discovery to a # The tracer-bullet guest: the thinnest complete path from discovery to a
# running nested container. Its interior is just the guest-base — the baseline # 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. # toolset and SSH access — so it proves the concept without carrying a service.
my.guest { name = "sample"; } args dotfiles.guest { name = "sample"; } args

View File

@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
dotfiles,
pkgs, pkgs,
inputs, inputs,
... ...
@@ -63,8 +64,7 @@ in
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = { extraSpecialArgs = {
inherit inputs; inherit dotfiles inputs;
my = inputs.self.lib;
}; };
users.${user.name} = { users.${user.name} = {
home.username = user.name; home.username = user.name;

View File

@@ -1,14 +1,14 @@
{ {
config, config,
lib, lib,
my, dotfiles,
... ...
}: }:
# The host networking foundation: per-VLAN bridges over a tagged trunk. # The host networking foundation: per-VLAN bridges over a tagged trunk.
let let
cfg = config.modules.network.vlans; cfg = config.modules.network.vlans;
inherit (my) bridgeName; inherit (dotfiles.lib) bridgeName;
vlanName = id: "${cfg.trunk}.${toString id}"; vlanName = id: "${cfg.trunk}.${toString id}";
in in