Flakes and Inputs
- Type: Tutorial
- Status: Current
- Scope: Reading the root flake, lock file, host outputs, and input policy in
nixos-config- Canonical sources:
flake.nix;flake.lock;lib/auto-update-policy.nix;modules/services/redview.nix;modules/services/jellyfin.nix; Flakes on nix.dev; Adding Packages and Flake Inputs- Last verified: Source commit
556df88494686003b1c4f20c8e0b99b5afc16a6e(2026-09-12); source HEADb2831d33132967b4c4fb69e6068b2b05fff8fdffchanges onlyflake.lock. Root inputs/outputs, examples, and policy shape checked 2026-09-13; no input was updated.- Review triggers: Flake inputs/outputs, stable/unstable host selection, external package output shapes, lock/update policy, or linked upstream explanation
Learning goal and prerequisites
Explain where this repository obtains external code, which targets it exposes, and why a new input needs both a lock entry and update-policy classification. Read the Guided Repository Tour and Nix Language Essentials first. For general flake semantics, use the official nix.dev Flakes concept; this page teaches this repository's shape, not every flake feature.
Read flake.nix in four passes
First, inputs declares roots. nixpkgs tracks unstable; nixpkgs-stable
tracks NixOS 26.05 for Cosmos and Chaos. Home Manager has matching unstable
and stable inputs. Other roots supply hardware modules, Disko, SOPS,
packages/services, the standalone updater, and formatting. flake.lock
records the resolved graph and revisions. A URL in flake.nix alone is not
an exact build record, while a lock file alone does not declare which output
a host consumes. Do not hand-edit the lock file.
Second, follow inputs.<name>.inputs.nixpkgs.follows = "nixpkgs" where it
exists. It asks that input to use this root's Nixpkgs dependency. It is not
universal: the Redview input currently has no such follows declaration.
bash-it and pi-ollama have flake = false, meaning their fetched source
is consumed as a path, not as a flake with packages or nixosModules
outputs. Do not copy an output expression without checking its real shape.
Third, inspect the outputs function. It binds named inputs and the entire
set as inputs; makeNixosSystem then calls the chosen Nixpkgs
lib.nixosSystem. Its host import is ./hosts/${configName}. The builder
adds common external modules, passes inputs to NixOS modules via
specialArgs, and separately configures Home Manager. The next tutorial
explains module merging and the later one explains the two argument paths.
Fourth, inspect nixosConfigurations, checks, packages, and formatter.
The six registered hosts are Electra, Lena, Vega, Lyra, Cosmos, and Chaos.
Cosmos/Chaos pass the stable Nixpkgs and matching Home Manager inputs to
the same builder; a selected package may still come from a different input.
For example, Lyra's Jellyfin module explicitly chooses a stable Jellyfin
package while Lyra itself remains an unstable host. The root flake also
exports the deployment/remediation packages, formatting check, and pinned
updater state-machine check. potential/nova is not a flake target, so it
is not one of the host outputs.
Why update policy is part of the input story
lib/auto-update-policy.nix maps each root input to the hosts that actually
consume it, or deliberately pins it. flake.nix derives the rootInputs
inventory from its input argument set so an unclassified input can be
rejected by the guarded update producer. A transitive shared input can
affect several hosts even when only one module visibly mentions it.
This is a validation map, not a statement that all hosts run the same
channel or service. ADR-005 explains
the producer/consumer design; Adding Packages and Flake
Inputs gives the change procedure.
Guided check
Without changing the lock file, trace redview from its root input in
flake.nix through modules/services/redview.nix to the Lyra host import.
Identify the external nixosModules output, the package output keyed by
pkgs.stdenv.hostPlatform.system, and the corresponding update-policy
group. Then compare the nixpkgs-stable host-builder use with the narrow
Jellyfin package use. The same input can play different roles; name the
consumer rather than saying merely that the fleet "uses stable."
Common mistakes: assuming every input has packages.<system>.default,
assuming flake = false produces flake outputs, changing a root input
without policy/consumer builds, or claiming a registered host was deployed
because its flake output evaluates. The authoritative engineering steps are
in Adding Packages and Flake Inputs.