Wheelhouse

What is finished, and what is not#

Every product has this list. Most keep it internal. This one is public because a reader who finds a gap here first is a reader who can still make a decision; a reader who finds it after paying is a reader who was misled.

It is the same list README.md keeps in the repository, and the two are changed in the same edit.

Built and exercised#

  • The agent. A Go binary fronting VyOS' HTTP API: staging, native commit-confirm, revision rollback, an attributed audit log, parsed operational state (counters, conntrack, routes, leases, certificates, logs) and a live telemetry WebSocket. It authenticates real accounts (Argon2id, TOTP, sessions with CSRF, three roles, scoped API tokens), speaks OIDC as a relying party, serves Prometheus metrics, terminates TLS and embeds the interface. 214 Go test functions, race-clean.
  • The web UI. A React single-page application: 29 left-navigation entries across eight groups, 38 page components, every editor rendering its commands, one Commit Bar, live state beside configured intent with drift flagged, ⌘K over pages and configuration objects, dark and light.
  • The app store. 38 catalogue entries — 36 containers declared in the configuration tree, plus 2 built-in feature modules that gate native pages. Installed apps get a navigation entry, integration offers on the pages they affect, an update check and a restart.
  • Migration and unattended installs. An importer that turns an OPNsense config.xml into commands plus a report, with --check-against to compare a running router with the configuration it should have; and an installer that finds a seed and installs with nobody at the keyboard.
  • Multi-WAN. Uplinks through every mechanism the platform has, health-checked failover, load balancing, policy routing and per-uplink NAT — proven on a dual-WAN VM built from the ISO.
  • Inline IPS. Suricata in the packet path via NFQUEUE, entirely configuration-tree, so it diffs, commits and rolls back. Fail-open twice over, each layer verified separately on the bench.
  • The image pipeline. CI builds the .deb and the ISO on every tag, inspects nothing in between (see below), and publishes both with a checksum file, a corresponding-source record and an update-channel index.

Every release is driven in a browser against a live router replica before it is tagged.

Every count above is one command away from being re-checked, which is the point of printing them rather than rounding them:

