nix icon indicating copy to clipboard operation
nix copied to clipboard

Guarantee that store entries appear atomically

Open jeltsch opened this issue 4 months ago • 5 comments

When Nix has performed a derivation, the output is moved from the temporary directory in which it currently resides to /nix/store. This can be and apparently is done atomically if /tmp and /nix/store reside on the same volume.

However, what happens if they don’t? Is the derivation then just copied into /nix/store (and afterwards deleted from /tmp)? This could result in a directory under /nix/store that has the appropriate name but lacks part of the contents, in case the command that triggered the derivation is interrupted. An approach that would guarantee atomic appearance of the derivation output in the store is to copy the corresponding directory with its contents into the store under a temporary name that doesn’t follow the pattern of ordinary in-store directory names and then rename the directory, which would be an atomic operation.

Has such an alternative approach be considered, or is it perhaps even what Nix is using?


Add :+1: to issues you find important.

jeltsch avatar Sep 05 '25 14:09 jeltsch

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/nixos-rebuild-hangs-while-downloading-from-cache-nixos-org/68875/22

nixos-discourse avatar Sep 05 '25 14:09 nixos-discourse

Somewhat related: https://github.com/NixOS/nix/issues/11655.

xokdvium avatar Nov 29 '25 08:11 xokdvium

When Nix has performed a derivation, the output is moved from the temporary directory in which it currently resides to /nix/store.

Note that the output that gets moved is not in /tmp. When using sandboxing on Linux, it's in the chroot directory (/nix/store/<derivation>.chroot) which is in the same filesystem as /nix/store. When not using sandboxing, builders write their output directly to /nix/store.

This could result in a directory under /nix/store that has the appropriate name but lacks part of the contents, in case the command that triggered the derivation is interrupted.

The output is not considered valid until it is registered as such in /nix/var/nix/db/db.sqlite, so interrupting the derivation is not a problem. However, unless fsync-store-paths is set, it's not guaranteed that writes to /nix/store are flushed to disk before the database is updated. So if the system crashes after the derivation has finished, you might end up with a corrupted store path.

edolstra avatar Dec 01 '25 12:12 edolstra

However, unless fsync-store-paths is set, it’s not guaranteed that writes to /nix/store are flushed to disk before the database is updated.

Interesting. Is fsync-store-paths enabled in NixOS by default? Where would I enable it if it weren’t?

jeltsch avatar Dec 01 '25 17:12 jeltsch

nix.settings.fsync-store-paths = true;

eclairevoyant avatar Dec 01 '25 19:12 eclairevoyant