The flavor and the branding hooks#
Three files decide what a Wheelhouse image is as distinct from a VyOS image: a flavor
file that vyos-build reads, and two live-build hooks that run inside the build. The
flavor sets the default configuration the image boots with and takes ownership of
/etc/os-release. The chroot hook fixes identity and licence files that no flavor key can
reach. The binary hook brands both boot menus. All three are written to fail the build
rather than produce an image that still says VyOS, because a boot menu with the wrong name
on it is a trademark problem as well as a branding one.
Where these files live at build time#
packaging/iso/build-iso.sh copies them into the
vyos-build checkout:
| Source | Destination in vyos-build |
|---|---|
packaging/iso/wheelhouse.toml | data/build-flavors/wheelhouse.toml, with @VERSION@ and @VYOS_BASE@ substituted |
packaging/iso/branding/50-wheelhouse-brand.chroot | data/live-build-config/hooks/live/ |
packaging/iso/branding/50-wheelhouse-brand.binary | data/live-build-config/hooks/live/ |
packaging/iso/branding/doc/*.txt | data/live-build-config/includes.chroot/usr/share/doc/wheelhouse/ |
packaging/iso/branding/splash.png | over both of upstream's copies |
build-vyos-image copies data/live-build-config/ wholesale into the live-build
configuration directory, which is how the hooks arrive where live-build will run them.
The flavor#
packaging/iso/wheelhouse.toml declares three
things.
image_format = "iso"#
default_config#
The configuration the image boots with when /config/config.boot does not exist yet — a
live boot, and the first boot after an install. build-vyos-image writes it to
config.boot.default, replacing the one vyos-1x ships. It is upstream's own default
with four changes, kept otherwise verbatim so the syntax stays upstream's:
| Change | Why |
|---|---|
host-name wheelhouse | The live login prompt, the banner header, the DHCP client identity the upstream router logs, and the common name of the self-signed certificate the agent generates on first boot |
NTP from pool.ntp.org, not VyOS' servers | A router we sold should not ask the VyOS project for the time forever, and the customer should not see time1.vyos.net on the System page |
system login banner set | Without banner post-login, vyos-1x renders its own template into /etc/motd, which opens "Welcome to VyOS", draws the VyOS logo and points at VyOS' support portal — on the console and, through pam_motd, over SSH. Setting the node replaces the template wholesale. The upstream credit stays, one line, at the bottom |
system option kernel quiet | How the boot of an installed box stops being a screen of the base's systemd unit descriptions. The live boot is handled separately, on the kernel command line, because the bootloader rather than this file decides that one |
The body also carries commit-revisions 100, which is where the archived-revision count a
rollback works against comes from.
[[includes_chroot]] for /etc/os-release#
PRETTY_NAME="Wheelhouse OS @VERSION@"
NAME="Wheelhouse"
ID=wheelhouse
ID_LIKE="vyos debian"
VERSION="@VERSION@"
VERSION_ID="@VERSION@"
VYOS_VERSION="@VYOS_BASE@"This is owned in the flavor and nowhere else, and the reason is mechanical:
build-vyos-image writes a hardcoded VyOS os-release into
config/includes.chroot/etc/os-release, and the [[includes_chroot]] loop runs later
in the same function and overwrites it. Nothing else competes for that path — the only
other [[includes_chroot]] entries in upstream's data/ are the EULA in the two build
types. Setting the flavor's website_url or support_url keys would not work: those
are read from the build defaults rather than from the merged build configuration.
ID_LIKE and VYOS_VERSION stay so that support tooling, monitoring and Ansible facts
can still see what the base is. The fuller credit is in /usr/share/doc/wheelhouse.
HOME_URL, DOCUMENTATION_URL and SUPPORT_URL name hosts that resolve; BUG_REPORT_URL
is deliberately absent, because there is no public issue tracker and an os-release key
is optional, so leaving it out is the honest answer.
The chroot hook#
50-wheelhouse-brand.chroot
runs from live-build's lb chroot_hooks, which is after
lb chroot_includes_after_packages — so everything the flavor and build-iso.sh staged
under includes.chroot is already in place. It does four things, and asserts after each.
1. The licence documents are present, and complete#
for f in TERMS.txt THIRD-PARTY.txt SOURCE-OFFER.txt SOURCES.txt; do
[ -f "${DOC}/${f}" ] || fail "${DOC}/${f} is missing — build-iso.sh did not stage it"
…
if grep -qF '<TODO' "${DOC}/${f}"; then … fail "still has an unfilled placeholder"; fi
donebuild-iso.sh checks the source copies; this checks what actually landed on the image.
These files are the licence and source-code answer a customer gets, so an unfilled
placeholder in one is a compliance defect rather than a typo.
The hook also refuses a SOURCE-OFFER.txt that reads like a GPLv2 §3(b) written offer —
"write to:", "by post", "three years". The corresponding source is published, which is
§3(a); a written offer would need a real postal address standing behind it for three
years, and there is none.
2. /usr/share/vyos/EULA points at the Wheelhouse terms#
--build-type release makes vyos-build add an [[includes_chroot]] entry whose body is
VyOS Inc.'s commercial end-user licence agreement, installed at /usr/share/vyos/EULA.
The flavor cannot outrank it: list values are concatenated as source plus defaults, the
flavor is merged last so its entries land first in the list, and the include loop lets
the last entry for a path win. Changing the build type does not help, because the
development build type carries the same file. The only way to displace it is to get in
after the includes are written, which is what this hook is.
So the hook replaces the file with a symlink to ../doc/wheelhouse/TERMS.txt — replaces
rather than deletes, because vyos-1x's show license pages that exact path and would
otherwise break. It then checks the link resolves and that the target reads like the
Wheelhouse terms.
Nothing in the GPL requires shipping another company's commercial EULA, and removing it
strips no required notice: every notice is still on the image under /usr/share/doc.
3. /etc/os-release is ours#
grep -q '^ID=wheelhouse$' /etc/os-release \
|| fail "/etc/os-release was not overridden by the flavor (see wheelhouse.toml)"This is the safety net for the flavor's own override. If upstream ever moves the write or
adds a competing entry, the image would otherwise report itself as VyOS to hostnamectl,
monitoring agents and Ansible facts. The build fails instead.
The hook then copies /etc/os-release over /usr/lib/os-release through a temporary
file, because Debian's /etc/os-release is normally a symlink to the /usr/lib copy and
the include may have replaced the symlink with a regular file, leaving the other copy
saying VyOS. The round trip is needed because copying a file onto itself would fail under
set -e.
4. VyOS' Secure Boot certificate is removed#
build-vyos-image copies the whole of data/certificates into
/var/lib/shim-signed/mok, which would put a VyOS trust anchor on every machine sold
behind no signing story of our own. It is a public certificate rather than a key, and it
is not enrolled in firmware, so this is hygiene rather than a hole — but it is a leftover,
not a required notice. The files are removed and the directory kept, because a later
upstream hook lists it.
The binary hook#
50-wheelhouse-brand.binary
runs from lb binary_hooks with the binary tree as the working directory. That is the
only stage late enough to reach everything, because live-build generates two of the
three files:
| File | Written by | Carries |
|---|---|---|
boot/grub/grub.cfg | live-build's binary_grub_cfg | Live system (vyos) |
isolinux/live.cfg | live-build's binary_syslinux | The same string |
isolinux/menu.cfg | build-vyos-image, arriving through binary_includes | VyOS <version> (<flavor>) |
A flavor [[includes_binary]] entry could fix the third alone; it cannot reach the two
live-build generates. Hence a hook.
The 50- prefix is load-bearing. Hooks run in glob order, and upstream's
01-live-serial.binary rewrites the same lines first, appending " - KVM console" and
" - Serial console" with regular expressions that still expect the upstream text. Running
after it and replacing the bare substring is what lets those suffixes survive.
The replacements:
| Upstream | Wheelhouse |
|---|---|
Live system (vyos) | Install or run Wheelhouse |
Live system (vyos fail-safe mode) | Install or run Wheelhouse (fail-safe, verbose boot) |
menu title … | Wheelhouse <version>, read out of version.json |
Every substitution is checked, and there is a final sweep:
if grep -E '^[[:space:]]*(menu label|menuentry)' "${f}" | grep -qi vyos; then
fail "a menu entry in ${f} still mentions VyOS"
fiThe internal syslinux labels (label live-vyos, live-vyos-serial) are not drawn on
screen and are left alone, which is why the sweep looks only at the lines that are.
"verbose boot" is in the fail-safe label on purpose. build-iso.sh patches quiet into
the normal live boot's kernel command line, so the fail-safe entry — which boots from
upstream's --bootappend-live-failsafe, a line with no quiet on it — is the one that
shows the messages. build-iso.sh fails the build if upstream ever adds quiet there and
makes this label untrue.
A missing version in version.json is a warning rather than a failure — a menu headed
just "Wheelhouse" is still ours.
Why the hooks assert at all#
Every one of these checks exists because a silent no-op would ship an image that says VyOS. The pattern is the same throughout the image pipeline: patch the file, then verify the patch took; stage the file, then verify it is there; override the identity, then assert the override won. An upstream change should break the build loudly, on the machine that can still do something about it.
See also#
- Building the image — the script that stages all of this and runs the build.
- Making a release — what happens to the finished ISO.
- Working agreements — the licence hygiene rule behind these files.
- Built on VyOS · Trademarks · Third-party licences — the position these hooks implement, stated for a customer.
- What first boot does · The console banner — what happens after the image the flavor described has booted.
- Boot it — the boot menu these hooks brand, from the other side of the screen.
Checked against#
packaging/iso/wheelhouse.toml ·
packaging/iso/build-iso.sh ·
packaging/iso/branding/50-wheelhouse-brand.chroot ·
packaging/iso/branding/50-wheelhouse-brand.binary ·
packaging/iso/branding/make-splash.py ·
packaging/iso/branding/doc/TERMS.txt ·
packaging/iso/branding/doc/THIRD-PARTY.txt ·
packaging/firstboot.sh