Suggested pattern for using `allowUnfreePredicate` is overly permissive due to overloaded pnames

I want to install the zoom video conferencing software. Sadly, the package naming is slightly unclear, so rather than zoom (a text adventure game runner from the 90’s) I will actually be installing zoom-us.

Unfortunately, zoom-us is unfree software, and I don’t want to globally allow unfree software, I like per-package allowances instead. Poking around online, several sources recommend this allowUnfreePredicate solution, so we’ll go with that:

config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
  "zoom-us"
];

Well wouldn’t you know it, that doesn’t quite work - I still get yelled at about how I need to allow unfree software!

...
error: Package ‘zoom-6.0.12.5501’ in /nix/store/yqy82fn77fy3rv7lpwa9m11w3a2nnqg5-source/pkgs/applications/networking/instant-messengers/zoom-us/default.nix:195 has an unfree license (‘unfree’), refusing to evaluate.
...
       Alternatively you can configure a predicate to allow specific packages:
         { nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
             "zoom"
           ];
         }
...

Fortunately, the error message tells me exactly how to fix the problem, but now I’ve opened up a new problem, thanks to the use of lib.getName. Since getName basically just hands you back the pname of the package you hand it, and zoom and zoom-us have both set their pname to zoom, following the recommended approach results in me allowing both the zoom and zoom-us packages, if they are unfree.

Pragmatically, this isn’t an issue - zoom is free software and unlikely to change…ever. But the principal of it leaves a bad taste in my mouth. This is where I got stuck with the following questions:

  1. Have either the zoom or zoom-us authors made a mistake/violated some standard for nixpkg pnames here?
  2. What’s the correct approach here to allow the zoom-us package to be unfree, but not the zoom package? Is there a simple way?
  3. In the context of zoom-us, what would you even call the term zoom-us as it’s used here? It’s apparently not the package name, as that’s pname and/or name, it’s just kinda the nixpkgs path to the package definition or something…is it really just for nixpkgs organizational purposes and nothing else?
2 Likes

That “third thing” would be the attribute path in the nixpkgs attribute set, and the primary way to identify a single package.

pname is really just a pretty name for logs/store paths at this point - I’d almost call it a holdover from design flaws in early nix.

Originally, it was used to allow things like nix-env -i zoom, which intends to bridge the gap between traditional package managers and nix. That command goes and traverses the entire package tree to go find a package whose pname is zoom to install it. This causes a number of really serious issues from performance issues unintended downgrades.

Using the attribute path (which can be done using the -A switch on nix-env, though that doesn’t fix all issues because nix won’t “remember” that you used -A when upgrading) makes way more sense to uniquely identify packages, since attribute set paths can by design only hold one expression. For legacy reasons it is however not used across the board to identify packages - including the edge case of package filtering, apparently.

In fairness, until flakes become a thing, there isn’t really a good way to uniquely identify packages anyway - nixpgks isn’t the only source of packages.

Given the above, you might suspect that… Well, the short answer is no.

This interface is one of the things the community wants to improve a bit in general currently, see e.g.: Implement permittedUnfreePackages · Issue #55674 · NixOS/nixpkgs · GitHub

The whole checking infrastructure lives inside the generic stdenv.mkDerivation logic: nixpkgs/pkgs/stdenv/generic/check-meta.nix at 4c547b66635455ad061d4beecaf1805810dc0428 · NixOS/nixpkgs · GitHub

In here, since it’s the fundamental derivation builder for nixpkgs, you only have access to package attributes - such as pname. There is no way to know what the currently building packages’ attribute path is - fundamentally this is impossible, since a package may be built from entirely outside of nixpkgs altogether (e.g. in a third party overlay).

This, coupled with the current difficulty of bridging between different nix projects makes the current pname-dependent interface pretty much the only possible solution. You could pass in the attribute path as a string, but this would take some design work for project namespacing that doesn’t exist yet.

No. In fact, they’re following the explicit conventions for this (some more at-length discussion of what I explained here in there, too, by the way), though I would not be surprised if those packages predate the convention.

This is just an unfortunate inadequacy of the current meta checker.


Edit: Actually, thinking about this, would an interface like:

pkgs.zoom-us.override { allowUnfreeLicense = true; } 

be possible without forcing a rebuild of the package? Does that even matter since the meta checker disables building packages that fail the checks anyway?

6 Likes