Alpine Linux vm on OpenBSD's vmd(8)

Why alpine?

  • fedora bad
    • anaconda sucks.
    • even passing console=ttyS0, anaconda still doesn't want to give me a serial console.
    • red hat is very quickly marking all the things I actually use in Fedora as "deprecated"
  • alpine good
    • automatically gives you a serial console
    • no grubbing around in the massive operating system that is grub2
    • small
    • I need flatpak for the (2) friends I bullied into using signal and won't listen to me when I suggest "more free" solutions
  • really just want plan 9 but I can't tell if my hypervisor config is bad or if the guest is bad (it was the hypervisor (I have difficulties typing (it always ends up being

The setup

shell commands:

daedalus.localnode# mkdir -p /var/vmd && cd /var/vmd
daedalus:localnode# curl > alpine-standard-3.18.0-x86_64.iso
daedalus.localnode# vmctl create -s 25G alpine.qcow2


Write a configuration file for /etc/vm.conf

#   $OpenBSD: vm.conf,v 1.11 2021/11/11 09:38:14 claudio Exp $

vm "alpine"{
    memory 2048M
    disk "/var/vmd/alpine.qcow2"
    cdrom "/var/vmd/alpine-standard-3.18.0-x86_64.iso"
    owner root
        switch "local"

switch "local" {
    interface bridge0


2 interfaces are needed: vether0 and bridge0:




add vether0

ip forwarding should also be enabled if the vm should be allowed to talk to the internet:


#	$OpenBSD: sysctl.conf,v 1.5 2019/09/18 08:39:06 solene Exp $

A dhcp server is also needed so that the guests can automatically configure networking. An alternative option is to use static addresses.


#   $OpenBSD: dhcpd.conf,v 1.1 2014/07/11 21:20:10 deraadt Exp $
# vmd
subnet netmask {
    option routers;
    option domain-name "";
    option domain-name-servers;

And finally, all the pieces must be assembled using pf.conf. This configuration file contains extra things that aren't strictly necessary for virtualizatoin with networking.


#   $OpenBSD: pf.conf,v 1.55 2017/12/03 20:40:04 sthen Exp $

set skip on lo0

# hypervisor config, allow SSH and DHCP. 
# Note: this configuration can cause your system to become a rogue 
# DHCP service on the external LAN if your dhcpd flags contain more interfaces than 'vether0'
tcp_services="{ssh bootps bootpc}"
udp_services="{bootps bootps}"
block in on {em0 iwn0}
pass in proto tcp to any port $tcp_services keep state
pass in proto udp to any port $tcp_services keep state
pass out all

# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010

# Port build user does not need network
block return out log proto {tcp udp} user _pbuild

# VMD config
pass out on egress from to any nat-to (egress)
pass in proto { udp tcp } from to any port domain rdr-to port domain

Run some commands to make things work:

daedalus.localnode# sysctl net.inet.ip.forwarding=1
daedalus.localnode# sysctl net.inet6.ip6.forwarding=1
daedalus.localnode# rcctl enable dhcpd vmd
daedalus.localnode# rcctl set dhcpd flags vether0
daedalus.localnode# rcctl start dhcpd vmd
daedalus.localnode# pfctl -e /etc/pf.conf

installing alpine

Should be easy enough. If you're having trouble your pf.conf is probably borked. Remember that pf matches packets sequentially (from top to bottom) and the last matching rule is selected. You can remedy this by moving more specific rules to the bottom of the file or by using the quick keyword to indicate that pf should stop here and use this rule as the logical "final matching rule".

x220# vmctl start -c alpine
Connected to /dev/ttyp5 (speed 115200)

Boot failed: not a bootable disk

ISOLINUX 6.04 6.04-pre1 ETCD Copyright (C) 1994-2015 H. Peter Anvin et al

Welcome to Alpine Linux 3.18
Kernel 6.1.27-2-lts on an x86_64 (/dev/ttyS0)

localhost login: root
Welcome to Alpine!

The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <>.

You can setup the system with the command: setup-alpine

You may change this message by editing /etc/motd.

localhost:~# setup-alpine

The rest of the alpine setup is documented in the Alpine user handbook and is about as easy as installing OpenBSD. When finished, the system should be stopped using the poweroff command.

The serial connection will hang and the system will (slowly) halt. The .iso line should now be commented out in /etc/vm.conf and the vmd service should be restarted. You can now restart alpine and proceed to install the things you need. I will do this over ssh because it's better than serial. This also enables me to test the guest's ssh config before I spend 3-4 hours trying to figure out why X forwarding doesn't work just to find out that it's something I overlooked. Keep in mind that default openssh server configurations typically disable x11 forwarding by default so this will also need to be modified.

Using VNC to access graphical programs running on the guest is also possible but this would require making the guest significantly larger than it needs to be.

To make this kluge work, xorg and flatpak must be installed. Note that you will need to enable edge/main and edge/community repos to install flatpak.

alpine:~$ su 
alpine:~# setup-xorg-base
alpine:~# apk add flatpak
alpine:~# flatpak remote-add --if-not-exists flathub
alpine:~# flatpak install flathub org.signal.Signal
alpine:~# exit
alpine:~$ dbus-run-session flatpak run org.signal.Signal

And now signal should run.

Signal on OpenBSD, running in a vm via x11 forwarding over ssh

I hate dbus so much it's unreal.