-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stabilize discard-references
#8322
Conversation
I'm not in favor of stabilizing this. The objections I gave in #7087 (comment) and #7087 (comment) still exist, namely that this is a potentially dangerous loosening of Nix's closure invariant. Having it as an experimental feature that people have to opt into makes it clear they're doing something potentially dangerous, and avoids people starting to abuse this (e.g. in Nixpkgs to have optional dependencies or whatever). |
What solution do you suggest to the problem of disk images with spurious references? Spectrum builds are composed of several layers of disk images (e.g. VM images are built, and then put into a root filesystem image), and when I substitute one of those, Nix will separately, pointlessly, download all the paths included in the image before downloading the image itself, which contains its own copies of all those paths. |
I don't think this should be stabilized. The Nix store database's reference graph is just a cache which can be discarded and reconstructed from the store itself. Stabilizing this feature destroys that property.
Obfuscate your disk image. Compression, rot13, morse code, an invertible version of Something somewhere has to bear the burden of remembering that a particular outpath is special and exempt from reference-scanning. Stabilizing this feature shifts that burden from the special outpath to Nix itself. This is a lossy conversion: the "specialness bit" is not recoverable from the outpath. |
When one outpath is just a concatenation or |
No, it isn't. The reference scanning only detects whatever is in the closure of the derivation so you can embed (nearly) arbitrary references that won't be picked by Nix by hardcoding them properly. For example $ nix build nixpkgs#hello and $ nix store add-path $(nix build --no-link --print-out-paths nixpkgs#hello) have the exact same content, but a different set of references. You can even implement a (very inefficient) pure Nix version of
Well, that's not what experimental features are made for, is it? They are meant as a temporary way for trying out a feature, not a permanent gatekeeping measure |
That distinction mattered back when Nix lacked a sandbox... In an alternate (better?) universe where Nix had a sandbox from the very beginning we might never have needed string contexts.
I wouldn't object to changes which break this pathological example, and in fact I happen to have one in mind.
If you'd like to rename |
Adam, I'm not sure making this opt in would actually preserve the property you want (which arguably doesn't exist today anyway). References are determined when a path is built, so it's the build machine that would get to opt in or out. As an end user, if you wanted to make sure your reference graph was reconstructable from outputs, you'd have to make sure you never used a substituter that was configured to discard references. Even today, a substituter could have been set up to strip references without support from Nix, and you'd end up with store paths whose references weren't rescannable.
|
That one is a bit contrived indeed, but just nixpkgs already contains several hundreds of literal store paths in its source: $ grep -R -E '/nix/store/[a-z0-9]{32}-' $(nix eval --raw nixpkgs#path) | wc -l
314 That being said, what's the change you have in mind?
I'm not sure what you mean by that. What's the link with string contexts? |
So, let's breakdown this 314.
(used in
magic with various representations of the same store path for the empty file in JSON files about fetching which mention the store path used only for updating not for evaluation. Various kinds of documentation.
Overall: effectively, there is one true instance, two more questionable instances, and 311 cases that are not actually used in evaluation. I could have missed one more semi-true instance? So the impact of changing the behaviour here is absolutely manageable |
Maybe I misunderstood what you meant here, but them being used in evaluation or not doesn't change anything. My point was simply that if we were to refscan nixpkgs assuming that everything that looks like a store path in it is indeed a reference, then we're in trouble. And that the literal store path references in Nix store paths aren't the source of truth for a good reason. |
If we scan store paths searching for things identical to other present store paths, we will actually do pretty OK. |
But that wouldn't be deterministic, right? something like |
But that wouldn't be deterministic, right? something like `writeText "foo" "${builtins.unsafeDiscardStringContext hello.outPath}"` would be different depending on whether `hello` is in store or not
Correct, and it also breaks the basic expectations about references, which is why we try to keep such things rare and exotic.
|
It's part of the Nix trust model that you have to trust your substituters to faithfully realize the derivations you send to them, including much worse things like not injecting malware into outpaths. Do any substituters existing today corrupt the references in the way you describe? I would consider this a serious bug in the substituter!
Here's another possibility: represent the "ignore references" bit explicitly in the outpath. It's ugly, but I suppose a magic file in The trickiest part about this approach is keeping all the different parts in sync, since the "discard references" decision comes from the derivation but is also represented in the outpath. IMHO the best solution would be to eliminate
Then there is no synchronization problem, since the derivation no longer has a |
I find it easiest to understand Nix's worldview using the analogy to the Boehm-Demers-Weiser Garbage Collector from section 3.4 of @edolstra's thesis. Using that analogy, |
I agree and initially suggested this early in the other thread, but it didn't catch on. |
Hrm, that seems pretty complicated... What I'm suggesting is much simpler:
|
That is what I meant |
That wouldn't work for file store paths, just directories. |
This was discussed in the Nix team meeting last week. We agreed on merging it so I'll fix the conflicts and merge. Discussion log- @edolstra: Still concerned about optional references like people abusing this to build pluggable derivations that would have undeclared reference to other store paths (and would behave differently depending on the presence of these) - But the fact that it's all-or-nothing (can't selectively discard only a subset of the derivations) makes this much less dangerous in that regard - @edolstra: Let's stabilize this - Agreement |
It has been there for a few releases now (landed in 2.14.0), doesn't seem to cause any major issue and is wanted in a few places (NixOS#7087 (comment)).
0e51087
to
ad410ab
Compare
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2023-07-31-nix-team-meeting-minutes-76/31486/1 |
Motivation
It has been there for a few releases now (landed in 2.14.0), doesn't
seem to cause any major issue and is wanted in a few places
(#7087 (comment)).
Context
The xp feature got introduced in #7087
Checklist for maintainers
Maintainers: tick if completed or explain if not relevant
tests/**.sh
src/*/tests
tests/nixos/*
Priorities
Add 👍 to pull requests you find important.