From a flake
Most flakes grow the same shape: a mkHost helper, a common.nix, one file per host, and home-manager
as a NixOS module. This page moves that shape to yen. The docs check that each host gives the same toplevel
drvPath before and after.
# A typical flake: a helper builds each host from shared and per-host modules.{ inputs.nixpkgs.url = "https://nixos.org/channels/nixos-25.05/nixexprs.tar.xz"; inputs.home-manager = { url = "github:nix-community/home-manager/release-25.05"; inputs.nixpkgs.follows = "nixpkgs"; };
outputs = { nixpkgs, home-manager, ... }: let mkHost = name: nixpkgs.lib.nixosSystem { modules = [ ./common.nix ./hosts/${name}.nix home-manager.nixosModules.home-manager { networking.hostName = name; home-manager.useGlobalPkgs = true; home-manager.users.alice = import ./home.nix; } ]; }; in { nixosConfigurations.web = mkHost "web"; nixosConfigurations.desk = mkHost "desk"; };}{ pkgs, ... }:{ boot.loader.systemd-boot.enable = true; time.timeZone = "UTC"; services.openssh.enable = true; users.users.alice = { isNormalUser = true; extraGroups = [ "wheel" ]; }; environment.systemPackages = [ pkgs.git ]; system.stateVersion = "25.05";}{ fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; nixpkgs.hostPlatform = "x86_64-linux"; services.nginx.enable = true; networking.firewall.allowedTCPPorts = [ 80 ];}{ fileSystems."/" = { device = "/dev/nvme0n1p2"; fsType = "ext4"; }; nixpkgs.hostPlatform = "x86_64-linux"; services.printing.enable = true;}{ programs.git = { enable = true; userName = "Alice"; }; home.stateVersion = "25.05";}The helper becomes a kind
Section titled “The helper becomes a kind”mkHost knew how to build a host. In yen, the host kind knows it: its nixos sink builds the system.
A user’s homeManager sink forwards to nixos on each host the user lives under.
# Hosts build NixOS. Users live under their hosts; a user's home-manager content goes into each host.{ yen, lib, inputs, ...}:{ yen.kinds.fleet = { spawns.host = _: yen.host; sinks.out.reduce = yen.lib.reduce.merge; }; yen.kinds.host = { spawns.user = s: lib.filterAttrs (_: u: lib.any (yen.lib.same s) u.hosts) yen.user; sinks.nixos.out = { host, nixos, ... }: { nixosConfigurations.${host.name} = inputs.nixpkgs.lib.nixosSystem { modules = nixos; }; }; }; yen.kinds.user = { fields.hosts = yen.lib.is lib.isList; sinks.homeManager.nixos = { user, homeManager, ... }: { home-manager.users.${user.name}.imports = homeManager; }; };
yen.fleet.main = { }; yen.flake = { out, ... }: out;}Shared modules become aspects
Section titled “Shared modules become aspects”common.nix was in every host’s list. As an aspect it is active at every host. home-manager is active only
where a user lives:
# The old common.nix and the mkHost helper, as aspects at every host.{ yen, inputs, ... }:{ yen.aspects.common = { at = yen.kinds.host; nixos = { host, pkgs, ... }: { networking.hostName = host.name; boot.loader.systemd-boot.enable = true; time.timeZone = "UTC"; services.openssh.enable = true; environment.systemPackages = [ pkgs.git ]; system.stateVersion = "25.05"; }; }; yen.aspects.home-manager = { at = yen.lib.has yen.kinds.user; # only hosts with users nixos = { imports = [ inputs.home-manager.nixosModules.home-manager ]; home-manager.useGlobalPkgs = true; }; };}Host files hold data and hardware
Section titled “Host files hold data and hardware”A host file declares the instance and the parts only that host has. Features that only one host uses are
aspects with that host in at:
{ yen, ... }:{ yen.host.web = { }; yen.aspects.web-hardware = { at = yen.host.web; nixos = { fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; nixpkgs.hostPlatform = "x86_64-linux"; }; };}{ yen, ... }:{ yen.host.desk = { }; yen.aspects.desk-hardware = { at = yen.host.desk; nixos = { fileSystems."/" = { device = "/dev/nvme0n1p2"; fsType = "ext4"; }; nixpkgs.hostPlatform = "x86_64-linux"; }; };}{ yen, ... }:{ yen.aspects.nginx = { at = yen.host.web; nixos = { services.nginx.enable = true; networking.firewall.allowedTCPPorts = [ 80 ]; }; }; yen.aspects.printing = { at = yen.host.desk; nixos.services.printing.enable = true; };}People own their homes
Section titled “People own their homes”home-manager.users.alice was written in the flake for every host. Now alice is data: she says which hosts
she uses, and her aspect gives her account and her home:
# A user: an account on each of her hosts, and her home.{ yen, ... }:{ yen.user.alice.hosts = [ yen.host.web yen.host.desk ]; yen.aspects.alice = { at = yen.user.alice; nixos = { user, ... }: { users.users.${user.name} = { isNormalUser = true; extraGroups = [ "wheel" ]; }; }; homeManager = { programs.git = { enable = true; userName = "Alice"; }; home.stateVersion = "25.05"; }; };}