Virtualising OpenBSD on macOS

technology macos, virtualisation, openbsd, qemu, utm

I wanted to set up a virtual machine running some form of Unix on my M1 Mac, primarily just to fiddle around with. There were a few constraints: I wanted it to be a native ARM installation, not emulated x86 or anything else, and I wanted to use UTM (a frontend for qemu) rather than virtualbox/vmware/etc. For no particular reason beyond curiosity, I settled on OpenBSD. The process had a few hiccups, so I thought I’d document it here.

I had used these instructions from Sorin Dolha to set up a NetBSD image already, and began by trying the same with an OpenBSD installer image.

The basic problem seemed to be that UTM wasn’t setting up the bootloader right — I’m not sure why, as it worked for other installers, but it kept just dropping me back to the UEFI shell, which is cryptic even for someone who is pretty comfortable working in a Unix terminal.

Searching online led me to Connor Kuehl’s writeup which got me a fair chunk of the way there. Specifically, he lists qemu parameters to get it to boot.

I modified the steps slightly, as follows:

qemu-img create -f qcow2 openbsd.qcow2 16G

I’m pretty sure you could actually just use the image UTM created here, see below; but for the time being I just created a new one.

qemu-system-aarch64 \
    -M virt \
    -accel hvf \
    -m 2048 \
    -cpu cortex-a57 -M virt,highmem=off \
    -drive file=/opt/homebrew/share/qemu/edk2-aarch64-code.fd,if=pflash,format=raw,readonly=on \
    -drive file=install72.img \
    -drive file=openbsd.qcow2,format=qcow2 \
    -nographic \
    -serial tcp::4444,server,telnet,wait

I didn’t save this to a script, as he suggests, because this was going to be a one-off, more or less. Also note that if you’re doing this on an Intel Mac the /opt/homebrew part should be /usr/local.

(As an aside: on my second attempt at this I realised the suggested -nographic -serial options were unnecessary: -display curses (and others, see the qemu documentation) also allow access to the serial console (Alt-2 or Ctrl-Alt-2). That also makes the below telnet step unnecessary.)

At that point, I could log into the machine in another terminal and run the installer there:

telnet localhost 4444

Success! Nearly. I shut the machine down, rebooted without the install72.img disk attached, and it booted into a fresh OpenBSD installation as expected. So then I looked for the UTM virtual machine to stick it into place:

$ find ~/Library -name '*.qcow2'

/Users/ben/Library/Containers/com.utmapp.UTM/Data/Documents/OpenBSD.utm/Data/65781234-0D57-43E7-A668-E1DBE4DE2913.qcow2


$ cp openbsd.qcow2 /Users/ben/Library/Containers/com.utmapp.UTM/Data/Documents/OpenBSD.utm/Data/65781234-0D57-43E7-A668-E1DBE4DE2913.qcow2

$

I started it up and… nothing. Or, actually, the bootloader prompt, then nothing. Further than I got earlier, but not ideal.

With a little more digging it turned out that it was actually running, but not outputting to the graphical terminal. I enabled a serial terminal in UTM and booted it up again, and sure enough I got output and a login prompt that way. Then I followed the OpenBSD documentation on serial consoles to enable ttyC0 in /etc/ttys. (I tried tty00 first, but that didn’t help.)

When I rebooted this time, there was no output after the bootloader at first — however, once it reached the login prompt that displayed on the terminal. (Boot messages went to the serial console as before.) I was able to log in and even run X11 now.