How does Nix prevent side effects?

I’ve been wondering how exactly does Nix prevent side effects? I tried to manually insert some side effects in the builder.sh file by inserting a touch /home/<username>/side-effect in the shell script. When I ran nix-build, it failed with the following error

touch: cannot touch '/home/<username>/temp/side-effect': No such file or directory

How exactly does this happen, i.e. how does Nix know that this line in the shell script will cause a side effect?

Followup question: if I replace touch /home/<username>/side-effect with touch /tmp/side-effect, nix-build runs without errors, but there’s no file named side-effect in /tmp anyways? Why is this happening?

Thanks!

This is done using sandboxing. The builds happen in a special environment where the network is unavailable, the users, groups and permissions are faked, and the filesystem is completely disjoint (and only the /nix/store path is shared).

On linux, this is done using namespaces as can be seen here in the sources around the clone() call.

This is comparable to Bazel that can use docker sandboxes to isolate builds. In the spawned docker, Bazel copies the necessary files in the sandbox, and disables network access. Therefore, the /tmp that the build sees is completely different from the /tmp of the whole system and was just created in the sandbox because many builds need it. On the other hand, /home/<username> does not even exist in the sandbox, and writing there fails.

Hope this gives you a global idea of what happens.

5 Likes