Skip to content

Install and deploy kits

The install lane puts a machine’s disk layout and hardware report into an install command, and gives a deploy command. The flake sink carries apps like any other output: an out value that gives apps.<system>.<name> merges with the rest. The two kits are modules: you put them in imports of the top module. See Kits batteries for kits and assemblies.

modules/fleet.nix
# Machines, the sinks that install and deploy read, and the kits of the install lane.
# The kits are modules: in your flake they go in `imports` of the top module (`inputs.yen.lib.kits.disko`).
{
yen,
lib,
inputs,
...
}:
let
b = yen.lib.batteries;
inherit (yen.lib) maybe;
pkgs = inputs.nixpkgs.legacyPackages.x86_64-linux;
in
{
imports = [
# (1)
inputs.yen.lib.kits.disko
inputs.yen.lib.kits.facter
];
yen.kinds.fleet = {
spawns.host = _: yen.host;
sinks.out.reduce = yen.lib.reduce.merge;
};
yen.kinds.host = {
fields = {
addr = yen.lib.str;
buildHost = maybe yen.lib.str;
};
spawns.member = yen.lib.batteries.kits.members {
assemblies = lib.attrValues yen.assembly;
inherit (yen.lib) holds;
};
sinks = {
# what the machine's own modules say; the facter and disko batteries write here
nixos = {
reduce = yen.lib.reduce.merge;
out =
{ scope, sinks, ... }:
{
config.${scope.name} = sinks.nixos;
};
};
# the disk layout: disko reads it; install makes the app `install-<machine>` of it
disks = {
reduce = yen.lib.reduce.merge;
out = b.install.apps {
# (2)
from = yen.kinds.host.sinks.disks;
inherit pkgs;
report = h: "./hardware/${h.name}.json";
target = h: "root@${h.addr}";
};
};
# the deploy target (one per machine); rebuild makes the app `rebuild-<machine>` of it
deploy = {
reduce = yen.lib.reduce.one;
out = b.deploy.rebuild {
# (3)
from = yen.kinds.host.sinks.deploy;
inherit pkgs;
};
};
};
};
yen.fleet.main = { };
yen.host = {
lb = {
addr = "10.0.0.1";
};
web = {
addr = "10.0.0.2";
buildHost = "10.0.0.1";
};
nas.addr = "10.0.0.3";
};
yen.flake = { out, ... }: out;
yen.aspects = {
nixos-disko = {
at = yen.kinds.host;
nixos = b.disko { from = yen.kinds.host.sinks.disks; }; # (4)
};
deploy-target = {
at = yen.host.web;
deploy =
{ host, ... }:
{
inherit (host) buildHost;
address = host.addr;
user = "deploy";
};
};
};
}
  • (1) imports the kits disko and facter.
  • (2) is the out of the disks sink. It gives the app install-<machine>: nixos-anywhere with the disko layout. It writes the facter report to the path report gives for the machine. The app name comes from the scope name.
  • (3) is the out of the deploy sink. It gives the app rebuild-<machine>: nixos-rebuild switch --target-host user@address. It adds --build-host when the deploy target has a buildHost.
  • (4) is the NixOS key of the disks sink: disko.devices is the merge of what the machine gave there.

No disks element, no install app; no deploy target, no rebuild app. Arguments after -- go to the tool: a deploy user that is not root runs nix run .#rebuild-<machine> -- --sudo.

The assemblies of the two kits:

modules/assemblies.nix
# Assemblies of the library kits. `layout` is a ref to a layout, never a string; `dir` holds one facter report per machine.
{ yen, lib, ... }:
{
yen.kinds.member = { };
yen.kinds.kit.fields = {
roles = yen.lib.opt yen.lib.attrs { };
constraints = yen.lib.opt yen.lib.attrs { };
};
yen.kinds.assembly.fields = {
kit = yen.kinds.kit;
roles = yen.lib.opt yen.lib.attrs { };
};
yen.aspects.settings-typed = {
at = yen.kinds.member;
errors = yen.lib.batteries.kits.settings-typed; # (1)
};
yen.assembly = {
disk-lb = {
kit = yen.kit.disko;
roles.default = {
at = yen.host.lb;
settings = {
device = "/dev/sda";
layout = yen.kit.disko.layouts.single-ext4; # (2)
};
};
};
disk-web = {
kit = yen.kit.disko;
roles.default = {
at = yen.host.web;
settings = {
device = "/dev/nvme0n1";
layout = yen.kit.disko.layouts.btrfs-luks;
};
};
};
disk-nas = {
kit = yen.kit.disko;
roles.default = {
at = yen.host.nas;
settings = {
device = "/dev/sda /dev/sdb";
layout = yen.kit.disko.layouts.zfs-mirror;
};
};
};
hardware = {
kit = yen.kit.facter;
roles.default = {
at = yen.host.lb;
settings.dir = ../hardware; # (3)
};
};
};
}

(1) checks the types of the settings. At (2), layout is a ref to a layout of the kit disko: yen.kit.disko.layouts.<name>. A layout is a value of the kit, not a kind, so the kit adds no name outside itself. Each layout has a devices function of the device string: single-ext4, btrfs-luks and zfs-mirror (two devices, separated by a space). At (3), dir is the directory with one facter report per machine. Kit facter reads <dir>/<machine>.json. The report of the install app is a function from the machine to a path, such as ./facter/<machine>.json. Point it into that directory. Commit the report after the install, and the next build uses it. A machine with no report gets no facter config.

The disk layouts reach each machine’s disko.devices, and the facter report its hardware.facter.reportPath:

result
{
lb = [
"main"
];
nas = [
"d0"
"d1"
];
web = [
"main"
];
}

The apps, one per machine that has the input:

result
[
"install-lb"
"install-nas"
"install-web"
"rebuild-web"
]

A string where the layout goes is an error record, not a silent default:

variants/layout-string.nix
# a name where a ref goes: the layout is a string
{ yen, ... }:
{
yen.assembly.disk-bad = {
kit = yen.kit.disko;
roles.default = {
at = yen.host.web;
settings = {
device = "/dev/sda";
layout = "single-ext4";
};
};
};
}
result
[
"kits: disk-bad.default: setting layout is not a layout of kit disko (yen.kit.disko.layouts.<name>)"
]
Battery Value of Gives
disko { from; } a NixOS key disko.devices: the merge of what the machine gave to sink from
install.apps { from; pkgs; report; target; flake; } out of the machine’s disks sink apps.<system>.install-<machine>: nixos-anywhere with the disko layout, writing the facter report to the path report gives for the machine
deploy.rebuild { from; pkgs; flake; } out of the machine’s deploy sink apps.<system>.rebuild-<machine>: nixos-rebuild switch --target-host user@address, with --build-host when the deploy target has a buildHost
Kit Role Interface Does
lib.kits.disko default device (str), layout (one of yen.kit.disko.layouts) gives the layout’s disko devices to sink disks; owns its layouts, yen.kit.disko.layouts
lib.kits.facter default dir (path) imports <dir>/<machine>.json with nixos.facter
ContributeCommunitySponsor