Resflash is a tool for building scriptable 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, SSD, or spinning hard drive) and make great boot drives for firewalls, NAS, or VM servers, including this web server! Resflash was written from scratch, with inspiration drawn from NanoBSD and flashrd.
*
, /etc/ssh/
, /var/db/dhcp*
).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 and /efi partitions are used to maintain the BIOS and UEFI boot code, respectively.
--syspatch
flag.Create an OpenBSD base directory with a minimum of the following:
bsd
(sp or mp supported)baseXY.tgz
(base dir)/var/sysmerge/etc.tgz
Sets must be unpacked as root using tar zxfph set.tgz
.
Run build_resflash.sh:
usage: build_resflash.sh [-huV] [-p pkg_dir] [--pkg_list pkg1,pkg2]
[--pkg_path path1:path2] [-s com0_speed]
[--swap reserve_swap_in_mb] [--syspatch]
img_size_in_mb openbsd_base_dir
Write the .img file (not the .fs file) to the drive: dd if=resflash-amd64-1906MB-com0_115200-YYYYMMDD_HHMM.img of=/dev/rsd3c bs=1m
Sample usage with --pkg_list pkg1,pkg2
:
# ./resflash/build_resflash.sh --pkg_list xxhash-- -s 115200 1906 /usr/rdest
resflash 7.6.0
Validating OpenBSD base dir: /usr/rdest
Creating disk image: resflash-amd64-1906MB-com0_115200-20240930_1553.img
Creating filesystem: resflash-amd64-1906MB-com0_115200-20240930_1553.fs
Populating filesystem and configuring fstab
Running fw_update (16s)
Installing packages: https://cdn.openbsd.org/%m/ (2s)
Populating filesystem complete (30s)
Calculating filesystem checksum (6s)
Writing filesystem to disk image (11s)
Build complete! (49s)
File sizes:
884M resflash-amd64-1906MB-com0_115200-20240930_1553.fs
1.9G resflash-amd64-1906MB-com0_115200-20240930_1553.img
Disk usage:
537M resflash-amd64-1906MB-com0_115200-20240930_1553.fs
886M resflash-amd64-1906MB-com0_115200-20240930_1553.img
Sample usage with --syspatch
:
# ./resflash/build_resflash.sh -u -s 115200 --syspatch 3336 /usr/rdest
resflash 7.6.0
Validating OpenBSD base dir: /usr/rdest
Creating disk image: resflash-amd64-3336MB-com0_115200-20240930_1553.img
Creating filesystem: resflash-amd64-3336MB-com0_115200-20240930_1553.fs
Populating filesystem and configuring fstab
Running fw_update: amd intel (4s)
Relinking kernel and running syspatch (26s)
Populating filesystem complete (47s)
Calculating filesystem checksum (15s)
Writing filesystem to disk image (21s)
Build complete! (87s)
File sizes:
1.6G resflash-amd64-3336MB-com0_115200-20240930_1553.fs
3.3G resflash-amd64-3336MB-com0_115200-20240930_1553.img
Disk usage:
1.4G resflash-amd64-3336MB-com0_115200-20240930_1553.fs
1.6G resflash-amd64-3336MB-com0_115200-20240930_1553.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 user@build_IP 'gzip -1c resflash/resflash-amd64-1906MB-com0_115200-YYYYMMDD_HHMM.fs'|gzip -d|/resflash/upgrade.sh
ssh -C user@upgrade_IP 'doas /resflash/upgrade.sh' < resflash-amd64-1906MB-com0_115200-YYYYMMDD_HHMM.fs
nc -lv 1234|gzip -d|/resflash/upgrade.sh
gzip -1c resflash-amd64-1906MB-com0_115200-YYYYMMDD_HHMM.fs|nc -Nv upgrade_IP 1234
Sample output:
Writing filesystem to inactive partition
af3201651512fae9ab68f3ebec00e3581936a3c3a18b200af5a67000df3397d4
Writing filesystem complete (10s)
Checking filesystem
/dev/sd0e (b5010779e6344cfc.e): 10962 files, 239249 used, 197038 free (806 frags,
24529 blocks, 0.2% fragmentation)
Overlaying data from /cfg/upgrade_overlay to filesystem
Updating fstab
Updating MBR
Updating BOOTX64.EFI BOOTIA32.EFI bootloader(s)
Everything looks good, setting the new partition active
Upgrade complete! (13s)
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 destination drive. The .fs files are filesystems that are used for in-place upgrades by /resflash/upgrade.sh
.
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/etc
or /cfg/var
, retaining the directory structure (i.e. /cfg/etc/hostname.em0
or /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. /root/.ssh/authorized_keys
).
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.sh
image 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 myname
or hostname.em0
in /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.