#! /bin/sh # Auto-install OpenBSD/amd64 6.7 on QEMU. # # Copyright (c) 2020 Stefan Kreutz set -o errexit set -o nounset # Accept parameters from environment. SSH_KEY="${SSH_KEY-${HOME}/.ssh/id_rsa.pub}" HTTPS_MIRROR="${HTTPS_MIRROR-https://ftp.openbsd.org/pub/OpenBSD/}" RSYNC_MIRROR="${RSYNC_MIRROR-rsync://ftp.halifax.rwth-aachen.de/openbsd/}" DISK_FILE="${DISK_FILE-disk.qcow2}" DISK_SIZE="${DISK_SIZE-24G}" CPU_COUNT="${CPU_COUNT-4}" MEMORY_SIZE="${MEMORY_SIZE-4G}" # Fail early on missing dependencies. for cmd in qemu-img qemu-system-x86_64 curl signify rsync ssh socat ; do if ! command -v "${cmd}" >/dev/null ; then ( >&2 printf "command not found: %s\\n" "${cmd}" ) exit 1 fi done # Fetch base public key from trusted HTTPS mirror. mkdir -p mirror/pub/OpenBSD/6.7 if [ ! -e mirror/pub/OpenBSD/6.7/openbsd-67-base.pub ] ; then curl \ --silent \ --output mirror/pub/OpenBSD/6.7/openbsd-67-base.pub \ "${HTTPS_MIRROR}6.7/openbsd-67-base.pub" fi # Fetch kernel, PXE bootstrap program, and file sets from untrusted # rsync mirror. if [ ! -d mirror/pub/OpenBSD/6.7/amd64 ] ; then mkdir -p tmp rsync --recursive --delete --quiet \ "${RSYNC_MIRROR}6.7/amd64/SHA256" \ "${RSYNC_MIRROR}6.7/amd64/SHA256.sig" \ "${RSYNC_MIRROR}6.7/amd64/bsd" \ "${RSYNC_MIRROR}6.7/amd64/bsd.*" \ "${RSYNC_MIRROR}6.7/amd64/pxeboot" \ "${RSYNC_MIRROR}6.7/amd64/*67.tgz" \ tmp/ ( cd tmp && signify -C -q \ -p ../mirror/pub/OpenBSD/6.7/openbsd-67-base.pub \ -x SHA256.sig \ -- bsd bsd.* pxeboot *67.tgz ) mv tmp mirror/pub/OpenBSD/6.7/amd64 fi # Create autoinstall configuration if not exists. if [ ! -e mirror/install.conf ] ; then cat << EOF > mirror/install.conf Change the default console to com0 = yes Which speed should com0 use = 115200 System hostname = openbsd Password for root = ************* Allow root ssh login = no Setup a user = puffy Password for user = ************* Public ssh key for user = $( cat "${SSH_KEY}" ) What timezone are you in = UTC Location of sets = http HTTP Server = 10.0.2.1 Unable to connect using https. Use http instead = yes URL to autopartitioning template for disklabel = http://10.0.2.1/disklabel Set name(s) = site67.tgz Checksum test for site67.tgz failed. Continue anyway = yes Unverified sets: site67.tgz. Continue without verification = yes EOF fi # Create disklabel configuration if not exists. if [ ! -e mirror/disklabel ] ; then cat << EOF > mirror/disklabel / 2G swap 8G /tmp 1G /var 1G /usr 2G /usr/X11R6 500M /usr/local 4G /usr/src 1M /usr/obj 1M /home 4G EOF fi # Create site-specific file set if not exists. if [ ! -d site ] ; then mkdir site cat << EOF > site/install.site #! /bin/ksh set -o errexit echo "https://cdn.openbsd.org/pub/OpenBSD" > /etc/installurl echo "permit nopass keepenv :wheel" > /etc/doas.conf #echo "syspatch && shutdown -r now" >> /etc/rc.firsttime EOF chmod +x site/install.site fi # Package site-specific file set if not exists or changed. site_dir_changed="$( find site -exec stat -c %Y {} \; | sort -r | head -n 1 )" if [ ! -e mirror/pub/OpenBSD/6.7/amd64/site67.tgz ] || [ "$( stat -c %Y mirror/pub/OpenBSD/6.7/amd64/site67.tgz )" -lt "${site_dir_changed}" ] ; then rm -f mirror/pub/OpenBSD/6.7/amd64/site67.tgz ( cd site && tar -czf ../mirror/pub/OpenBSD/6.7/amd64/site67.tgz . ) ( cd mirror/pub/OpenBSD/6.7/amd64 && ls -l > index.txt ) fi # Create TFTP directory if not exists. if [ ! -d tftp ] ; then mkdir tftp ln -s ../mirror/pub/OpenBSD/6.7/amd64/pxeboot tftp/auto_install ln -s ../mirror/pub/OpenBSD/6.7/amd64/bsd.rd tftp/bsd.rd mkdir tftp/etc cat << EOF > tftp/etc/boot.conf stty com0 115200 set tty com0 boot tftp:/bsd.rd EOF fi # Remove existing disk image if configuration changed. if [ -e "${DISK_FILE}" ] ; then vm_created="$( stat -c %W "${DISK_FILE}" )" for f in mirror/install.conf mirror/disklabel mirror/pub/OpenBSD/6.7/amd64/site67.tgz tftp/etc/boot.conf do if [ "${vm_created}" -lt "$( stat -c %Y "$f" )" ] ; then ( >&2 printf "%s changed. Recreating virtual machine." "$f" ) rm "${DISK_FILE}" fi done fi # Create disk image if not exists. if [ ! -e "${DISK_FILE}" ] ; then qemu-img create -f qcow2 "${DISK_FILE}" "${DISK_SIZE}" fi # Wait until ./mirror is served at http://127.0.0.1:8080/. while [ ! "$( curl --silent --location --write-out '%{http_code}\n' --output /dev/null http://127.0.0.1:8080/install.conf )" = 200 ] ; do ( >&2 printf "Please serve the directory ./mirror/ at http://127.0.0.1:8080/.\n" ) sleep 5 done # Auto-install OpenBSD. qemu-system-x86_64 \ -enable-kvm \ -m "${MEMORY_SIZE}" \ -smp "cpus=${CPU_COUNT}" \ -device e1000,netdev=n1 \ -netdev "user,id=n1,hostname=openbsd-vm,tftp-server-name=10.0.2.1,tftp=tftp,bootfile=auto_install,hostfwd=tcp::2222-:22,guestfwd=tcp:10.0.2.1:80-cmd:socat - tcp:127.0.0.1:8080" \ -drive "file=${DISK_FILE},media=disk,if=virtio" \ -nographic