3 41 Repository Structure and Import Chain
Nimmo edited this page 2026-09-13 11:16:09 +01:00

Repository Structure and Import Chain

  • Type: Reference
  • Status: Current
  • Scope: nixos-config source layout and NixOS/Home Manager evaluation entry points
  • Canonical sources: flake.nix; hosts/*/default.nix; modules/common/base.nix; modules/profiles/gui.nix; modules/profiles/laptop.nix; modules/server/base.nix; home/users/nimmo/default.nix; modules/common/default-config.nix; AGENTS.md
  • Last verified: Source commit 556df88494686003b1c4f20c8e0b99b5afc16a6e (2026-09-12); source HEAD b2831d33132967b4c4fb69e6068b2b05fff8fdff changes only flake.lock. Paths and import chain checked 2026-09-13.
  • Review triggers: Changes to flake outputs or makeNixosSystem, registered hosts, host imports, common/profile composition, Home Manager wiring, or repository directories

Purpose and ownership

This page shows where evaluation begins and how a file becomes part of a host. It is a source-navigation reference, not a live fleet inventory or a recipe for adding a host. For current placement and deployment state use the Host Inventory; for the choice between modules, profiles, hosts, users, and Home Manager use Configuration Ownership Boundaries.

The key rule is imports are explicit. A .nix file in modules/ does nothing merely because it exists. It affects a host only when that host's module graph imports it or when flake.nix adds it to every host. Likewise, a directory under potential/ is not a NixOS target until registered in flake.nix.

Source map

Path Responsibility in this repository
flake.nix, flake.lock Pin inputs; construct NixOS targets, packages, checks, formatter, and update-policy export. The lock records exact input revisions.
hosts/<host>/ Entry module, hardware configuration, Disko layout, and host-only settings for each registered target.
modules/common/ Shared options and baseline. base.nix is imported by every registered host, sometimes transitively through a profile.
modules/profiles/ Curated groups of imports or opt-in workload configuration; a profile is still a NixOS module.
modules/services/, modules/databases/, modules/containers/ Reusable native services, database composition, and declared OCI/container workloads imported by selected hosts.
modules/boot/, modules/desktop/, modules/hardware/, modules/maintenance/, modules/networking/, modules/power/, modules/server/, modules/virtualization/ Capability-specific NixOS modules, selected by host or profile imports.
users/ NixOS system accounts, groups, and privileges; not Home Manager.
home/users/nimmo/ Primary user's Home Manager modules; home/nimmo.nix is a compatibility entry point, not the path selected by the current flake builder.
packages/ Fleet-local derivations exposed or consumed through Nix expressions. Larger independently maintained packages can instead be flake inputs.
secrets/, .sops.yaml Encrypted source files and recipient policy. Runtime use is declared by importing modules; files are not automatically loaded.
lib/auto-update-policy.nix Root-input classification and affected-host policy used by the guarded update producer.
justfiles/, scripts/, tests/, .forgejo/workflows/ User commands, implementation helpers, regressions, and CI. These are not NixOS modules merely by location.
potential/ Staged or legacy host material. Nova is not in nixosConfigurations; media1 retains only a legacy reference note.

Evaluation path

flake.nix: nixosConfigurations.<host>
  -> makeNixosSystem { configName = "<host>"; ... }
     -> nixpkgs.lib.nixosSystem (or nixpkgs-stable.lib.nixosSystem)
        -> hosts/<host>/default.nix
           -> its direct and transitive imports (profiles, common, services,
              hardware, users, host-local files, external modules)
        -> shared modules added by makeNixosSystem
           -> SOPS, Home Manager, Paseo, nixos-auto-update,
              cache settings and configuration revision
           -> Home Manager: home/users/<primaryUser>/default.nix

flake.nix registers electra, lena, vega, and lyra against the unstable nixpkgs input. It registers cosmos and chaos with nixpkgs-stable and home-manager-stable (26.05). These six names, not the contents of hosts/ or potential/, define the current flake target set. The builder also sets system.configurationRevision from self.rev or self.dirtyRev where available; it does not turn a dirty checkout into a published source revision.

makeNixosSystem passes the whole inputs attrset as NixOS specialArgs. Thus a host or module that declares inputs can select a pinned package or external NixOS module without another global forwarding file. The same builder wires SOPS, Home Manager, Paseo, and the standalone updater as shared modules. Do not add a second copy of those modules to a host merely because they are absent from its imports list.

Home Manager is part of each NixOS target, not a separate top-level flake configuration here. flake.nix selects home/users/${config.nixosConfig.primaryUser} and passes inputs, isServer, flakeRepo, primaryUser, userEmail, and hostName as home-manager.extraSpecialArgs. isServer is derived from nixosConfig.host.role == "server"; the home modules use it to omit desktop configuration on server roles. NixOS account definitions under users/ are a different layer.

How the host chains differ

  • electra and lena import modules/profiles/laptop.nix, which imports profiles/gui.nix, then common/base.nix, plus laptop capabilities. Their own entry modules add hardware, networking, users, and selected workloads. Electra keeps battery base plus igpu/dgpu specialisations in one host target; see ADR-001.
  • vega, lyra, cosmos, and chaos import modules/common/base.nix and modules/server/base.nix directly. Each then selects its own service, container, database, network, and hardware modules. server/base.nix itself imports common system packages and the opt-in backup profile; common/base.nix no longer imports Backrest directly.
  • Every registered host reaches common/base.nix, which imports Disko's module, Nix settings, locale, nixosConfig default options, SOPS host-key handling, garbage collection, Btrfs maintenance, Beszel, and the failure monitor option provider. A feature inside a selected module may still have its own enable option or host-specific configuration; import alone does not prove that every service is active or deployed.

modules/common/default-config.nix declares portable nixosConfig defaults such as primaryUser, flakeRepo, sshKeyPath, and host inventory metadata. Each host entry module overrides the relevant values and declares its own networking.hostName. The System Atlas owns the evaluated current inventory; do not duplicate it in this structural map.

Trace a proposed change

  1. Start with the target name in flake.nix. If it is not under nixosConfigurations, no host build or deployment path exists for it. Use Adding a Host to prepare a new target.
  2. Follow ./hosts/${configName} to that host's default.nix. Read its imports, including external flake modules and transitive profile imports.
  3. Check the builder's shared modules before adding a duplicate host import. Then inspect the defining option module and every host that selects it.
  4. If the change is user-environment-only, follow the Home Manager path and distinguish it from users/ account configuration.
  5. Stage newly created .nix files before flake evaluation: Git-backed flakes do not see untracked source files. Validate using the relevant Testing and Deployment contract and the Engineering Handbook guidance for the type of change.

For a root input addition, also update lib/auto-update-policy.nix; see Wrapper-Repository Packaging for an integrated example. Nothing in this map authorizes a live deployment or a data migration.