You may want to inform yourself about human rights in China.

On OpenBSD Automatic Installation an OVH's VPS

date: 2022-02-11
update: 2022-08-24

Update: I’ve just learnt that OVH provides a rescue mode for its VPSs, from which we can boot a qemu(1) instance, configured to use the VPS’s disk as a drive. From there, we should be able to leverage qemu(1) abilities (for instance, its tftp server) to avoid tweaking the bsd.rd through an existing OpenBSD instance, which definitely is the sore point of the procedure below. Unfortunately, it seems rebooting the VPS in rescue mode can’t be performed from the API (yet?).

OVH does not provide a default OpenBSD image for its VPSs, nor, AFAIK, does it provide the ability to use one own image (e.g. qcow2) for VPSs, while the feature is available for other services.

However, OVH does provide an API allowing to automatize default images (re)installation, including setting up SSH’s authorized keys. Besides, OpenBSD can be manually installed on such VPSs; autoinstall(8) provides a way to automate the installation process.


OpenBSD 6.9’s release artwork

OpenBSD 6.9’s release artwork by Joy Sanlikely, available for fair use

Installation process

The installation process to automatize is as such:

  1. start on a fresh “bootstrapping” OS, one of the default system images provided by OVH, say, a Debian;
  2. from the Debian, download a bsd.rd;
  3. setup Debian’s GRUB to allow booting on that bsd.rd
  4. reboot;
  5. boot on the bsd.rd, and follow OpenBSD’s FAQ regarding the installation process, and/or the handbook’s take.

The (re)installation of the bootstrapping OS (Debian) can be performed through OVH’s API.

OpenBSD’s installation can be automated through autoinstall(8). Rather than using an external server that the installation process could contact to get answers to the installer’s question, we’ll tweak the default bsd.rd to include a /auto_install.conf file, which can be daunting from Linux, as the bsd.rd filesystem is a UFS (Unix File System, not Universal Flash Storage) one, for which Linux has writing issues.

There may be better ways to achieve the same results, but I haven’t reached them yet. Feel free to help me clean this clumsy solution.

Automatic Debian setup via OVH’s API

Note: This used to be performed with a Python script, using the official Python wrapper, which was partially dissected here.

Instead, there’s now a dedicated article exploring how to reach a similar goal with a more polished version of the previous script, written in Go. As such, there’s little need to expand much further here: what matters is that those tools provide a command to automatically reset a VPS to use the latest Debian image available, while setting up automatically a SSH key.

