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/consoleis available for I/O (it is underbuild-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:
- The key file is parsed and validated as a valid Ed25519 private key.
- 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 onsystem.build.installBootLoaderbetween the grub and init-script loaders.virtualisation.qemu.consoles = [ "tty0" "ttyS0,115200n8" ]: routes boot logs and/dev/consoleto the serial port so they are visible with-nographic(the lastconsole=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>