Infrastructure Modules
Full source for the core infrastructure of a dendritic flake: target systems, flake-parts extras, shared top-level options, and the per-class configuration plumbing for NixOS, home-manager, and nix-darwin. These correspond to Steps 3-4 of the conversion in SKILL.md.
systems.nix - Define Target Systems
{
systems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
];
}flake-parts.nix - Import flake-parts Extras
{ inputs, ... }:
{
imports = [
# Provides flake.modules option for deferredModules
inputs.flake-parts.flakeModules.modules
];
}meta.nix - Declare Shared Top-Level Options
Move values you used to pass via specialArgs into top-level options. Keep them settable - readOnly = true would freeze each value in this file instead of letting hosts or users override it:
{ lib, ... }:
{
options.username = lib.mkOption {
type = lib.types.singleLineStr;
default = "myuser";
};
options.stateVersion = lib.mkOption {
type = lib.types.str;
default = "24.11";
};
}nixos.nix - NixOS Configuration Infrastructure
Turns configurations.nixos.<name>.module into flake.nixosConfigurations and generates flake.checks for each configuration’s toplevel:
{ lib, config, ... }:
{
options.configurations.nixos = lib.mkOption {
type = lib.types.lazyAttrsOf (
lib.types.submodule {
options.module = lib.mkOption {
type = lib.types.deferredModule;
};
}
);
default = {};
};
config.flake = {
nixosConfigurations = lib.mapAttrs (
name: { module }: lib.nixosSystem { modules = [ module ]; }
) config.configurations.nixos;
# Add checks for each configuration's toplevel
checks = lib.mkMerge (
lib.mapAttrsToList (
name: nixos: {
${nixos.config.nixpkgs.hostPlatform.system} = {
"configurations:nixos:${name}" = nixos.config.system.build.toplevel;
};
}
) config.flake.nixosConfigurations
);
};
}home-manager.nix - home-manager Configuration Infrastructure
{ lib, config, inputs, ... }:
{
options.configurations.homeManager = lib.mkOption {
type = lib.types.lazyAttrsOf (
lib.types.submodule {
options.module = lib.mkOption {
type = lib.types.deferredModule;
};
}
);
default = {};
};
config.flake.homeConfigurations = lib.mapAttrs (
name: { module }:
inputs.home-manager.lib.homeManagerConfiguration {
pkgs = inputs.nixpkgs.legacyPackages.x86_64-linux;
modules = [ module ];
}
) config.configurations.homeManager;
}Note:
pkgsis hardcoded tox86_64-linuxhere for brevity. Derive it per configuration and system (e.g. storesystemalongsidemodulein the submodule andimport inputs.nixpkgs { system = ...; }) so aarch64-linux and Darwin hosts work.
darwin.nix - nix-darwin Configuration Infrastructure
{ lib, config, inputs, ... }:
{
options.configurations.darwin = lib.mkOption {
type = lib.types.lazyAttrsOf (
lib.types.submodule {
options.module = lib.mkOption {
type = lib.types.deferredModule;
};
}
);
default = {};
};
config.flake.darwinConfigurations = lib.mapAttrs (
name: { module }:
inputs.nix-darwin.lib.darwinSystem {
modules = [ module ];
}
) config.configurations.darwin;
}All three infrastructure modules share the same shape: a configurations.<class> option of lazyAttrsOf (submodule { module = deferredModule; }), mapped into the matching flake output. Add a new class (e.g. nixos-darwin combined configs) by following the same template.
Since each host’s toplevel lands in flake.checks, a plain nix flake check builds every host closure - use nix flake check --no-build for eval-only iteration (see Best Practices in SKILL.md).