`allowUnfree[?Predicate]` does not apply to `self.packages`?

I have created a basic package that extracts Microsoft fonts from the enterprise evaluation ISO, ported from the AUR. This package is locally-defined, and is marked with meta.license = lib.license.unfreeRedistributable.

When I attempt to use this package, I see the one we’ve all seen before:

building the system configuration...
error: Package ‘ttf-ms-win11-1’ in /nix/store/24v22brcimxjb21g46zkizswc36bn8bs-source/dotpkgs/ttf-ms-win11/package.nix:146 has an unfree license (‘unfreeRedistributable’), refusing to evaluate.

       a) To temporarily allow unfree packages, you can use an environment variable
          for a single invocation of the nix tools.

            $ export NIXPKGS_ALLOW_UNFREE=1

        Note: For `nix shell`, `nix build`, `nix develop` or any other Nix 2.4+
        (Flake) command, `--impure` must be passed in order to read this
        environment variable.

       b) For `nixos-rebuild` you can set
         { nixpkgs.config.allowUnfree = true; }
       in configuration.nix to override this.

       Alternatively you can configure a predicate to allow specific packages:
         { nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
             "ttf-ms-win11"
           ];
         }

       c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
         { allowUnfree = true; }
       to ~/.config/nixpkgs/config.nix.
(use '--show-trace' to show detailed location information)

Obviously I have already set nixpkgs.config.allowUnfree = true, and have also tried using the allowUnfreePredicate = _: true. Neither works.

The usage is here, the package is added to my flake.nix here and the package definition is here.

I see this post but I would prefer to find a way to inherit the configuration.

allowUnfree is a configuration option of a single nixpkgs instance.

Your package in self uses the nixpkgs from the inputs, in its own instantion, while the system or HM instantiates its own version.

There is currently no solution to the unfree licenses in a flakes output but to lie.

Time for another one of my hacks that you hate then.
How can I create my own .config for a flake?

You can import nixpkgs { config = <setting the allowunfree thing>; }, and then use the callPackage from that nixpkgs instance.

No way around evaluating nixpkgs in this case.

I think it is completely reasonable and not a hack to configure Nixpkgs instance used by most of the flake by importing nixpkgs and passing in the config, instead of relying on the default configuration. The Nixpkgs instance created by nixpkgs.legacyPackages.${system} cannot pick up any configuration from the environment in hermetic evaluation of flakes and that is great.

I do not think the same would be right for the pkgs used by packages since then third-party consumers of your flake’s packages might end up using unfree packages unwittingly. Although, maybe using allowUnfreePredicate would be permissible in this case, since user still needs to accept EULA explicitly. But, in general, it would not be very convenient (e.g. when building the font would depend on another unfree package).

I would suggest not exposing unfree packages in the packages attribute at all, and instead only defining them as an overlay. Then they will inherit the configuration from the overlaid system:

pkgs = import nixpkgs {
  inherit system;
  overlays = [
    self.overlays.fonts
  ];
  config = {
    allowUnfree = true;
  };
};

Overlays will not allow you to easily build the package with nix build but that will already not be easy since the packages require accepting EULA.

And do not forget to use the created pkgs in your NixOS config:

jacob-thinkpad = nixpkgs.lib.nixosSystem {
  inherit system;

  modules = [
    …

    {
      nixpkgs = {
        inherit pkgs;
      };
    }
  ];
  …
};
2 Likes

This definitely shows the need for a better workflow around this, especially when put into context of consumers. Is there an issue tracking this problem somewhere?

I ended up doing this:

  # spoof the license of every package
  spoofAllowUnfree = maybe: flake: (
    if maybe
    then lib.recursiveUpdate flake {
      # this works for system config
      nixpkgs.config.allowUnfree = maybe;
      # there is a bug in nixpkgs that prevents the global
      # "allowUnfree" from working, so instead just specify
      # a callback that says yes every time something asks
      # if it can install a package with a proprietary license
      # <https://github.com/nix-community/home-manager/issues/2942>
      nixpkgs.config.allowUnfreePredicate = _: maybe;
      # spoof the licenses for local flake packages
      packages =
        builtins.mapAttrs (_: system:
          builtins.mapAttrs (_: package:
            package.overrideAttrs (old: {
              meta.license =
                old.meta.license // { free = true; };
            })
          ) system
        ) flake.packages;
    }
    else flake
  );

And I used the function on the root of my flake:
https://github.com/spikespaz/dotfiles/commit/ce5373f41544a561597c8ac32cd923e5b68744da
https://github.com/spikespaz/dotfiles/commit/7dd4bb239391074c64e1ec88a960ef9eb0383498

