I’m new to NixOS, but learning. I’m using NixOS + HM with flakes.
One thing I find confusing is the decision of whether to install a typical package through the
“top-level” NixOS configuration or through HM. I have a one user on all of my systems. Even if I were to have another user, it wouldn’t bother me if they had the same packages.
Some packages need to be installed at the top-level. Why shouldn’t I just install all my packages like that?
Sorry if this is a frequently discussed topic. I did some searching and couldn’t find anything that seemed directly related. I’d be grateful for a link if it’s well covered already.
The short answer is that it probably doesn’t matter, for you. Put them all together, and I wouldn’t suggest anyone start using home-manager if you’re not already, just for this, although you seemingly already are.
The longer answer, as always, is “it depends”. Some reasons it might matter:
anything that runs as a system service obviously needs to be part of the system config, as you note
if it’s just programs you want in path, there’s very little practical difference
for end user shell and desktop items, sometimes HM has more extensive options for configuration of things like shell hooks, and sometimes there are just differences in configuration method, and (rarely) you might prefer one over the other for a specific tool
if you think you might want to have your user config on another machine that isn’t nixos, then you can use home-manager on that machine to get the same tools and settings
there’s another option, too: some of those programs may be things like development tools or similar utility software that logically belongs with a project rather than a user or machine. You may wish to pin a version to the project’s state, rather than have machine upgrades break the project unexpectedly, or even have different versions in different projects. For these, it’s better to use a devshell and something like nix-direnv to pull them into the project workspace. Even for single-user projects. These don’t have to be “software development” projects with compilers, it could also be your photo library and the tools you use to import and edit pictures, or other things that you want to upgrade on a different schedule tied to the data and your workflow.
Finally, for some, consider not “installing” them at all: sometimes it’s easier to just use nix shell or nix run or comma to fetch things on-demand that are used rarely.
If it’s a system service, hardware driver, kernel module, web server, etc. generally the answer is neither and you should use the correct option instead.
Generally, check https://search.nixos.org/options for an .enable option for the software you’re looking for, and failing that, you’ll likely have to search a bit regarding what would be the best option to use. (Or ask here.)
I should have mentioned: I am using .enable options whenever possible for either NixOS or HM, with a preference for HM. And the reason I am using HM is precisely to manage my configurations, not so much the packages.
A couple of lingering questions.
Is there any security difference? I have a probably wrong impression that somehow having a package installed system-wide is less secure. This seems wrong but I’m not sure I understand why.
Is there any difference in disk usage? Would this change if I were to have two users? For example, suppose both users want firefox. Would having HM manage firefox for each user create two instances in the nix store, whereas managing at the NixOS level would only create one? Does this have to do with flakes, since either way I still have a single flake providing all of the input?
The main difference is making the package available on the PATH of all users vs a single user.
It depends on your threat model, but I personally don’t find this to be substantially different security-wise, as all files in the nix store are world-readable, and if a user (or program) is sufficiently motivated to find a specific executable in the store and run it, they can do so.
No, unless the users are overriding the firefox package in different ways. And even then, with file-level dedup (i.e. store optimisation), the effects may be practically minimal.