Real 3-2-1 Backups with restic and Proxmox Backup Server
Three copies of your data, on two kinds of media, one offsite -- built with restic and Proxmox Backup Server, and proven with an actual timed restore, not a backup job that's never been tested.
What you'll build and why
3-2-1 is a simple rule with real teeth: 3 copies of your data, on 2 different kinds of media, with 1 copy offsite. Each number defends against a specific failure a smaller setup doesn't: a single copy dies with its only disk; two local copies both die in the same fire, flood, or theft; only an offsite copy survives your house being the problem. This guide builds exactly that with restic for general files, notes where Proxmox Backup Server fits for VM/container backups specifically, and ends with a timed restore drill -- because a backup you've never restored from is a hope, not a plan.
Don't build this if: you don't have any data that would actually hurt to lose -- if everything on a given host is fully reproducible from somewhere else (a fresh install plus redeployed configs you already version-control), a backup of that host specifically may not need this level of rigor. Be honest about what's actually irreplaceable before investing in this for everything.
How it works
Source data (your files, or a Proxmox VM's disk)
│
├──► Copy 1: the original, on its normal disk
│
├──► Copy 2: restic backup to a second local
│ target (a different disk, or a NAS) --
│ different media from copy 1
│
└──► Copy 3: restic backup to an offsite/cloud
target -- the one that survives a local
disaster
All restic copies: encrypted client-side before
leaving the source machine -- the backup target
never sees your data unencrypted, even if it's a
cloud provider.
Before you start
Decision: restic or Borg? Both are well-regarded, actively maintained backup tools with client-side encryption. restic has broader native backend support (S3-compatible, B2, SFTP, and more, directly); Borg's particular strength is deduplication efficiency across many similar snapshots. This guide uses restic for its backend flexibility, which fits the "one copy offsite" requirement especially well -- either is a legitimate choice.
Where's your offsite copy actually going? Decide before Step 3: a cloud object storage service (Backblaze B2 and similar S3-compatible providers are commonly paired with restic), or a genuinely separate physical location for a drive you rotate. Both satisfy "offsite" -- a second drive in the same room does not, regardless of how it's connected.
Steps
Step 1: Initialize a local restic repository
$ restic init --repo /mnt/backup-disk/restic-repo
You'll set a repository password -- losing this password means losing access to every backup in this repository, by design (it's what makes client-side encryption real). Store it in a password manager, not a text file next to the repo.
Step 2: Take your first local backup
$ restic -r /mnt/backup-disk/restic-repo backup /path/to/important/data
Expected output: a summary showing files scanned, new/changed data, and total repository size. Run this on a schedule (cron or a systemd timer) going forward, not just once.
Step 3: Initialize and configure the offsite copy
$ restic init --repo s3:https://s3.<region>.backblazeb2.com/<bucket-name>
(Substituting your actual offsite target -- the exact repository URL syntax differs by backend; check restic's own backend documentation for yours.) Back up to it the same way as Step 2, pointed at this second repository instead.
Step 4 (if running Proxmox): set up Proxmox Backup Server for VM-level backups
Proxmox Backup Server is a separate install (its own VM or dedicated machine, not the same as your Proxmox VE cluster) that VM/container-level vzdump-style backups can target directly, with deduplication and retention built in -- complementary to restic (which backs up files), for backing up whole VMs. See the CLI reference guide's backup section for the vzdump/qmrestore commands once Proxmox Backup Server is registered as a storage target.
Verify it works
-
restic -r /mnt/backup-disk/restic-repo snapshotslists your local backups -
restic -r s3:...(your offsite repo)snapshotslists your offsite backups - The actual point of this guide -- a timed restore drill: pick a real file or small directory from a recent snapshot, and time how long it takes to fully restore it to a different location than the original (not overwriting the source -- you're proving restore works, not just that the command runs):
$ time restic -r /mnt/backup-disk/restic-repo restore latest --target /tmp/restore-test --include /path/to/important/data
Record how long this took. This number matters -- it's your real recovery time, not a guess, and it's what you'd actually be waiting on during a real incident.
- Confirm the restored files are correct (open one, check it matches what you expect) -- a successful
restic restorecommand exiting cleanly proves the tool worked, not that the data itself is what you think it is
Secure it
- What's exposed: your restic repository password is the single point of failure for accessing every backup -- protect it like the credential it is. Cloud backend credentials (API keys for your offsite target) similarly need real protection, not a plaintext file.
- The failure that hurts most: losing the repository password with no other copy of it -- this makes every backup in that repository permanently inaccessible, which is functionally the same as never having backed up at all. Store it somewhere that survives the same disaster your backups are meant to survive (a password manager with its own backup/sync, not a note taped to the backup drive).
- Update strategy: restic and Proxmox Backup Server both ship regular releases; update on your own schedule, but don't let backup tooling silently go stale for years -- check for updates when you do periodic restore drills (Go further), which is a natural moment to also confirm you're on a reasonably current version.
Back it up and maintain it
(This section is normally about protecting other things -- for a backup tool itself, "maintaining it" means keeping the backup process itself healthy.)
What matters: the repository password (see Secure it) and confirming backup jobs are actually running on schedule, not silently failing.
Update cadence: review your backup job's logs periodically -- a cron job that's been failing silently for months is worse than no backup at all, because you believe you're protected when you're not.
What to monitor: restic snapshot lists growing on schedule (a repository that hasn't gained a new snapshot recently means the job stopped running); repository size trends, so you're not surprised by offsite storage costs.
Troubleshooting
Logs: whatever captures your scheduled job's output (cron mail, systemd journal for a timer unit) -- restic itself doesn't have a persistent log by default, so capturing the command's own output is on you.
| Symptom | Likely cause | Diagnostic | Fix |
|---|---|---|---|
| Backup job hasn't produced a new snapshot | The scheduled job stopped running or is failing silently | Check cron/systemd timer status directly; check for captured error output | Fix the underlying job failure (often a changed path, expired credential, or full disk) |
restic backup fails with a permission error |
The user running the backup lacks read access to the source data | Check file/directory permissions against the backup job's running user | Adjust permissions or run the backup as a user with appropriate access |
| Offsite backup fails specifically | Expired or revoked cloud credentials, or a network issue reaching the offsite endpoint | Test connectivity/credentials to the offsite backend directly, outside of restic | Refresh credentials; confirm the offsite endpoint is reachable |
| Restore drill takes far longer than expected | Restoring from the offsite/cloud copy specifically (bandwidth-limited), or restoring a much larger dataset than intended | Check which repository you actually restored from, and the size of what was restored | This may just be an honest finding -- if your real recovery time is too slow for your needs, that's exactly what the drill is for catching, before a real incident |
| Repository shows as locked / a stale lock error | A previous restic operation was interrupted mid-run | restic unlock (only after confirming no other restic process is actually still running against that repository) |
Remove the stale lock; investigate why the previous run was interrupted if it keeps happening |
Undo
Delete the repository directories/buckets to remove the backups themselves (irreversible -- confirm you actually want to before doing this). Remove the scheduled job (cron entry or systemd timer) to stop future backups.
Go further
- Automate the restore drill itself on a schedule (quarterly is a reasonable cadence) rather than doing it once and assuming it stays valid
- Add
--tagvalues to your restic backups to distinguish different data sets within one repository, and retention policies (restic forget --keep-daily --keep-weekly) so old snapshots don't accumulate forever - If you're running Proxmox, pair this file-level backup with the CLI reference guide's
vzdump/Proxmox Backup Server coverage for full VM-level backups, not just files
Resources
Official documentation:
- restic documentation -- repository init and backup syntax, verified this session
- Proxmox Backup Server documentation
- BorgBackup documentation -- the alternative mentioned in Before you start
Source and releases:
Community:
Related DaemonPress projects:
- Build a 3-Node Proxmox VE Cluster
- Proxmox VE Command-Line Reference --
vzdump/qmrestorefor VM-level backups
Last verified: 2026-09-21, checked against official restic documentation.