-
Notifications
You must be signed in to change notification settings - Fork 2
archive and rollback
Pre-Alpha. This page describes behavior that may change.
Every committed configuration in Ze is kept. Rollback is not a best-effort undo against the last edit: it is a restore from a structured archive that retains every committed revision indefinitely. In addition, Ze can copy each committed config to external destinations (local filesystem, HTTPS endpoint) on a trigger, so your config history survives a daemon restart or a disk failure.
ze config history config.conf # List revisions
ze config diff 3 config.conf # Diff revision 3 against the current file
ze config diff 3 7 # Diff two revisions
ze config rollback 3 config.conf # Restore revision 3Inside the editor, rollback 1 is "undo the last commit". rollback 5 jumps back five commits. show archive lists what is available.
Each commit is transactional. Ze stores every committed config as an immutable, timestamped blob and tracks the current state with named pointers rather than overwriting a single file.
| Pointer | Meaning |
|---|---|
active |
The config version that boot and the running daemon consider live. |
candidate |
The version staged for the current commit attempt (transient). |
rollback |
The previous active version, set after a successful promotion. |
recovery |
An operator-selected known-good version for future recovery commands. |
A commit stages the proposed config as candidate, runs the verify and apply phases across the subsystems, and promotes candidate to active only after the runtime reload succeeds. On success, the old active becomes rollback. On failure, candidate is cleared and active is left unchanged, so the running config never reflects a partially applied change. The transaction is gated on the blob store: if the versioned config cannot be persisted, the commit does not proceed. On boot, a stale candidate left by a crash is ignored and cleaned up, and the daemon loads active.
Committed config blobs carry a schema version stamp tied to the Ze release that wrote them. When the daemon loads a config written by a newer release, downgrade recovery prunes fields the running schema does not recognize rather than rejecting the whole file, so an older binary can still come up on a config that a newer binary produced.
Named archive blocks under system { archive { } } copy every committed config to an external destination. Each block has its own trigger, filename format, and timeout.
system {
host router1;
domain dc1.example.com;
archive local-backup {
location file:///var/backups/ze;
trigger commit;
}
archive offsite {
location https://archive.example.com/configs;
trigger daily;
on-change true;
timeout 10s;
filename "{host}-{date}-{time}";
}
}
| Field | Default | Description |
|---|---|---|
location |
required | Destination URL. file://, http://, or https://. |
trigger |
manual |
When to archive: commit, manual, daily, hourly. |
filename |
{name}-{host}-{date}-{time} |
Filename format with token substitution. |
timeout |
30s |
HTTP upload timeout. |
on-change |
false |
Time-based triggers only: skip the upload if the config is unchanged since the last archive. |
commit-revisions |
0 |
Maximum number of committed revisions to keep. 0 means keep all (default). When set, older revisions are pruned after each commit. |
file:///path writes to the local filesystem. Parent directories are created as needed. Files are written with 0600 permissions. Use absolute paths: Go's URL parser does not handle file://./relative correctly.
http://host/path and https://host/path POST the config as text/plain. The filename goes in the X-Archive-Filename header. Any HTTP 2xx response is treated as success.
commit fires after every editor commit. The archive is unconditional: the on-change flag is ignored for commit triggers.
manual fires only when you run ze config archive <name> <file> from the CLI.
daily fires every 24 hours from daemon start. It fires once on daemon boot regardless of on-change (to establish a baseline), and every 24 hours thereafter. Subsequent fires respect on-change when it is set.
hourly works the same way, every hour.
{name} The config file basename without extension (router)
{host} The system.host value (router1)
{domain} The system.domain value (dc1.example.com)
{date} YYYYMMDD (20260329)
{time} HHMMSS (143045)
{archive} The archive block name (local-backup)
The .conf extension is always appended. The default format produces a filename like router-router1-20260329-143045.conf.
ze config archive <name> <config-file>The <name> must match a named block under system { archive { } }. The command parses the config, extracts the settings for the block, and uploads. Reading from stdin is supported with - as the config file argument.
ze config archive local-backup router.conf
cat router.conf | ze config archive offsite -If the named block does not exist, the command prints the available archive names and exits with code 1.
When the editor starts, it reads the archive blocks from the config. Blocks with trigger commit are wired into the editor's commit path. After every successful commit, the editor archives the config content to every trigger commit destination in parallel.
Archive errors during commit are non-fatal. The commit succeeds and the editor reports the number of archive failures in the status line. Other trigger types (manual, daily, hourly) are not fired by the editor: the daemon's background scheduler fires them.
Adding a new archive block during an editing session requires restarting the editor for the block to take effect.
For time-based triggers with on-change true, Ze tracks config changes with SHA-256 hashes in memory. Each named archive block has its own hash. The first check after daemon start always reports "changed" (no baseline yet), so the boot archive fires unconditionally. Subsequent checks compare the current config hash against the last archived hash and skip the archive when unchanged.
The tracker resets on daemon restart because the hashes are in-memory only.
The system { host; domain; } block provides values used in archive filenames and elsewhere. Both fields support $ENV variable expansion.
system {
host $HOSTNAME;
domain $DOMAIN;
}
If the environment variable is empty or unset, the literal string is kept ($HOSTNAME stays as $HOSTNAME). When host is not configured, it defaults to os.Hostname().
system {
host edge-01;
archive local {
location file:///var/backups/ze;
trigger commit;
}
archive central {
location https://hub.example.com/configs;
trigger hourly;
on-change true;
}
}
The local backup fires on every commit, unconditionally. The central server receives an hourly copy that is skipped when nothing has changed. Manual archives to either destination work too: ze config archive local edge-01.conf.
-
Editor workflow for the
rollbackcommand andcommit confirmed. - Overview for the surrounding commit model.
- In-tree archive guide for the full reference.
Adapted from main/docs/guide/config-archive.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology