I am new to nix and in my research so far, I have seen various comments on flake design issues. Some of these could perhaps be addressed iteratively but it seems like the copying of local file trees to the store is the biggest blocker?
Regarding this, I have read that lazy trees offer only a partial solution, and in any case it looks like they won’t be merged soon.
So are there any serious alternatives that could be worked on?
Ideas come to mind easily: containers, bind mounts, overlay filesystems, symlinks, or just skipping it and accepting the impurity risk; and then, a configurable choice over such options. But I am sure these aren’t new ideas and there have probably been good reasons to rule them out. Hence my question, as I’d like to know if there is any feasible alternative, and anyone who wants to work on it.
One eval purity issue Flakes solve is the issue that embedding toString ./. into a derivation can yield different results on different machines. Now “/home/myuser/src/myproject” becomes part of my derivation input, and on another machine, the path might be different.
Flake’s conclusion is that if the whole repo is copied into the /nix/store, and that we use Git as the data source, this path will be the same on two different machines.
Another approach would be to disallow embedding non-store paths into derivations, since they are a source of impurity.
Implementing this is fairly easy. It requires adding non-store paths to the string context. And then rejecting them at the point where the derivation calculates the inputs.
In terms of impact, this would be a breaking change. In my experience, we don’t lose much from reducing the language, and examples I found in the wild were usually mistakes.
Change this, and remove the flakes eval cache, and I believe lazy trees are not needed anymore (to be verified, I haven’t looked at this for a while now).
One example of something that would break with losing ./. is the case of setting nixos-config in nix.path to /home/user/some/folder/that/might/occasionally/be/moved.
On the other hand, if that folder gets moved it’s not like the older generations get updated to point at the right place, so it’s more a convenience thing than a strictly correct thing.
Your framing of flakes solves a problem that shouldn’t exist in the first place. toString ./. is still a bad practice (with or without flakes) due to rebuilds and unnecessary copies. Hence Working with local files — nix.dev documentation.
IMO the way to fix flakes is to kill off flakes entirely - they don’t bring us anything new.
Imagine modulesPath is of type “path”. Because of the automatic path to string interpolation, the interpolated string would look like /nix/store/<hash>-modules/virtualization/qemu-guest.nix. This is is extra copying into the store that’s not needed.
That’s why modulesPath is first converted to a string using toString.
Now the interpolated string is /home/myuser/path/to/nixpkgs/nixos/modules/virtualization/qemu-guest.nix. It’s fine because the string doesn’t end up in a derivation, and so doesn’t affect the inputs.
These are subtle issues that I have seen many users encounter or trigger, without even realizing it happening.
If you re-read my quick and dirty proposal, you’ll see that it’s a language change that both fixes flakes, and also improve the language itself. Regardless of flakes, I still want my evaluations to be pure and reproducible.
Making diamond-syntax reproducible is a different endeavor, but doable.
And we have the pure-eval option for that.
It’s really unfortunate that everything gets credited to flakes, because while some of these improvements may have been done in service of flakes, they can stand on their own.
I was on this train for so long but gave up; it seems like the convergence to Flakes feels inevitable.
I like the idea though of just adding --impure and restricting the language a little more (i.e. what @zimbatm said about paths like ./. to get us 90% there). Something like niv then gets you the remaining 10%.
Having contributed to the codebase slightly; I’m always in favor of less entropy and removing what you can from the system to the smallest amount necessary to keep it great.
(probably offloading the sandbox code would be worthwhile too… but then we start to get spiritually similar to Snix)