NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.9k stars 1.53k forks source link

Relocatable store objects #9549

Open Ericson2314 opened 11 months ago

Ericson2314 commented 11 months ago

Is your feature request related to a problem? Please describe.

Windows

In https://github.com/NixOS/nix/issues/9389 I propose N:\x\store which is the same length, allowing some janky sedding. But it is still not the same thing. I don't think it is not possible to have the same store dir on Windows and Unix, which is a big impediment to having e.g. a single CI system managing remote build on both platforms.

Unprivilaged users without fancy sandboxing

Even on Unix /nix/store is a impediment on systems that do not have good sandboxing support for regular users. Many people have dreamed of instead being able to dump a store in a home directory and simplify the installation process greatly. Of course, without sandboxing builds are sketchy, but that may be an acceptable tradeoff for those wanting to just try out Nix lightly for the first time.

Content addressing build products

We support self-references for content addressed build products, but this solution doesn't always work. For example, imagine if we file paths need to be sorted keys in an on-disk map. When we rewrite hashes, we can break the alphabetical sorting, and it may be impossible to choose a place in the order for our self reference that doesn't have this problem: for every slot chosen, "the content addresses modulo self references" would give us a hash that moves the reference elsewhere in the lexicographical order!

The proper solution to this problem is domain-specific ways to do self references, like $ORIGIN in ELF RUNPATHs, or simply relative paths. But if we do that for self references, we can consider doing that for all store paths.

Describe the solution you'd like

A store object that isn't allowed to refer to the store directory at all. References are still tracked, by looking for their hashes as is done today, but /nix/store/ (or whatever the store dir is) cannot appear before any of those hashes. We will call these relocatable store objects.

Additionally the property much be transitive: relocatable store objects must only refer to other relocatable store objects, that way entire closures are relocatable if the root object(s) is (are) relocatable.

Normally the store object is used as part of the computation of the store path, but for this that would defeat the purpose, so we will not include it, and just use the other information. I think it would also be nice to not support this for input-adressing --- easy to just drop support for this "legacy" way of doing things in this case.

For Nix itself this should be quite easy. The big question is whether packages in the wild (i.e. in Nixpkgs) can be made to cope without absolute store paths. There's only one way to figure out! :)

Describe alternatives you've considered

While only transitively relatable store objects are really relocatable, it might be useful to still also assert in a derivation that its outputs are "locally" relatable. (I.e. "I only refer to my references with relative store paths, but they sadly my use absolute store paths"). Such store objects as those asserted derivation outputs are sadly non-reloctable, but the assertion it still useful when fixing packages in nixpkgs, so progress can be made "out of order" (referring packages before referenced packages) without accidental regressions.

Then again, this sort of check could also just be done "in user space" with a script at the end of the derivation, rather than by Nix itself.

Additional context

Add any other context or screenshots about the feature request here.

Priorities

Add :+1: to issues you find important.

bjornfor commented 11 months ago

For Nix itself this should be quite easy. The big question is whether packages in the wild (i.e. in Nixpkgs) can be made to cope without absolute store paths.

What about the program interpreter in ELF exectuable files, which has to be an absolute path? That's the first thing that comes to mind (as a blocker).

Ericson2314 commented 11 months ago

Patch the kernel? :D

In general, on the Nixpkgs side, this would be a process of creating workaround patches and negotiating with upstream what to do about it.

edolstra commented 11 months ago

I cannot realistically see this happening since it's so far outside of how Nix and in particular Nixpkgs are designed. References to the store directory are everywhere, and there is no reliable way to prevent them (grepping for the store directory wouldn't work). So we would have to trust the user that a store path doesn't contain such references.

Ericson2314 commented 11 months ago

I think it should be quite easy in Nix itself thanks to you introducing the StorePath type? We just need to store the store dir or lack thereof in ValidPathInfo and voila we can represent this stuff. For reference scanning we already scan for hashes not store path. I think we should just check that that before every found reference there isn't the store directory.

For Nixpkgs, I don't know how are it would be. I think the only way to figure out is to try. It's pretty hard, but so is squashing bugs relating to the limitations of rewriting self-references. Package by package, I would rather spend the time making it relocatable than ensuring absolute self reference rewriting works. (And it's a good thing that many packages already care about relocatability!)

A lot of people that want to distributed relocatable stuff created with Nix would also benefit from this.

edolstra commented 11 months ago

Yes, the Nix changes wouldn't be too hard. But in Nixpkgs, every dependency is expressed as an absolute path. Without the /nix/store, scripts wouldn't even know where to look for dependencies in the filesystem (presumably we would need to pass an environment variable to pass the store directory). Relative paths would sometimes work, but they require knowing the path is relative to. And dynamically-linked ELF executables wouldn't work at all, due to the ELF interpreter field.

BTW I don't see the problem with self-references. Seems to me that they should work exactly the same as they do today?

Ericson2314 commented 11 months ago

BTW I don't see the problem with self-references. Seems to me that they should work exactly the same as they do today?

Supposed we have this file which is supposed to be in lexicographical order

/nix/store/bbbbbbbbbbbbb-foo
/nix/store/xxxxxxxxxxxxx-out

and the second one is the temporary path. Then we do are usual hash modulo and rewrite, and get:

/nix/store/bbbbbbbbbbbbb-foo
/nix/store/aaaaaaaaaaaaa-out

uh oh, they are no longer in order!

now, we try it the other way:

/nix/store/xxxxxxxxxxxxx-out
/nix/store/bbbbbbbbbbbbb-foo

but then after rewriting we get:

/nix/store/zzzzzzzzzzzzz-out
/nix/store/bbbbbbbbbbbbb-foo

still out of order!