examples/vm — bootable qcow2 + real-hardware installer
A minimal demo of Elpe.Image, elpe’s derivation for building
UEFI-bootable disk images out of Ubuntu packages. No dpkg, no chroot,
no root privileges: the whole thing is a bash script running inside
elpe’s regular build container.
Build the qcow2
cd examples/vm
elpe build build.ml # -> <store-path>/disk.qcow2 + run.sh
disk.qcow2 is a GPT image with two partitions:
/dev/vda1— 128 MiB FAT32 ESP holding a Unified Kernel Image at/EFI/BOOT/BOOTX64.EFI(kernel + baked-in cmdline)./dev/vda2— 4 GiB ext4 rootfs populated from the Ubuntu packages listed inImage.base_packagesplus the config’sextra_packages.
Boot it in QEMU
The store path ships with run.sh. It expects OVMF firmware:
sudo apt install ovmf qemu-system-x86
$(elpe build build.ml)/run.sh
Install on real hardware
elpe build install.ml # -> <store-path>/{install.sh,rootfs.tar.zst,BOOTX64.EFI}
Copy the store path to a USB stick booted from any live Linux with
sgdisk, mkfs.fat, mkfs.ext4, tar, and zstd available, then:
sudo ./install.sh /dev/sdX
The script wipes the target, lays down GPT+ESP+ext4, extracts the rootfs, and drops the UKI into the ESP.
Install from inside a VM, onto a simulated disk
This is elpe’s answer to booting a NixOS installer ISO and running
nixos-install. Instead of needing a separate live Linux, the built
image is the installer: it boots, carries the installer payload and
tooling, and lays itself down onto a blank second disk.
elpe build install-vm.ml # -> disk.qcow2 + target.qcow2 + run.sh
$(elpe build install-vm.ml)/run.sh # boots the live VM with /dev/vdb attached
run.sh wires two virtio disks: disk.qcow2 (the live system) as
/dev/vda and a blank target.qcow2 as /dev/vdb. Inside the VM, log
in as root (password elpe) and run:
elpe-install /dev/vdb
systemctl poweroff
elpe-install partitions /dev/vdb (GPT + ESP + ext4), extracts the
pristine rootfs from /opt/elpe-install/rootfs.tar.zst, and copies the
systemd-boot ESP tree from /opt/elpe-install/esp. Then boot what you
installed:
$(elpe build install-vm.ml)/boot-installed.sh
The live image and the installed system share one configuration
(install-vm.ml); the base modules — init (systemd, from
base_packages), DHCP networking (systemd_networkd_dhcp), and SSH
(openssh) — are all it takes to reach a usable login on either.
Notes and current limits
- No initrd. The Ubuntu kernel has virtio-blk and ext4 built in, so
QEMU boots without one; on real hardware add an initrd package (e.g.
initramfs-tools) once you need extra module loading. /etc/passwd,/etc/shadow, etc. are synthesised from the OCamlconfiguration— dpkg post-install scripts don’t run.- The default
kernel_cmdlinehard-codesroot=/dev/vda2; override it in yourconfigurationsubclass if you use a different disk controller or want to switch toroot=LABEL=ELPEROOT.