Custom classes and forward
In Den, a custom class is a new aspect key, such as nix or persist, and den.batteries.forward sends its
content into another class at a path: fromClass, intoClass, intoPath, adaptArgs. It is the fifth most
used battery in public Den configurations.
In yen a custom class is a sink. Aspects give elements to it by its name. The sink’s other keys give the reduced
content to other sinks, such as nixos or homeManager, and the function places it at any path. There is no
adaptArgs: the function gets yen args, and the content is plain data.
| Den forward | yen sink |
|---|---|
den.classes.nix |
yen.kinds.<kind>.sinks.nix |
fromClass = _: "nix" |
the sink name |
intoClass, each = [ "nixos" "homeManager" ] |
one key per target, on each kind that has the sink |
intoPath = _: [ "nix" "settings" ] |
the attribute path in the key’s function |
adaptArgs |
not needed: yen args, such as host, are args of the key’s function |
One class, two targets
Section titled “One class, two targets”The same nix settings go to nix.settings of NixOS on hosts, and of home-manager on standalone homes.
The hosts and homes are declared in the fleet.nix tab below.
# Den: a `nix` class, forwarded with den.batteries.forward into nix.settings of nixos and of homeManager.# yen: a `nix` sink on each kind. Its other key gives the settings to the class of that kind.{ yen, ... }:let merge = yen.lib.reduce.merge;in{ yen.kinds.host.sinks.nix = { # (1) reduce = merge; nixos = # (2) { nix, ... }: { nix.settings = nix; }; }; yen.kinds.home.sinks.nix = { reduce = merge; homeManager = { nix, ... }: { nix.settings = nix; }; };
# written once, for both yen.aspects.nix-settings = { # (3) at = [ yen.kinds.host yen.kinds.home ]; nix = { experimental-features = [ "nix-command" "flakes" ]; warn-dirty = false; }; }; yen.aspects.builders = { at = yen.kinds.host; nix.max-jobs = 4; };}(1) declares the nix sink on the host kind. The home kind has its own. (2) is the nixos key of the
sink: it gives the reduced settings to the nixos sink. (3) is one aspect that gives nix elements to
every host and every home, so the settings are written once.
A class under a path
Section titled “A class under a path”This is also the DRY aspect of the dendritic design guide, for options inside an attribute set of submodules.
# A class that lands under a path: forward's intoPath. `lan` content goes to networking.interfaces.<host.lan>.# Features add routes to the LAN without knowing the interface name.{ yen, lib, ... }:{ yen.kinds.host.sinks.lan.nixos = # (1) { host, lan, ... }: { networking.interfaces.${host.lan} = lib.mkMerge lan; # (2) };
yen.aspects.subnet-a = { # (3) at = yen.kinds.host; lan.ipv4.routes = [ { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; } ]; }; yen.aspects.server-address = { at = yen.host.server; lan.ipv4.addresses = [ { address = "10.0.0.1"; prefixLength = 16; } ]; };}A feature writes lan content, as at (3). The lan sink at (1) puts it under the interface that the
host names in its lan field. It uses lib.mkMerge at (2), so two features never overwrite each other.
# A NixOS host, and a standalone home on a machine without NixOS.{ yen, lib, inputs, ...}:{ yen.kinds.fleet = { spawns = { host = _: yen.host; home = _: yen.home; }; sinks.out.reduce = yen.lib.reduce.merge; }; yen.kinds.host = { fields.lan = yen.lib.str; # the name of the LAN interface sinks.nixos.out = { host, nixos, ... }: { nixosConfigurations.${host.name} = inputs.nixpkgs.lib.nixosSystem { modules = nixos; }; }; }; yen.kinds.home = { fields.system = yen.lib.str; sinks.homeManager.out = { home, homeManager, ... }: { homeConfigurations.${home.name} = inputs.home-manager.lib.homeManagerConfiguration { pkgs = inputs.nixpkgs.legacyPackages.${home.system}; modules = homeManager; }; }; }; yen.fleet.main = { }; yen.flake = { out, ... }: out;
yen.host.server.lan = "enp86s0"; yen.home.ana.system = "x86_64-linux"; yen.aspects.machine = { at = yen.host.server; nixos = { networking.hostName = "server"; boot.loader.grub.device = "nodev"; fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; nixpkgs.hostPlatform = "x86_64-linux"; system.stateVersion = "25.05"; }; }; yen.aspects.home = { at = yen.home.ana; homeManager = { pkgs, ... }: { home.username = "ana"; home.homeDirectory = "/home/ana"; home.stateVersion = "25.05"; nix.package = pkgs.nix; }; };}