Point one agent at several routers#
You will end up with one agent holding connections to several routers: their health and version on the Fleet page, and changes applied to each router from pending changes of its own. Read what it does not do before you build anything on it.
Before you start#
- A licence with the fleet feature. Every per-router route —
GET /api/fleet/{id}/config,/versionand/staged, andPOST /api/fleet/{id}/stage,/stage/remove,/discard,/commit,/commit/confirmand/configure— answers402without one. ThoseGETs are the only reads in the product behind the licence gate, because they read a different router.GET /api/fleet, the list itself, is not gated. - The API address and API key of each router. A router's API key is root-equivalent on that router.
- A shell on the machine running the agent. The fleet file and the option that loads it are not settings in the web interface.
Step 1 — Write the fleet file#
{
"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:
- 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
urlis trimmed. Left in place it turns every call into a double-slash path the far router answers with a 404. - At least one router, or the file is refused.
sudo sh -c 'umask 077; cat > /config/wheelhouse/fleet.json'Step 2 — Point the agent at it#
A systemd drop-in, not the packaged service:
[Service]
ExecStart=
ExecStart=/usr/bin/wheelhouse-agent … --fleet-config /config/wheelhouse/fleet.jsonsudo systemctl daemon-reload
sudo systemctl restart wheelhouse-agentStep 3 — Read the fleet#
System → Fleet. The navigation shows Fleet when the licence includes the feature. The page checks every router at once, every 30 seconds. Without the fleet file, or without the licence feature, it says Fleet mode is off and why.
From the API:
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"/api/fleet/{id}/config is redacted below the admin role, like every other configuration read.
Step 4 — Change one router#
Changes reach a router's pending changes through the API — or, in Advanced mode, through the
Add commands panel on its page. 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:
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/stage"Then open the router on the Fleet page, read the pending changes, and apply them — with Apply with auto-revert when the change could cut the router off from this agent. The same from the API:
curl -sk -X POST -H "Authorization: Bearer $T" -H 'Content-Type: application/json' \
-d '{"confirm_minutes":2}' "$R/api/fleet/branch/commit"
# ... check the router still answers ...
curl -sk -X POST -H "Authorization: Bearer $T" "$R/api/fleet/branch/commit/confirm"Auto-revert is per router, both halves of it. confirm_minutes starts the far router's own
timer, and POST /api/fleet/{id}/commit/confirm stops it on that same router. Do not reach for the
local POST /api/commit/confirm: it confirms this agent's own router, which would leave the far one
to restart and end a window here instead.
Applying does not save the configuration on the far router: save it there, or it is lost at that router's next restart. The audit log records Applied changes on a fleet router, Kept changes on a fleet router and Discarded pending changes on a fleet router, each with the router's id; applied changes are recorded with the exact commands.
What to use instead, for most of this#
For a handful of routers that should look alike, configuration as code is the better answer today: one file, applied to each router by its own agent, with each router's own pending changes, audit log, revisions and auto-revert doing their jobs.
for host in edge branch; do
wheelhouse-agent apply --file agent.yaml --agent-url "https://$host:8443" \
--admin-token-file ~/.wheelhouse/$host.token
doneThat gets you review, audit and restorable revisions on each router, which fleet mode gives only in part.
What fleet mode does not do#
- No fleet-wide upgrade. The page has no image action. Upgrade each router from its own System page, and do one first: Upgrade the whole system.
- No fleet-wide backup. Take a backup on each router.
- No saving on the far router. Applied changes last until that router restarts unless they are saved there.
Check it worked#
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 an address 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.
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