--- name: nix-config-new-host description: Use when adding a NixOS, macOS, or MicroVM host in this repo, or wiring an existing machine into `outputs/`, `hostsAddr`, secrets recipients, and the eval tests. --- # Adding a host Copy the closest existing host and change what differs. The current inventory and naming scheme are in [hosts/README.md](../../../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 `, and `just build-host ` 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 - 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`; deploy it with the procedure in WA-026 of [WORKAROUNDS.md](../../../WORKAROUNDS.md), not `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//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//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/.nix` or `home/hosts/darwin/.nix` - only for a host with Home Manager; otherwise leave `home-modules` out. 4. `outputs//src/.nix` - add the output types appropriate to the host: `nixosConfigurations.` for NixOS, `darwinConfigurations.` for macOS, and a `packages.` installer image only where the platform provides one. Add `colmena.` 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. = { 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; `homeOnly = true` only drops the SSH alias and the local exporters, not `known_hosts` or the scrape targets. 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](../../../outputs/README.md#which-tests-cover-a-new-host) 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](../../../nixos-installer/README.md) and the host's own README. - Remote hosts: `just col ` 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: the user runs `just local` or `just niri`. ## 5. Verify - `ssh 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.