This explains how to create an Alpine Linux unified kernel image (UKI) with netboot.
For this we need:
- a kernel
- an initramfs image
- a modloop image (a squashfs image with the kernel modules for the kernel)
- the
ukifytool from systemd
Download the latest netboot tarball from https://cdn.alpinelinux.org/ For example: https://dl-cdn.alpinelinux.org/alpine/v3.23/releases/x86_64/alpine-netboot-3.23.2-x86_64.tar.gz
Extract the image: tar -zxf alpine-netboot-3.23.2-x86_64.tar.gz
The kernel, initramfs and modloop are found in the boot/ directory:
boot/
boot/System.map-6.18.1-0-virt
boot/config-6.18.1-0-virt
boot/initramfs-virt
boot/modloop-virt
boot/vmlinuz-virt
boot/dtbs-virt/
boot/System.map-6.18.1-0-lts
boot/config-6.18.1-0-lts
boot/initramfs-lts
boot/modloop-lts
boot/vmlinuz-lts
boot/dtbs-lts/
apk add ukify
We use the -virt flavored kernel, which is optimized for virtual machines and is significantly lighter than the -lts flavored kernel.
We set alpine_repo and modloop to a http repo because we don't have the certificates for https.
At this point it is non-trivial to embed the modloop in the initramfs, so we tell alpine to download it from network via the modloop=<URL> boot option.
We also set console=ttyS0 for serial console.
ukify build \
--linux=./boot/vmlinuz-virt \
--initrd=./boot/initramfs-virt \
--cmdline="alpine_repo=http://dl-cdn.alpinelinux.org/alpine/v3.23/main modloop=http://dl-cdn.alpinelinux.org/alpine/v3.23/releases/x86_64/netboot-3.23.2/modloop-virt console=ttyS0" \
--output alpine-virt-3.23.2.efiBoot the image with qemu, using a virtio network device:
qemu-system-x86_64 \
-accel kvm \
-cpu host \
-nic user,model=virtio-net-pci \
-m 1024 \
-nographic \
-bios /usr/share/ovmf/bios.bin
-kernel ./alpine-virt-3.23.2.efiYou can also create a tiny-cloud (a mini cloud-init implementation) and pass it to qemu via the network.
Create the meta-data and user-data files:
cat >meta-data<<EOF
hostname: alpine-vm
EOF
cat >user-data<<EOF
#cloud-config
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIiHcbg/7ytfLFHUNLRgEAubFz/13SwXBOM/05GNZe4 ncopa@ncopa-desktop
EOFSpin up a tiny http server to serve those files:
python -m http.server --directory .From a second console, run qemu with -smbios option where we set the nocloud data source URL to qemu's default IP address. We can also port forward localhost:22000 to the VM so we can ssh in to the VM.
qemu-system-x86_64 \
-accel kvm \
-cpu host \
-netdev user,id=net0,hostfwd=tcp:127.0.0.1:22000-:22 \
-device virtio-net-pci,netdev=net0 \
-m 1024 \
-nographic \
-bios /usr/share/ovmf/bios.bin \
-smbios type=1,serial=ds='nocloud;s=http://10.0.2.2:8000/' \
-kernel ./alpine-virt-3.23.2.efiOnce it is booted you can ssh in via port 22000
ssh -p 22000 [email protected]