microvm tooling: qemu-microvm engine, tap+NAT pools, cloud-init seeds (#615)

Firecracker-class microVMs for dev: 13-microvm-setup.sh (idempotent
installer) + microvm CLI + microvm-net.service (per-user tap pools,
/30s, NAT). Debian 13 cloud assets in /usr/local/lib/microvm/base.
Firecracker v1.16.1 installed but its KVM cap check is refused by this
nested Westmere KVM; qemu -M microvm engine default, FC retry after #601.

Details + UAT: https://projects.knownelement.com/issues/615
This commit is contained in:
2026-09-01 13:27:06 -05:00
parent e37152495e
commit eeeca9bde9
5 changed files with 333 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
# 13-microvm-setup.sh — install Firecracker-class microVM tooling (#615)
# Idempotent; run as root: RUN=1 sudo -E ./13-microvm-setup.sh
# Engine note: qemu -M microvm + KVM is the default engine. Firecracker
# v1.16.1 is installed but its strict KVM capability check
# (USER_MEMORY/SET_TSS_ADDR/VAPIC) is refused by this host's nested KVM
# (Westmere under PVE) — retry MICROVM_ENGINE=firecracker after the
# #601 hardware upgrade.
set -euo pipefail
[ "${RUN:-0}" = 1 ] || { echo "gate: RUN=1 to execute"; exit 1; }
[ "$(id -u)" = 0 ] || { echo "must be root"; exit 1; }
FC_VER=1.16.1
FC_SHA=382a02a869e4d6d5cb14c40577f9545e8458021ea8b0b2d3fc10ec14d9c242e6
FC_URL=https://github.com/firecracker-microvm/firecracker/releases/download/v${FC_VER}
IMG_URL=https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2
SUMS_URL=https://cloud.debian.org/images/cloud/trixie/latest/SHA512SUMS
BASE=/usr/local/lib/microvm/base
SRC=${SRC:-$(cd "$(dirname "$0")" && pwd)/microvm}
echo "== packages"
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
qemu-system-x86 qemu-utils dosfstools mtools curl
echo "== kvm group"
for u in reachableceo reachableceo-offstage; do
id -nG "$u" | tr ' ' '\n' | grep -qx kvm || usermod -aG kvm "$u"
done
echo "== firecracker v${FC_VER}"
if [ ! -x /usr/local/bin/firecracker ] || ! /usr/local/bin/firecracker --version 2>/dev/null | grep -q "$FC_VER"; then
t=$(mktemp -d)
curl -fsSL -o "$t/fc.tgz" "$FC_URL/firecracker-v${FC_VER}-x86_64.tgz"
echo "$FC_SHA $t/fc.tgz" | sha256sum -c -
tar xzf "$t/fc.tgz" -C "$t" release-v${FC_VER}-x86_64/firecracker-v${FC_VER}-x86_64 \
release-v${FC_VER}-x86_64/jailer-v${FC_VER}-x86_64
install -m0755 "$t/release-v${FC_VER}-x86_64/firecracker-v${FC_VER}-x86_64" /usr/local/bin/firecracker
install -m0755 "$t/release-v${FC_VER}-x86_64/jailer-v${FC_VER}-x86_64" /usr/local/bin/jailer
rm -rf "$t"
fi
/usr/local/bin/firecracker --version
echo "== base assets"
mkdir -p "$BASE"
if [ ! -f "$BASE/debian-13-generic-amd64.qcow2" ]; then
curl -fsSL -o "$BASE/debian-13-generic-amd64.qcow2" "$IMG_URL"
curl -fsSL -o "$BASE/SHA512SUMS" "$SUMS_URL"
(cd "$BASE" && grep 'debian-13-generic-amd64.qcow2$' SHA512SUMS | sha512sum -c -)
fi
if [ ! -f "$BASE/vmlinuz" ] || [ ! -f "$BASE/initrd" ]; then
modprobe nbd max_part=8
qemu-nbd -c /dev/nbd0 --read-only "$BASE/debian-13-generic-amd64.qcow2"
sleep 2
mkdir -p /mnt/microvm-base
mount -o ro /dev/nbd0p1 /mnt/microvm-base
cp -L /mnt/microvm-base/boot/vmlinuz-* "$BASE/vmlinuz"
cp -L /mnt/microvm-base/boot/initrd.img-* "$BASE/initrd"
umount /mnt/microvm-base
qemu-nbd -d /dev/nbd0
fi
if [ ! -f "$BASE/base-rootfs.raw" ]; then
qemu-img convert -O raw "$BASE/debian-13-generic-amd64.qcow2" "$BASE/base-rootfs.raw"
qemu-img resize "$BASE/base-rootfs.raw" 10G >/dev/null
fi
chmod 644 "$BASE"/vmlinuz "$BASE"/initrd "$BASE"/base-rootfs.raw "$BASE"/debian-13-generic-amd64.qcow2
ls -lh "$BASE"
echo "== tooling"
install -m0755 "$SRC/microvm" /usr/local/bin/microvm
install -m0755 "$SRC/microvm-net.sh" /usr/local/sbin/microvm-net.sh
install -m0644 "$SRC/microvm-net.service" /etc/systemd/system/microvm-net.service
systemctl daemon-reload
systemctl enable --now microvm-net.service
/usr/local/sbin/microvm-net.sh
echo
echo "DONE. As a human account:"
echo " microvm create test1 && microvm start test1 && microvm ssh test1"
echo "(first ssh needs one logout/login if kvm group was just added)"