Skip to content

Flake (concept)

Overview

A flake is a Nix project's standardized entry point: a directory whose root contains flake.nix, declaring inputs (dependencies on other flakes or sources) and outputs (packages, NixOS modules, dev shells, and other values). The first time you build or evaluate, Nix writes flake.lock, pinning each input to an exact revision so two checkouts get the same dependency graph.

Flakes are an experimental feature (enable nix-command and flakes in nix.conf, or pass --extra-experimental-features 'nix-command flakes'). They remain experimental in current CppNix stable manuals (e.g. 2.34.x) even though widely used. They replace the implicit NIX_PATH / <nixpkgs> lookup of channels with explicit, version-controlled inputs. Schema, workflows, registries, and migration are covered in Flakes—this page stays at the concept level.

Channel Flake
Pin Moving channel URL + local channel state flake.lock commit per input
Discovery NIX_PATH, <nixpkgs> inputs block + registry
Eval purity Classic workflows often impure Flake commands default to pure eval
Update nix-channel --update nix flake update

Details

A flake directory is anchored by flake.nix, which must provide outputs as a function of the realized inputs. Optional top-level attributes include description, inputs, and nixConfig. Inputs are named references such as nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; outputs returns the artifacts this flake provides (often keyed by system, e.g. packages.x86_64-linux.default).

Unlocked URLs in flake.nix resolve to concrete Git revisions (or tarball hashes) in flake.lock. Commit the lockfile so CI and collaborators share the same pins; run nix flake update when you intentionally bump inputs. A channel subscription points at a moving release URL—nix-channel --update pulls whatever commit that branch currently names, so two machines can diverge until each updates. flake.lock pins exact input commits in version control, independent of upstream branch motion.

The Nix 3 CLI treats flake references—., github:owner/repo, or nixpkgs#hello—as first-class targets for nix build, nix run, nix develop, and nix flake show. A flake registry maps symbolic names to default URLs.

When evaluating a flake, Nix restricts filesystem and environment access unless declared as inputs. That supports hermetic, cache-friendly builds and makes “what went into this evaluation?” auditable. Impure escape hatches and flags are documented under pure eval and impure.

CppNix and Lix both expose flake evaluation and the flake CLI under the same experimental feature flags; treat flag availability and exact CLI surface as implementation- and version-dependent. Other evaluators may lack or partially implement flakes—check that evaluator’s docs before assuming parity.

Scope. This page defines vocabulary only. Output schemas, NixOS composition, publishing workflows, lockfile JSON, pure-eval path rules, and nixosConfigurations wiring belong in 07-flakes and linked pages (lockfile, pure eval and impure, nixos-configurations).

Examples

  • Minimal shape: flake.nix lists inputs.nixpkgs and exposes outputs.packages.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.hello. Runnable fixture: hello-flake/flake.nix.
  • Pinned third-party input: After nix build, flake.lock records the exact nixpkgs commit; another clone builds against the same revision without running nix-channel --update.
  • Remote reference: nix run nixpkgs#hello uses the registry to find Nixpkgs and run a package output—no local channel subscription required. Requires nix-command and flakes.

References

See also