Unfree packages from many files
nixpkgs.config.allowUnfree = true allows every unfree package. To allow only some, nixpkgs has
allowUnfreePredicate. It is a function, so the module system cannot merge it: when two modules set it, they
conflict (nixpkgs#55674,
discourse).
The usual fix declares a list option and sets the predicate once from it. Den ships the same fix as
den.batteries.unfree, its most used battery (Every Den battery).
In yen the list option is a sink. This file declares it on the host kind:
# allowUnfreePredicate is a function: two modules that set it conflict. A sink collects names; one predicate reads them.{ lib, ... }:{ yen.kinds.host.sinks.unfree = { # (1) nixos = # (2) { unfree, ... }: { nixpkgs.config.allowUnfreePredicate = pkg: lib.elem (lib.getName pkg) (lib.flatten unfree); }; # the list per host, as a flake output: review it before a deploy out = # (3) { host, unfree, ... }: { unfree.${host.name} = lib.sort lib.lessThan (lib.flatten unfree); }; };}(1) is the sink. (2) is its nixos key: one predicate that reads every name the sink collected. (3) is
its out key: the list of each host becomes a flake output, so you can see it.
A feature gives the names that it needs, next to the packages. A user can give names too: they go up to each host of the user.
# Each feature names the unfree packages it needs, next to the packages. No file knows the whole list.{ yen, ... }:{ yen.aspects.gaming = { at = yen.host.desk; unfree = [ # (1) "steam" "steam-unwrapped" ]; nixos.programs.steam.enable = true; }; # from a user: a user has no `unfree` sink, so the names go up to each of its hosts yen.aspects.ana-editor = { at = yen.user.ana; unfree = [ "vscode" ]; # (2) nixos = { pkgs, ... }: { users.users.ana = { isNormalUser = true; packages = [ pkgs.vscode ]; }; }; };}(1) gives the names of the gaming aspect. (2) gives the names from a user. The
server host has no names, so its sink gives nothing: nixpkgs refuses every unfree package there, as by
default. The flake output shows the list of each host:
{ desk = [ "steam" "steam-unwrapped" "vscode" ];}# Hosts build NixOS and hold their users.{ yen, inputs, ...}:{ yen.kinds.fleet = { spawns.host = _: yen.host; sinks.out.reduce = yen.lib.reduce.merge; }; yen.kinds.host = { spawns.user = yen.lib.pointing "hosts" yen.user; sinks.nixos.out = { host, nixos, ... }: { nixosConfigurations.${host.name} = inputs.nixpkgs.lib.nixosSystem { modules = nixos; }; }; }; yen.kinds.user.fields.hosts = yen.lib.listOf yen.kinds.host;
yen.fleet.main = { }; yen.flake = { out, ... }: out;
yen.host.desk = { }; yen.host.server = { }; yen.user.ana.hosts = [ yen.host.desk ]; yen.aspects.machine = { at = yen.kinds.host; nixos = { host, ... }: { networking.hostName = host.name; boot.loader.grub.device = "nodev"; fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; nixpkgs.hostPlatform = "x86_64-linux"; system.stateVersion = "25.05"; }; };}