Wheelhouse docs

The .deb#

wheelhouse-agent_<version>_<arch>.deb is the whole product minus the base: the agent binary, the built web UI, the installer, the seed tooling, the OPNsense importer, four systemd units and the licence files. It is built by packaging/build-deb.py, which is Python standard library only — no dpkg-deb, no build dependencies, no toolchain in CI.

Installing it on a running router reloads the units, starts the console-banner timer and restarts the agent, so an upgrade takes effect without a reboot.

Control fields#

Package: wheelhouse-agent
Version: <version>
Architecture: <arch>
Maintainer: <set by --maintainer>
Installed-Size: <computed>
Depends: bash, python3, dialog, curl
Section: net
Priority: optional
Homepage: https://releases.rhymelikedi.me
Description: Wheelhouse router control plane (agent + web UI)

Four runtime dependencies, and each earns its place:

DependencyNeeded by
bashThe installer, the seed finder, first boot, the console banner, the wait script.
python3seed-to-answers.py, install-driver.py, the OPNsense importer, and the live-boot check inside the installer.
dialogThe interactive installer's whole interface.
curlFetching a seed or a payload over HTTPS.

Installed-Size is computed from the binary plus the UI tree, in kilobytes, with 64 KB of slack. The Maintainer field comes from --maintainer; the default is a string set in the build script — <TODO: owner> for the address that should be published there.

What it installs#

The full path list, with modes, is on Files and directories. In summary:

WhereWhat
/usr/bin/wheelhouse-agent, wheelhouse-install, wheelhouse-autoinstall, wheelhouse-opnsense-import
/usr/lib/wheelhouse/firstboot.sh, wait-for-vyos.sh, console-banner.sh, install-driver.py, seed-to-answers.py
/usr/share/wheelhouse/ui/ and dialogrc
/lib/systemd/system/three services and one timer
/lib/systemd/system-generators/wheelhouse-live-installer
/usr/share/doc/wheelhouse-agent/copyright and README

The package does not run systemctl enable. It ships the symlinks directly:

/etc/systemd/system/multi-user.target.wants/wheelhouse-agent.service
/etc/systemd/system/multi-user.target.wants/wheelhouse-firstboot.service
/etc/systemd/system/multi-user.target.wants/wheelhouse-console.service
/etc/systemd/system/timers.target.wants/wheelhouse-console.timer

That is what lets the same package be installed inside a live-build chroot, where systemctl cannot talk to anything.

postinst and prerm#

sh
# postinst
set -e
if [ "$1" = configure ] && [ -d /run/systemd/system ]; then
    systemctl daemon-reload || true
    systemctl start wheelhouse-console.timer || true
    systemctl try-restart wheelhouse-agent.service || true
fi
exit 0
sh
# prerm
set -e
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
    systemctl stop wheelhouse-agent.service || true
fi
exit 0

Both are guarded on /run/systemd/system and every call is allowed to fail, because inside the image build there is no systemd to talk to. try-restart rather than restart: an agent that was deliberately stopped stays stopped.

README is the file Documentation= on every unit points at. It is the one place on a running box that says what this thing is, what it is built on, and where the corresponding source lives — because the forge is private and a URL is no substitute for a file.

What an upgrade does not do#

Removing the package stops the agent and removes the files it owns. It does not remove /config/wheelhouse, and it does not undo the configuration nodes first boot committed — the API key, the REST switch and the loopback binding stay in the router's configuration.

Building one#

bash
(cd ui && npm ci && npm run build)
(cd agent && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
  go build -trimpath -ldflags="-s -w -X main.version=1.2.3" -o wheelhouse-agent-amd64 .)
packaging/build-deb.py --version 1.2.3 --arch amd64 \
  --binary agent/wheelhouse-agent-amd64 --ui ui/dist --out dist/
OptionDefaultMeaning
--version(required)Goes into the control file and the file name.
--archamd64amd64 or arm64.
--binary(required)The built agent for that architecture.
--ui(required)ui/dist. Refused if it holds no index.html.
--out.Output directory.
--maintainera string in the scriptThe Debian Maintainer field.

SOURCE_DATE_EPOCH sets the timestamp stamped into every archive member, so the same inputs produce the same bytes.

Architectures#

amd64 and arm64 packages are both built. That is not the same as an arm64 product: there is no arm64 image and no VM image of any kind. The arm64 package exists for running the agent off-router against an arm64 router. The supported install is amd64 UEFI.

Inspecting one#

bash
dpkg-deb --info  wheelhouse-agent_0.5.1_amd64.deb
dpkg-deb --contents wheelhouse-agent_0.5.1_amd64.deb
dpkg -L wheelhouse-agent                              # on an installed box

See also#

Checked against#

packaging/build-deb.py, packaging/copyright, packaging/README.md, packaging/wheelhouse-agent.service, docs/hardware.md "Architecture", docs/upgrade.md.

Updated 2026-09-02 packaging deb debian upgrade