## On the host and for the user it is called by, creates/registers a VirtualBox VM meant to run the shells target host. Requires the path to the target host's »diskImage« as the result of running the install script. The image file may not be deleted or moved. If »bridgeTo« is set (to a host interface name, e.g. as »eth0«), it is added as bridged network "Adapter 2" (which some hosts need).
# TODO: The serial settings between qemu and vBox seem incompatible. With a simple »console=ttyS0«, vBox hangs on start. So just disable this for now an use qemu for headless setups. The UX here is awful anyway.
qemu+=( -cpu host -enable-kvm )# For KVM to work vBox may not be running anything at the same time (and vBox hangs on start if qemu runs). Pass »--no-kvm« and accept ~10x slowdown, or stop vBox.
elif[[ @{config.preface.hardware}== aarch64 ]];then# assume it's a raspberry PI (or compatible)
if[[ @{config.boot.loader.systemd-boot.enable}||${args[efi]:-}]];then# UEFI. Otherwise it boots something much like a classic BIOS?
#qemu+=( -bios @{pkgs.OVMF.fd}/FV/OVMF.fd ) # This works, but is a legacy fallback that stores the EFI vars in /NvVars on the EFI partition (which is really bad).
for param in "@{config.boot.kernelParams[@]}";doif[[$param=='console=ttyS0'||$param=='console=ttyS0',* ]];then
qemu+=( -nographic )# »-nographic« by default only shows output once th system reaches the login prompt. Add »config.boot.kernelParams = [ "console=tty1" "console=ttyS0" ]« to log to serial (»-nographic«) and the display (if there is one), preferring the last »console« option for the initrd shell (if enabled and requested).
# To pass a USB device (e.g. a YubiKey for unlocking), add pass »--usb-port=${bus}-${port}«, where bus and port refer to the physical USB port »/sys/bus/usb/devices/${bus}-${port}« (see »lsusb -tvv«). E.g.: »--usb-port=3-1.1.1.4«
if[[${args[usb-port]:-}]];thenfor decl in ${args[usb-port]//:/ };do
## Creates a random static key on a new key partition on the GPT partitioned »$blockDev«. The drive can then be used as headless but removable disk unlock method.
# To create/clear the GPT: $ sgdisk --zap-all "$blockDev"
function add-bootkey-to-keydev {(set -eu # 1: blockDev, 2?: hostHash
## Tries to open and mount the systems keystore from its LUKS partition. If successful, adds the traps to close it when the parent shell exits.
# See »open-system«'s implementation for some example calls to this function.
function mount-keystore-luks {# ...: cryptsetupOptions
# (For the traps to work, this can't run in a sub shell. The function therefore can't use »( set -eu ; ... )« internally and instead has to use »&&« after every command and in place of most »;«, and the function can't be called from a pipeline.)
## Performs any steps necessary to mount the target system at »/tmp/nixos-install-@{config.networking.hostName}« on the current host.
# For any steps taken, it also adds the reaps to undo them on exit from the calling shell, and it always adds the exit trap to do the unmounting itself.
# »diskImages« may be passed in the same format as to the installer. If so, any image files are ensured to be loop-mounted.
# Perfect to inspect/update/amend/repair a system's installation afterwards, e.g.:
( @{native.systemd}/bin/udevadm settle -t 15||true)&&# sometimes partitions aren't quite made available yet
if[[ @{config.wip.fs.keystore.enable}&& ! -e /dev/mapper/keystore-@{config.networking.hostName!hashString.sha256:0:8}]];then# Try a bunch of approaches for opening the keystore: