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”- 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.)
- 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). - 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).
- Save. The job runs on its schedule, or hit Run now to fire it immediately — each run appears under Snapshots as it completes.
What else you can do
Section titled “What else you can do”- 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.
How it works
Section titled “How it works”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:
| Action | Job dispatched | Agent runs |
|---|---|---|
| Run a job | backup.v2-run | backup v2 run … → .tar.gz per target + updates manifest.json |
| List / reconcile | backup.v2-list | backup v2 list (reads manifest.json) |
| Check existence | backup.v2-verify | backup v2 verify (which archives are still present) |
| Restore | backup.v2-restore | backup v2 restore --scope … [--target-site …] |
| Delete | backup.v2-delete | backup v2 delete (removes the archive) |
| Reveal key | backup.v2-reveal | returns 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.
CLI & automation
Section titled “CLI & automation”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:
mz backup full example.com # files + database → local tarmz backup db example.com # database only → local tarmz backup all # every site on the box → local tarThese 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).
Gotchas & troubleshooting
Section titled “Gotchas & troubleshooting”- 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).
Related
Section titled “Related”- Cron jobs — the box-side scheduler that backs backup timers.
- Site overview — per-site health, disk, and database size.
- The mz CLI · Command catalog · API reference