Is this evil?

In my opinion this is only solvable in the long term if licenses were understood by nix, and not only by nixpkgs.

And in general filtering possibilities should be massively extenden on.

Back at my prev. employer we were not allowed to use GPL licensed libraries or tools at runtime, though using them for compiletime was fine…

In the current situation we even had the problem that in the hypothetical case that there is an unfree not distributable compiler used to compile the program. It is not required at runtime. Still, the MIT licensed tool built with that hypothetical compiler requires accepting unfree…

1 Like
  1. yes this is evil, still a suitable workaround
  2. meta.license can be a list as well
  3. It is not a bug of nixpkgs. Or would you consider it a bug in your browser that one tab has a different view to a webpage than another because they have been opened with different parameters?
1 Like

I think unfree is a bug

As someone who pays his bills by selling software. No it is not. It is a legitimite demand to secure the income and company secrets through the license.

My statement is a double entendre.

  1. Unfree is a bug such that society requires it; we do not live in a utopia–and that is a mistake.
  2. Unfree doesn’t work well with Nix-anything. Some notable compilers treat anti-ergonomic APIs and error messages to be a bug; if you follow this philosophy nixpkgs and Nix is a bug.

Don’t worry, I like making money too–I enjoyed Atlas Shrugged and The Fountainhead.

I would not say it is particularly evil but I noticed a few problems with it:

  • I am pretty sure adding nixpkgs.config to flake with recursiveUpdate will have no effect on the flake, only the transformation of packages is doing anything.
  • overrideAttrs does not do a recursive update so your code will clear out the other meta attributes.
  • It will only skip the checks for top-level packages, not their unfree dependencies.
  • meta.licence can contain a list or even a string.

So I would still go with using overlays over packages with this hack. Instantiating nixpkgs is expensive and overlays allow you to do it just once. Although sometimes it is impossible to avoid, e.g. when a flake depends on a specific version of Nixpkgs and you want to use a different one for the rest of your system.

  1. commit
  2. Noted
  3. Noted
  4. Noted

foot: Ok

Yeah, I would call that evil, since you are modifying a flake in a way that no longer matches the flake schema in order to have a side channel. You are working in a single flake that you control so you do not even need to change the unfree status of packages, just pass the proper config when you are creating a Nixpkgs instance as suggested above.

flake outputs attr

    overlays = genSystems (system: (final: prev:
      with prev.packages.${system}; {
        ttf-ms-win11 = (ttf-ms-win11.overrideAttrs
          (lib.recursiveUpdate { meta.license.free = true; })
          prev
        );
      }
    ));

flake outputs let

    pkgs = import nixpkgs {
      inherit system;
      overlays = [ self.overlays.${system} ];
      config = { allowUnfree = true; };
    };

hm config and system configs

modules = [ { nixpkgs = { inherit pkgs; }; } ];
error: Package ‘ttf-ms-win11-1’ in /nix/store/b03gx22q08hdvns51fiswwki6pq4n0w6-source/dotpkgs/ttf-ms-win11/package.nix:146 has an unfree license (‘unfreeRedistributable’), refusing to evaluate.

Also tried this, realizing I was updating in the wrong direction

    overlays = genSystems (system: (final: prev:
      with prev.packages.${system}; {
      ttf-ms-win11 = (ttf-ms-win11.overrideAttrs
        (lib.recursiveUpdate prev { meta.license.free = true; })
      );
    }));

Hard to tell what’s going on without context due to that with, you might be using an explicitly declared lib from an outer scope, because those will override what with introduces into the scope (quite sensibly so, but sadly also confusingly).

Hence all the calls for just not using with ever.

I don’t know off the top of my head what happens if you use recursiveUpdate from multiple nixpkgs libs, it depends on where the logic for checking licenses hooks in. Pretty sure you have to be more careful about which pkgs is used where, either way, I’ve used this workaround a few times and it should work.

After I import nixpkgs with system, does it mean that overlays are applied to pkgs.legacyPackages.${system}? Can I omit the entire logic of handling system in my overlay, and just use

    overlays = {
      spoofAllowUnfree = (final: prev: {
        ttf-ms-win11 = lib.recursiveUpdate prev {
          meta.license.free = true;
        };
      });
    };
    overlays = {
      spoofAllowUnfree = (final: prev: {
        ttf-ms-win11 = prev.ttf-ms-win11.overrideAttrs {
          meta = prev.meta // {
            license = prev.license // { free = true; };
          };
        };
      });
    };

To my knowledge, yes, assuming you use the nixos option for it you can even avoid any import nixpkgs {};.