diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-28 21:45:59 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-28 21:45:59 +0200 |
| commit | bdb0899bdf996da826310ea3b4efa3ecad47b34b (patch) | |
| tree | 9a08d89675059bbbede4998b551f676e283a2205 /packages/buildvm | |
| parent | c141a204ed4a14759795804f87280ffef765f9c6 (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/.gitignore | 5 | ||||
| -rwxr-xr-x | packages/buildvm/install-expect.exp | 167 | ||||
| -rw-r--r-- | packages/buildvm/install.conf | 18 | ||||
| -rwxr-xr-x | packages/buildvm/provision.sh | 61 | ||||
| -rwxr-xr-x | packages/buildvm/setup.sh | 41 | ||||
| -rwxr-xr-x | packages/buildvm/start.sh | 51 | ||||
| -rwxr-xr-x | packages/buildvm/stop.sh | 34 |
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" |
