-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Deterministic evaluation of Nix expressions (and tracking who produced a derivation) #553
Comments
Okay, I think I have a more concrete proposal for how this could work: My goalI want a cryptographically verifiable link between a derivation and a nix expression that built it (the most common case will be NixOS's configuration.nix, but this would be handy for any derivation). The problem I'm tackling is the fact that something like What I want is a "complete" If you accept its value for configuration.nix, it shouldn't be a huge jump to see why someone might want it for arbitrary derivations, particularly if it doesn't incur much disk space overhead. To be clear, I want this to be auditable more than .drv files are. I consider Building blocksA "record mode" for NixThis is not a primop, but rather a flag you run
Thus, the semantics of
A corresponding playback modePlayback mode would take a derivation that contains a
|
I also think the intensional store wouldn't solve the same thing this solves, although it would change its flavor a bit. What this does (or tries to, at least) is provide a strong link between the input and the output. |
I probably don't understand your goals. Currently you can re-evaluate a configuration and see if it produces the same derivation (even the name is a strong hash). With some hacking, the derivations should even be well-diffable. The problem I see is that in principle, all packages transitively referenced from configuration do affect your system, which is quite a lot to audit by itself. |
We where just talking about this on NixConf2015, and I have to say: +1! |
following the NixConf-discussion +1 from me too |
Is there any update on this? just looking for something along the lines of |
Those two are sort of different from this, and more akin to either how Nix works already or #520 if you squint. Unless I'm misunderstanding you, Nix builds are already pretty deterministic, and if you lock down the channel and the expression you're evaluating, you're more locked down than e.g., a I did actually start work on a new version of #709 but haven't put much effort against it recently. I'd want to understand if we already do what you want though, because in most cases we behave more like the locked versions of other package managers than anything else. This issue is about an even higher level of determinism and reproducibility. |
I've been doing a lot of work on this privately recently, and it's renewed my interest in it. I can't promise a timeline, but this is definitely not dead. |
@copumpkin Sorry for the super delayed reply. I never have as much time for Nix (and other things) as I'd like. Is there a way to do Also, I applaud the efforts in this issue to make such a feature even "more deterministic". Awesome! Edit I put my efforts on doing this at: https://stackoverflow.com/questions/50242387/how-to-record-a-reproducible-profile-in-nix-especially-from-nix-env/50257762#50257762 It looks like it will probably work, but haven't heavily tested it yet. Also, the user experience of doing this sort of thing could probably be improved if it was integrated a bit more into the standard tooling. |
@copumpkin I had started thinking about this concept just now. Basically I noticed that as I wrote Nix expressions, they are not really pure. Since they refer to things that are in the external world. For example using Instead what really happens is sort of like multi-stage evaluation. Where we have source that executes within the context of the outside world. And the production of a derivation from that Nix expression which is in the I got thinking about this when thinking about development workspaces such as inside nix-shell project based workflows vs Go's shared workspace structure, and about how names we use in programming refer to things that is sometimes deterministic and other times depends on some constraints (such as versions) and other times refer to whatever is at that that path. I'd be interested in this feature though, seems like it would be useful for debugging. |
@CMCDragonkai Regarding |
I love the direction |
@edolstra What about a |
@copumpkin Any update on this? |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: |
I marked this as stale due to inactivity. → More info |
I closed this issue due to inactivity. → More info |
The idea of a record mode is useful beyond just figuring out the evaluation-level inputs of an output like a NixOS toplevel. Unfortunately "recording" doesn't compose, because the language is call-by-need: when you record one thing and then record the next, things that were already evaluated for the first will not be evaluated again, and therefore not be recorded. So a faithful recording of a second thing requires a restart of the evaluator. Of course that doesn't mean that we couldn't take advantage of such a tracking feature. Often enough we only need one thing, and such a single thing that comes to mind in particular is evaluating a devshell. So I would argue that this functionality like this should still be implemented - as part of the eval cache layer (which is currently separate from the normal evaluator). Unfortunately storing it in the output or in the store does not seem feasible because it's really up to the "evaluation driver" to discover and use this information, and only "after" the underlying two layers have done their work (evaluator and store). |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/pre-rfc-implement-dependency-retrieval-primitive/43418/14 |
I don't have a good sense of how gnarly this is. It's certainly impure from a Haskell pure FP standpoint, and might not even be possible in the way I describe.
What I want is something like:
to return some summary that would allow me to reconstruct the evaluation of
foo
later, in as faithful a manner as possible. As such, it would need to include something like:dataFile
from the store (with the full store path used).NIX_PATH
entries, and other stuff that might be involved in evaluating it.I could see one implementation just making
evalClosure
into a derivation containing a "self-contained" nix tree that represents the elements I list above in a way that just evaluates properly. Such a primop could be calledsnapshot
or something like that. I don't expect it to be fully possible to make 100% effective, but if it could capture most evaluation structures or fail loudly, that would achieve 99% of the goal.The ultimate goal, if it isn't obvious, is providing reproducible evaluations. I want cryptographic linkage between a derivation in the store and a "nix language closure" that leads to it.
I don't know what would happen if you pass a "thunk that has already been forced" (in Haskell lingo) into the function. Ideally it would still work properly, but that seems even harder.
Does what I'm saying make sense? Is there something I'm missing that would make this fundamentally impossible?
The text was updated successfully, but these errors were encountered: