Ansible, OpenBSD, & upobsd

Thanks to Ansible, upobsd, and OpenBSD's autoinstall(8) feature, automating OpenBSD installs is easier than ever.

This Ansible playbook will download OpenBSD install sets via rsync, install the upobsd package, and then use the elfrdsetroot program to customize the OpenBSD installer with a custom disklabel template in the newly-created bsd.rd, and then make a .ISO file that you can use to perform totally unattended OpenBSD installs.

File layout

Please be aware of the standard Ansible role directory structure. Assuming your Ansible playbooks are in ~/playbooks, the files needed to run this playbook are arranged like this:

~/playbooks
|-- hosts
|-- id_ed25519
|-- roles
|   `-- create-openbsd-iso
|       |-- defaults
|       |   `-- main.yml
|       |-- files
|       |   `-- disklabel.template
|       |-- tasks
|       |   `-- main.yml
|       `-- templates
|           |-- conf65.j2
|           `-- site65.j2
`-- upobsd.yml

Usage

  1. Create the Ansible layout as described above.

  2. Edit hosts with the IP/FQDN of your target OpenBSD host. Edit the values of [openbsd:vars] as needed.

  3. Set up the target host to work with Ansible.

  4. Edit roles/create-openbsd-iso/defaults/main.yml. Depending on your system, you may need to edit arch, network_interface, and python_pkg_version. At a minimum, set valid values for:

  5. Edit roles/create-openbsd-iso/templates/site65.j2. This file will be renamed to install.site and contains post-install, pre-restart steps that autoinstall(8) will run. You can use this script to add users, add software, enable/disable services, or do other administrative actions. The included site65.j2 performs these actions:

  6. Rename roles/create-openbsd-iso/templates/conf65.j2 and site65.j2 as necessary to match your desired version of OpenBSD. For every version of the OS, different files may be needed.

  7. Run ansible-playbook -i hosts upobsd.yml and check the target host for a final .ISO file in iso_path.

  8. Export the ISO. When you want to put OpenBSD onto a VM, attach the ISO and boot from it one time only.

How it works

OpenBSD's autoinstall(8) can read an answer file called install.conf and will use the answers provided in that file to install OpenBSD for you. autoinstall(8) can also configure your disk layout from a template file, but typically both install.conf and your disklabel template files need to be accessible, for example from a local webserver. If your install.conf URL isn't precisely "http://192.168.0.1/install.conf", you need to enter the URL manually at install time.

It would be better if you could (a) fetch the OpenBSD install sets, (b) verify them for correctness with signify(1), and then (c) build your own custom OpenBSD install ISO that includes an install.conf answer file, a disklabel template, and a script to eject the CD when it's done. That's exactly what this playbook does.

Because we are including a custom ramdisk and creating our own siteXX.tgz file, our install.conf answer file needs to acknowledge that those files will not be cryptographically signed, accept that that is OK, and continue. conf65.j2 contains "Checksum test for ______ failed. Continue anyway = yes" lines to allow this.

Editing bsd.rd

Creating a custom installer is easy thanks to upobsd, which is a utility that can create a new bsd.rd for you to run at boot time from your installation media. While the OpenBSD installer script can understand "file:///disklabel.template" as a valid location to find your disklabel template file, bsd.rd assumes /disklabel.template to be the root directory of the ramdisk, not the root of the file contents on the ISO.

Unfortunately, when the ramdisk is used at install time, you either still need a URL to a local webserver to host the disklabel template, or you can alter the upobsd utility to copy a file into the ramdisk for you. upobsd already does this with the install.conf file you give it, but it doesn't have an option to include a disklabel template.

At one point I patched upobsd-v1.1 to include the ability to add a disklabel template file. Easily enough, upobsd is a script that creates a "uo_addfile" function that can put files into the ramdisk, so if it can add an autoinstall answer file, it can add just about anything. This works... but my patched version of upobsd only added support for a disklabel template file. Sometimes, you want to make more customizations to an installer.

My legacy upobsd patch is still available so you can see how it works.

Rather than patching upobsd, you can use the elfrdsetroot binary (part of the upobsd-v1.1 package) directly along with vnconfig(8) to mount the ramdisk and make any changes you want to it.

You can do this by hand if you have a bsd.rd ramdisk available.

The contents of the ramdisk will be editable in ./ramdisk.d. Here you can add your customizations:

To unmount your ramdisk so you can use your new bsd.rd:

These steps are done automatically by tasks/main.yml.

To Do

In the near future, this playbook will be revised to patch upobsd directly on the target host.

Due to OpenBSD 6.7 changing the default file system type, there's more I want to do to the ramdisk. So I've outlined how to mount bsd.rd with elfrdsetroot and make the changes directly.

Notes & Resources

Ansible Week - Bonus - Automating OpenBSD Installs

Automating OpenBSD Installs Even Further

YouTube - LinuxFest Northwest 2020 - "Building Systems That Build Systems"