I’m new to Nix and NixOS and have been installing new packages by adding them to environment.systemPackages in /etc/nixos/configuration.nix then rebuilding, which I thought was the same as using the package manager. Today I used nix-env -i hello and realized that it doesn’t put that package in the configuration.nix file.
What’s the difference between those installation methods? Is it like installing to /Applications vs ~/Applications on macOS?
packages listed in configuration.nix get added to a system profile. This also gives you the generations
no, nix-env is meant to give you a similar experience to other package managers, however, i manages it’s own gcroots (what derivations can be cleaned up), and even generations. Generally you should avoid using nix-env for package installation as it doesn’t leverage the power of nix.
The preferred way is to use declarative ways of installing packages. The most common ways to do so is the system configuration (/etc/nixos/configuration.nix) or home-manager.
Also, I’d warn about reading the pills as a beginner. It explains installing quite nice, but then does a deep dive into the inner workings of nix. Though nixpkgs provides a lot of nice abstractions, such that direct usage and understanding of builtins.derivation is rarely necessary. Reading the pills becomes necessary once you either want to understand how mkDerivation works or you want to implement your own version of it from scratch.
Thanks. I like the idea of installing everything via /etc/nixos/configuration.nix. I would like to have a 100% reproducible setup.
You brought up home manager. How can I install this via /etc/nixos/configuration.nix.? The official instructions seem to go off the rails and have us run imperative commands: nix-channel, nix-shell, etc. Do I have to remember to run these commands again after I rebuild?
Seems a little ironic how many NixOS-centric tutorials and READMEs are pushing non-NixOS-philosophy instructions. As a NixOS beginner it’s felt as though I’m constantly jumping through hoops just to find out how to do things “the right way”.
Most instructions and blog posts I’m aware of, do as little imperative things as possible and then use declarative tooling.
Sadly there are still things you can’t do declaratively without jumping through even more hoops.
Without flakes it’s not trivial to manage/pin your channels. Without flakes, it’s actually not common that people even use one of the various pinning techniques, though if they do, they usually know how to translate the imperative commands into their specific declarative way.
I mean the little NixOS documentation that does exist  doesn’t explain NixOS package management to beginners clearly enough, and most Google search results for the subject are misleading.
For example the official NixOS manual , when it first introduces nixos-rebuild switch, introduces it quite robotically in a way that only someone already versed with NixOS could understand—it took me a full day to understand how to install packages. Googling “NixOS how to install packages” was a frustrating experience, and the few Reddit/Stackoverflow/blog results will trick a newbie into using nix-env -i  and concluding that’s how you do it in NixOS, because it reminds them of other package managers and so fits their old mental model.
Without flakes it’s not trivial to manage/pin your channels.
Next, then, I’ll need to learn what channels flakes are.
I’ll just add that I’m having similar confusing experiences trying to use nix “the right way” as well. Just trying to figure out how to install docker was a day-long experience, and I ended up using nix-env -i because that’s the only example I could find. Everything nix-related seems to focus on the BUILDING rather than the USING of software. So for someone coming fresh to nix, it’s frustration after frustration just trying to USE the system as it’s supposed to be used (as in, I want my machine to be deterministic, so I can just save the config files, destroy the system, rebuild, and be back where I started).
This gets even more frustrating because every blog post, manual, and example is couched in terms of “You could do it this way or that way or this other esoteric way or …”
As a beginner, I don’t have the mental model to process the millions of ways to do the same thing and by-the-way-there-are-these-other-wonderful-shiny-features-over-here. I’m left screaming in frustration “Won’t someone PLEASE just post an opinionated, best-practice-for-nixos way of using my system in the day-to-day???” It starts to feel like CMake documentation after awhile. OK, rant off.
I think this thread is a great chance for us to reflect on some of the failures of our documentation, esp. when it comes to onboarding new users. Although the nix ecosystem has a lot to offer, it is quickly moving and a lot of different documentation suggests many different approaches to solving the same problem. Nix also has a plethora of different concepts: derivations, the language itself, channels, nix-env, nix-shell, flakes, nix-foo commands vs nix foo commands, generations, GC, and so on. It’s kind of a nightmare.
I remember going through the rough patches in the beginning as well, and I still don’t understand everything that nix has to offer. IMHO we ought to rethink what kind of “first impression” experience we want newcomers to have.
For a start I’d like to propose that we
Deprecate nix-env -i installation with a warning message. Replace it with nix-shell on https://search.nixos.org/ and all of the documentation.
Make it dead-simple to install home-manager straight from nixpkgs, no channels funny business. Pointing users towards home-manager straight away will help to alleviate many of the “how do I do X in nix?” issues.
It would also be great to have some kind of semi-official tutorial/video/documentation that walks newcomers through the basic steps of installing and setting up nix, opinionated towards the tools/patterns of the future and avoiding all of the cruft from the past (cough nix-env cough).
What I mean is: I want to take what I have on machine A and save it so that I can destroy machine A and rebuild it from scratch in a deterministic way, or I can take machine A and replicate it to machine B without copying gigabytes of OS data (just my configuration, then rebuild the exact same env on the new machine). That’s really what I’m hoping for in nixos. Something like terraform or ansible on steroids, where everything I want to run is just a nixos-install on a blank machine away.
Ideally, my /etc/nixos dir would be a git repo, so whenever I change something, I can commit and push those changes. Then rebuilding/replicating the machine is a git clone + nixos-install away.
You’ve described the way to do it, make a git repository from your /etc/nixos and clone it next time you want to install it on a new machine; The one thing that’s less easy to do declaratively is managing /etc/nixos/hardware-configuration.nix, since it will be different for every machine. I recommend just running the configuration generation script once before cloning on a new machine, and adding a file for that specific machine, import-ing it based on hostname.
If you used the installation instructions, you should already have some basic configuration doing exactly that while explaining it too
There is a documentation problem, at least for the official docs. I think I learned by scouring other people’s repositories on github - it would be great to have a basic tutorial for “basic declarative install from git” in the manual.
Deprecating nix-env -i seems important too, it’s nothing but a footgun that confuses new users, I have never used it.