Best way to do declarative package management

With guix I am able to manage packages with a manifest file like this:

(specifications->manifest
  '("git-minimal"
    "font-hack"))

And then run guix pull --manifest=/path/to/file to add/remove/update packages.

I am looking for something similar with nix.

I found this related thread which shows roughly 5 different ways to do declarative package management per-user:

  1. attrset
  2. buildenv (packageOverrides/overlays)
  3. home-manager
  4. this bash script
  5. nix-env -irf /path/to/file

I need a method which will work on linux distrubutions other than nixos (I’m currently on artix). Also, I plan on using the same method as root to manage global packages.

Which will work for my use case and what are the tradeoffs?

1 Like

Only method I’m aware of is to use NixOS with configuration.nix, which will configure the system as a whole.

This looks like a user command, and I assume you probably had to run this per-user to get the updates. This would be similar to home-manager, in which you would do:

home-manager -f=/path/to/home.nix switch

to get a user to have all the same packages.

I would highly recommend not using nix-env to manage per-package installs. I’ve never used it to install a set of packages though.

Only method I’m aware of is to use NixOS

Packages root installs are global on any multi-user installation, at least according to my understanding of the cheatsheet.

Packages root installs are system-wide. It does so through /etc/nixos/configuration.nix. If root installs packages the same way users do, through ~/.nixpkgs/config.nix, they are also global. Root’s default profile is the system-wide default profile.

I’m not on NixOS. If this weren’t true nix would be a bit less useful for me.

Anyway, I’m still in the dark. Which of these methods work for my use-case, and what are the tradeoffs?

My use case:

  1. I’m not on NixOS
  2. I plan on using the same method to manage global packages

Correct :slight_smile:

1 and 5 are the same thing. I’m not sure home-manager can be used as root to affect all users (@rycee can probably confirm/correct!). Expression for a buildEnv-based declarative user environment. · GitHub, where I describe the buildEnv approach, also contains a short feature comparison between the two nix-env approaches and home-manager.

1 Like

Thanks. That helps a lot.

I’m going to try the buildEnv approach, then the attrset approach if I don’t like it for some reason.

I like buildEnv after playing around with it a bit. It’s simple and works just how I wanted.

I just wish I had renamed the script to nix-update-profile or update-nix-profile so it would be less ambiguous.

EDIT: spoke too soon. This kills query functionality for nix-env. Going to try the attrset approach.

What do you mean by “query functionality of nix-env”?

buildEnv writes manifest.nix to your .nix-profile, which does this:

        throw ''
          Your user environment is a buildEnv which is incompatible with
          nix-envs built-in env builder. Edit your home expression and run
          update-profile instead!
        ''

It’s designed to lock you into buildEnv’s way of package management, but it’s a bit too indiscriminate for my liking, as queries no longer work.

image

EDIT: nix search ... still works, though. I’ll stick with it for now.

Not sure, I’ve never tried it :slightly_smiling_face:

The attrset overlay approach has worked well for me for a long time. And it’s convenient to be able to do once-off nix-env -iA commands, in particular if one of my current packages is temporarily broken and can’t update (and therefore I can’t rebuild my whole environment), but I need to install or update a separate one.