Nix and NixOS Version Reference

Updated

September 12, 2026

A structured reference for Boring-NixOS readers tracking which Nix CLI features and NixOS system options became available in each release. Coverage spans Nix 2.18 – 2.35 and NixOS 23.05 – 26.05. This book’s examples target Nix 2.35 and NixOS 26.05 “Yarara”. Earlier rows are history so you can read old flakes.

Each section contains a table of reader-relevant changes followed by one short runnable example that exercises the most impactful addition in that release. All examples assume the infrastructure desk scenario: a shared flake that builds team tooling and drives a set of NixOS workstations.


Nix CLI Releases

Nix 2.18

Area Change
nix flake metadata Prints flake description, inputs, and their resolved URLs; last-modified timestamp now shown per input.
--log-format Accepts raw, internal-json, bar, bar-with-logs; useful for CI pipelines that consume structured output.
Evaluator builtins.fetchTree no longer fetches tarballs eagerly when the hash is already in the store.
Error messages Multi-line errors now include a source excerpt with a caret pointing at the offending token.

Key feature — nix flake metadata

Save as show-meta.sh:

# show-meta.sh
nix flake metadata \
  --log-format bar \
  github:NixOS/nixpkgs/nixos-26.05

Run:

bash show-meta.sh

Output:

Resolved URL:  github:NixOS/nixpkgs/nixos-26.05
Locked URL:    github:NixOS/nixpkgs/a1b2c3d4e5f6...
Description:   Nix Packages collection & NixOS
Path:          /nix/store/xxxxxxxx-source
Last modified: 2024-11-30 12:00:00
Inputs:
└───nixpkgs: (this flake)

Nix 2.19

Area Change
nix store gc Replaces nix-collect-garbage progressively; supports --max-freed <bytes> to cap space reclaimed per run.
nix store gc --dry-run Reports paths that would be deleted without touching the store.
nix profile nix profile diff-closures added; shows package diff between two profile generations.
Daemon Store lock contention reduced for concurrent multi-user builds.

Key feature — nix store gc --dry-run

Save as gc-preview.sh:

# gc-preview.sh
# Preview how much the desk workstation store can shrink
# before committing to deletion.
nix store gc --dry-run --max-freed $((10 * 1024 * 1024 * 1024))

Run:

bash gc-preview.sh

Output:

Would delete: /nix/store/aaa...-old-toolchain-2023
Would delete: /nix/store/bbb...-devshell-2023-11
...
Would free 7.4 GiB (limit was 10.0 GiB)

Nix 2.20

Area Change
nix flake archive Copies all flake inputs into a binary cache or a local store, enabling fully offline evaluation afterwards.
nix flake archive --to Accepts file:///path, s3://bucket, or ssh://host as destination.
nix copy --substitute-on-destination flag added; destination fetches missing paths from its own substituters before failing.
Build sandbox Linux sandbox now mounts /proc as tmpfs by default, improving isolation.

Key feature — nix flake archive to a local mirror

Save as archive-inputs.sh:

# archive-inputs.sh
# Snapshot all flake inputs into a local binary cache so the
# desk's air-gapped build box can evaluate without internet.
nix flake archive \
  --to file:///srv/nix-cache \
  /home/ops/desk-infra

Run:

bash archive-inputs.sh

Output:

archiving input 'nixpkgs'
  /nix/store/xxxxxxxx-source → file:///srv/nix-cache
archiving input 'home-manager'
  /nix/store/yyyyyyyy-source → file:///srv/nix-cache
done — 2 inputs archived

Nix 2.21

Area Change
nix eval --apply Applies a Nix function to the evaluated result before printing; enables one-liner transformations.
nix eval --json Now handles null and true/false correctly in all output formatters.
nix flake update --commit-lock-file flag commits the updated flake.lock with a machine-generated commit message.
Repl :reload re-reads the current file without restarting the session.

Key feature — nix eval --apply

Save as list-packages.sh:

# list-packages.sh
# Print just the names of packages exposed by the desk flake
# without writing a separate script.
nix eval \
  /home/ops/desk-infra#packages.x86_64-linux \
  --apply 'pkgs: builtins.attrNames pkgs' \
  --json

Run:

bash list-packages.sh

Output:

["desk-tools","lint-runner","release-packager"]

Nix 2.22

Area Change
nix build --rebuild Rebuilds a derivation even if its output is in the store, then compares the new result to the cached one — a fast reproducibility check.
nix copy --from / --to Both flags marked stable; no longer experimental.
nix flake check Reports unfree license violations when --allow-unfree is absent.
Evaluator builtins.readFileType added: returns "regular", "directory", "symlink", or "unknown".

Key feature — nix build --rebuild

Save as verify-repro.sh:

# verify-repro.sh
# Rebuild the desk tool and confirm the output hash is stable.
# A mismatch here means a non-deterministic build is lurking.
nix build \
  /home/ops/desk-infra#packages.x86_64-linux.desk-tools \
  --rebuild

Run:

bash verify-repro.sh

Output (reproducible):

warning: performing a check build
[3/0/1 built] building desk-tools-1.4.0...
/nix/store/abc123...-desk-tools-1.4.0 (deterministic ✓)

Output (non-reproducible):

warning: performing a check build
error: derivation '/nix/store/...-desk-tools-1.4.0.drv' may not
       be deterministic: output '/nix/store/abc123...' differs
       from '/nix/store/def456...'

Nix 2.23

Area Change
Lazy trees Flake inputs are fetched only when their subtree is actually evaluated; large monorepo inputs no longer block evaluation.
nix fmt Declared stable; runs the formatter specified in flake.nix formatter output.
nix repl :doc Prints the docstring attached to any Nix function or built-in.
nix repl :log Shows the build log for a derivation path without leaving the REPL.
nix flake update Accepts multiple named inputs: nix flake update nixpkgs home-manager.

Key feature — nix fmt enforced in CI

Save as fmt-check.sh:

# fmt-check.sh
# Fail CI if any Nix file in the desk flake needs reformatting.
nix fmt /home/ops/desk-infra -- --check

Run:

bash fmt-check.sh

Output (clean):

All Nix files already formatted.

Output (needs formatting):

Would reformat: /home/ops/desk-infra/modules/workstation.nix
error: 1 file would be reformatted

Nix 2.24

Area Change
nix path-info --json Output is now a structured JSON array with path, narHash, narSize, references, registrationTime, and deriver fields.
nix flake check Checks nixosConfigurations, darwinConfigurations, and homeConfigurations outputs for module evaluation errors.
nix store diff-closures Declared stable; compares the full runtime closure of two store paths and reports added/removed/changed paths.
nix build --print-build-logs Default changed to true in interactive terminals.

Key feature — nix store diff-closures

Save as diff-release.sh:

# diff-release.sh
# Compare the desk-tools closure between the last release and
# HEAD so the team knows exactly what changed before shipping.
OLD=$(nix build \
  "/home/ops/desk-infra?ref=v1.3.0#packages.x86_64-linux.desk-tools" \
  --no-link --print-out-paths)

NEW=$(nix build \
  /home/ops/desk-infra#packages.x86_64-linux.desk-tools \
  --no-link --print-out-paths)

nix store diff-closures "$OLD" "$NEW"

Run:

bash diff-release.sh

Output:

desk-tools: 1.3.0 → 1.4.0
openssl: 3.2.1 → 3.2.2 (+12 KiB)
python3: 3.11.8 → 3.12.3 (+1.1 MiB)
curl: (unchanged)
added: zlib 1.3.1