refactor(flake): split assembly by concept

This commit is contained in:
2026-08-28 11:01:15 -04:00
parent fc834168aa
commit d0b00ada96
11 changed files with 117 additions and 81 deletions

View File

@@ -5,26 +5,11 @@
}: }:
let let
registryAssembly = import ./registry.nix { inherit lib self; }; registryAssembly = import ./registry.nix { inherit lib self; };
modules = import ./modules.nix { inherit lib; };
dotfilesLib = import ../lib { inherit lib; };
collectNixFiles = moduleFiles = modules.mkModules (self + "/modules");
dir: guestFiles = modules.mkModules (self + "/guests");
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)
);
moduleFiles = collectNixFiles (self + "/modules");
guestFiles = collectNixFiles (self + "/guests");
collectedRegistry = registryAssembly.collect { hosts = self.nixosConfigurations; }; collectedRegistry = registryAssembly.collect { hosts = self.nixosConfigurations; };
@@ -37,15 +22,10 @@ let
registry = collectedRegistry; registry = collectedRegistry;
}; };
bridgeName = id: "br-vlan${toString id}";
dotfiles = { dotfiles = {
inherit (guests) guest; inherit (guests) mkGuest;
lib = { lib = dotfilesLib;
inherit bridgeName;
inherit (guests) deriveMac;
};
}; };
guests = import ./guests.nix { guests = import ./guests.nix {
@@ -54,43 +34,24 @@ let
lib lib
self self
specialArgs specialArgs
bridgeName
moduleFiles moduleFiles
registryAssembly registryAssembly
dotfilesLib
; ;
}; };
mkHost = hosts = import ./hosts.nix {
{ inherit
hostName, inputs
system ? "x86_64-linux", lib
}: self
inputs.nixpkgs.lib.nixosSystem { specialArgs
inherit system specialArgs; moduleFiles
modules = guestFiles
moduleFiles registryAssembly
++ 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 in
{ {
inherit mkHosts; inherit (hosts) mkHosts;
} }

View File

@@ -3,22 +3,12 @@
lib, lib,
self, self,
specialArgs, specialArgs,
bridgeName,
moduleFiles, moduleFiles,
registryAssembly, registryAssembly,
dotfilesLib,
}: }:
let let
inherit (lib) escapeShellArg mapAttrsToList; mkGuest =
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 =
{ {
name, name,
interior ? { }, interior ? { },
@@ -59,13 +49,13 @@ let
createdMounts = lib.filterAttrs (_guestPath: m: m.create != null) cfg.mounts; createdMounts = lib.filterAttrs (_guestPath: m: m.create != null) cfg.mounts;
mountCreateScript = lib.concatStringsSep "\n" ( mountCreateScript = lib.concatStringsSep "\n" (
mapAttrsToList ( lib.mapAttrsToList (
_guestPath: m: _guestPath: m:
let let
create = m.create; create = m.create;
in 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 ) createdMounts
); );
@@ -113,7 +103,7 @@ let
}; };
mac = lib.mkOption { mac = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = deriveMac name; default = dotfilesLib.deriveMac name;
defaultText = lib.literalMD "a stable address derived from the guest's namespace path"; defaultText = lib.literalMD "a stable address derived from the guest's namespace path";
example = "bc:24:11:00:00:01"; example = "bc:24:11:00:00:01";
description = '' description = ''
@@ -316,7 +306,7 @@ let
} }
(lib.mkIf networked ( (lib.mkIf networked (
let let
bridgeDevice = "sys-subsystem-net-devices-${lib.replaceStrings [ "-" ] [ "\\x2d" ] (bridgeName cfg.vlan)}.device"; bridgeDevice = "sys-subsystem-net-devices-${lib.replaceStrings [ "-" ] [ "\\x2d" ] (dotfilesLib.bridgeName cfg.vlan)}.device";
in in
{ {
after = [ bridgeDevice ]; after = [ bridgeDevice ];
@@ -329,7 +319,7 @@ let
containers.${machineName} = lib.mkIf (cfg.backend == "container") { containers.${machineName} = lib.mkIf (cfg.backend == "container") {
autoStart = cfg.autoStart; autoStart = cfg.autoStart;
privateNetwork = lib.mkDefault true; privateNetwork = lib.mkDefault true;
hostBridge = lib.mkIf networked (bridgeName cfg.vlan); hostBridge = lib.mkIf networked (dotfilesLib.bridgeName cfg.vlan);
privateUsers = lib.mkDefault "no"; privateUsers = lib.mkDefault "no";
additionalCapabilities = lib.optionals cfg.nesting [ "CAP_NET_ADMIN" ]; additionalCapabilities = lib.optionals cfg.nesting [ "CAP_NET_ADMIN" ];
allowedDevices = lib.optionals cfg.nesting [ allowedDevices = lib.optionals cfg.nesting [
@@ -366,5 +356,5 @@ let
}; };
in in
{ {
inherit deriveMac guest; inherit mkGuest;
} }

44
flake/hosts.nix Normal file
View File

@@ -0,0 +1,44 @@
{
inputs,
lib,
self,
specialArgs,
moduleFiles,
guestFiles,
registryAssembly,
}:
let
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; });
in
{
inherit mkHosts;
}

22
flake/modules.nix Normal file
View File

@@ -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
{
mkModules = collectNixFiles;
}

View File

@@ -10,7 +10,7 @@ let
in in
{ {
imports = [ imports = [
(dotfiles.guest { (dotfiles.mkGuest {
name = "actualbudget"; name = "actualbudget";
interior = { interior = {
modules.services.actualbudget = { modules.services.actualbudget = {

View File

@@ -35,7 +35,7 @@ let
in in
{ {
imports = [ imports = [
(dotfiles.guest { (dotfiles.mkGuest {
name = "copyparty"; name = "copyparty";
interior = { interior = {
modules.services.copyparty = { modules.services.copyparty = {

View File

@@ -1,7 +1,7 @@
args@{ dotfiles, ... }: 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.
dotfiles.guest { dotfiles.mkGuest {
name = "nesting-sample"; name = "nesting-sample";
interior = { interior = {
virtualisation.oci-containers.containers.hello = { virtualisation.oci-containers.containers.hello = {

View File

@@ -9,7 +9,7 @@ let
in in
{ {
imports = [ imports = [
(dotfiles.guest { (dotfiles.mkGuest {
name = "reverse-proxy"; name = "reverse-proxy";
interior = { interior = {
modules.services.reverse-proxy.enable = true; modules.services.reverse-proxy.enable = true;

View File

@@ -2,4 +2,4 @@ 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.
dotfiles.guest { name = "sample"; } args dotfiles.mkGuest { name = "sample"; } args

7
lib/default.nix Normal file
View File

@@ -0,0 +1,7 @@
{ lib }:
let
network = import ./network.nix { inherit lib; };
in
{
inherit (network) bridgeName deriveMac;
}

12
lib/network.nix Normal file
View File

@@ -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 ]);
}