My biggest problem with flakes is that it is too much added complexity for tiny incremental gains (as per my limited understanding, happy to be corrected). Not only do most users gain very, very little from it, it also deters users from using nix for two reasons:
1) There is more to learn now.
2) Split ecosystem.
I'm looking to be educated, I've made contributions to nixpkgs (two "mid-sized" changes) but for some reason I couldn't bring myself to learn flakes ... Although that could have been because they were in limbo.
I have to say though, nix is increasingly becoming a nerd thing philosophizing over minute issues rather than "getting shit done" to benefit the maximum number of users ... :-(
> Not only do most users gain very, very little from it
How do you come to that conclusion?
Those who switch to using flakes are enthusiastic about the improved UX.
> flakes is that it is too much added complexity for tiny incremental gains
A 'flake' is more/less a set of inputs and a set of outputs. I'd say it's less complicated than a package.json file in an NPM project.
The benefits are hard to get otherwise.
With flakes, `flake.nix` provides a standard entrypoint to a Nix codebase. Without flakes, you might see a `default.nix`, but would have to read the `default.nix` to know how it's supposed to be called.
With flakes, the exact version of Nixpkgs used is locked. Without flakes, I'm not aware of an easy way to do this with channels; and there are a variety of ways (read: no standard way) to do this in Nix code.
- flake-specific state is fully captured and locked
- this locking applies for all platforms the flake targets
- extreme ability to be composed
The first two solve the same issue as Gemfile.lock, its the PLATFORMS section, and the platform annotations on each of its gem line, which allows `bundle lock` to lock not just for the platform it's being run on but all platforms that are targeted.
It also canonicalizes the way to declare targets to build, whereas previously it was kind of TIMTOWTDI (e.g default.nix evaluation is the default target and calling nix-build sans arguments builds that to `result`, and if you want more you write alternative nix files, the whole organisation of that is on you)
These are very useful for project-oriented nix stuff.
For system (nixos, nix-darwin)/environment/profile/home management I still prefer classic channels, which gives me a single, consistent nixpkgs source, kind of like BSD's base which is handled as a whole (except here it applies to the whole of packages). I am still able to locally override this or that by selectively pulling another nixpkgs (or other source) and use that to pick a specific package version (either forward or backward) but otherwise I stick to the single consistent one.
It feels to me that using flakes for the whole system would be like using npm and having a whole recursive tree of `node_modules`. I certainly don't want to have a thousand different openssl around!
> A 'flake' is more/less a set of inputs and a set of outputs. I'd say it's less complicated than a package.json file in an NPM project.
It's conceptually comparably complicated, but the actual practical experience of writing flakes is much more complicated. This is not the fault of flakes specifically, but rather due to the complexity of nixpkgs. Although on second thoughts the fact that there are a bunch of libraries like flake-utils and flake-parts out there does seem to point at a verbosity UX issue.
I think we all have our own aha moments with things like this. I thought like you until I really dug in and set up Home Manager as well. My moment, and maybe this means nothing to you, was when I realized I could reference any package in a config file without even “installing” it. So it’s no longer that I have config files in Git somewhere, and then also a list of all the packages I need to install somewhere else; the config files themselves pull in the packages they need by virtue of referencing them. There are a million other things, but that’s when I was like, “Okay, I’m actually gonna do this.”
Yes, in Nix code it is possible to refer to arbitrary Nix codebases from Nix code.
I'd point to the home-manager installation instructions for an example of Nix flakes having a nicer UX. Running flake-enabled codebases is just much nicer than non-flake codebases.
The former involves running `nix-channel --add <...> home-manager && nix-channel --update` in order for `<home-manager>` to mean anything. With the latter, it's simply `nix run home-manager/release-23.05 -- init --switch`. (Albeit, `home-manager` is already registered as an alias for `github:nix-community/home-manager`).
One key detail is that `nix-channel --add` modifies the 'system state', whereas running flakes essentially does not.
-- Regarding "you can pull in arbitrary Nix code by reference". With flakes, you have a standard entry point where you know the interface it has. Whereas, having a 'default.nix' is a convention, and there's no way to know how a `default.nix` is to be used without reading its source.
I'm familiar with home manager (or as I like to call it, a hammer looking for a nail, that solves no problem). I don't think home manager has any relationship with flakes. Also, nix solves actual real problems, home manager doesn't. There are better dotfile managers. In fact, vim understands the syntaxes of a lot of dotfiles, with home manager, you even lose that.
> In fact, vim understands the syntaxes of a lot of dotfiles, with home manager, you even lose that.
Nix is perfectly capable of referencing external text files (e.g. `./my-config-file.ini`), which you can write with vim or whatever if you like.
It's trivial to put such files in place with Home Manager (or NixOS config) if you want, e.g.
home.file.foo.source = ./my-config-file.ini;
Home Manager is certainly overkill if that's all you're using it for; but many more things become possible thanks to its use of Nix. For example, you can run some find/replace on the file contents (say, to splice in some Nix store paths, or the results of some calculation); you can fetch arbitrary files from arbitrary locations (e.g. some other git repo); you can choose between alternative contents based on arbitrary criteria (say, CPU type, or hostname); etc.
There are Nix LSP servers now that handle embedded config files. But beyond that, you can always just leave the config in its original format and import it into the Nix config, and not lose your syntax highlighting.
Speaking of vim, I've got neovim configured completely with home manager. It references plugins as first-class nix packages, and also any external dependencies like language servers, node packages, parsing tools etc are also managed by Nix. You can reference the deps in the vim config and it will automatically download and point to them in the nix store without even installing them.
It's amazing. Everytime I upgrade and building my system, my nvim setup gets upgraded automatically too. No need for a package manager or manual updates.
Which you can presumably only do on a 1 user system right? (I’m just trying to understand, I thought home manager makes more sense on a multi user system, and has some options for more fine grained configuration?
Home Manager is less useful if you're using NixOS. I've found it handy on non-NixOS systems, e.g. my phone; although I'm planning to switch that to NixOS at some point too ;)
Can you tell me which one of the nix lsp servers supports the embedded configuration in multiline strings? I think neither rnix-lsp, nil or nixd support this, but maybe I am missing something.
I moved from Chezmoi to Home Manager. Chezmoi is easily the best dotfile manager I had used at the time, and Home Manager is on a totally different level.
> vim understands the syntaxes of a lot of dotfiles, with home manager, you even lose that.
I wonder what we can do about this, or what is the best way to annotate long strings in Nix code that are actually source snippets. Something like how code snippets are handled in Org files would be awesome.
As a counter-anecdote, as someone who used to be a newcomer to Nix, it took until I encountered flakes before I went "aha, this is how it was always meant to be".
Do you have much development experience? I've been wondering lately whether the helpfulness or difficulty associated with flakes depends on familiarity with Nixlang and readiness to approach Nix code as code.
That fits with my hypothesis, which is that programmers tend to find that the way Nix flakes lay out a common interface and convention for certain things helpful, but people who are more IT-oriented and are used to relatively incapable conflangs are overwhelmed by the surface level verbosity of flakes, and hesitant to use libraries to deal with it because they take a bit longer getting their heads around the language.
FWIW I like Nixlang, but I agree that static typing would improve it. Maybe Nickel some day, blah blah blah :)
You can do everything without flakes as well by using fetchTarball, fetchGit etc, with shasums, but flakes just improves the ergonomics. Because of the lock files, flakes are also faster, especially nice if you use nix develop (the new nix-shell alt)
> Because of the lock files, flakes are also faster
I consider lock files to be labour-intensive work-arounds for fundamental design problems. One of the things I like about Nix is that its design doesn't need them, and even allows me to automate-away their need in other tools (e.g. defining a project's "main" derivations using import-from-derivation on the result of a lock-file-generating derivation; this works well with legacy tools like Maven, for example)
It's kind of scary because Nix is one of the coolest concepts for how to manage Linux systems... Most everything else has so much baggage from things that were designed around hand-maintained, non-disposable installs.
But the community does seem to be still tinkering focused.
I miss the early 2000s when even the hackers seemed to want to make their stuff easy to use(although my source for that is I saw a screenshot of low orbit ion cannon one time, I don't actually know much about hacker history).
> But the community does seem to be still tinkering focused.
Because Nix does NOT make packaging easier. Maintainers are the ones who create distros, and they can live a happy life with something as crude as PKGBUILD, since build instructions are almost always stable.
Even for users, most of them just don't need to juggle with package versions. Bleeding edge is mostly covered by Arch and package pinning works ridiculously well for daily uses.
So "make their stuff easy to use" doesn't apply here. Rather, Nix is harder to use in reality.
I've never heard of Arch and only fairly rarely heard of Manjaro as being suitable for anyone but tinkerers, at least not in the way Android is.
A few months ago Steam stopped working. Nobody seemed to know why. It's back now, but git-cola is gone and I'm not even sure how I broke it. Some nonsense about type errors in the hotkey module, which I don't have time to debug right now so I'm just ignoring and using the flatpak.
Most everything I use on a daily basis has 100s of MBs of dependencies in several layers... Forgetting the virtualeng when pip installing something that happens to have a PyQT dependency and trashing my git cola is... not great and Linux is full of stuff like this.
The amount of effort needed to avoid or fix this kind trouble is more that I imagine Nix would need if it was fully polished.
On Nix I was able to package a Python app in a matter of hours, and
1) There is more to learn now.
2) Split ecosystem.
I'm looking to be educated, I've made contributions to nixpkgs (two "mid-sized" changes) but for some reason I couldn't bring myself to learn flakes ... Although that could have been because they were in limbo.
I have to say though, nix is increasingly becoming a nerd thing philosophizing over minute issues rather than "getting shit done" to benefit the maximum number of users ... :-(