Nixpkgs naming vs local naming of installed packages

Hello, I am new to the nix package manager, and I am very confused about how packages are identified and named.

Let me try to present a scenario that confuses me.

When I go to search and search for a package I sometimes get multiple packages with the same name. For instance, I had to install zoom, and there turned out to be two different packages named zoom (see zoom search). The first one is for “Player for Z-Code, TADS and HUGO stories or games” (not sure what it is used for) and the second one is “zoom.us video conferencing application”. It was the second one that I needed, and it also had a unique attribute path (I assume that is what it is called) of nixpkgs.zoom-us. The first one had the attribute path nixpkgs.zoom. This is good since I am able to distinguish the two different packages when installing one of them. However, when one of them is installed it appears in the output of nix-env -q as zoom no matter if it is the first or the second one. Now my confusion is, how can I distinguish between these two packages that clearly have different functionality, but identical names when installed?
Of cause you could argue that they have different versions, and I could check the version of the installed package and use it to identify which “zoom” package it is, however they could have had the same version , by accident, which would make it impossible to know which “zoom” application was installed.
I feel like there should be a way to distinguish these packages, such that I could for instance tell nix that I want to upgrade the package, and then nix would fetch the newest version of zoom from the somewhere. However, as far I can see there is no way to get the attribute path of a package (get the nixpkgs.zoom-us name from the locally installed package).

I guess my confusion boils down to a few questions:

  • How are packages identified when installed locally?
  • How are packages identified on nixpkgs?
  • How do you find out where a locally installed package was installed from? Was it nixpkgs.zoom-us or nixpkgs.zoom?
  • In general what does the different attributes of a package mean in relation to identifying it? (pname, version, the attribute path, …?)

I hope some of you can help clarify this.
I am very exited to learn more about nix, and aside from my confusion I am very impressed with the principles of which nix is based on.

William

1 Like

This is an interesting topic covering many things, some of which are quite high level, some of which require understanding the guts of nix :slight_smile:

For the high level, you’re looking at a derivation name. These are ambiguous, and intended for human readability. This is indeed confusing for situations like this one, but you can get rid of the ambiguity when using nix-env with the -A flag, which makes it use attrpaths instead of names (and -P for query, though note this seems to not work for installed things for some reason - presumably because you need to evaluate the nixpkgs project in reverse to know the path, which is impossible if your package comes from somewhere else, but more on that later).

As someone only looking at nix-env's UX in hindsight, well over a decade after its initial design, I consider it a bit of a wart that mimics the design of traditional package managers, with odd side effects like this confusion. Not using the -A flag is often disrecommended for this ambiguity, and because it is significantly slower than using the attrpath. The new experimental nix CLI doesn’t repeat this mistake, so I think the actual nix developers probably think similar things :slight_smile:

Attrpaths simply are paths into nix attribute sets. Think of them like JSON objects or Python dictionaries. Nixpkgs actually is just a big attribute set, and your attribute path unambiguously refers to nested attribute sets, which eventually arrive at the derivation you install. Each package has its own entry in this big attribute set.

To visualize, think of it looking like this:

{
    zoom = <something defining a derivation>;
    zoom-us = <something defining a different derivation>;
}

As mentioned, those sets can be nested, so you could have something like communication.zoom and games.zoom, but in practice that isn’t done for nixos (some nesting does exist though, see python3Packages and linuxPackages for example, which relate to imported pip packages and kernel-related packages respectively).

The derivations then include instructions on how to build your packages, as well as the name that causes your confusion - as you see, the name is completely separate from its path in nixpkgs, and finding out what path a certain name comes from isn’t as trivial as the reverse, which is why nix-env without -A is slow and why this ambiguity can exist.

Also, you might realize that nixpkgs doesn’t need to be the only attrset that contains packages. By default, you’re usually referring to nixpkgs when installing things, but you can add others using NIX_PATH -f - further muddying the waters as to what name refers to what attrpath in which attrset. You can even have multiple different versions of nixpkgs, it’s not uncommon to have both stable and unstable available on one system. The derivation name is not a good way to identify packages :wink:

Edit: Well, I completely forgot about this detail. Hopefully we can get to the nice new nix profile world soon.

Coming back to your explicit questions:

  • Derivations are identified with their file paths in /nix/store, but this is sometimes exposed to users through their name for certain commands. These are never ambiguous, as they contain their input hashes, but if the name is used on the CLI things can get confusing, so use -A.
  • Paths into attribute sets, as sketched above.
  • This is surprisingly difficult! -A in general, but --query is a bit stuck? Personally, I recommend installing things using nix modules instead, assuming you’re using nixos or home-manager, but this can indeed be tricky when using raw nix.
  • pname and version are for human consumption (pname can sometimes be used in the CLI for convenience), the attrpath tells nix what expression it should evaluate and build, the nix store path is its canonical representation on the running system.

The nix pills would probably be more helpful than my mini summary here: NixOS - Nix Pills

Since you’re fairly new to the ecosystem, let me warn you that the pills aren’t particularly useful for learning how to use nix. Stick to the nixpkgs and nix manuals for that. But the pills do explain some of the inner workings, and rationale behind them.

3 Likes

Thanks a lot for the explanation.
I have checked out the nix profile command, and it seems to be a lot more consistent with naming. I still don’t really understand flakes though. There is a lot to learn.

1 Like

Yep, flakes have their own UX problems :wink: Good luck with the learning, eventually it all starts to make sense. Don’t hesitate to keep asking questions here, and make sure to feed back to wiki/docs where you can :slight_smile:

2 Likes