Skip to content

Architecture overview

This infrastructure combines three complementary architectural patterns to create a maintainable, multi-machine configuration that works across macOS and NixOS systems.

Foundation: Module system primitives (nixpkgs)

Section titled “Foundation: Module system primitives (nixpkgs)”

Uses nixpkgs’ module system primitives for configuration composition. Flake-parts wraps lib.evalModules for flake composition.

What it provides:

  • lib.evalModules: Fixpoint computation resolving modules into final configuration
  • deferredModule type: Option type for storing module values that are evaluated later by consumers
  • Option merging: Type-specific merge functions with priority handling

Framework: Flake composition (flake-parts)

Section titled “Framework: Flake composition (flake-parts)”

Uses flake-parts as the foundation for modular flake composition. Flake-parts wraps nixpkgs’ evalModules for flake outputs, adding flake-specific conventions and ergonomics.

What it provides:

  • Modular flake composition via evalModules wrapper
  • PerSystem configuration helpers (per-system evaluation)
  • flake.modules.* namespace convention (deferredModule type)
  • Clean separation of concerns across system types

Organization: Deferred module composition (aspect-based pattern)

Section titled “Organization: Deferred module composition (aspect-based pattern)”

Uses the deferredModule type (nixpkgs module system primitive) for storing configuration fragments. Every Nix file is a flake-parts module (evaluated at the top level) that exports deferredModule values (evaluated later when consumers import them), enabling cross-cutting concerns to reference the merged result.

The aspect-based deferred module composition pattern organizes these modules by aspect (feature) rather than by host, with flake-parts providing the evaluation context and namespace conventions.

Key principle: Configuration is organized by what it does, not which machine it runs on.

What it provides:

  • Aspect-based organization (features, not hosts)
  • Automatic module discovery via import-tree (adds to evalModules imports list)
  • Cross-cutting configuration spanning NixOS, nix-darwin, and home-manager
  • Aggregate modules for composing related features (deferredModule monoid composition)

See Deferred Module Composition for detailed explanation.

Orchestration: Multi-machine coordination (clan)

Section titled “Orchestration: Multi-machine coordination (clan)”

Uses clan for multi-machine coordination and deployment. Clan orchestrates deployments across the machine fleet but doesn’t replace underlying NixOS/nix-darwin configuration.

What it provides:

  • Machine registry and deployment targets
  • Inventory system for service orchestration
  • Secrets management with encryption (clan vars)
  • Unified deployment tooling

See Clan Integration for detailed explanation.

Packages: Overlay composition (multi-channel fallback)

Section titled “Packages: Overlay composition (multi-channel fallback)”

Adopts proven patterns from mirkolenz/nixos for handling nixpkgs unstable breakage with stable fallbacks.

Key components:

  • Multi-channel inputs: Stable, unstable, and patched nixpkgs variants
  • Stable fallbacks infrastructure: Platform-specific stable fallbacks
  • Five-layer overlay composition: Structured package and overlay merging

See Handling Broken Packages for operational details.

PlatformImplementationDeployment
Darwinnix-darwin via clanclan machines update <hostname>
NixOSNixOS via clanclan machines update <hostname>
Home-ManagerIntegrated with system configsActivates with system deployment
modules/
├── clan/ # Clan integration
│ ├── core.nix # Clan flakeModule import
│ ├── machines.nix # Machine registry
│ └── inventory/ # Service instances
├── darwin/ # nix-darwin modules (per-aspect)
├── home/ # home-manager modules (per-aspect)
├── machines/ # Machine-specific configs
│ ├── darwin/ # Darwin hosts
│ └── nixos/ # NixOS hosts
├── nixos/ # NixOS modules (per-aspect)
├── system/ # Cross-platform modules
├── terranix/ # Infrastructure as code
└── nixpkgs/ # Nixpkgs configuration and overlays
pkgs/
└── by-name/ # Custom package derivations

The overlay system provides stable fallbacks for nixpkgs breakage through internal and external overlays composed in a single pass:

# Overlay composition order (via lib.composeManyExtensions)
lib.composeManyExtensions [
channels # Multi-channel nixpkgs access (stable, unstable, patched)
stable-fallbacks # Platform-specific stable fallbacks
overrides # Build modifications
nvim-treesitter # External overlay: nvim-treesitter from flake input
nuenv # External overlay: nushell utilities from flake input
# ... other external overlays from flake inputs
] // customPackages # Custom derivations from pkgs-by-name
modules/nixpkgs/overlays/channels.nix
final: prev: {
inherit inputs nixpkgs patched;
stable = systemInput system; # darwin-stable or linux-stable
unstable = prev; # Default nixpkgs
}

All channels available throughout the configuration for selective package sourcing.

modules/nixpkgs/overlays/stable-fallbacks.nix
final: prev: {
# Platform-conditional stable fallbacks
inherit (final.stable) packageName; # Use stable version
# Documented with hydra links and removal conditions
}

When nixpkgs unstable breaks, apply surgical fixes (stable fallback for one package) without rolling back entire flake.lock (which affects O(10^5) packages).

Clan vars provides unified secrets management with sops encryption. All secrets (SSH keys, zerotier identities, API tokens, passphrases) are managed through clan vars for consistent deployment and access control.

Some secrets use legacy direct sops-nix patterns alongside clan vars.

See Clan Integration for detailed secrets architecture and migration status.

Infrastructure provisioning (terranix) creates cloud resources. Clan deploys NixOS configurations to those resources.

Terranix creates VMs → Clan installs NixOS → Clan deploys config

Deferred modules define configurations. Clan machines import and deploy those configurations.

Deferred modules (aspect-based) → Clan machines (host-based) → Deployment

Home-manager modules defined using deferred module composition. Machine configurations import home-manager modules. Clan deploys full machine config including home-manager.

HostnamePlatformTypePrimary User
stibniteaarch64-darwinLaptopcrs58
blackphosaarch64-darwinLaptopraquel
rosegoldaarch64-darwinLaptopjanettesmith
argentumaarch64-darwinLaptopchristophersmith
cinnabarx86_64-linuxVPS (Hetzner)cameron
electrumx86_64-linuxVPS (Hetzner)cameron
galenax86_64-linuxGCP VMcameron
scheelitex86_64-linuxGCP VM (GPU)cameron

All machines managed via clan machines update <hostname>.

The combination provides:

  • Scalable organization - The deferred module composition pattern retains interpretability of large configurations
  • Multi-machine coordination - Clan orchestrates heterogeneous fleet
  • Reliable nixpkgs handling - Overlay patterns provide stable fallbacks
  • Clean separation - Each layer has clear responsibilities