December 23, 2025
Reproducible Builds are a great way to convince yourself the binary artifacts you (or others) publish online were not tampered with on the build infrastructure.
NixOS is a Linux distribution that provides a nice starting point for reproducible builds, because it is very precise about build inputs, and runs its builds in a sandbox (so build processes can’t download arbitrary stuff from the internet during the build). This in itself does not guarantee reproducibility: for example timestamps and build parallelism can still lead to all kinds nondeterminisms. Fixing those is a large, cross-distribution effort.
As you can see on the NixOS Reproducible Builds page, we’re steadil…
December 23, 2025
Reproducible Builds are a great way to convince yourself the binary artifacts you (or others) publish online were not tampered with on the build infrastructure.
NixOS is a Linux distribution that provides a nice starting point for reproducible builds, because it is very precise about build inputs, and runs its builds in a sandbox (so build processes can’t download arbitrary stuff from the internet during the build). This in itself does not guarantee reproducibility: for example timestamps and build parallelism can still lead to all kinds nondeterminisms. Fixing those is a large, cross-distribution effort.
As you can see on the NixOS Reproducible Builds page, we’re steadily rebuilding individual items from the ‘official’ NixOS binary cache on independent infrastructure, and checking that they produce bit-by-bit identical outputs. This is good for finding problematic derivations, but typically still takes the dependencies of any rebuild from the binary cache, which weakens the signal. For this reason, I verified the Minimal Installation ISO can be fully reproduced with minimal reliance on the cache.
Reproducing the minimal ISO
I start with the NixOS 20.03 VirtualBox appliance in qemu:
$ tar -xvf ~/Downloads/nixos-20.03.1405.a17e021b948-x86_64-linux.ova
$ qemu-img convert -f vmdk -O qcow2 nixos-20.03.1405.a17e021b948-x86_64-linux-disk001.vmdk rb.qcow2
$ qemu-img resize rb.qcow2 150G
$ qemu-system-x86_64 -m 25600 -smp 16 -cpu host -enable-kvm -drive file=rb.qcow2
Then inside the vm (building as root to avoid a problem with using the old nix-daemon for new builds):
# Fetch the build definitions
$ nix-shell -p git
$ git clone https://github.com/nixos/nixpkgs
$ cd nixpkgs
# build the Nix version to build Nix with (with binary cache disabled)
$ git checkout 8e8f31731938
$ nix-shell -p nix -I nixpkgs=/home/demo/nixpkgs --option substitute false
# get the commit to reproduce from
$ git checkout 09eb77e94fa2
# build the Nix version to build the ISO with (with binary cache disabled)
$ sudo nix-build -p nix -I nixpkgs=/home/demo/nixpkgs --option substitute false
$ nix-shell -p nix -I nixpkgs=/home/demo/nixpkgs --option substitute false
# workaround for https://github.com/NixOS/nixpkgs/issues/467866
$ nix-build . -A elfutils
# perform the iso build (with binary cache disabled)
$ sudo nix-build nixos/release-combined.nix -A nixos.iso_minimal.x86_64-linux --option substitute false --max-jobs 6 --arg nixpkgs "{ revCount = 901827+1335; shortRev = \"09eb77e94fa2\"; rev = \"09eb77e94fa25202af8f3e81ddc7353d9970ac1b\"; }" --arg stableBranch true
I was able to take nixpkgs at 09eb77e94fa2 and produce an ISO with sha256sum 57bcfaef17a57fb544cea59b735da569ad7e174e7b4fde31661e3fd4f1815f0f, which matches what was built on Hydra (hit ‘details’ or download the iso and see for yourself).
Limitations
This is a pretty good reproduction: it rebuilds pretty much all build dependencies and actual packages that go into the ISO, without relying on an archive of existing binary packages.
It is not perfect: we start with that NixOS 20.03 VirtualBox appliance. We have to start somewhere (we don’t have Bootstrappable builds yet), and the chance that someone could have backdoored that image in the year 2020 in a way that both went undetected and is still effective today is very slim.
Also, while we don’t rely on the Nix binary cache, there are some build definitions (notably go) that use a binary upstream instead of building fully from source.
Hash Collection
Partly supported by the Sovereign Tech Fund, me and JulienMalka have been working on hash collection infrastructure. This now helps us make better reports giving insight in the reproducibility of the objects in our binary cache, but also unlocks hash verification without having to rely on a single trusted party, as multiple builders can upload their (signed) hashes. It’ll also help doing more continuous rebuilds rather than the one-off checks we did before. We hope to build this out further in the future. You can view live reports at https://reproducibility.nixos.social/ .
Where to from now?
Further plans:
- Continue fixing known nondeterminisms, upstreaming as much as possible, notably working towards making the Graphical ISO reproducible as well.
- Continue on hash collection
- Extend the infrastructure to regularly independently rebuild artifacts, instead of ‘one-off’ checks like the ones described in this thread.
- Flag which derivations still depend on a binary upstream release instead of being built from source
Want to help?
- Join us at #reproducible-builds:nixos.org
- Check out the GitHub project board
- Check out lila
- Check out the NixOS Reproducible Builds website
Also appeared at: