Skip to content
Backups Fleet-wide backup control tower — plain per-site archives, encrypted destinations, scheduled jobs, existence checks, and restore.

Backups

Backups (/backups) is the account-level control tower for protecting every site, Docker app/stack, and whole server across your fleet. You add destinations once (they hold the storage credentials), attach jobs to individual servers, and watch every run land as a snapshot you can restore from. The section is owner-only and available on all plans — the Free plan backs up to a local disk, Plus unlocks offsite object storage, and Pro/Max add cross-server peer destinations.

Add a destination and back up a server, step by step

Section titled “Add a destination and back up a server, step by step”
  1. Go to the Destinations tab and add where backups will live:
    • Add object storage — S3, Cloudflare R2, Backblaze B2 (all native S3-compatible), or any rclone remote (Google Drive, Dropbox, OneDrive, WebDAV/Nextcloud, SFTP, …). (Plus and up.)
    • Add local — a directory on one server’s own disk. (All plans.)
    • Add peer — archives pushed over SFTP onto another of your servers’ spare disk, ideally riding the private WireGuard mesh. (Pro and up.)
  2. Pick the destination’s encryption mode: Basic (plain archives, maximally portable) or Advanced (each archive is gpg-encrypted with a per-server password the box generates automatically — download and keep it).
  3. Back on the Overview tab, open a server card and click New job. Choose what to back up (site, Docker app/stack, or the whole server — one or many targets), the kind (full, database, or files), a schedule, one or more destinations, and a retention (keep N copies or days).
  4. Save. The job runs on its schedule, or hit Run now to fire it immediately — each run appears under Snapshots as it completes.
  • Overview tab — a backup coverage card per server (backed-up / scheduled / no-backup), a fleet 3-2-1 nudge, Docker app/stack coverage, and a Recent failures log with per-row error snippets and a Clear failures button.
  • Server drawer (open a coverage card) — list, run, pause/resume, edit, duplicate, and delete that server’s jobs; see its recent snapshots; and Download backup key for Advanced-mode servers.
  • Snapshots tab — the fleet-wide history, filterable by status, kind, target type, and server. Restore (single or bulk), Check existence (re-verify each archive is still at its destination), Refresh from servers (reconcile the history with each destination’s manifest.json), and delete a snapshot (removes the remote archive too).
  • Restore a snapshot with a chosen scope (full / database only / files only), optionally to a different server (a migration — both must be online), or remapped to a different domain (re-provisions the site shell, rewrites the URL). A deleted site is recreated (user, database, PHP pool, vhost, SSL) before files and database are replayed.

Backups are orchestrated by the control plane (/v1/backups/* and /v1/servers/:id/backup-jobs/*) but run on the box. Destinations, jobs, and snapshot history live in Postgres; the actual archives live only at their destination. Each action dispatches a backup.v2-* job to the target server’s agent, which runs it natively:

ActionJob dispatchedAgent runs
Run a jobbackup.v2-runbackup v2 run ….tar.gz per target + updates manifest.json
List / reconcilebackup.v2-listbackup v2 list (reads manifest.json)
Check existencebackup.v2-verifybackup v2 verify (which archives are still present)
Restorebackup.v2-restorebackup v2 restore --scope … [--target-site …]
Deletebackup.v2-deletebackup v2 delete (removes the archive)
Reveal keybackup.v2-revealreturns the per-server Advanced passphrase

Object-store credentials are sealed in your browser before they ever reach the control plane — the server stores only ciphertext, and only the agent unseals them at run time. Object destinations use rclone, so all clouds share one code path. Retention is enforced as keep-N per job: older archives are pruned right after each run. A systemd timer on the box fires scheduled jobs, so backups keep running even if the control plane is briefly unreachable, and a daily existence check flips any vanished archive to Missing in the history.

Backups are an account-level concern, so scheduling lives in the dashboard — but the archives run on the box, and you can trigger a local backup directly with mz over SSH (the same engine the panel drives). An on-box AI (ClaudeCode) runs the same commands:

Terminal window
mz backup full example.com # files + database → local tar
mz backup db example.com # database only → local tar
mz backup all # every site on the box → local tar

These write a local archive on the server; offsite destinations, schedules, retention, and restore are managed from /backups in the dashboard. See The mz CLI and the command catalog.

For programmatic fleet control (create destinations/jobs, list snapshots, trigger restores), the control-plane REST API exposes the same /v1/backups/* endpoints — see the API reference (Max plan).

  • Local and peer destinations can’t be reached from anywhere. A local disk belongs to one machine, so only that server can back up to it; a peer is usable by every server except the one holding it. A cross-server restore needs an object destination — a local archive lives on the origin server’s disk and can’t be pulled onto another box.
  • Advanced encryption: don’t lose the key. In Advanced mode the passphrase lives only on the box. Download backup key from the server drawer and store it safely — an encrypted archive cannot be restored without it if the server is lost. Basic-mode archives have no such risk (they’re plain).
  • “Missing” means the archive is gone, not that the run failed. The daily (or manual Check existence) sweep marks a completed snapshot Missing when its file has vanished from the destination — usually pruned by keep-N retention or deleted out-of-band. Use Refresh from servers to re-sync the history with the destination’s manifest.json.
  • Restore overwrites the target. A database-only restore replaces the live database; a full restore replaces files and database. There’s no undo — restore to a different domain first if you want to compare.
  • Everything live needs the agent online. Running, restoring, verifying, and deleting remote archives all reach through the agent. Clearing failed rows and deleting a snapshot with no archive are offline-safe (pure database deletes).