Proxmox and QEMU test log
This page records what has actually been executed on hardware, so a reader can tell a verified statement from an expectation.
Environment
| Item | Value |
|---|---|
| Proxmox VE | 9.2.21, node pve02, local-btrfs for disks, local for ISO images |
| QEMU | 11.0.3 (the same binary Proxmox uses) |
| Test guest | 4 GB RAM, 2 vCPU, 60 GB disk, VirtIO NIC on a user-mode network with DHCP |
| Base image | ubuntu-24.04-live-server-amd64.iso |
| Nestbox image | nestbox-24.04-slim.iso, 3151 MiB, SHA-256 34c76c4f516526f6c3e5733997c2264892e20e1fedfd1db7c9200ca9beb98db7 |
| Creator image | nestbox-ct.iso, 3151 MiB, SHA-256 42e63947a526491ebc5351b5e64869859d9c120147ec2a8df2d9c26800081a00: a recipe made in the Image Creator, hostname nestbox-ct, UI port 8443, self-signed TLS, one preseeded nest |
What is verified
| Step | Result |
|---|---|
Remaster with xorriso -boot_image any replay |
ok — El Torito BIOS and UEFI entries preserved |
Seed embedded (/user-data, /meta-data, /nocloud/*, volume label cidata) |
ok |
Payload embedded (/nestbox.tar.gz, 2.3 MB) |
ok |
GRUB linux line patched with autoinstall ds=nocloud |
ok |
| Unattended install, no question asked | ok — reboot after 236 s |
Installed system boots, cloud-final finishes without failure |
ok |
nestbox-firstboot.service present and enabled by the installer |
ok |
First boot installs Docker, writes /etc/nestbox/nestbox.env, creates the certificate |
ok |
| Controller image builds inside the guest and starts | ok — PostgreSQL healthy, controller up |
| UI answers on the configured port (443) with the self-signed certificate | ok — HTTP 302 to /accounts/login/ |
| Sign-in with the generated administrator account | ok |
| Dashboard reads the Docker socket | ok — both containers listed as running |
| Creator settings reach the installed system | ok — hostname nestbox-ct, UI on :8443, certificate CN nestbox-ct.local |
| Preseeded nest appears without manual work | ok — hermes-01 on port 8080, https://hermes-01.apps.localhost:8080/ |
| Stack survives a reboot without first boot | ok — restart: unless-stopped, UI back after 302, nest still there |
The same sequence was repeated on Proxmox VE with a VM created through the web UI (VM 210, 4 GB,
2 cores, 60 GB on local-btrfs, ISO attached as ide2), which is the walkthrough in the
install guide.
The four load-bearing details
Each of these cost a failed install cycle. They are the reason the build script looks the way it does.
- The autoinstall document must be nested in the seed's
user-data. A siblingautoinstall.yamlon the ISO is ignored and subiquity silently falls back to the interactive installer. The document therefore lives underautoinstall:inside/user-data. - GRUB ends a command at an unquoted
;. The datasource is passed asds=nocloudand found through thecidatavolume label instead ofds=nocloud;s=/cdrom/nocloud/. - The payload's late-commands belong in
user-dataas well, not inautoinstall.yaml. With them in the wrong file the payload was copied butnestbox-firstboot.servicewas never enabled. - The installer must not need a package mirror. Only
openssh-servercomes from the ISO pool; everything else is installed on first boot, with retries.
All late-commands are written as … || true: one failing command must never abort an otherwise
good install.
Runtime defects this test found
These only appear after the install, when the controller starts for the first time:
| Symptom | Cause | Fix |
|---|---|---|
collectstatic fails: KeyError: 'NESTBOX_SECRET_KEY' |
the production settings require the runtime secret at image build time | the build layer passes a throwaway key |
ModuleNotFoundError: unfold |
the admin theme was used but never declared | django-unfold is a dependency |
ModuleNotFoundError: fido2 |
allauth's MFA URLs are mounted, but the extra was missing | django-allauth[mfa] |
gunicorn: PermissionError on key.pem |
the container runs as uid 10001, the key was 0600 root |
first boot hands the pair to 10001 |
dashboard: runtime.unavailable |
uid 10001 is not in the Docker socket's group | first boot records the host's Docker GID, compose adds the group |
| unstyled sign-in page | allauth's default templates | branded account/login.html and account/logout.html |
seed_nests fails: PermissionError on recipe.json |
the installer writes it 0600 root, the controller runs as uid 10001 |
first boot hands the file to 10001 |
| one reboot leaves the appliance without a controller | neither service had a restart policy | restart: unless-stopped |
Reproduce it without Proxmox
Any Linux host with KVM, xorriso and qemu-img can run the same test:
./scripts/iso/build_iso.sh \
--base ubuntu-24.04-live-server-amd64.iso \
--out dist/nestbox-24.04-slim.iso \
--seed dist/seed \
--payload dist/nestbox.tar.gz
qemu-img create -f qcow2 /tmp/nestbox.qcow2 60G
qemu-system-x86_64 -m 4096 -smp 2 -cpu host -enable-kvm \
-drive file=/tmp/nestbox.qcow2,if=virtio,format=qcow2 \
-cdrom dist/nestbox-24.04-slim.iso \
-display none -serial file:/tmp/install.log -no-reboot
The install is done when /tmp/install.log ends with reboot: Restarting system. Boot the disk
again, and follow /var/log/nestbox/firstboot.log until it prints [nestbox] first boot complete
together with the URL and the generated administrator password.
Not covered yet
- Real hardware, and Proxmox with a physical NIC trunk or VLAN tags.
- Ubuntu 22.04 and 26.04 base images (the seed format is the same, the ISOs are untested).
- ACME certificates; the appliance ships with a self-signed pair and the TLS app has a certbot wrapper, but no public domain has been exercised end to end.