#! /bin/sh # Auto-install OpenBSD/amd64 6.6 to a QEMU guest machine. # # Run the following command to serve the OpenBSD mirror at http://127.0.0.1 # (port 80): # # sudo python3 -m http.server \ # --directory ./openbsd-vm/mirror \ # --bind 127.0.0.1 80 # # Pass the following options to ssh or scp to connect to the guest machine: # # ssh \ # -o "StrictHostKeyChecking no" \ # -o "UserKnownHostsFile /dev/null" \ # -o "Port 2222" \ # puffy@127.0.0.1 # # For example, the following command forwards port 8080 on the host to port 80 # on the guest: # # ssh \ # -o "StrictHostKeyChecking no" \ # -o "UserKnownHostsFile /dev/null" \ # -o "Port 2222" \ # -N \ # -L 127.0.0.1:8080:127.0.0.1:80 \ # puffy@127.0.0.1 # # Press C-a x to stop the guest machine. Press C-a h to show other options. # # The virtual network: # # network = 10.0.2.0/24 # host = 10.0.2.2 # nameserver = 10.0.2.3 # guest = 10.0.2.15-31 # # Port forwardings: # # host:2222 -> guest:22 # # Copyright (c) 2020 Stefan Kreutz set -o errexit set -o nounset set -o xtrace # Set parameters. VM_FILE="${VM_FILE-openbsd-vm.qcow2}" DISK_SIZE="${DISK_SIZE-160G}" CPU_COUNT="${CPU_COUNT-6}" MEMORY_SIZE="${MEMORY_SIZE-4G}" # Remove existing virtual machine if configuration changed. if [ -e "${VM_FILE}" ] ; then vm_created="$( stat -c %W "${VM_FILE}" )" for f in boot.conf disklabel install.conf install.site do if [ "${vm_created}" -lt "$( stat -c %Y "$f" )" ] ; then ( >&2 printf "%s changed. Recreating virtual machine." "$f" ) rm "${VM_FILE}" fi done fi if [ ! -e "${VM_FILE}" ] ; then # Download and verify OpenBSD/amd64 6.6 installation images and file sets. mkdir -p .openbsd-vm/mirror/pub/OpenBSD/6.6 if [ ! -e .openbsd-vm/mirror/pub/OpenBSD/6.6/openbsd-66-base.pub ] ; then curl \ --output .openbsd-vm/mirror/pub/OpenBSD/6.6/openbsd-66-base.pub \ --silent \ https://ftp.openbsd.org/pub/OpenBSD/6.6/openbsd-66-base.pub fi if [ ! -d .openbsd-vm/mirror/pub/OpenBSD/6.6/amd64 ] ; then mkdir -p .openbsd-vm/tmp rsync --recursive --delete --quiet \ rsync://ftp.halifax.rwth-aachen.de/openbsd/6.6/amd64/ \ .openbsd-vm/tmp/ ( cd .openbsd-vm/tmp && \ signify -C -q -p ../mirror/pub/OpenBSD/6.6/openbsd-66-base.pub -x SHA256.sig ) mv .openbsd-vm/tmp .openbsd-vm/mirror/pub/OpenBSD/6.6/amd64 fi # Create site-specific file set. if [ ! -x install.site ] ; then chmod +x install.site fi rm -f .openbsd-vm/mirror/pub/OpenBSD/6.6/amd64/site66.tgz tar -czf .openbsd-vm/mirror/pub/OpenBSD/6.6/amd64/site66.tgz install.site ( cd .openbsd-vm/mirror/pub/OpenBSD/6.6/amd64 && ls -l > index.txt ) # Add public ssh key to install.conf. cp install.conf .openbsd-vm/mirror/ if ! grep -q -e "^Public ssh key for user" install.conf ; then ssh_pub_key="$( cat ~/.ssh/id_rsa.pub )" echo "Public ssh key for user = ${ssh_pub_key}" \ >> .openbsd-vm/mirror/install.conf fi # Copy disklabel template. cp disklabel .openbsd-vm/mirror/ # Wait until the HTTP server is online. # # TODO: Serve HTTP and TFTP from another virtual machine to remove the # necessity to bind to a privileged port. Maybe use Linux' tftpd from Arch # Linux package tftp-hpa. Redirect ports using qemu. while [ ! "$( curl --silent --location --write-out '%{http_code}\n' --output /dev/null http://127.0.0.1/install.conf )" = 200 ] ; do ( >&2 printf "Please serve the directory ./openbsd-vm/mirror at http://127.0.0.1 (port 80).\n" ) sleep 5 done # Collect files to be served over TFTP. rm -rf .openbsd-vm/tftp mkdir .openbsd-vm/tftp ln -s ../mirror/pub/OpenBSD/6.6/amd64/pxeboot .openbsd-vm/tftp/auto_install ln -s ../mirror/pub/OpenBSD/6.6/amd64/bsd.rd .openbsd-vm/tftp/bsd.rd mkdir .openbsd-vm/tftp/etc cp boot.conf .openbsd-vm/tftp/etc/ # Create copy-on-write disk image. qemu-img create -f qcow2 "${VM_FILE}" "${DISK_SIZE}" fi # Auto-install guest machine. 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=.openbsd-vm/tftp,bootfile=auto_install,hostfwd=tcp::2222-:22 \ -drive "file=${VM_FILE},media=disk,if=virtio" \ -nographic