Is NixOS truly reproducible?

What “reproducible” means in NixOS

  • Several commenters emphasize two notions:
    • Bitwise reproducible builds (identical output bytes).
    • Reproducible environments (same inputs, toolchains, configs).
  • Nix is seen as very strong at the latter: exact dependency graph and sandboxed builds, but bit-exactness still depends on upstream build determinism.
  • Some argue Nix historically used “reproducible” in a looser, “repeatable builds with the same inputs” sense, whereas today the term usually implies bitwise identity.

Current state and limits of reproducibility

  • A study cited in the article: nixpkgs reproducibility rose from ~69% (2017) to ~91% (2023).
  • One critique: the absolute number of non-reproducible packages (~5k) hasn’t really dropped; percentages improved mainly because the package set grew.
  • Causes of non-determinism mentioned:
    • Timestamps in archives/JARs, lack or misuse of SOURCE_DATE_EPOCH.
    • Parallel compilation and thread scheduling (output order differences).
    • Uninitialized data in binaries.
    • Build tools that depend on system time or environment (Java, Erlang in older days).
  • Some note you can often “paper over” issues with post-processing (reset timestamps, normalize archives).

Nix vs Bazel, Debian, Arch, Guix, others

  • Debate around Bazel:
    • Pro-Bazel side: sandboxing, network blocking, hermetic toolchains for many languages, reproducible Java/C++ builds if toolchain fixed.
    • Critique: sandboxing/network isolation and hermetic toolchains are often opt-in or partial; default toolchains may use host headers; not always hermetic by default.
  • Nix is argued to enforce stronger hermeticity by default: own toolchains, host FS hidden, tightly controlled network.
  • Debian and Arch also have strong reproducible-builds efforts; Debian tracks ~37k packages, Arch uses rebuilderd. One view: at this point most distros converge because real issues are in upstream build systems, not the package manager.
  • Guix’s strict FOSS, build-from-source stance is seen as a prerequisite for complete from-source reproducibility but also more restrictive for users.

Binary blobs and policy

  • Binary-only / unfree packages can’t be fully reproducible from source.
  • Nixpkgs tracks license and source provenance and by default avoids evaluating unfree packages, but still includes them; some see exclusion (as in Guix) as ideological rather than technical.
  • Others argue even with blobs, having the rest of the graph reproducible is still valuable for supply-chain verification.

Monitoring, metadata, and possible features

  • There is a Nix reproducibility project and automated testing, but not continuous monitoring “at nixpkgs scale” yet.
  • Suggested features:
    • Mark packages as reproducible/non-reproducible in metadata; allow a “only reproducible” flag similar to nonfree.
    • Propagate non-reproducibility transitively through dependency graphs.
    • Community-driven telemetry: hash (inputs → outputs) pairs from many users to detect cohorts and outliers (“build chromatograph” idea).
  • One caveat: you can only definitively prove non-reproducibility; proving determinism is hard without formal methods.

Trust, supply chain, and the intensional store model

  • Several discuss that reproducible builds only help if someone is actually comparing hashes across independent builders.
  • Today, most users just trust the main binary cache; that makes it a high-value target.
  • Proposed direction: use Nix’s formal build descriptions plus:
    • Multiple builders attesting to outputs.
    • Policies like “two independent attestations must agree” rather than a single trusted builder.
  • Intensional store model (content-addressed Nix store) is mentioned:
    • Hash paths by outputs instead of build instructions.
    • Better deduplication and can skip rebuilds when outputs are unchanged.
    • Can support stronger supply-chain properties, but you still need to trust signatures mapping input hashes to output hashes.

Runtime state vs system configuration

  • One user equates reproducible with “immutable” and reports breaking NixOS by cycling desktop environments.
  • Others clarify:
    • NixOS makes system configuration (builds, /etc contents, etc.) reproducible/roll-backable, not user home directories or runtime state.
    • Desktop environments and apps still write dotfiles and mutable state; to get closer to immutable systems you need patterns like:
      • Impermanence-style setups (wipe local changes at reboot).
      • Containers/VMs or ephemeral nix run environments.
  • NixOS is compared to “Ansible + Docker in one system”: declarative host config and build envs, but not full runtime isolation like containers or Flatpak.

Practical benefits and criticisms

  • Supporters highlight:
    • Very high reproducibility out of the box; easy local verification: nix build ...; nix build ... --rebuild and compare.
    • Huge package set where reproducibility has been pushed much further than many thought feasible.
  • Skeptics point to:
    • Usability and complexity costs (“right idea, wrong abstraction”, “nightmare” experiences).
    • Persistence of a hard core of non-reproducible packages.
    • The fact that ultimate guarantees still depend on upstream compilers and build systems being deterministic, which Nix cannot enforce.