WASM Derivations in Nix


Nix promises us reproducibility, which must come from builds doing the same thing
every time.

"It works on my machine" is what we must avoid.
In practice, Nix has mostly succeeded, but not quite.
While build failures due to different hardware (but same platform/system-type) are very uncommon,
differences in the output are very common, even sandboxed.

Linux's sandboxing facilities aren't perfect, and any information about the host
system leaked into the sandbox could change the results.
This is especially problematic with content-addressed derivations, where
we name build outputs not by what they were built with, but by what they resulted in.
For the benefits of content-addressing, see Tweag's material on this.

Derivations run in WASM solve this.
It could theoretically not be WASM, but WASM gives us an easy way of running
derivations in a completely reproducible and identical manner (modulo bugs),
such that theoretically every user would get the exact same output.

This is not the only benefit of WASM derivations.
Let's say you build your Raspberry Pi's system derivation on your x86 desktop,
you push it, and then locally on the RPi you change one thing, and try to rebuild.
This would cause a whole-world rebuild, because unintuitively, nothing is cached!
When building from your x86 desktop, you built _different_ derivations, with a different
system, "x86_64-linux", whereas the derivations you build locally would be "aarch64-linux" (or 32-bit ARM),
unless you build the ARM derivations using QEMU (see boot.binfmt.emulatedSystems option).
WASM derivations in fact would allow us to build the derivations natively on _any_ platform obviously,
even Windows.

The possibilities end not here, for we could go further, do cryptographic attestation of correct
building (complementing Trustix), expose the GPU to the sandbox in a secure manner (as WebGPU perhaps),
or extend/restrict the interface between the build process and the host system arbitrarily in a secure manner.

The path however is arduous.
Say you wish to build Firefox in a WASM derivation, how would you go about this?
The current derivation assumes a standard Linux environment, one with bash, gcc, ld,
make, coreutils, _all_ of these have to work in WASM!
This is where most of the work is, porting tools to work in WASM,
using e.g. WASIX (https://wasix.org/) or WALI (https://arxiv.org/abs/2312.03858),
interfaces for accessing system APIs from WASM (such as fork).

The work to implement WASM support in Nix (libstore) itself is simpler,
albeit with many ways of doing it with different trade-offs.

Room 212
Sunday, March 17, 2024 - 11:45 to 12:45