Install a Host
This runbook defines and installs a clean NixOS host with
nixos-anywhere and the repository’s Disko
configuration.
Safety Warning
Warning: The installation phases repartition the target disk and destroy existing data. Confirm the host, target address, and disk configuration before running them. The procedure also changes the host’s agenix recipient, so encrypted secrets must be rekeyed before installation.
Define the Host
- Create
hosts/<host>/default.nixwith its target system, users, and profile selections. - Create
hosts/<host>/configuration.nixandhosts/<host>/hardware-configuration.nix. - Register the host in the
hostsattribute set inflake.nix. - Configure and review its stable disk identifier or existing
partition paths through
rootFs.
The host’s agenix recipient is added after generating its identity below.
Requirements
- The target has booted into a NixOS live installer with network access.
- The deploy machine has this repository checked out and can reach the target over SSH.
- Existing data on the target disk has been backed up.
- The target disk layout in the host configuration has been reviewed.
Prepare the Installer
Set a temporary root password from the live installer:
sudo passwdOn the deploy machine, enter the repository development shell and set the target values:
nix develop
host_name="<host>"
target_host="root@<host-ip-or-dns>"Confirm SSH access before proceeding:
ssh "$target_host" trueGenerate the Host Identity
Generate the host identity in the persistent path expected by agenix:
host_key_name="${host_name//-/_}"
tmpdir="$(mktemp -d)"
mkdir -p "$tmpdir/persist/etc/agenix"
age-keygen -o "$tmpdir/persist/etc/agenix/host.agekey"
chmod 755 -R "$tmpdir/persist"
chmod 600 "$tmpdir/persist/etc/agenix/host.agekey"Update the matching host key declaration in secrets.nix,
then rekey all affected secrets:
sed -i "s|^ ${host_key_name} = \".*\";| ${host_key_name} = \"$(age-keygen -y "$tmpdir/persist/etc/agenix/host.agekey")\";|" secrets.nix
agenix -rValidate the Configuration
Review the secrets.nix change and verify the
configuration before modifying the target disk:
just check
just dry-run "$host_name"Prepare the Nix Daemon
Prepare the live installer’s Nix daemon for a remote build. This temporarily allows generated, unsigned store paths such as Home Manager activation scripts to be imported; the installed system restores signature checking:
ssh "$target_host" '
cp --dereference /etc/nix/nix.conf /tmp/nix.conf
printf "\nrequire-sigs = false\n" >> /tmp/nix.conf
mount --bind /tmp/nix.conf /etc/nix/nix.conf
systemctl restart nix-daemon
nix --extra-experimental-features nix-command config show require-sigs
'Verify that the command prints false.
Install NixOS
Run the destructive installation. The explicit substituters allow installation when the private cache is unavailable:
NIX_CONFIG=$'substituters = https://cache.nixos.org https://nix-community.cachix.org' \
nix run github:nix-community/nixos-anywhere -- \
--build-on remote \
--no-use-machine-substituters \
--debug -L --show-trace \
--option substituters "https://cache.nixos.org https://nix-community.cachix.org" \
--flake .#"$host_name" \
--phases disko,install,reboot \
--extra-files "$tmpdir" \
"$target_host"Remove the temporary copy of the private host key after the installation completes:
rm -rf "$tmpdir"Verify the Installation
After the target reboots, verify its configuration revision and failed units:
ssh "$target_host" 'nixos-version --configuration-revision; systemctl --failed'Confirm that /etc/agenix/host.agekey exists and that the
filesystems or datasets declared by rootFs are mounted.
Then verify a normal deployment from the repository:
just dry-run "$host_name"
just switch "$host_name"Enroll TPM2
For a host with rootFs.encrypted = true, boot the
installed system once and inspect the encrypted partition before
enrolling TPM2 auto-unlock:
lsblk -f
cryptsetup luksDump /dev/disk/by-partlabel/disk-main-encrypted
sudo systemd-cryptenroll --tpm2-device=auto /dev/disk/by-partlabel/disk-main-encryptedAdd a recovery passphrase after enrollment if the installation does not already have one:
sudo systemd-cryptenroll /dev/disk/by-partlabel/disk-main-encryptedVerify that both the TPM2 token and a recovery method are present before rebooting.
Recovery and Troubleshooting
- If evaluation fails, fix
hosts/<host>/,secrets.nix, or recipient declarations before runningnixos-anywhere; do not bypassjust check. - If the installer cannot import store paths, confirm that
nix config show require-sigsreportsfalsein the live installer and thatnix-daemon.servicerestarted successfully. - If Disko selects an unexpected device, stop before installation and
correct the stable disk identifier or explicit partition paths in
rootFs. - If agenix fails after reboot, verify
/etc/agenix/host.agekey, the matching recipient insecrets.nix, and that secrets were rekeyed withagenix -r. - If the installed system does not boot, use the live installer to
unlock encrypted devices and mount or import the configured
rootFsbackend before repairing the system profile.