% ovh-do rebuild-debian vps-78c9bb08.vps.ovh.net
2022/08/25 00:55:16 Installing Debian 11 (62129106-e97f-4ad2-b356-e9854f86a990) to vps-00ac1791.vps.ovh.net
44%
44%
44%
66%
2022/08/25 01:11:06 Warning: ssh-keyscan '2001:4:701:::5555' failed:
2022/08/25 01:11:06 connect (`2001:4:701:::5555'): Network is unreachable
2022/08/25 01:11:06 connect (`2001:4:701:::5555'): Network is unreachable
2022/08/25 01:11:06 connect (`2001:4:701:::5555'): Network is unreachable
2022/08/25 01:11:06 connect (`2001:4:701:::5555'): Network is unreachable
2022/08/25 01:11:06 connect (`2001:4:701:::5555'): Network is unreachable
$ ssh -p 22 debian@10.10.4.1 echo hello, world
hello, world
Quartz with enclosed rutile

Quartz with enclosed rutile by Rob Lavinsky through mindat.org wikimedia.orgCC-BY-SA-3.0

Tweaking bsd.rd, autoinstall

Introduction

OpenBSD’s autoinstall(8) works by either contacting a remote server or looking for a special embedded file for answers to the installer’s question.

One can refer to various existing guides regarding OpenBSD’s automatic installation:

We’ll here rely on the special file, that we need to store within the bsd.rd. The tricky part being, how to edit that ramdisk from a Linux system.

rdsetroot.c

The OpenBSD ramdisk contains a UFS disk. Such disks can be mounted from Linux, but writing to them is disabled by default, as the drivers simply aren’t stable.

The brave ones can use rdsetroot(8) and quickly patch the source to get it working on Linux:

--- rdsetroot.c 2022-02-11 01:04:29.294112626 +0100
+++ $HOME/rdsetroot.c     2022-02-11 01:05:02.650557548 +0100
@@ -29,6 +29,15 @@
 #include <string.h>
 #include <unistd.h>

+/*
+ * NOTE: Original from:
+ *     https://raw.githubusercontent.com/openbsd/src/master/usr.sbin/rdsetroot/rdsetroot.c
+ */
+#define ELF_SYMTAB      ".symtab"       /* symbol table */
+#define ELF_STRTAB      ".strtab"       /* string table */
+#define __dead
+#define pledge(x,y) (1)
+
 int find_rd_root_image(uint64_t *, uint64_t *, off_t *, size_t *);
 int symbol_get_u64(const char *, uint64_t *);
 __dead void usage(void);

Needs to be linked with libelf:

cc -W -o rdsetroot rdsetroot.c -lelf

Actually editing the bsd.rd with it is left as an exercise to the reader.

Tweaked bsd.rd, install.conf

A more “stable” solution would be to rely an on existing, reachable OpenBSD installation. This could either be a local QEMU instance, or a remote one. The script mkbsdrd allows to work with one available via ssh(1), and will then work as a stripped down version of upobsd.

Note: mkbsrd has only been tested for amd64; upobsd clearly does some work to get wider support, and still is cautious about supporting every architecture.

mkbsdrd proceeds as such:

  1. Download (locally) a bsd.rd as specified by CLI arguments or “configuration”;
  2. Push it, gzipped, to the remote OpenBSD instance, alongside an install.conf file, specified via CLI argument, to the format described by autoinstall(8);
  3. Remotely, execute an ad-hoc script that:
    1. Extract the UFS filesystem from the ramdisk via rdsetroot(8);
    2. Use the vnode disk driver (vnd0, see vnd(4) and vnconfig(8)) to mount that filesystem for edition;
    3. mount(8) the filesystem;
    4. Push the install.conf file to that filesystem’s /auto_install.conf
    5. Clean things up; recreate the tweaked ramdisk and transfer it back to the local computer

The install.conf file will look like:

System hostname = hostname
Password for root = secret
Network interfaces = vio0
Allow root ssh login = yes
IPv4 address for vio0 = dhcp
Public ssh key for root = ssh-ed25519 ... user@computer
Which disk is the root disk = sd0
What timezone are you in = Europe/Paris
Unable to connect using https. Use http instead = no
Location of sets = http
Server = ftp.spline.de
Set name(s) = -all bsd* base* comp* man*
Quartz with enclosed rutile

Quartz with enclosed rutile by Simon A. Eugster through wikimedia.orgCC-BY-SA-3.0

Automatic OpenBSD installation

Note: ovh-do get-console can be used to retrieve the URL to the KVM HTTP console; it relies on the POST /vps/<vps-id>/getConsoleUrl access. It might be a good idea to have it opened.

Note: You can hardly brick the installation: in case of trouble, you can always start again from a fresh Debian with ovh-do rebuild-debian.

Assuming:

We can now use install-openbsd-to to actually launch the OpenBSD installation. The script assumes the default Debian to come with a GRUB2. It:

From there, you should be able to see the installation process unrolling itself automatically from the KVM console.

Jade, an ornamental stone. White and green.

Jade, an ornamental stone. White and green. by Simon A. Eugster through wikimedia.orgCC-BY-SA-3.0

Finally, the script ovh-install-openbsd wraps the three previous scripts:

And perform an automatic installation from a single configuration file/CLI arguments set.

# Launch an OpenBSD installation on vps-ab8971d9.vps.ovh.net, using
# gw as an existing OpenBSD remote to create the bsd.rd
$ ovh-install-openbsd vps-ab8971d9.vps.ovh.net -r gw -i ../../install.conf
ovh-install-openbsd                     : Current KVM console link...
https://compute.gra8.cloud.ovh.net:6080/vnc_lite.html?path=somewhere
ovh-install-openbsd                     : Resetting to a stock debian...
Installing Debian 11 (19f226bb-79f1-4293-b260-3faf93c5a5a5) on vps-ab8971d9.vps.ovh.net key: ovh-do-key
progress: 11
...
progress: 66
ovh-install-openbsd                     : Resetting known_hosts entries for 127.0.0.1...
ovh-install-openbsd                     : Current KVM console link...
https://compute.gra8.cloud.ovh.net:6080/vnc_lite.html?path=somewhere
ovh-install-openbsd                     : Building a bsd.rd...
ovh-install-openbsd                     : Installing OpenBSD with /tmp/bsd.rd.413323...
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.10.0-10-cloud-amd64
Found initrd image: /boot/initrd.img-5.10.0-10-cloud-amd64
done
Connection to 127.0.0.1 closed by remote host.
ovh-install-openbsd                     : Pooling for root@127.0.0.1 ssh link...
ovh-install-openbsd                     : Retrying...
...
ovh-install-openbsd                     : Retrying...
Connection to 127.0.0.1 22 port [tcp/ssh] succeeded!
ovh-install-openbsd                     : Resetting known_hosts entries for 127.0.0.1...
hello, world
OpenBSD main.openstacklocal 7.0 GENERIC.MP#232 amd64
OVH KVM console opened on a running OpenBSD automatic installation

OVH KVM console opened on a running OpenBSD automatic installation


Comments

By email, at mathieu.bivert chez:

email