Venue backups
A backup is a venue’s configuration captured and kept. It is the durable sibling of a venue-copy snapshot: the same capture, but retained indefinitely, encrypted at rest, and restorable.
Backups ship with the Copy feature — enable that under Features in the
dashboard and the backup_* tools appear.
Backup or snapshot?
Section titled “Backup or snapshot?”They capture the same thing. What differs is what happens to it afterwards.
Snapshot (venue_extract) | Backup (backup_create) | |
|---|---|---|
| Retention | 30 days, then swept | Indefinite — nothing expires it |
| How it goes away | Ages out, or venue_snapshot_delete | Only backup_delete |
| Per user | 20 | 50 |
| Encrypted at rest | Yes | Yes |
| Purpose | The working input to a copy | The artifact you keep |
Use a snapshot to do something now. Use a backup to be able to do something later.
Both capture paths end in the same sealed artifact, and a restore from it can target the venue it came from, a brand-new venue, or a different tenant.
Taking one
Section titled “Taking one”There are two ways in, and the cheap one is worth knowing.
-
Capture a venue directly. Pass
venueId, optionallyconnectionanddomains. This runs the same extract a copy does, so it is chunked for the 30-second run budget: if it needs more calls it returns{ status: "building", snapshotId, domainsRemaining }and must be called again with thatsnapshotId. It seals itself once the extract completes. Passlabelandnoteon the final call. -
Or seal a snapshot you already have. Pass the
snapshotIdof a completedvenue_extractinstead. Nothing is re-read from R1, so this is cheap — if you have just extracted a venue in order to copy it, sealing that same snapshot costs one call.
backup_create returns { id, venueId, venueName, label, note, domains, domainsIncomplete, objectCounts, plaintextBytes, encrypted, createdAt }.
The tools
Section titled “The tools”| Tool | What it does |
|---|---|
backup_create | Capture and seal a venue, from a venueId or a completed snapshotId |
backup_list | Your backups, newest first — venue, label, source tenant, domains, counts, size |
backup_get | One backup’s metadata |
backup_restore | Compile a restore into a reviewable MOP |
backup_delete | Delete the D1 row and its encrypted blob — irreversible |
The config blob is never returned
Section titled “The config blob is never returned”No tool returns a backup’s configuration, and there is deliberately no export
path. backup_list and backup_get return metadata only — venue, label,
captured domains, per-domain object counts, sizes, timestamps.
The reason is what a venue config contains: DPSK passphrases and RADIUS secrets. The blob is encrypted at rest with the Worker’s key and only ever decrypted server-side, to diff it while compiling a restore.
Restoring
Section titled “Restoring”backup_restore does not run anything. It diffs the stored config against a
target and compiles exactly the same reviewable apply-MOP that
venue_copy_plan produces — which means the review, arm,
verify, and undo steps are identical, and so are the limits.
Pass backupId and exactly one of:
target.venueId— restore into an existing venue, including the one it came from. This is restore-in-place.target.newVenue.{name, address}— rebuild it as a fresh venue.
Optionally targetConnection (a different saved connection makes it a
cross-tenant restore, recreating shared objects in that tenant exactly as a
cross-tenant copy does), domains to restore a subset — just the WLANs, say —
plus collisionPolicy, sharedCollision, acceptWarnings, and mode.
Then the familiar cycle:
-
Review with
mop_replay { mopId, dryRun: true }. -
Run it with
mop_replay { mopId, armWrites: true }— arming names the target tenant before any write executes. -
Confirm with
venue_copy_verify { backupId, targetVenueId }. -
Reverse it with
venue_copy_undo { runId }if you need to.
What a restore cannot bring back
Section titled “What a restore cannot bring back”Everything a copy cannot carry, a restore cannot either — with one addition that catches people out:
- Write-only secrets were never in the backup. R1 masked the RADIUS shared
secrets and bind passwords on read, so they were never captured. They come back
as
operatorInputRequiredbindings you supply at run start; the run refuses withmissing_capturerather than restoring a venue with silently missing secrets. - Physical devices are never restored. Switch inventory and AP serial membership are not part of a backup in any mode.
- A partial backup restores partially — see its
domainsIncomplete.
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Backups per user | 50 — backup_limit_reached, and nothing frees itself |
| Retention | Indefinite; backup_delete is the only removal |
| Size | 5 MB of captured config; over it returns backup_too_large — back up fewer domains separately |