Files
nix-config-ryan4yin/.agents/skills/nix-config-new-host/SKILL.md
T

6.5 KiB

name, description
name description
nix-config-new-host Use when adding a NixOS, macOS, or MicroVM host in this repo, including its outputs, networking, secrets, and eval-test wiring.

Adding a host

Copy the closest existing host and change what differs. The current inventory and naming scheme are in hosts/README.md.

Core rules

  1. Three names, decided up front. The directory (hosts/idols-ai/), the hostname (hostName = "ai"), and the configuration name (ai-niri) differ. Servers use the hostname as the configuration name; Niri desktops append -niri, because just niri deploys $(hostname)-niri. The hostname eval test encodes this.
  2. Secrets come from another repository. The new host decrypts nothing until its host key is a recipient in nix-secrets; see the nix-config-secrets skill. A new desktop also needs its synced dotfiles restored before the first switch, or the shell starts without them.
  3. The shared policy modules are not optional. Several eval tests assert a policy for every configuration, so an under-wired host fails just test instead of failing in production.
  4. Build before you install. just test, just eval-host <name>, and just build-host <name> pass before anything is partitioned or flashed. disko destroys the target disk, and partitioning and installing are user-run actions on a device the user has confirmed.

1. Pick the template

New host Copy from
Desktop workstation hosts/idols-ai/ + outputs/x86_64-linux/src/idols-ai.nix
Homelab server / VM host hosts/12kingdoms-shoryu/ + outputs/x86_64-linux/src/12kingdoms-shoryu.nix
Apple Silicon Linux hosts/12kingdoms-shoukei/ + outputs/aarch64-linux/src/12kingdoms-shoukei.nix
macOS hosts/darwin-fern/ + outputs/aarch64-darwin/src/fern.nix (darwinConfigurations, no Colmena)
MicroVM guest hosts/k8s/k3s-test-1-worker-1/ + outputs/x86_64-linux/src/k3s-test-1-worker-1.nix

A MicroVM guest is also registered in its VM host's microvm.nix, and is deployed with just microvm-deploy. On a VM host with the br0 bridge it also needs a systemd.network.networks unit that attaches the guest's tap to br0; the tap name comes from the guest IP (192.168.5.116 to vm116). Some guest outputs also expose a Colmena node for evaluation or other workflows; do not assume the physical-host deployment is done through Colmena.

2. Files to create or edit

  1. hosts/<dir>/default.nix - sets hostName and imports the host's modules. Some hosts (shoryu, shushou, youko, akane) import mylib.scanPaths ./., which pulls in every other .nix file in the directory; keep scratch files out of those.
  2. hosts/<dir>/hardware-configuration.nix - generated on the target machine (nixos-generate-config --show-hardware-config), never copied from another host. Where the layout is declarative, add disko-fs.nix and record the install command in the host's README.md, as hosts/idols-ai/README.md does.
  3. home/hosts/linux/<name>.nix or home/hosts/darwin/<name>.nix - only for a host with Home Manager; otherwise leave home-modules out.
  4. outputs/<system>/src/<name>.nix - add the output types appropriate to the host: nixosConfigurations.<name> for NixOS, darwinConfigurations.<name> for macOS, and a packages.<name> installer image only where the platform provides one. Add colmena.<name> only for a host deployed through Colmena; it then needs tags, ssh-user, and usually targetHost. MicroVM guests also need the VM-host microvm.nix registration. Keep the leading comment about unused args: haumea passes them lazily and they are still required.
  5. vars/networking.nix - hostsAddr.<name> = { iface; ipv4; } for a LAN host. That entry drives the static address, the SSH Host alias used for remote builds, and known_hosts, so a wrong iface takes the host offline at activation. Skip it for a DHCP or mobile host. If the host enables modules.networking.mihomo and runs systemd-resolved, it needs a DNS takeover tied to mihomo's lifecycle (resolvectl dns/revert in ExecStartPost/ExecStopPost, see hosts/idols-ai/default.nix); a static link DNS would kill DNS when mihomo dies.
  6. hosts/README.md - add the host to the inventory.

Pin service user and group ids (service-user-ids.nix, as on shoryu) before the host has state on disk. A dynamically allocated id that moves on a later rebuild orphans the files it owned (9187e4d9 fix(youko): pin dynamically-allocated service uid/gid (#320)).

3. Tests that fail until the host is wired

outputs/README.md lists which eval tests check every configuration and which list hosts by name:

  • hostname: a new -niri configuration needs a specialExpected entry, in the test for its platform (ai-niri in x86_64-linux, shoukei-niri in aarch64-linux).
  • security-*, kernel, nix-system-features: apply to every configuration automatically.
  • home-manager, btrbk, and the other host-listing tests: add the host if it should be covered.

just test fails (non-zero) unless the suite returns true.

4. Install and deploy

  • First install: boot the ISO, partition with disko, install, then deploy normally. Partitioning, formatting, and installing destroy the target disk, so they are user-run actions on a device the user confirmed: check lsblk/findmnt first, name the exact device, and get authorization for it before any destroy,format,mount. Follow nixos-installer/README.md and the host's own README.
  • Remote hosts: just col <tag> or the host's own recipe, once its key is a secrets recipient. Deploying is a separate impactful action; use the nix-config-update skill's staged deployment (confirm the target, preview the closure, and get authorization).
  • The machine you are on: just local or just niri, which prompt for sudo, so the user runs them.

5. Verify

  • ssh <name> true, then systemctl --failed and journalctl -b -p err on the host.
  • Secrets decrypted, checked by mode and owner only.
  • The role works: the service, VM, or desktop the host exists for.