Wheelhouse docs

Point one agent at several routers#

You will end up with one agent holding connections to several routers, reporting their health, version and configuration from one place. Read what it does not do before you build anything on it.

Before you start#

  • A licence with the fleet feature. Every /api/fleet/* route answers 402 without one.
  • The API URL and API key of each router. A VyOS API key is root-equivalent on that router.
  • Shell access to the machine running the agent.

Step 1 — Write the fleet file#

/config/wheelhouse/fleet.json
{
  "routers": [
    {"id": "edge",   "label": "Head office",  "url": "https://192.0.2.1",    "key": "…"},
    {"id": "branch", "label": "Branch",       "url": "https://198.51.100.1", "key": "…"}
  ]
}

The rules the agent enforces when it reads this file, each because of a failure it prevents:

  • Mode 0600. The file holds an API key per router, each root-equivalent on that router, so it gets the same check as every other secret file: it must not be readable by group or other. The agent refuses to start otherwise.
  • Every entry needs a non-empty id. Fleet routes are /api/fleet/{id}/…; an entry with no id is unaddressable.
  • Ids must be unique. A duplicate would silently replace the first client while both kept a status row — two rows, one reachable router.
  • A trailing slash on url is trimmed, because it made every call //show, a 404 that the status check then reported as online.
  • At least one router, or the file is refused.
bash
sudo sh -c 'umask 077; cat > /config/wheelhouse/fleet.json'

Step 2 — Point the agent at it#

A systemd drop-in, not the packaged unit:

/etc/systemd/system/wheelhouse-agent.service.d/fleet.conf
[Service]
ExecStart=
ExecStart=/usr/bin/wheelhouse-agent … --fleet-config /config/wheelhouse/fleet.json
bash
sudo systemctl daemon-reload
sudo systemctl restart wheelhouse-agent

Step 3 — Read the fleet#

bash
R=https://<router>:8443
T=wh_...
curl -sk -H "Authorization: Bearer $T" "$R/api/fleet"
curl -sk -H "Authorization: Bearer $T" "$R/api/fleet/branch/version"
curl -sk -H "Authorization: Bearer $T" "$R/api/fleet/branch/config"

The Fleet page shows every router the agent holds a connection to, health-checked concurrently, with its label, its endpoint and whether it is online.

/api/fleet/{id}/config is redacted below the admin role, like every other configuration read.

Without the licence feature, the page says so and shows the flag that turns it on rather than an empty table.

Step 4 — Configure one router#

The body is a bare JSON array of operations — not an object with an ops key, which is where the local POST /api/stage differs.

bash
curl -sk -X POST -H "Authorization: Bearer $T" -H 'Content-Type: application/json' \
  -d '[{"op":"set","path":["service","dns","forwarding","cache-size","10000"]}]' \
  "$R/api/fleet/branch/configure"

What to use instead, for most of this#

For a handful of routers that should look alike, config as code is the better answer today: one file, applied to each router by its own agent, with each router's own Commit Bar, audit log and commit-confirm doing their jobs.

bash
for host in edge branch; do
  wheelhouse-agent apply --file agent.yaml --agent-url "https://$host:8443" \
    --admin-token-file ~/.wheelhouse/$host.token
done

That gets you review, audit and rollback per router, which fleet mode does not.

What fleet mode does not do#

  • No per-router staging or commit. Reads, health, and one configure call.
  • No fleet-wide upgrade. The page has no image action. Upgrade each router through its own POST /api/system/image, and do one first.
  • No fleet-wide backup. Take a backup is per router.

Check it worked#

bash
curl -sk -H "Authorization: Bearer $T" "$R/api/fleet"

Every router online, with the label you gave it. A router that shows online but returns nothing useful from /version is usually a URL with a path on it, or the wrong API key.

Undoing it#

Remove the drop-in, restart, and delete the file — it is a credential store.

bash
sudo rm /etc/systemd/system/wheelhouse-agent.service.d/fleet.conf
sudo systemctl daemon-reload
sudo systemctl restart wheelhouse-agent
sudo shred -u /config/wheelhouse/fleet.json

See also#


Checked against agent/fleet.go · agent/main.go · ui/src/pages/Fleet.tsx · docs/deploy.md

Updated 2026-09-02 fleet multi-router automation