Getting started
This page builds one NixOS host with yen. You write four small files. At the end you have a
nixosConfigurations.laptop that nixos-rebuild can use.
-
Get the template. It has a
flake.nixand amodules/directory.Terminal window nix flake init -t github:vic/yen#getting-started -
Read
flake.nix. Theyeninput is a normal flake input. import-tree loads every file inmodules/.flake.nix {description = "yen: one NixOS host";outputs =inputs:inputs.yen.lib.mkFlake {imports = [ (inputs.import-tree ./modules) ];_module.args = {inherit inputs;inherit (inputs.nixpkgs) lib;};};inputs = {yen.url = "github:vic/yen";import-tree.url = "github:denful/import-tree";nixpkgs.url = "https://nixos.org/channels/nixos-25.05/nixexprs.tar.xz";};} -
Build the host:
Terminal window nix build .#nixosConfigurations.laptop.config.system.build.toplevel
The fleet
Section titled “The fleet”yen has no built-in kinds. You say what a fleet is. The root kind is the one that nothing spawns.
Here the root fleet spawns every host, and its out sink is the flake.
# The root of the tree. Nothing spawns it. Its `out` sink is the flake.{ yen, ... }:{ yen.kinds.fleet = { spawns.host = _: yen.host; # every host lives under the fleet sinks.out.reduce = yen.lib.reduce.merge; }; yen.fleet.main = { }; yen.flake = { out, ... }: out;}The host
Section titled “The host”A kind has fields (the data of each instance) and sinks (where behavior goes).
The nixos sink collects NixOS modules. Its out key gives the built system to the flake.
# A host has a system. Its `nixos` sink collects NixOS modules and builds the host.{ yen, lib, inputs, ...}:{ yen.kinds.host = { fields.system = lib.types.str; sinks.nixos.out = { host, nixos, ... }: { nixosConfigurations.${host.name} = inputs.nixpkgs.lib.nixosSystem { inherit (host) system; modules = nixos; }; }; };
yen.host.laptop.system = "x86_64-linux";}Behavior
Section titled “Behavior”An aspect is active where its at holds. Each key of an aspect gives one element to the sink
of that name. base is active at every host. motd is active at laptop only.
# Behavior: active at every host, gives one NixOS module to the `nixos` sink.{ yen, ... }:{ yen.aspects.base = { at = yen.kinds.host; nixos = { host, ... }: { networking.hostName = host.name; boot.loader.grub.device = "nodev"; fileSystems."/" = { device = "/dev/disk/by-label/nixos"; fsType = "ext4"; }; system.stateVersion = "25.05"; }; };
yen.aspects.motd = { at = yen.host.laptop; nixos.environment.etc.motd.text = "managed by yen"; };}Ask it
Section titled “Ask it”yen answers queries on the fleet. This is the scope tree of this example, generated from r.graph:
flowchart TD n6c4c773b6d["fleet main"] ne01d911511["host laptop"] n6c4c773b6d --> ne01d911511
And r.active: which aspect is active at which scope.
{ base = { "fleet:main" = false; "fleet:main/host:laptop" = true; }; motd = { "fleet:main" = false; "fleet:main/host:laptop" = true; };}