Resflash is a tool for building reproducible OpenBSD images for embedded and cloud platforms with easy, single-file upgrades. Resflash uses read-only and memory-backed filesystems, and because the filesystems are written to only during system upgrades, they are not subject to corruption or fsck due to power loss - and even cheap USB flash drives can last virtually forever. Resflash images can be written to any bootable media (flash or conventional) and make great boot drives for firewalls, NAS, or VM servers. Resflash was written from scratch, with inspiration drawn from NanoBSD and flashrd.
Resflash images contain two main data partitions, one active and one inactive. During the upgrade process, the inactive partition is updated, tested, and set active for the next boot. A /cfg partition can be used to store modifications from the mfs filesystems (/etc and /var) and are overlaid at boot time. Small /mbr, /efi, and /ofw partitions are used to maintain the BIOS, UEFI, and Open Firmware boot code, respectively.
Create an OpenBSD base directory with a minimum of the following:
bsd(sp or mp supported)
Sets must be unpacked as root using
tar zxfph set.tgz.
usage: build_resflash.sh [-ihnV] [-p pkg_dir] [-s com0_speed (com0 console)] [--pkg_list pkg1,pkg2] [--swap reserve_swap_in_mb] img_size_in_mb openbsd_base_dir
Write the .img file (not the .fs file) to the drive:
dd if=resflash-amd64-3814MB-com0_1906MB-20200713_0137.img of=/dev/rsd3c bs=1m
Sample usage with
# ./resflash/build_resflash.sh -s 115200 --pkg_list go-- 3814 /usr/rdest resflash 6.7.3 Validating OpenBSD base dir: /usr/rdest Creating disk image: resflash-amd64-3814MB-com0_1906MB-20200713_0137.img Creating filesystem: resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs Populating filesystem and configuring fstab Running fw_update -a Installing packages: https://cdn.openbsd.org/%m/ Writing filesystem to disk image and calculating checksum Compacting disk image and calculating checksum Build complete! File sizes: 1.8G resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs 3.7G resflash-amd64-3814MB-com0_1906MB-20200713_0137.img Disk usage: 982M resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs 984M resflash-amd64-3814MB-com0_1906MB-20200713_0137.img
Same usage with
# ./resflash/build_resflash.sh -s 115200 -p /usr/rpkg 3814 /usr/rdest resflash 6.7.3 Validating OpenBSD base dir: /usr/rdest Creating disk image: resflash-amd64-3814MB-com0_1906MB-20200713_0137.img Creating filesystem: resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs Populating filesystem and configuring fstab Running fw_update -a Installing packages: /usr/rpkg Writing filesystem to disk image and calculating checksum Compacting disk image and calculating checksum Build complete! File sizes: 1.8G resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs 3.7G resflash-amd64-3814MB-com0_1906MB-20200713_0137.img Disk usage: 982M resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs 984M resflash-amd64-3814MB-com0_1906MB-20200713_0137.img
Unlike the initial installation, upgrades use .fs filesystem files. Upgrades take place by piping the .fs file through the
/resflash/upgrade.sh script. This can be accomplished in many ways:
ssh -C firstname.lastname@example.org 'doas /resflash/upgrade.sh' < resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs
nc -v -l 1234|gzip -d|/resflash/upgrade.sh
gzip -5c resflash-amd64-3814MB-com0_1906MB-20200713_0137.fs|nc -Nv 10.0.x.y 1234
Writing filesystem to inactive partition a113c3fed99b8aeadc006d7d7df8d12652856ae91271006a556678dab44147b1874503b7101824e4 3c977bc35b60528f1d5e8bfa0308cdcca51f58c3fbf4ca00 Checking filesystem /dev/sd0e (a3f53fb2e8e87988.e): 12306 files, 189834 used, 255589 free (61 frags, 31941 blocks, 0.0% fragmentation) Overlaying data from /cfg/upgrade_overlay to filesystem Updating fstab Updating MBR Updating biosboot(8) and boot(8) Updating BOOTX64.EFI BOOTIA32.EFI bootloader(s) Everything looks good, setting the new partition active Upgrade complete!
Note: When upgrading from OpenBSD 6.6 to 6.7, the upgrade script must be updated in place before performing an upgrade:
mount -uw / ftp -o /resflash/upgrade.sh https://gitlab.com/bconway/resflash/-/raw/master/host/upgrade.sh mount -ur /
Attempting to use the existing 6.6 upgrade script without updating first will yield a system that fails to boot with:
Using drive 0, partition 3. Loading......
mount_resflash.sh- Mount all the partitions of a resflash .img or .fs file. This is useful for scripting configuration after a build.
umount_resflash.sh- Unmount a mounted resflash .img or .fs file.
/etc/resflash.conf- Optional configuration file for automating backup of files in /etc or /var on shutdown. Consult the file for available options.
/resflash/save_ssh_ike_soii_keys.sh- Save SSH, IKE, and SOII keys to /cfg.
/resflash/set_root_pass.sh- Update root password and save necessary password db files to /cfg.
/resflash/BUILD- Documents the version, build command, and build date used to create the image. Useful for keeping filesystem sizes consistent.
Resflash is not a supported OpenBSD configuration. Please do not email bugs@ or misc@ asking for help. If you have a question or a bug to report, please post to our mailing list, submit an issue on GitLab, or email me directly.
This project would not be possible without the work of the fine folks at OpenBSD. Please support them with a donation (1, 2) or purchase.
Root passwords are generated dynamically at build time in the form 'resflashYYYYMMDD', where YYYYMMDD corresponds to the date value in the image filename. After logging in, run
/resflash/set_root_pass.sh to set and persist a new root password to /cfg.
The .img files are disk images, including MBR partition tables, that are used for initial installation to a flash drive. The .fs files are filesystems that are used for in-place upgrades by
The /cfg partition is usually unmounted and stores modifications to the /etc and /var mfs filesystems. Files are saved either manually or on shutdown according to
/etc/resflash.conf. To manually save a file, mount /cfg and then copy any file you want re-populated to
/cfg/var, retaining the directory structure (i.e.
/cfg/etc/ssh/sshd_config). Unmount /cfg when finished. You can also run
/resflash/resflash.save manually to save configured files at any time.
Additionally, any directory hierarchy under
/cfg/upgrade_overlay which will be copied over to the new root filesystem upon upgrade. This allows lightweight customization of the root filesystem (i.e.
Resflash requires an LBA-aware BIOS. CHS numbers have been bogus for 25 years, and I don't have the hardware for - or much interest in - supporting them. Make sure to set your Alix board to LBA mode.
build_resflash.shimage size matter if I'm only building .fs files for upgrades?
Yes! Filesystem sizes are calculated from image size, so you will want to keep your image size consistent over the life of an image (see
/resflash/BUILD if you forget). You can scale image size down without issue, but if you attempt to use a filesystem from a larger image for an upgrade, the filesystem will exceed the available space of the inactive partition, and the upgrade will fail.
At the OpenBSD boot prompt, enter
set device hd0d and press enter, assuming that the 'e' partition is your upgraded partition that is failing to boot. If 'd' is failing, set it to hd0e. Before doing any diagnosis on your failed upgrade, you will want to mount /mbr and edit /mbr/etc/boot.conf to point to the working boot device.
There is no wrong answer here. If you're scripting your builds, it probably makes sense to use the (u)mount_resflash.sh tools to make all your changes to the .img or .fs directly, and then use /cfg exclusively for runtime files (i.e.
/var/db/host.random). If you're using resflash for a single system, it's perfectly reasonable to save things like
/cfg/etc. If you need to modify files outside of /etc or /var, such as /root, that is best done via the .img or .fs file.
First, write a .img to the system's USB storage. There are two ways to do this:
ddas in the Usage section above.
tftpbootfrom the U-Boot menu. Choose the shell option from the installer, then run:
ftp -o - http://myserver/resflash-octeon-3814MB-com0_1906MB-20200713_0137.img|dd of=/dev/rsd0c bs=1m
Next, from within the U-Boot menu, run
setenv bootcmd 'usb reset; fatload usb 0 $loadaddr bsd; bootoctlinux $loadaddr coremask=0x3 rootdev=sd0'. You may also wish to run
setenv bootdelay 5. Save the changes and reboot with
Enter Open Firmware by holding
Cmd-Alt-o-f on boot. Set your USB drive as the boot device by running
setenv boot-device ud:,ofwboot. Finally,
reset-all will save the changes and reboot. If your version of Open Firmware is too old to support a
ud alias, you will need to follow the steps listed here (
dev / ls, find the USB entry with a
/disk attached to it, look up that entry in
devalias). You will likely end up with something like
setenv boot-device usb1/disk@1:1,ofwboot.