Where can one find more info on the motivation(s) behind `nix-instantiate --read-write-mode`?

I was wondering

  • when is a read-write Nix store path useful? (e.g., using writeTextFile?)
  • what are the implications? (reproducibility, security, etc.)
  • what were the issues it was initially meant to solve? (i.e., historical hindsight)

In the blog post Scripting with Nix, there is this paragraph (emphasis mine):

nix-instantiate --read-write-mode --show-trace --eval -E 'import ./my-script.nix'

The --eval tells Nix to evaluate an expression, rather than build a package. -E is the expression to evaluate (in this case, importing our “script” file). --read-write-mode allows the script to add things to the Nix store (which is normally read-only). --show-trace will help us to debug, by showing a backtrace if a runtime error occurs.

Looking up the documentation for nix-instantiate, the entry for --read-write-mode option says the following:

When used with --eval , perform evaluation in read/write mode so nix language features that require it will still work (at the cost of needing to do instantiation of every evaluated derivation). If this option is not enabled, there may be uninstantiated store paths in the final output.

Based on this description alone I would have no clue of what this actually does (and it has already been clarified…).

Investigating the source of nix-instantiate with git blame, I found the related commits below, but they didn’t help much (or I just wasn’t able to interpret them correctly).

Consider this command:

nix-instantiate --eval -E 'with import <nixpkgs> {}; builtins.readFile (runCommand "hi.txt" {} "echo some text > $out")'

It creates a derivation named hi.txt that simply creates a file with “some text” as its contents. Then it uses readFile on that derivation to get an eval-time string containing “some text”. Without --read-write-mode, you’ll get:

error: cannot read '/nix/store/ni69d524pq5g4jbkpzb5ipvva5bjll1b-hi.txt', since path '/nix/store/hzv9haawrck6mk5q8749a85cs57n4zab-hi.txt.drv' is not valid, at (string):1:27

Because nix-instantiate can’t create the .drv file for the hi.txt derivation, and therefore can’t build the derivation. Without that derivation built, there is no file to import and the eval has to fail.

With --read-write-mode you get:

$ nix-instantiate --eval -E 'with import <nixpkgs> {}; builtins.readFile (runCommand "hi.txt" {} "echo some text > $out")' --read-write-mode 
building '/nix/store/hzv9haawrck6mk5q8749a85cs57n4zab-hi.txt.drv'...
"some text\n"
1 Like