-
-
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
Self-contained outputs #7087
Self-contained outputs #7087
Conversation
I think CI is failing because the daemon doesn't have the patch? Checks pass locally EDIT: ah, it's because of the check against a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that's a much needed thing, glad to see a PR for that!
Left a few comments/suggestions, but overall 👍
std::set_intersection(referenceablePaths.begin(), referenceablePaths.end(), | ||
spec.begin(), spec.end(), | ||
std::inserter(tmp, tmp.begin())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be useful to also log (notice
I would say) the references that we erase here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit skeptical: I don't think it adds any information that the user doesn't already know, and I think there are usually too many paths in referenceablePaths
for this to be useful and not spam.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could be useful to debug some potential errors where you're accidentally referencing too much. But I might be wrong and the spamming argument is totally valid. So let's keep things that way)
03f04dc
to
ab929ec
Compare
I renamed the attribute to |
I'm not in favor of this. It breaks a fundamental property of Nix, namely the closure invariant, i.e. every reference of a valid path is also present and valid, and thus there are no "gaps" in closures. It decouples the references stored in the Nix DB from the actual references in the filesystem. I realize that the main use case here is filesystem images, where it is desirable and reasonable to ignore references, but this PR also opens the possibility of optional runtime dependencies and is sure to be (ab)used to for that. E.g. if I have a package like A minor issue is that it's currently at least theoretically possible to recover the references graph (i.e. the contents of the Nix database) simply by scanning all store paths for references to all other store paths. With this PR, that property no longer holds since you need the |
Regarding the first point, Nix does not have that property. I can easily make a program that effectively references a store path in a way that is not detected by the scanner, simply by mangling the hash. We are using a heuristic to detect references, which works well enough but is nonetheless sometimes faulty, and this PR allows overriding the heuristic when it is faulty. This does not change any fundamental property of Nix. If you fear that it would be abused, we can always add a big red warning in the documentation. I agree that the second point is more of a problem. How about, as an alternative, storing the list of possible references in a designated path under the output tree, say |
I agree that this isn't really breaking the closure invariant since we can already @edolstra Is the If that's the case, would it be reasonable to just make it possible to ignore all the references? That should solve the most common use-case while not allowing this kind of optional dependencies pattern |
Of course you can hide dependencies, just as you can hide pointers to a conservative garbage collector by negating the bits in the pointer, but then it's kind of clear you're doing something naughty. This would make dangling references a supported feature and that's a pretty fundamental change. At the very least, this should be an experimental feature. |
I'm not sure an experimental feature really makes sense for this. If the intent is to make sure it's not "too easy" to (ab)use, how about giving it a scary name like |
That's just not true.
Bottom line is, the references are not mere metadata, or a mere cache of scanning. References are data proper, as much part of the store object as its file system objects are. This is the only correct way to account for how Nix actually behaves. |
Experimental feature still makes sense, however. By default things should start as experimental features this is good. |
ab929ec
to
5d91526
Compare
I've renamed the attribute to I'm not sure what else needs to be done, e.g. should this interact with |
That could be good (so that you don't dispatch a build to a builder that doesn't have the xp feature), but it's not a blocker imho. And maybe not really needed at all since I hope that this won't stay experimental for too long (ideally it could ship as Xp for the next release and then stable in the following one) |
std::set_intersection(referenceablePaths.begin(), referenceablePaths.end(), | ||
spec.begin(), spec.end(), | ||
std::inserter(tmp, tmp.begin())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could be useful to debug some potential errors where you're accidentally referencing too much. But I might be wrong and the spamming argument is totally valid. So let's keep things that way)
5d91526
to
bfa55c3
Compare
Not sure how to get the test daemon to pick up the experimental feature, |
If you haven't done that, I think you need to call |
bfa55c3
to
bfabcb9
Compare
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/nix-team-meeting-minutes-oct-7-2022/22369/1 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2022-10-14-nix-team-meeting-minutes-4/22811/1 |
Is anything else blocking this? |
Here's another case. It'd be much easier to test as well, if it wouldn't pull in all the contents as transitive dependencies of the test. |
Well, this as experimental will not really get us data on the drawbacks of this compared to the safer «declare an output self-contained», as the hiding will need to be very explicitly asked by the user. Hopefully this will stay experimental… |
@7c6f434c makes a good point. Actually having this as experimental makes the feature much worse because any mistakenly unconfigured builder will ignore the attribute and produce an output with a ton of dependencies that will propagate through caches etc. Users won't know why it happened and then think that this feature has a bug. The real problem is forward compatibility. I don't think we have a way for a derivation to request that it's built by a Nix that has specific support for something, do we? |
It will fail, actually.
I think ignoring the attribute would actually be preferable. People who know about the experimental feature can try it out. Others get the status quo ("ton of dependencies"). |
Right, so now we have the worst of all options
I don't know what we're afraid of or why we should make life so hard for everyone including ourselves (Nix team) who need to learn about this feature's use. Unknown unknowns, really? |
Well, it violates a pretty fundamental assumption that everyone considers a foundational principle of Nix. It definitely can be abused badly… Is it that hard to overrideDerivation its use into any image-generating expression, though (provided you have it enabled)? |
It's not hard, provided the image builder supports With the above PR I'm able to build a reference-free ISO with |
So does
Abused sure, anything can be abused, but badly? In a way where the responsibility falls on Nix? I suggest we remove the experimental flag soon, and if anyone wants to exercise their caution, work on a forward compatibility attribute instead; a known problem. |
«I have done a GC and now a package I have installed has reduced functionality, isn't this supposed to be impossible» is quite likely to be blamed on Nix. |
Sure. I'd rather have a useful tool than a safe tool. Let's agree to disagree. |
It's not merely about a safe tool, it is about whether a tool gives you guarantees you can quickly understand and reason about. Reducing unpredictable interactions is more or less the whole point of Nix, so exceptions to it that can be hidden in an expression reduce the value. As a useful tool I would prefer a trusted user dropping all the references of a specific path, as this is a clearly informed local choice, and the user could just do this anyway via pushing to a local cache and dropping the references (or prefetching as FOD, or whatever they prefer) |
How often do you see people complaining that Nix is not pure enough, or not safe enough? How often do you see people complaining about Nix being too resource-hungry or wasteful? I certainly see the latter way more often.
No they don't. GHC wouldn't exist without Using a heuristic for determining references and not providing an escape hatch for false positives in the heuristic is nonsensical.
The burden shouldn't fall on the user though (no matter how trusted or high-up-the-supply-chain). As a derivation author, I know that the hashes appearing in |
I personally? A lot of time. Like a significant part of discussion about flakes is specifically about what is the proper make to get things more pure. I do also see discussions of how to make sandboxing safer. I do see complaints that are basically «deduplication needs to be improved a lot», which seems to be primary motivation for Content-Addressed work. Of model-breaking complaints, I mostly see «how do I make one store path writeable and seeded by some nix-build provided contents». Somehow, the idea of actually making it an option doesn't seem to get traction. Some of the issues can be resolved with carefully constructed FHS user envs, but not all of then. |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/nix-team-report-2022-10-2023-03/27486/1 |
Hello, we are multiple projects who are interested into that feature:
Unfortunately, the way this feature is designed makes it very hard to let user who want to opt-in into this unsafeness get the benefits. For example, Furthermore, if we want to have it in the Hydra buildfarm for our current disk images, this would make it very hard because of the experimental status. I don't know what are the right ways to get out of this situation, but I would appreciate if we could make this feature useful for the interested consumers, it would definitely bring awesome improvements for the community. I understand where @edolstra and @7c6f434c come from on the risk but I feel like we can be proactive against abuse and be very clear about it. I would even go and say there could be some flag which can disable this feature at runtime with a flag or an environment variable if needed? Thank you to everyone involved into this! |
I don't know what are the right ways to get out of this situation, but I would appreciate if we could make this feature useful for the interested consumers, it would definitely bring awesome improvements for the community.
I understand where @edolstra and @7c6f434c come from on the risk but I feel like we can be proactive against abuse and be very clear about it. I would even go and say there could be some flag which can disable this feature at runtime with a flag or an environment variable if needed?
For the record, if this is an experimental feature I am in favour of just pretending that the parameter name is not special in case the feature is off, so that the same build happens (just without discarding the references).
The mixed use between systems with and without the feature would actually keep people honest.
If anything, regression where some expression with no underscore-named settings goes from working to not working on Nix update is not a good thing…
|
Having the same derivation build two different ways depending on experimental feature usage sounds very bad to me. Failing so the success means the same result is much better. We could add a primop to ask if an experimental feature is enabled (impure mode only until eval cache keys improve), and that will allow ergonomic falling back at a better layer of abstraction. What is hard about Hydra? If one is running ones own hydra, one can just change the Nix configuration. |
Having the same derivation build two different ways depending on experimental feature usage sounds very bad to me. Failing so the success means the same result is much better.
The _build_ happens exactly in the same way. The only difference is which of the false-positive references are recorded as runtime dependencies.
|
Then s/build/realization process/ or whatever. "Derivation -> set of store objects" is the mapping I want to not depend on which extensions are enabled (modulo failing to produce a key-value pair at all). |
Another idea is to add a flag to the Nixpkgs So to summarize, it seems that we have to give up on one of
The last one seems least bad to sacrifice. |
Yeah I agree experimental features should probably not be changing behavior, more like monotonically increasing behaviors. e.g. when we add something like |
Also on a tangent, instead of periodically stealing |
Well, the set of objects in the store here is the same. If the argument for the feature is that the references ignored don't matter, well, then they shouldn't matter in either direction. (And dropping some references when pushing to a cache is already pretty easy). |
I think it makes sense to just stabilize this per https://nixos.org/manual/nix/stable/contributing/experimental-features.html#lifecycle-of-an-experimental-feature. @NixOS/nix-team, any thoughts on that? That obviously wouldn't solve all the problems (since everything but the latest Nix versions would still fail on it), so the idea of a nixpkgs config option like @roberth mentioned seems very good. That's fairly similar to what CA derivations have (there's a |
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)).
|
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)).
Fixes #5633
Adds a new derivation attribute
possibleReferences
which restricts the list of paths that are searched in build outputs in order to establish runtime references.Useful when creating filesystem images containing their own embedded Nix store: setting
possibleReferences = [];
makes them self-contained blobs of data with no runtime dependencies.To do:
allowedReferences
. Not clear if this is useful, but why not. We can intersect the list of output names with the keys ofscratchOutputs
when adding those to the set.impossibleReferences
as well? (I don't think so)EDIT: the attribute has been made a
__structuredAttrs
boolean (unsafeDiscardReferences.out = true;
) and hidden under thediscard-references
experimental feature.