System — history#
The History tab lists the router's archived configuration revisions, shows what each one changed, and restores one. It is the answer to "what changed my NAT rule, when, and can I put it back".
Revisions are the base platform's own mechanism: every commit archives the configuration
as a numbered, gzipped file under /config/archive/. Revision 0 is the running
configuration; revision 1 is the commit before it, and the numbers grow older from
there. GET /api/history is show system commit, parsed into one row per line.
The table#
| Column | From | Notes |
|---|---|---|
| Rev | the revision number | Sorts numerically. |
| Committed | the timestamp the router recorded | YYYY-MM-DD HH:MM:SS. |
| By | the router account that committed | |
| Made by | the transport the router recorded | Translated — see below. |
| Diff and Restore | Restore is offered on every revision except 0. |
"Made by" is a translation#
The router records the transport that carried each commit, so a change this product
made is filed under the base platform's API component. vyos-http-api is a true
statement about plumbing and a useless answer to "who changed my NAT rule", so the
column translates it — ui/src/pages/System.tsx:
| The router recorded | The column shows |
|---|---|
vyos-http-api | Wheelhouse (in accent colour) |
cli | Console |
init, boot | Boot |
| anything else | verbatim |
The raw token is on the badge's tooltip: the router recorded this commit as "via vyos-http-api". Nothing is hidden; it is renamed and the original is one hover away.
The diff#
Diff opens a side panel titled Revision <n>, subtitled with its time, its
committing account and the translated transport. The body is
GET /api/history/diff?rev=<n>, which is show system commit diff <n>.
The panel is explicit about the direction, because a diff with no legend is a coin toss:
Lines marked + exist in this revision; lines marked − exist in the running config.
Lines are coloured to match: additions green, removals red — and both - and the
typographic − are recognised, because some builds print the latter. A revision
identical to the running configuration says so rather than showing an empty box.
Above the diff is a one-line summary the browser computes:
4 added, 2 removed · touches firewall, nat
The touched sections come from the [edit …] headers the router prints above changed
lines; when the diff is in command form instead, the first word after set or delete
is used. That summary is what you scan a restore for — does this touch the firewall —
before reading the lines themselves.
GET /api/history/diff is wrapped in redactSecrets(RoleAdmin, …): below the admin
role, secrets in the diff are redacted.
Restoring a revision#
Restore is deliberately two clicks. Restore arms the button; it turns into Confirm restore and stays armed for 20 seconds before disarming itself — arming a restore and then walking away should not leave a red button primed on a page someone else picks up.
The same confirmation is available from inside the diff panel, where the button reads
"Confirm — load revision <n> and commit", which is exactly what happens.
POST /api/rollback with {"revision": n} loads /config/archive/config.boot.<n>.gz
and commits it. There is no rollback operation in the router's HTTP API; the CLI
command works by loading the archived file for that revision, and the agent does the
same thing — agent/main.go, handleRollback. An empty body
defaults to revision 1, which is "undo the last commit".
After a successful restore the page says what happened and offers the way back:
Restored revision 3. The router is now running that config.
Loading a revision commits, so the config that was running before this restore should now be revision 1. — [Review revision 1]
That is offered as open the diff, not as a second blind restore, because the page cannot prove what the router archived.
What a restore does not restore#
A revision is a configuration. It is not a backup of the router.
| Restored | Not restored |
|---|---|
| Interfaces, firewall, NAT, DHCP, DNS, routing | Wheelhouse accounts and password hashes |
| Container declarations — so apps revert with everything else | TOTP enrolments, API tokens, sessions |
Everything else under config.boot | The audit log |
| The licence key | |
| Container images and volume contents |
Those live in /config/wheelhouse/state.json and on disk, outside the configuration
tree entirely. Backup and restore is the page for the rest.
An app that was rolled back to a revision naming an older image tag gets the tag, not the bytes: the image on disk is whatever was last pulled.
Doing it from the CLI or the API#
show system commit
show system commit diff 1# undo the last commit
curl -sk -X POST -H "Authorization: Bearer $T" \
-H 'Content-Type: application/json' -d '{"revision":1}' \
https://<router>:8443/api/rollbackBoth the success and the failure are written to the audit log as rollback, with the
archive file in the path field.
When the table is empty#
A router that has never been committed through shows the empty state with two commands and one fact: "Revision 0 is the running config." An empty history usually means a freshly installed box, or an archive directory that has been cleared.
See also#
- System — Save to boot config and Download config, in the header.
- System — audit — who made each of these commits.
- Backup and restore — everything a revision does not contain.
- One app — why rolling back takes the apps with it.
Checked against ui/src/pages/System.tsx,
agent/opmode.go, agent/main.go,
agent/parse.go, agent/vyos.go,
docs/backup-restore.md.