summaryrefslogtreecommitdiff
path: root/packages/buildvm
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-28 21:45:59 +0200
committerPaul Buetow <paul@buetow.org>2026-03-28 21:45:59 +0200
commitbdb0899bdf996da826310ea3b4efa3ecad47b34b (patch)
tree9a08d89675059bbbede4998b551f676e283a2205 /packages/buildvm
parentc141a204ed4a14759795804f87280ffef765f9c6 (diff)
Add OpenBSD build VM and dtail package infrastructure
Add a QEMU/KVM OpenBSD VM for native compilation of CGo packages (e.g. dtail with DataDog/zstd). The VM is fully automated via expect driving the serial console installer. - packages/buildvm/: setup, provision, start, stop scripts and expect installer - packages/scripts/pkg-dtail-openbsd.sh: multi-binary package with signify signing - packages/Makefile: build VM management and dtail-openbsd target using git archive - frontends/Rexfile: dtail_install task uses custom pkg repo, dtail task enabled Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/buildvm')
-rw-r--r--packages/buildvm/.gitignore5
-rwxr-xr-xpackages/buildvm/install-expect.exp167
-rw-r--r--packages/buildvm/install.conf18
-rwxr-xr-xpackages/buildvm/provision.sh61
-rwxr-xr-xpackages/buildvm/setup.sh41
-rwxr-xr-xpackages/buildvm/start.sh51
-rwxr-xr-xpackages/buildvm/stop.sh34
7 files changed, 377 insertions, 0 deletions
diff --git a/packages/buildvm/.gitignore b/packages/buildvm/.gitignore
new file mode 100644
index 0000000..d036f27
--- /dev/null
+++ b/packages/buildvm/.gitignore
@@ -0,0 +1,5 @@
+*.qcow2
+*.iso
+*.pid
+custom-pkg.sec
+custom-pkg.pub
diff --git a/packages/buildvm/install-expect.exp b/packages/buildvm/install-expect.exp
new file mode 100755
index 0000000..e3f0c16
--- /dev/null
+++ b/packages/buildvm/install-expect.exp
@@ -0,0 +1,167 @@
+#!/usr/bin/expect -f
+# Automated OpenBSD installer via serial console.
+# Called by setup.sh — arguments: disk iso ram cpus ssh_port
+
+set timeout 600
+log_user 1
+
+set disk [lindex $argv 0]
+set iso [lindex $argv 1]
+set ram [lindex $argv 2]
+set cpus [lindex $argv 3]
+set sshport [lindex $argv 4]
+
+spawn qemu-system-x86_64 \
+ -machine accel=kvm \
+ -cpu host \
+ -m $ram \
+ -smp $cpus \
+ -drive file=$disk,format=qcow2,if=virtio \
+ -cdrom $iso \
+ -boot d \
+ -netdev user,id=net0,hostfwd=tcp::${sshport}-:22 \
+ -device virtio-net-pci,netdev=net0 \
+ -nographic
+
+# Redirect console to serial at boot prompt
+expect "boot>"
+send "set tty com0\r"
+expect "boot>"
+send "\r"
+
+# Installer menu
+expect "(I)nstall"
+send "i\r"
+
+# Terminal type — accept default vt220
+expect "Terminal type"
+send "\r"
+
+expect "System hostname"
+send "buildvm\r"
+
+# Network — accept default vio0
+expect "Network interface to configure"
+send "\r"
+
+# IPv4 — default is autoconf
+expect "IPv4 address"
+send "\r"
+
+expect "IPv6 address"
+send "none\r"
+
+# Done configuring interfaces
+expect "Network interface to configure"
+send "done\r"
+
+# DNS domain — installer may skip this prompt entirely.
+# Either way, wait for the password prompt.
+expect -re "will not echo.*$"
+sleep 2
+send "build123\r"
+
+expect -re "again.*$"
+sleep 2
+send "build123\r"
+
+expect "Start sshd"
+send "\r"
+
+expect "Do you expect to run the X"
+send "no\r"
+
+# Console redirect prompt (because we set tty com0)
+expect "Change the default console"
+send "yes\r"
+
+# Speed — accept default
+expect "Which speed"
+send "\r"
+
+# User setup — wait for full prompt to appear before sending
+expect -re "etup a user.*\\]"
+sleep 1
+send "pbuild\r"
+
+expect "Full name"
+send "\r"
+
+# User password — same serial console timing as root password
+expect -re "will not echo.*$"
+sleep 2
+send "build123\r"
+
+expect -re "again.*$"
+sleep 2
+send "build123\r"
+
+expect "Allow root ssh login"
+send "no\r"
+
+expect "timezone"
+send "UTC\r"
+
+expect "root disk"
+send "\r"
+
+# Disk encryption — decline (OpenBSD 7.8+)
+expect "Encrypt the root disk"
+send "\r"
+
+# Whole disk
+expect "Use (W)hole"
+send "w\r"
+
+# GPT or auto layout
+expect {
+ "Use (G)PT" { send "\r"; exp_continue }
+ "(A)uto layout" { send "a\r" }
+}
+
+expect "Location of sets"
+send "cd0\r"
+
+expect "Pathname to the sets"
+send "\r"
+
+expect "Set name"
+send -- "-game*\r"
+
+expect "Set name"
+send -- "-x*\r"
+
+expect "Set name"
+send "\r"
+
+expect "without verification"
+send "yes\r"
+
+# After sets install, installer asks if we want more sets — accept "done" default
+expect -timeout 600 "Location of sets"
+send "\r"
+
+# Wait for finalization
+expect -timeout 120 "CONGRATULATIONS"
+
+# Time may or may not appear wrong
+expect -re "Time appears wrong|Exit to"
+if {[string match "*Time*" $expect_out(0,string)]} {
+ send "\r"
+ expect "Exit to"
+}
+
+# Drop to installer shell instead of rebooting (CD is still attached,
+# reboot would boot the installer again). The installed system is at /mnt.
+send "s\r"
+expect "#"
+
+# Configure doas and wheel group on the installed system
+send "chroot /mnt usermod -G wheel pbuild\r"
+expect "#"
+send "echo 'permit nopass pbuild' > /mnt/etc/doas.conf\r"
+expect "#"
+
+# Shut down cleanly
+send "halt -p\r"
+expect -timeout 60 eof
diff --git a/packages/buildvm/install.conf b/packages/buildvm/install.conf
new file mode 100644
index 0000000..7a509e6
--- /dev/null
+++ b/packages/buildvm/install.conf
@@ -0,0 +1,18 @@
+System hostname = buildvm
+Which network interface do you wish to configure = vio0
+IPv4 address for vio0 = autoconf
+IPv6 address for vio0 = none
+Which network interface do you wish to configure = done
+DNS domain name = local
+Password for root = build123
+Setup a user = pbuild
+Password for user = build123
+Allow root ssh login = no
+What timezone are you in = UTC
+Which disk is the root disk = sd0
+Encrypt the root disk = no
+Use (W)hole disk MBR, whole disk GPT, (O)penBSD area or (E)dit = whole
+Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout = a
+Location of sets = cd0
+Set name(s) = -game*.tgz -x*.tgz
+Continue without verification = yes
diff --git a/packages/buildvm/provision.sh b/packages/buildvm/provision.sh
new file mode 100755
index 0000000..0d95856
--- /dev/null
+++ b/packages/buildvm/provision.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# Provision the OpenBSD build VM after a fresh install.
+# Run once from the host after setup.sh completes.
+#
+# Installs Go, gmake, git, sets up SSH key access,
+# doas for the build user, and signify keys for package signing.
+# Uses sshpass for initial password-based SSH (before key is installed).
+
+set -e
+
+VMDIR="$(cd "$(dirname "$0")" && pwd)"
+SSH_PORT=2222
+SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p $SSH_PORT"
+
+# First boot the VM
+echo "Starting build VM..."
+"$VMDIR/start.sh"
+
+# Set up SSH key — use sshpass if available, fall back to manual prompt
+echo "Setting up SSH key access..."
+if command -v sshpass &>/dev/null; then
+ sshpass -p build123 ssh-copy-id $SSH_OPTS pbuild@localhost 2>/dev/null
+else
+ echo "sshpass not found. Enter the build user password (build123) when prompted:"
+ ssh-copy-id $SSH_OPTS pbuild@localhost
+fi
+
+SSH="ssh $SSH_OPTS pbuild@localhost"
+SCP="scp $SSH_OPTS"
+
+# Configure doas for passwordless access (may already be set by setup.sh)
+echo "Configuring doas..."
+$SSH "echo 'permit nopass pbuild' | doas tee /etc/doas.conf > /dev/null"
+
+# Install build tools
+echo "Installing Go, git, gmake..."
+$SSH "doas pkg_add go git gmake"
+
+# Copy signify keys for package signing (if available locally)
+if [ -f "$VMDIR/custom-pkg.sec" ] && [ -f "$VMDIR/custom-pkg.pub" ]; then
+ echo "Installing signify keys..."
+ $SCP "$VMDIR/custom-pkg.sec" "$VMDIR/custom-pkg.pub" pbuild@localhost:/tmp/
+ $SSH "doas cp /tmp/custom-pkg.sec /tmp/custom-pkg.pub /etc/signify/ && \
+ doas chmod 600 /etc/signify/custom-pkg.sec && \
+ doas chmod 644 /etc/signify/custom-pkg.pub && \
+ rm /tmp/custom-pkg.sec /tmp/custom-pkg.pub"
+ echo "Signify keys installed."
+else
+ echo ""
+ echo "WARNING: Signify keys not found at $VMDIR/custom-pkg.{sec,pub}"
+ echo "Copy them from fishfinger before building signed packages:"
+ echo " scp rex@fishfinger.buetow.org:/etc/signify/custom-pkg.sec $VMDIR/"
+ echo " scp rex@fishfinger.buetow.org:/etc/signify/custom-pkg.pub $VMDIR/"
+ echo "Then re-run: $0"
+fi
+
+echo ""
+echo "Verifying..."
+$SSH "go version && uname -a"
+echo ""
+echo "Build VM provisioned. Ready for: make dtail-openbsd"
diff --git a/packages/buildvm/setup.sh b/packages/buildvm/setup.sh
new file mode 100755
index 0000000..49312bd
--- /dev/null
+++ b/packages/buildvm/setup.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Create and configure an OpenBSD QEMU/KVM VM for native package builds.
+#
+# Fully automated via expect driving the serial console installer.
+# The expect script is in install-expect.exp (separate file avoids
+# bash/expect quoting issues with password prompts).
+#
+# Prerequisites: qemu-system-x86_64, expect, KVM (/dev/kvm)
+
+set -e
+
+VMDIR="$(cd "$(dirname "$0")" && pwd)"
+DISK="$VMDIR/openbsd-build.qcow2"
+OBSD_VERSION="7.8"
+ISO="$VMDIR/install${OBSD_VERSION//./}.iso"
+SSH_PORT=2222
+RAM=1024
+CPUS=2
+
+if [ -f "$DISK" ]; then
+ echo "Disk $DISK already exists. Delete it first to reinstall."
+ exit 1
+fi
+
+# Download install ISO if not cached
+if [ ! -f "$ISO" ]; then
+ echo "Downloading OpenBSD $OBSD_VERSION install ISO..."
+ curl -L -o "$ISO" "https://cdn.openbsd.org/pub/OpenBSD/$OBSD_VERSION/amd64/install${OBSD_VERSION//./}.iso"
+fi
+
+echo "Creating ${DISK}..."
+qemu-img create -f qcow2 "$DISK" 4G
+
+echo ""
+echo "Starting automated OpenBSD install (takes ~5 minutes)..."
+echo ""
+
+expect "$VMDIR/install-expect.exp" "$DISK" "$ISO" "$RAM" "$CPUS" "$SSH_PORT"
+
+echo ""
+echo "OpenBSD install complete. Now run: $VMDIR/provision.sh"
diff --git a/packages/buildvm/start.sh b/packages/buildvm/start.sh
new file mode 100755
index 0000000..2cc3e54
--- /dev/null
+++ b/packages/buildvm/start.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# Start the OpenBSD build VM in the background.
+# SSH available at localhost:2222 after boot (~15s).
+
+set -e
+
+VMDIR="$(cd "$(dirname "$0")" && pwd)"
+DISK="$VMDIR/openbsd-build.qcow2"
+PIDFILE="$VMDIR/qemu.pid"
+SSH_PORT=2222
+RAM=1024
+CPUS=2
+
+if [ ! -f "$DISK" ]; then
+ echo "Error: $DISK not found. Run setup.sh first."
+ exit 1
+fi
+
+if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
+ echo "Build VM already running (PID $(cat "$PIDFILE"))"
+ exit 0
+fi
+
+# Use -display none + -serial null for headless background operation.
+# -nographic cannot be combined with -daemonize.
+echo "Starting OpenBSD build VM..."
+qemu-system-x86_64 \
+ -machine accel=kvm \
+ -cpu host \
+ -m "$RAM" \
+ -smp "$CPUS" \
+ -drive file="$DISK",format=qcow2,if=virtio \
+ -netdev user,id=net0,hostfwd=tcp::${SSH_PORT}-:22 \
+ -device virtio-net-pci,netdev=net0 \
+ -display none \
+ -serial null \
+ -daemonize \
+ -pidfile "$PIDFILE"
+
+echo "VM started (PID $(cat "$PIDFILE")), waiting for SSH..."
+
+# Wait for SSH to become available
+for i in $(seq 1 30); do
+ if ssh -q -o ConnectTimeout=2 -o StrictHostKeyChecking=no -p "$SSH_PORT" pbuild@localhost true 2>/dev/null; then
+ echo "SSH ready at localhost:$SSH_PORT"
+ exit 0
+ fi
+ sleep 2
+done
+
+echo "Warning: SSH not responding after 60s. VM may still be booting."
diff --git a/packages/buildvm/stop.sh b/packages/buildvm/stop.sh
new file mode 100755
index 0000000..923ddaa
--- /dev/null
+++ b/packages/buildvm/stop.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Shut down the OpenBSD build VM gracefully.
+
+set -e
+
+VMDIR="$(cd "$(dirname "$0")" && pwd)"
+PIDFILE="$VMDIR/qemu.pid"
+SSH_PORT=2222
+
+if [ ! -f "$PIDFILE" ] || ! kill -0 "$(cat "$PIDFILE")" 2>/dev/null; then
+ echo "Build VM is not running."
+ rm -f "$PIDFILE"
+ exit 0
+fi
+
+echo "Shutting down build VM..."
+# Graceful shutdown via SSH, fall back to SIGTERM
+ssh -q -o ConnectTimeout=5 -p "$SSH_PORT" pbuild@localhost "doas halt -p" 2>/dev/null || true
+
+# Wait for QEMU process to exit
+PID=$(cat "$PIDFILE")
+for i in $(seq 1 15); do
+ if ! kill -0 "$PID" 2>/dev/null; then
+ echo "VM stopped."
+ rm -f "$PIDFILE"
+ exit 0
+ fi
+ sleep 1
+done
+
+# Force kill if still running
+echo "Force-killing QEMU (PID $PID)..."
+kill "$PID" 2>/dev/null || true
+rm -f "$PIDFILE"