Skip to content

archive and rollback

Thomas Mangin edited this page May 17, 2026 · 6 revisions

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.

Listing and diffing revisions

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 3

Inside the editor, rollback 1 is "undo the last commit". rollback 5 jumps back five commits. show archive lists what is available.

Archive destinations

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}";
    }
}

The fields

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.

Location schemes

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.

Triggers

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.

Filename tokens

{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.

Manual archive

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.

Editor integration

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.

Change detection

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.

System identity

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().

Example: local backup on every commit plus hourly central

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.

See also

Adapted from main/docs/guide/config-archive.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally