The configuration tree#
A Wheelhouse router keeps its entire configuration in one tree. Every setting is a path through that tree ending in a value, and every change adds, changes or removes such a setting. There is no second place where the router's configuration lives.
The web interface's pages are editors over that one tree. A page shows its settings as tables and forms, by their names (DNS servers, Time zone, Allowed clients), and its editors turn what you enter into changes to the tree, which wait in the pending changes until they are applied. Nobody has to type a path.
Paths, nodes and values#
For readers who use the router's own language, a path reads as words separated by spaces, the way the router's command line spells it:
set interfaces ethernet eth1 address 203.0.113.2/24
set interfaces ethernet eth1 description 'primary uplink'
set protocols static route 0.0.0.0/0 next-hop 203.0.113.1Three kinds of thing appear in a path.
| Kind | Example | What it is |
|---|---|---|
| A node | interfaces, protocols static | A branch with a fixed name. Its children are fixed too. |
| A tag node | ethernet eth1, route 0.0.0.0/0, name adguard | A branch whose children are named by you. ethernet is the tag node; eth1 is one instance of it. |
| A value | 203.0.113.2/24, 'primary uplink' | The leaf. It is the last word of a set command. |
A node can also exist with no value at all: set service ssh switches SSH on and has
nothing after it. A desired-state file has to be able to express that
shape.
Where the tree is visible#
Without Advanced mode, it is not: pages name settings in words, pending changes read as sentences (Change the host name to edge-1), and the History tab describes what each revision changed.
With Advanced mode on (Account → Preferences), the router's own language appears beside the words:
- each page names the part of the tree it edits beside its title;
- editors show the commands a change would add;
- the Commit Bar lists pending changes as
setanddeleteoperations; - System → Configuration tree shows the whole tree.
The Configuration tree page renders the running configuration as a tree you can
search (Search settings and values…) or, with All commands, as the set lines that
recreate all of it. Selecting a setting shows the commands that recreate that setting and
everything under it.
The Configuration tree page is read only. It never adds anything to the pending changes, and nothing on it applies a change. A setting that no page edits is changed through the API, a desired-state file or the router's console. Which page edits which part of the tree is in Which page writes which subtree.
The search in the top bar also finds the objects the pages edit — firewall and NAT rules, DHCP reservations, WireGuard peers, networks, static routes, interfaces and installed apps — so a rule number or a peer name is a search away from any page.
What the tree is not#
- It is not the agent's data. The router owns it. The agent keeps only what the
router cannot: accounts, API token hashes, sessions, settings, the licence key and the
audit log, in
/config/wheelhouse/. Everything else the web interface shows is read from the router when it is needed. - It is not everything the router is doing. The tree is intent. What the kernel has installed is a separate question, and where the two disagree the web interface says so; see State, intent and drift.
- It does not cover the whole of Linux. Some things the kernel can do have no node in the tree. Where that matters, the page in question says so with a Platform gap callout rather than inventing a node.
For automation#
GET /api/config returns the tree, or the part of it named by path, as JSON:
R=https://<router>:8443
T=wh_... # an API token with the viewer role
curl -sk -H "Authorization: Bearer $T" "$R/api/config?path=%5B%22service%22,%22dns%22%5D"{"forwarding": {"cache-size": "10000", "listen-address": {"192.0.2.1": {}}}}Three details about that request:
path is a JSON array, not a slash-joined string. The agent accepts both, but a
slash-joined string cannot name a node whose key contains a slash, and plenty do:
route 0.0.0.0/0, subnet 192.0.2.0/24. The web interface always sends the array form.
A tag-node read comes back wrapped in its own name. The router answers a read ending
at an ordinary node with the bare subtree, but a read ending at a tag node with the
subtree inside a single key named after the node: container name answers
{"name": {"adguard": …}}, not {"adguard": …}. The agent unwraps that before returning
it.
An unset subtree is not an error. The router answers a read of an empty path with HTTP 400 and the words Configuration under specified path is empty. That is the normal state of a router with, for example, no high-availability configuration, so the agent tests for it rather than reporting the router as unreachable.
GET /api/config/commands renders any part of the tree as the set lines that would
recreate it. It is what the Configuration tree page and the Advanced mode previews are
built from:
curl -sk -H "Authorization: Bearer $T" "$R/api/config/commands?path=%5B%22nat%22%5D"set nat destination rule 10 description 'web'
set nat destination rule 10 destination port 443
set nat destination rule 10 inbound-interface name eth1
set nat destination rule 10 translation address 192.0.2.10A third form exists for backups: GET /api/config/raw returns the configuration in the
router's native curly-brace format. It is the only configuration read that is not
redacted, so it requires the admin role. It is what Download configuration on the
System page saves.
See also#
- Advanced mode and the router's commands: what Advanced mode adds to every page.
- Pending changes: where a change goes when you press Save or Add.
- Desired state: the same tree, written down as a file.
- Agent endpoints:
/api/config,/api/config/commandsand/api/config/raw. - What the agent asks the router: why these reads are cached.