bash
grep -h '^func Test' agent/*_test.go | wc -l     # test functions
grep -c "to: '/" ui/src/components/nav.ts        # left-navigation entries
ls ui/src/pages/*.tsx | wc -l                    # page components
python3 -c "import json;print(len(json.load(open('agent/catalog.json'))['apps']))"

Not shipped at all#

Do not expectWhat is actually true
Packet capture from the interfacePOST /api/capture answers 501 and returns the monitor traffic command to run by hand. The Diagnostics page shows you that command
UPnP or NAT-PMPThere is no answer. The miniupnpd catalogue entry was removed because no credible published image exists, and the Companions page says the gap is open
A one-to-one NAT editorThe nat static table reads rules made elsewhere; the editor is switched off, because committing nat static through this build's HTTP API stops the API process. The CLI accepts the same lines
An OpenVPN instance editorInstances are listed with status and can be disabled or deleted. Creating one waits on a generate pki flow and is not built
An nftables ruleset inspectorFirewall hit counters come from the router's own firewall statistics. A per-object nftables view is not built
Network namespace or VRF panelsNot built
Per-host traffic history, or long-term graphsLive counters and a short server-sampled series only. Flow export exists so a collector can keep the history
Git-backed configuration exportNot built. Revisions, per-revision diffs and a configuration download exist
An OpenAPI documentThere is none. The endpoint table in the operator reference is the contract
A support-bundle commandThere is none. Four manual API calls are the procedure
An in-product update notificationNothing on the router reads the release channel. The channel index exists for a person or a script
A rescue boot entry, or self-service upgrade recoveryNot built. Recovery is a documented order of steps at the console
Ethtool or offload controlsNot built
Per-app dashboard widgetsNot built, deliberately — the health probe is TCP plus an optional HTTP path, never an app-specific API
Starting or stopping a container out of bandThere is no control socket. Stop stages disable, start deletes it, restart is a two-commit bounce
A signed catalogue fetched from an indexThe catalogue is embedded in the binary; a corrected entry needs an agent release

Shipped, but narrower than the name suggests#

  • QoS. The editor stages a CAKE policy with bandwidth, flow-isolation and RTT, attached as egress on one interface. There is no ingress or IFB pipeline, no docsis option, no ack-filter, and no direct tc programming. The page shows the attached policy beside the qdisc the kernel installed.
  • Companions. The page reports the configuration state of the platform's own UPnP, DNS and DHCP services. The agent supervises no external process. dnsmasq is available as a catalogue app, not as an agent-managed daemon.
  • The desired-state file. The schema sketched in the project's plan document is not what shipped. The file mirrors the VyOS configuration tree.
  • WireGuard. Tunnels, peers and configuration are shown. Handshake and transfer counters need wg show exposed by the agent, which it does not do.
  • Conntrack byte counters require nf_conntrack_acct enabled on the router; without it they are absent.
  • Uplink health is the router's verdict — is the failover daemon's route in the forwarding table, and what does the load balancer say — not a Wheelhouse probe. There is no per-target RTT or loss history, and this build has no failover status command.
  • Fleet is a JSON file of routers, concurrent health, and per-router configuration and version reads. Per-router staging and commit are not routed, and fleet writes are not audited.
  • The audit log is attributed and persisted. It cannot leave the box, is not tamper-evident, and root can rewrite it invisibly.
  • Roles are three, enforced per route. Per-object permissions do not exist, and neither does a hardware-key second factor.
  • Two-factor is TOTP only. No recovery codes, and no admin reset of another account's second factor. Losing the device means console access and a hand-edited state file.
  • App images float. All 36 container entries use floating tags. Digest pinning is tooled but not applied.
  • Releases are not signed. The pipeline signs checksums the moment a key exists; no key does. A checksum proves transport, not provenance.
  • IPv6 is configurable and not observable. No v6 route view, the uplink model has no v6 concept, and the Firewall page is v4-first. The installer's firewall checkbox does write an IPv6 ruleset, and says so at the end if the image has no firewall ipv6 node.
  • It runs on amd64 only. The arm64 .deb runs the agent off-router against an arm64 router; there is no arm64 image, and no VM image at all.

Not yet proven, so not claimed#

  • Bare metal. The live image has been booted on physical hardware. A complete install to disk followed by a reboot into the installed system is not recorded there. Every end-to-end verification names a VM.
  • Tested hardware. There is no compatibility list. The image's driver packages can be listed; that is not a compatibility claim.
  • In-place upgrade. An add system image upgrade of a Wheelhouse box is not recorded, on hardware or in a VM.
  • Any performance figure. None measured, on hardware or in CI. The resident-memory and idle-CPU budget is a target.
  • Testing is not uniform. The agent has 214 test functions and CI runs them race-clean. The interface has no tests; CI only typechecks and builds it.

Security gaps worth knowing before you deploy#

  • The agent binds every interface (0.0.0.0:8443), so the firewall is the only thing keeping the management interface off the WAN. There is no listen-address setting short of editing the systemd unit, which an image upgrade replaces.
  • GET /api/oidc/status discloses the identity provider's issuer URL without authentication, undoing what the login screen's own probe deliberately withholds.
  • No factory reset and no rescue boot entry. Lock yourself out and the documented recovery is a console shell, stopping the agent, and editing the state file by hand.
  • Redaction below the admin role matches secret leaf names, so a value that is sensitive because of where it sits — a container's environment variable, an SNMP community string — is not matched.
  • The dependency scan does not gate a release, and nothing inspects an ISO between building it and publishing it.
  • The licence fingerprint derives from /etc/machine-id, and nothing in the build guarantees two machines installed from the same image get different ones. Check it if you run several.

The full treatment is in the project's own security documentation (docs/security.md), and reporting a flaw is on the security page.

Commercially not ready#

  • No price. Both monthly figures are unset.
  • No licence agreement and no terms of service. What ships is a stopgap that says in its own first paragraph that it has not been through legal review.
  • No published support address, issue tracker, chat channel or status page. The forge is private, so "file an issue" is not something a customer can do.
  • The beta is closed and invite-only.
  • It is not open source. The agent and the interface are proprietary, driving GPL components as separate programs. The base is GPL and its corresponding source is published with every release.

How to check any of this#

Everything above is a file in a repository, and most of it is a grep. The wiki keeps the same status page with the citations attached, and the known-gaps page covers the security list in detail.

Read on#

  • Roadmap — what is planned, in what order, with nothing dated.
  • Beta — what a seat is for.

Updated 2026-09-02