It seems using nix-env for installing packages is a bad habit for nix/NixOS users and that it’s not recommended from the community. If this is true, we should update the Wiki to stop referring to this command as the way to install a package, or put a warning after each use of this command in the wiki for installing a package that would lead to a Wiki page explaining why nix-env is special and shouldn’t be used if possible.
Here are some Wiki links where nix-env is recommended as the way to install packages:
It seems using nix-env for installing packages is a bad habit for nix/NixOS users and that it’s not recommended from the community.
It gets repeated a lot, often without explanation.
To my understanding:
Part of the justification against it is that running however many nix-env -iA (or nix profile install) commands to set your system up is less elegant than writing down a list of packages in one place, and installing based on that. (e.g. in the NixOS configuration, or in a home manager configuration, or using buildEnv or so).
I think the main reasoning otherwise is the foot-gun-like nature of it, especially using it on non-NixOS systems. There’s a risk of causing problems due to “I forgot I did that” or “I didn’t know I did that”. e.g. usually with Linux distributions, you run package management with sudo, but not with nix.
I think the main ‘trouble’ is that if you installed something somehow, and forget where, you end up with programs in PATH without knowing how they got there, or disk space being used up & it not being clear how to clean that. – And then, this leads to people asking for help as to why, after having forgotten (or not understood the implications of) running the commands.
Is there another way to globally install packages from Nix in a scenario where NixOS is not used? We have Nix rolled out on several Ubuntu machines and use it to manage our build environment. For this, I need direnv and nix-direnv to be available for all users and so far, nix-env -iA seems to be the only way (well, I could use direnv from Ubuntu, but that’s not really nice, either).
I would prefer a more declarative approach to profiles, but it does not seem to exist.
That said, yes installation via nix-env (and nix profile) cannot be removed from nix itself, because this is their use case. home-manager is not an official tool, and doesn’t really cover the same use case.
Lots of third party tools (such as the aforementiomed home-manager) also use them to actually do their jobs.
With that said, I’ve commented on one of those articles asking very much the same question - can we stop recommending this workflow? It’s harmful for the new user experience. At the very least, it should be “only use this when you’re using nix on MacOS” or something.
This is not the only problem. Unless you explicitly update using nix-env --upgrade, packages installed through it will never update. People will happily update their channels thinking it’s a full system update and end up unable to log in because their window manager is 4 NixOS releases behind.
This is a slow and insidious failure mode, because by the time it breaks you will have forgotten about it. Worse, in the mean time this leaves you up to all kinds of security issues (for worst cases, think e.g. about installing firefox via nix-env).
Using either nix-env or nixos-rebuild or home-manager isn’t per-se an issue. The problem is mixing all of these, and not understanding the implications, as new users reading those wiki entries will do.
A very large percentage of NixOS update failures come from mixing these, and this is why I will always tell new users to forget the nix-env command exists - more nuance than that is confusing and using it in a more nuanced fashion is clearly poor practice anyway.
This is better than having swathes of users get annoyed and give up after their first major version upgrade, thinking the basic promise of NixOS was a lie. It’s not, but mixing imperative and declarative practices leaves you vulnerable to mistakes that could be avoided entirely if you picked one approach - it’s a shame we recommend both in the same wiki section.
@Solene feel free to just edit the Wiki. In case of the above two articles it seems to be easiest to just remove the parts where nix-env is used.
That one would need a bit more care, because the use of nix-env appears almost entirely legitimate for imperative package management, especially when comparing to Ubuntu.
It seems to be a good candidate to to migrate to the imperative package management chapter. Feel free to open a PR.
It does not help with @polygon’s use case, where nix-env indeed appears more appropriate, as it works for all users and does not introduce additional layers of complexity.
I know you mean well and privately, I am the biggest fan of home-manager. But requiring every user (most of which are not very Nix-savy) to manage a home-manager installation would certainly raise some practicality questions.
The next best thing is probably NixOS.
Painfully aware of that. But this is an enterprise network. I was surprised enough that I could start introducing Nix here to manage build systems. I guess even just writing a NixOS configuration that contains all their enterprise-y programs and tools would be a monumental undertaking.
What I am saying is, introducing Nix into larger companies is hard enough as it is. Please don’t put deprecation or other warnings saying that this shouldn’t be used before there is a workable alternative. I don’t like the imperative approach one bit, but it’s a necessary evil that I need to live with for now. Having statements like this in the official docs can and will raise questions and may actively harm NixOS adaptation.
The use if nix-env really puzzled me when I started using NixOS, because I didn’t really understand why I would want to register the packages in my global config while I can install the packages as a regular user. It wasn’t clear if nixos-rebuild was magically upgrading them. I also had issues with X related libs conflicting with the one from the system, removing the packages from my user and adding them to the system solved the issues.
In my experience, using nix-env made me lose time figuring out why a package was still in an older version or why a package stopped working after a NixOS update. The command man page also looks like it’s an entire package manager that allows you to search, install, remove or update packages, which is confusing when you start on NixOS and you are still learning its unusual concepts.
Also, it seems that when you enable flakes, nix-env isn’t usable anymore to install a program. People trying nix-env commands to install a program may not understand what’s happening given the error returned in that case:
> nix-env -iA nixos.git
error: profile '/nix/var/nix/profiles/per-user/solene/profile' is incompatible with 'nix-env'; please use 'nix profile' instead
Yep, hence my later caveat to this. In your situation, imperative management is definitely the best option currently.
I wonder how hard it would be to have some kind of shared global profile, managed similarly to how home-manager is. Launching profiles as part of /etc/bashrc can’t be that challenging, I say naïvely…
I’m happy to give it a try, might be a few days before I get around to it though Happy to raise it in this discussion when I’m done for some review too, though I’ll try to keep it as succinct as possible.
What no one seems to have mentioned here is that nix-env is also semi-broken. Specifically, upgrading packages sometimes does quite nonsensical things, because the upgrades are found by matching the name attributes of all the packages in pkgs, rather than by checking if the derivation at the same attribute path in pkgs now points to something new, like everything else in the nix ecosystem.
I tried nix quite a few years ago, found it utterly horrible, threw it away as a bad experiment, and largely forgot about it. A few years later, NixOS caught my attention due to its declarativity, and I loved it. For a while, I never even connected it with that thing I had tried and found so horrible. Eventually I made the connection when I stupidly tried using nix-env for user packages for a bit and it was, once again, horrible. I can’t speak for anyone else, but the existence of nix-env as a suggested way to use nix held back my adoption of it at least 3 years. Had I remembered and connected NixOS with it, I probably would have never tried it. Based on my own experience, I can’t imagine that it doesn’t hold back nix adoption significantly.
That said, home-manager isn’t viable as an alternative. We do need something that’s distributed as part of nix itself. nix profile is at least not broken in this way, but it’s still imperative, and given how important declarativity is for getting the real benefits of nix, I feel that pure nix should be distributed with a tool that declaratively installs packages. At it’s simplest, all we need as input is a .nix file which defines a function from pkgs to a list. If that’s distributed as part of nix, adding things to that file could replace nix-env -iA as the generically recommended way to install packages, and it would be fairly intuitively obvious that environment.systemPackages (or home.packages) is doing the same thing, and can thus replace it, leaving less confusion about which way you “should” do it when both are available.
Yes, probably. On a multi user host, nix-env would also be a way for unprivileged users to install packages.
The big problem with nix-env is that there is no alternative for it at the moment short of using home-manager (which is a completely separate project with its own drawbacks and reasons why we wouldn’t want to officially endorse it as the blessed way).
You can do declarative package management with nix-env, but it requires adapting an essentially custom solution and is not a good fit for new Nix users:
I think we could reasonably improve nix-env, migrate it to be more declarative and eliminate common gotchas, but the discussion of such things is usually dismissed immediately because Nix upstream doesn’t want to touch the (stable) nix-env in any way, as work is already underway on the new Nix 3.0 nix profile CLI.
This was installed by nix profile install. Whenever I change the flake, I run nix profile update 17 to update it. So far I’ve not noticed any problems with this approach, but I doubt I stress it much. The few gui apps I use are installed by my nixOS config; I do not know if nix profile would conflict.
Ultimately I am looking for a simple, declarative way to specify user packages for multiple machines. Being able to declare project tool dependencies in a project file is another important goal – especially to get team adoption.
My current best practice is using a Dockerfile to specify a project toolchain. While the Dockerfile is so much better than README instructions, using flake.nix might be that much more reliable.
I think this is an unpopular opinion in the Nix community, but I really like nix-env.
It is nice for tools that you use occasionally, but don’t want to bother running a nix-shell for. I personally like that things installed with nix-env don’t get automatically updated when you run nix-channel --update or nixos-rebuild. Sometimes I like to stick with specific versions of packages in nix-env, even if they are older (or newer) than the channel I’m currently on.
I am generally okay with the fact that the environment I setup with nix-env is imperative and non-reproducible.
I feel like “bad habit” is a little strong. There are a bunch of ways of installing packages, each having pros and cons. nix-env is one way of installing packages. Like pointed out in this thread, it has a bunch of surprising behaviors, so it may not be suitable for new users. But if you’re familiar with Nix (and especially nix-env), it can be a nice tool to have in your tool-belt.
Although maybe you’re specifically talking about newer users, in which case I may agree with you. There is certainly a trade-off between asking new users to jump into the deep-end and do everything completely declaratively (NixOS / home-manager / nix-shell), verses giving them an option to use a tool that sort-of works like they’d expect coming from another distro (nix-env?).
Purely anecdotal, but I’ve seen at least one company that has adopted Nix because of the ease of installing things with nix-env. Nixpkgs just has so many development tools, it can be really helpful for a company looking to setup a semi-reproducible dev environment, even if they have no interest in building their own projects with Nix. (Although nix-shell would be another good option here)
It would be really interesting to see some data on how many people got into Nix by using nix-env as a gateway drug, vs people that just got completely turned off of Nix because of the quirks of nix-env.
And we should make that clear without value judgement.
What are those reasons? I always thought it should be integrated much more tightly into the ecosystem. Exactly for the reasons you named why it is cumbersome to use nix-env for declarative environment management.
Well home-manager is a downstream project, to really endorse it, we would need to make it an upstream project (i.e. merge it into nixpkgs probably), since at the moment nothing is preventing a nixpkgs commit from breaking home-manager (it probably does so occasionally).
And upstreaming home-manager is nontrivial, I think, since you’d need to, for example, figure out how to eliminate the code duplication between nixpkgs nixos modules and the frequent reimplementation of said modules in home-manager for user services.
And I didn’t intend to suggest that the imperative approach be removed or anything, though my wording could have been clearer on that. nix profile is surely sticking around, even if nix-env should probably disappear at some point due to its semi-broken nature.
What I have a problem with is that the imperative approach is effectively raised above declarative approaches by being the sole method distributed as part of nix itself. Nix-standalone needs a declarative package management system that works easily for newbies out of the box, and is presented in documentation as a suggested way to manage packages with nix, if not the suggested way, with the imperative system being secondary. It would help if the default config file structure allowed “dumb” cut-and-paste substitution between it and environment.systemPackages / home.packages.
nix-env -iA is currently seen (by newbies and outsiders) as THE way to install packages with nix, and that really needs to change.
Distrowatch’s webmaster jessie reviewed NixOS 22.05 and had many issues (link to the review)
I was surprised to read about nix-env in multiple places, and as the author had issues such as bad desktop integration, I wonder if this could be related to the use of imperative package management instead of declarative global wide?