Permanently enabling unfree packages for nix profile (system config uses flake)

hello everyone :slight_smile:
i have a problem when trying to install any unfree packages using nix profile install on a flake based system. overriding using the environment variable NIXPKGS_ALLOW_UNFREE works (and for that matter installing unfree packages through the system config aswell), but i would like to allow unfree packages for nix profile permanently. as i understand, setting nixpkgs.config.allowUnfree = true in the system config only enables them in the nix files right? appart from that i have also set allowUnfree to true in ~/.config/nixpkgs/config.nix and tried overriding nixpkgs with config.allowUnfree right in my flake.nix. none of these had the desired effct though.
all these ways of enabling unfree packages are easily found online, but i have trouble finding anything about systems configured through a flake and using the nix profile command.

any hints are appreciated, thanks in advance

1 Like

So, the way allowUnfree specifically works is that it’s a property on the stdenv builder: nixpkgs/pkgs/stdenv/generic/check-meta.nix at 82deee3bfbf7dcb08ee8c3a1df2c1852101f49c9 · NixOS/nixpkgs · GitHub

As you can see, there’s a bit of a hack involved to read the environment variable. This of course is disabled in pure evaluation.

What you’re interested in is that config attrset which can be used alternatively, and since you’re using nix profile, specifically how to set it for an input flake.

The input flake for nix profile is the one that comes from your nix registry - this is importantly separate from the inputs of the flake you build your system with.

This is why setting allowUnfree on the config in configuration.nix doesn’t do anything here (that is also an anti-pattern by the way, you should be using the NixOS option) - even if you set your registry to use the same flake input, it would be evaluated from scratch, so the value of nixpkgs in your configuration.nix simply cannot affect whether unfree packages are allowed in nix profile.

The other way to change config is defined here: nixpkgs/pkgs/top-level/impure.nix at 82deee3bfbf7dcb08ee8c3a1df2c1852101f49c9 · NixOS/nixpkgs · GitHub

As importing from places outside of the flake is forbidden because that would be impure, this also cannot be used to change the settings in the context of nix profile. builtins.pathExists presumably evaluates to false if used on paths outside the flake, though this is a detail I’d also not realized before.

So there’s not really a good way to do this with flakes currently, this is one of their major limitations. There are proposals for adding flags to the input url and stuff, and suggestions to handle it some other way, but this hasn’t gone anywhere yet to my knowledge.

Until there’s a better solution, you can use GitHub - numtide/nixpkgs-unfree: nixpkgs with the unfree bits enabled. It simply takes its input nixpkgs (which you can either change by branch or through follows), modifies the config to allowUnfree, and re-exports everything. You’d need to set your entry for nixpkgs to it:

nix registry add nixpkgs github:numtide/nixpkgs-unfree/nixos-unstable

Or, alternatively, you can do so declaratively in your configuration.nix and set it to one of your flake inputs (in which case you would also need to add nixpkgs-unfree to your flake’s inputs, of course): dotfiles/nixos-config/default.nix at ef1a08cf30ab648f799c7369847fe935df7e7a93 · TLATER/dotfiles · GitHub

This additionally has the advantage that nix profile won’t randomly pull packages from a different version of nixpkgs than your system configuration does, because by default these are not synchronized - besides being frankly confusing, the default settings also add a delay to running nix profile every two hours.

5 Likes

thank you very much for the in-depth explanation. while i don’t have much of a deep understanding of all the inner workings of nixos, it’s still very helpful in understanding why things are the way they are.
replacing nixpkgs in the registry works just fine :slight_smile:
i just wish that quirk with nix profile and flakes would be documented somewhere. or if it already is, easier to find at the very least ^^’

Agreed! The problem is that nixpkgs and nix intend to be strictly decoupled, so this is really a thing nixpkgs should document, but flakes are not really considered real in nixpkgs yet, so there is no documentation for this stuff there.

I wish this quirk was completely abstracted away 99% of the time by better flakes integration in NixOS, too :slight_smile:

2 Likes

i have a a little addendum by now:
since this post, i have also found out how to add nix registry entries declaratively in your NixOS system configuration. here is an example of how i added the nixpkgs-unfree repository:

nix.registry."nixpkgs-unfree" = {
  from = { id = "nixpkgs-unfree"; type = "indirect"; };
  to = { type = "github"; owner = "numtide"; repo = "nixpkgs-unfree"; };
};

now i don’t fully understand how this works or what exactly the from and to mean (i know it has something to do with the way flakes and the flake.lock work), but entering the details of the github repo (owner, repo and using the repo name as the id) work just fine for me

That will work, but the packages won’t necessarily come from the same version of nixpkgs as the rest of your system.

This is probably slightly better:

nix.registry."nixpkgs-unfree" = {
  type = "path";
  # Assuming you have mapped your flake 
  # inputs with `extraSpecialArgs` or similar
  to = inputs.nixpkgs-unfree;
};

Caveat emptor: did not test

right, specifying the source of nixpkgs-unfree in my flake.nix would be much nicer. i tried your suggested code, but that does not quite work im afraid ^^’

this is how i got it to work after some trying:

nix.registry."nixpkgs-unfree" = {
  from = { id = "nixpkgs-unfree"; type = "indirect"; };
  flake = inputs.nixpkgs-unfree;
};

as i still don’t really know how any of this works, i kept the from.type = "indirect" and it does what it is supposed to

1 Like