Initial Commit

This commit is contained in:
2026-09-15 15:24:03 -04:00
commit 4dc7086e7e
605 changed files with 101380 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
#!/bin/bash
# =====================================================================
# Builds the frozen Ubuntu base image, unattended, from the stock ISO.
#
# sudo ./build.sh # ~25 minutes, mostly apt
#
# HOW THE INSTALL IS MADE UNATTENDED
#
# Subiquity will read an autoinstall config from a NoCloud volume, but it
# stops to ask for confirmation unless `autoinstall` is on the kernel
# command line. There is no way to pass a kernel argument to a CD-ROM, so
# the ISO is repacked with that one word added to its grub menu entry.
# The alternative - booting the ISO's kernel directly with -kernel - was
# rejected because it bypasses OVMF, and an image installed outside UEFI
# will not boot under owuivm-launch, which uses it.
#
# The repack is `xorriso ... -boot_image any replay`, which copies the
# original boot records across verbatim. Anything else produces an ISO
# that is subtly not bootable, usually only under UEFI, usually only on
# the second attempt.
#
# THE BUILD RUNS AS owuivm ON PURPOSE
#
# Same uid, same egress filter, same everything as a real session. If the
# sandbox's network rules would break `apt`, this is where that is found
# - not three phases later with an agent in the loop to confuse it.
# =====================================================================
set -euo pipefail
cd "$(dirname "$(readlink -f "$0")")"
[ "$(id -u)" -eq 0 ] || { echo "run as root" >&2; exit 1; }
ISO_DIR=/var/lib/owuivm/iso
BASE_DIR=/var/lib/owuivm/base
WORK=$(mktemp -d /var/tmp/owuivm-build.XXXXXX)
trap 'rm -rf "$WORK"' EXIT
SRC_ISO="$ISO_DIR/$(awk '{print $1}' "$ISO_DIR/ubuntu.manifest")"
AUTO_ISO="$WORK/ubuntu-autoinstall.iso"
SEED_ISO="$WORK/seed.iso"
DISK="$BASE_DIR/ubuntu.qcow2"
VARS="$BASE_DIR/ubuntu-OVMF_VARS.fd"
LOG=/var/log/owuivm-build-ubuntu.log
[ -f "$SRC_ISO" ] || { echo "no source ISO - run ../fetch.sh ubuntu first" >&2; exit 1; }
if [ -e "$DISK" ]; then
echo "$DISK already exists."
echo "Refusing to overwrite a base image: unfreeze and edit it through the"
echo "maintenance tool, or delete it deliberately and re-run."
exit 1
fi
echo "==> patching the ISO's boot menu"
xorriso -osirrox on -indev "$SRC_ISO" -extract /boot/grub/grub.cfg "$WORK/grub.cfg" >/dev/null 2>&1
# `autoinstall` - skips subiquity's confirmation prompt.
# `console=ttyS0`- so the install is watchable in $LOG instead of being a
# 25-minute black box that either works or does not.
sed -i -e 's|^\(\s*linux\s*/casper/vmlinuz\)\s*---|\1 autoinstall console=ttyS0,115200 ---|' \
-e 's|^set timeout=.*|set timeout=1|' "$WORK/grub.cfg"
grep -q 'autoinstall' "$WORK/grub.cfg" || { echo "grub.cfg patch did not apply" >&2; exit 1; }
xorriso -indev "$SRC_ISO" -outdev "$AUTO_ISO" \
-boot_image any replay \
-map "$WORK/grub.cfg" /boot/grub/grub.cfg \
-commit >/dev/null 2>&1
[ -s "$AUTO_ISO" ] || { echo "repack produced nothing" >&2; exit 1; }
echo "==> building the NoCloud seed"
# cloud-init finds this by volume label alone; no ds= argument needed.
mkdir -p "$WORK/seed" && cp user-data meta-data "$WORK/seed/"
xorriso -as mkisofs -o "$SEED_ISO" -V CIDATA -J -r "$WORK/seed" >/dev/null 2>&1
echo "==> creating the disk"
install -d -o owuivmadm -g owuivmadm -m 0755 "$BASE_DIR"
qemu-img create -f qcow2 "$DISK" 40G >/dev/null
cp /usr/share/OVMF/OVMF_VARS_4M.fd "$VARS"
chown owuivm:owuivm "$DISK" "$VARS"
chmod 0644 "$DISK" "$VARS"
chmod 0777 "$WORK"; chmod 0644 "$AUTO_ISO" "$SEED_ISO"
echo "==> installing (watch: tail -f $LOG)"
: > "$LOG"; chown owuivm:owuivm "$LOG"
# -no-reboot: subiquity reboots when it is done, and that is our signal
# that the install finished. Without it the fresh system boots and the
# build never returns.
setpriv --reuid=owuivm --regid=owuivm --groups=kvm --inh-caps=-all -- \
qemu-system-x86_64 \
-no-user-config -nodefaults -no-reboot \
-machine q35,accel=kvm -cpu host -smp 4 -m 4096 \
-drive "if=pflash,format=raw,unit=0,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd" \
-drive "if=pflash,format=raw,unit=1,file=$VARS" \
-drive "file=$DISK,if=none,id=disk0,format=qcow2,cache=unsafe" \
-device virtio-blk-pci,drive=disk0,bootindex=1 \
-drive "file=$AUTO_ISO,if=none,id=cd0,media=cdrom,readonly=on" \
-device ide-cd,drive=cd0,bus=ide.0,bootindex=2 \
-drive "file=$SEED_ISO,if=none,id=cd1,media=cdrom,readonly=on" \
-device ide-cd,drive=cd1,bus=ide.1 \
-netdev user,id=net0,ipv6=off -device virtio-net-pci,netdev=net0,romfile= \
-device VGA -display none \
-serial "file:$LOG"
echo "==> freezing"
# The write bit IS the freeze. owuivm is neither the owner nor in the
# group, so the uid that runs every session cannot clear it; only the
# maintenance unit, which runs as owuivmadm behind a polkit check, can.
chown owuivmadm:owuivmadm "$DISK" "$VARS"
chmod 0444 "$DISK" "$VARS"
sha256sum "$DISK" "$VARS" > "$BASE_DIR/ubuntu.sha256"
chown owuivmadm:owuivmadm "$BASE_DIR/ubuntu.sha256"
echo
echo "base image built and frozen:"
ls -l "$DISK" "$VARS"
cat "$BASE_DIR/ubuntu.sha256"