OpenRiot v6.4 — Installer Image
“Install OpenRiot in five minutes, offline, with no internet required.”
Release Overview
OpenRiot v6.4 ships a fully automated OpenBSD installer image builder. Run
make img on any OpenBSD 7.9 machine, flash the resulting .img to USB, and
boot. The installer handles disk selection, partitioning, base install,
offline package installation, doas.conf, and user setup — with only
hostname, passwords, and disk layout requiring input.
No network required during installation. No manual pkg_add. No setup.sh
run from the live system. Everything is baked into the image.
Total changes: image builder, offline packages, installer compliance,
doas automation, games excluded.
💾 Bootable Installer Image (make img)
The Problem: Installing OpenRiot required booting standard OpenBSD,
running a curl pipe to setup.sh, then manually installing dozens of
packages with pkg_add. This took 30+ minutes, required internet, and
assumed the user knew OpenBSD partitioning.
The Fix: make img builds a self-contained USB installer.
Workflow
doas make img # Build install/openriot.img (+ .sha256)
dd if=Build/Images/openriot.img of=/dev/rsdX bs=1m
The image is a standard OpenBSD install79.img expanded to hold ~1–1.5GB of packages, configs, and the OpenRiot repo. It shrinks to minimum size + 10% buffer after content injection. Final output is under 2GB.
What the User Sees
| Prompt | Default | Input Required |
|---|---|---|
| Disk selection | none | Choose SSD/HDD |
| Partition layout | Edit | Customize or accept |
| Hostname | none | Type name |
| Root password | none | Set password |
| User account | none | Create username |
| User password | none | Set password |
| Timezone | US/Pacific | Hit Enter or change |
Everything else — sets, packages, config, repo — happens automatically.
📦 Offline Package Installation
The Problem: Previous attempts at make img never actually installed
packages. install.site was packed inside the tarball (invisible to the
installer), used broken pkg_add syntax (stripped base names instead of
full .tgz paths), and tried to tar xzf a file on the install media
instead of the target filesystem.
The Fix:
site79.tgzis extracted by the OpenBSD installer as a standard set (replaces non-compliantopenriot.tgznaming)- Packages ship inside
site79.tgzat/openriot/packages/snapshots/amd64/ install.siteruns post-install and callspkg_addwith full.tgzpaths:pkg_add "$PKG_PATH_LOCAL"/*.tgzinstall.siteandinstall.confare copied to the install media root (not inside the tarball), so the OpenBSD installer discovers them
All packages from packages.yaml are installed offline. No pkg_add -i
over the network. No dependency resolution failures.
🛡️ doas and Wheel Configuration
The Problem: The installer creates a user account, but OpenBSD does not
automatically add it to the wheel group. Without wheel, doas.conf’s
permit nopass :wheel grants nothing. The user would need to su - and
usermod manually on first boot.
The Fix: install.site now explicitly adds every user in /home/* to
the wheel group:
usermod -G wheel "$username"
/etc/doas.conf is written with permit nopass :wheel and mode 0440.
The first login has working doas with no manual steps.
🚫 Games Excluded from Image
The Problem: Desktop games (gottet, wesnoth, openttd, cataclysm-dda,
etc.) total over 2GB. Including them would push the installer image past the
2GB practical limit for USB flashing and vnconfig/growfs workflows.
The Fix: Build/exceptions.yaml now supports module-level exclusion:
modules:
- desktop.games
DownloadPackages() skips the entire desktop.games module during image
builds. Games install normally via setup.sh on live systems.
🐛 Bug Fixes
Empty Image File Accepted
CheckPrereqs accepted 0-byte files as valid base images. A failed prior
wget left an empty install79.img, which was then truncated to 2GB of
zeros. growfs failed with “superblock not recognized.”
CheckPrereqsnow rejects files withSize() == 0downloadBaseImage()cleans up empty files on wget failure- Downloaded images are verified non-empty before continuing
Disklabel Geometry Faked
writeDisklabel() generated a hardcoded partition table with fabricated
DUID, cylinder counts, and geometry. This rarely matched the actual base
image, causing silent filesystem corruption or boot failures.
writeDisklabel()now reads the existing label viadisklabel vnd0- Only the
a:partition size is modified — DUID, geometry, and other partitions (c:,i:) are preserved exactly
📦 Package Changes
- Image-excluded:
desktop.gamesmodule (14 packages, >2GB) - Image-excluded:
go(Build/exception.yamlexclude:) - Added:
bitcoin-30.2p0remains in image (from v6.3)
🧾 Files Changed
| File | Nature of Change |
|---|---|
source/imaging/prereqs.go |
Auto-download base image, zero-file guard |
source/imaging/download.go |
Module exceptions.yaml, newline on warn fix |
source/imaging/site.go |
site79.tgz, pkg_add, usermod wheel fix |
source/imaging/build.go |
Media root inject, real disklabel update |
source/config/loader.go |
GetPackagesExcluding() module + package filter |
Build/exceptions.yaml |
modules: section, desktop.games excluded |
docs/v6.4-Release-Notes.md |
This file |
🗣️ Final Words
“v6.0 was beauty. v6.1 was correctness. v6.2 was readability. v6.3 was choice. v6.4 is independence.”
This release eliminates the single biggest barrier to OpenRiot adoption:
installing it. No more 30-minute pkg_add marathons over hotel WiFi. No
more partitioning anxiety. Burn the image, boot, answer five prompts, and
you have a fully configured OpenRiot workstation with doas, fish, i3,
Firefox, Bitcoin, Monero, and every tool we ship.
The installer fits on a 2GB USB stick. It works on a ThinkPad in a cabin with no cell service. That is the point.
— The OpenRiot Crew
“Privacy requires control. Control requires booting your own OS. Now you can, anywhere, no internet required.”