The console banner#
/etc/issue is what agetty prints above the login prompt, and on a Wheelhouse box it
is rewritten at boot and every 20 seconds afterwards with the one thing somebody
standing at the console needs: the URL of the web UI, on every address the router has.
It is the ESXi-and-OPNsense-style summary screen, and it is also how a brand new router
tells you its first-boot password.
Wheelhouse 0.5.1 -- edge [live image, not installed]
==========================================================================
Web UI: https://192.0.2.1:8443 (eth1)
https://[2001:db8::1]:8443 (eth1)
Sign in: admin / 3f9c1a72b8e4
first-boot password; you will be asked to change it
Console: vyos / vyos on the live image; the installer sets yours
Install: on the first console; elsewhere run: sudo wheelhouse-install
--------------------------------------------------------------------------
Built on VyOS 1.5-rolling-202608220006
Licences and source offer: /usr/share/doc/wheelhouse
==========================================================================Every line fits an 80-column console. A wrapped banner reads as broken.
Line by line#
| Line | Value | Source |
|---|---|---|
Wheelhouse <version> -- <host> | The package version and the host name. [live image, not installed] is appended on a live boot. | dpkg-query -W -f='${Version}' wheelhouse-agent; /proc/sys/kernel/hostname |
Web UI: | https://<address>:<port> for every globally-scoped address, IPv4 first, with the interface in brackets after it. IPv6 literals are bracketed so the port does not read as another hextet. | ip -4/ip -6 -o addr show scope global; the port is parsed out of --addr in the unit file, defaulting to 8443 |
At most five addresses, then and N more address(es). A router with a dozen VLANs would otherwise push the login prompt off a 25-line console. | ||
waiting for an address on any interface when there are none. | ||
Agent: | Printed only when the agent is not active, with the command to look at: journalctl -u wheelhouse-agent. | systemctl is-active wheelhouse-agent |
Sign in: | admin / <password> plus a second line saying it is the first-boot password — only while /config/wheelhouse/initial-password exists. Otherwise with your Wheelhouse admin account. | the agent writes that file at bootstrap and removes it when the password is changed |
Console: | On a live image, vyos / vyos on the live image; the installer sets yours; on an installed system, vyos, with the password chosen at install. | the live check below |
Install: | Live images only: on the first console; elsewhere run: sudo wheelhouse-install. | |
Built on VyOS <version> | The base version, as a footnote under a rule rather than as a headline. | /opt/vyatta/etc/version |
Licences and source offer: | /usr/share/doc/wheelhouse on an image, /usr/share/doc/wheelhouse-agent when only the package is installed. | whichever directory exists |
Live or installed#
boot=live is on an installed system's kernel command line too, so it cannot be the
test. The live image is the one with a mounted medium, which is what the base
platform's own check looks at:
[ -e /usr/lib/live/mount/medium/live/filesystem.squashfs ] ||
python3 -c 'from vyos.system import image; raise SystemExit(0 if image.is_live_boot() else 1)'The cache#
Three of the values cannot change within a boot except through a package upgrade — the
agent version, the base version, and the live-or-installed answer — and resolving them
costs a dpkg-query plus a Python interpreter that imports the platform's own module.
Paying that three times a minute on a small box is not reasonable, so they are cached in
/run/wheelhouse/banner-facts, keyed on the mtime of /var/lib/dpkg/status so an
in-place upgrade invalidates it. /run is a tmpfs, so the cache dies with the boot.
When it is redrawn#
wheelhouse-console.service writes it at boot, ordered before the getty units by name.
wheelhouse-console.timer runs the same script every 20 seconds
(OnBootSec=0, OnUnitActiveSec=20s, AccuracySec=5s).
The script only writes the file when the text has actually changed, and only then does it consider restarting anything.
Why the getty restarts#
agetty reads /etc/issue once, when it opens the terminal. A banner written afterwards
is invisible until somebody presses enter. So when the text changes, the script restarts
the login prompt on every console where doing so is safe — and the conditions are
deliberately narrow:
- the unit is one of
getty@*.serviceorserial-getty@*.service, and active; - its
MainPIDreally is anagetty(checked through/proc/<pid>/comm), so a console running something else is left alone; - not tty1 while
/run/wheelhouse-install.lockexists — on a live boot tty1's getty unit is the installer, and restarting it threw a person back to the welcome screen the moment their own answers changed the banner; - nobody is logged in on that terminal, per
who.
The permission rule#
mode=644
[ -n "$initpw" ] && mode=600/etc/issue is world-readable by convention, but while it carries the first-boot
password it is a credential. agetty reads it as root, so 0600 costs nothing and keeps
a local account from lifting the password off the file. It returns to 0644 as soon as
the agent removes initial-password.
Turning it off#
The banner is a service and a timer, so:
sudo systemctl disable --now wheelhouse-console.timer
sudo systemctl disable wheelhouse-console.service/etc/issue keeps whatever text was last written. VyOS rewrites it from
system login banner on the next boot configuration load.
See also#
- systemd units — the service, the timer and their ordering.
- What first boot does — the other banner, the one sshd serves.
- Files and directories —
initial-password,/etc/issue,banner-facts. - Ports and listeners — why the URL says 8443.
- First sign-in
- Console access
Checked against#
packaging/console-banner.sh,
packaging/wheelhouse-console.service,
packaging/wheelhouse-console.timer,
packaging/wheelhouse-agent.service,
packaging/wheelhouse-install,
agent/main.go (bootstrapAdmin, clearInitialPassword),
packaging/README.md.