Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Image

The image.nix module provides image and VM-related configuration for server hosts.

SSH Private Key Activation Script

On first boot of a freshly installed host, the SSH private key must be provisioned. The public key is baked into the image at /etc/ssh/ssh_host_ed25519_key.pub, but the private key is deliberately not packaged. Instead, the activation script prompts the operator interactively to input the private key, validates it, and stores it at core.openssh.hostPrivateKeyPath, where OpenSSH and sops age decryption both read the same canonical file. Before reading input, the script saves the current /dev/console tty state, switches the console into canonical line mode for reliable multiline paste handling, and restores the original tty state on exit.

The script is enabled unconditionally on all server hosts as a no-op unless both of the following hold:

  • /dev/console is available for I/O (it is under build-vm -nographic, where QEMU wires it to the host terminal)
  • A canonical host key does not already exist at core.openssh.hostPrivateKeyPath

Input handling and validation

The prompt ignores any lines before -----BEGIN OPENSSH PRIVATE KEY-----, then captures the key line-by-line until -----END OPENSSH PRIVATE KEY-----. If the final END line does not submit automatically, pressing Ctrl+D flushes that last line. Pressing Ctrl+D before the BEGIN line restarts the prompt with No key provided, and pressing Ctrl+D after BEGIN but before END discards the partial key and restarts the prompt.

The captured key is checked in two stages:

  1. The key file is parsed and validated as a valid Ed25519 private key.
  2. The derived public key must match the baked-in public key the image was built with.

On failure the key file is removed and the prompt repeats.

VM Variant Overrides

All servers import the proxmox-lxc module which inherently breaks nixos-rebuild build-vm because the Proxmox LXC image variant sets boot.isContainer = true and therefore disables the initrd. We override this behavior for build-vm so that a runnable QEMU VM can be built from such hosts with the following options:

  • boot.isContainer = false: restores the initrd and normal VM boot.
  • boot.loader.initScript.enable = false: avoids a unique-option conflict on system.build.installBootLoader between the grub and init-script loaders.
  • virtualisation.qemu.consoles = [ "tty0" "ttyS0,115200n8" ]: routes boot logs and /dev/console to the serial port so they are visible with -nographic (the last console= becomes /dev/console).
  • systemd.services."serial-getty@ttyS0".enable = true: enables root autologin on the serial console so the VM is usable with -nographic.

Building and running a VM

nixos-rebuild build-vm --flake .#<hostname>
./result/bin/run-<hostname>-vm -nographic

Building a Proxmox LXC image

nixos-rebuild build-image --image-variant proxmox-lxc --flake .#<hostname>