Homelab the Right Way

Home › Posts

Proxmox backups that actually work: 3-2-1, step by step

The whole backup playbook in one walk-through: the 3-2-1 plan, vzdump, Proxmox Backup Server, retention, an off-site copy, restore drills and the alert for jobs that quietly stop.

· 5 min read · proxmoxbackupspbs3-2-1

Proxmox backups that actually work: 3-2-1, step by step
Watch: Proxmox backups that actually work: 3-2-1, step by step on YouTube
The video for this post. Watch on YouTube

Your Proxmox backup job has a schedule, a storage target and a little green check. That check proves one thing: the job wrote some bytes somewhere. It does not prove every guest is covered, that the copy survives a dead host, or that anything actually restores.

This post walks through a complete homelab backup setup in the order you would build it, one layer at a time. Each layer closes a hole the previous one leaves open.

1. The plan: 3-2-1, honestly

Three copies of anything you care about, on two different kinds of storage, with one of them somewhere else.

A copy only counts if it survives the loss of the thing it was copied from. That rules out RAID and ZFS mirrors (one copy on resilient disks), snapshots (same pool as the data), a second copy on the same host, and sync folders (delete at home, delete in the cloud). The NAS is a real second copy, but it is still in the same house. Off-site means a different building.

Before touching any job, write a one-page inventory: each thing you run, how it is backed up, how far back you can go, and how you would restore it. The restore column is the one that exposes the gaps.

2. vzdump: the backup you already have

Every Proxmox install ships with vzdump. Point it at storage that is not the host's own disk, such as an NFS share on the NAS:

pvesm add nfs nas-backup --server 192.168.10.40 --export /volume1/proxmox \
  --content backup --options vers=4.1

Then create one job under Datacenter → Backup → Add with Selection mode: All and your scratch guests under Exclude, so every new guest is protected the day it is created. Snapshot mode, ZSTD compression, a nightly schedule and a notes template like {{guestname}} on {{node}}.

Install the QEMU guest agent in every VM and enable it in the VM's Options. With it, snapshot mode asks the guest to flush its filesystems first, which is the difference between a consistent backup and one that needs fsck on restore.

3. Proxmox Backup Server: when vzdump isn't enough

PBS adds deduplication, incremental backups, verify jobs and client-side encryption. The trap is running it on the same host, or in a VM on the same host with its datastore on the same pool. It works beautifully until the host dies, and then the backups die with it. Give PBS its own hardware, however modest: an old office PC with one large disk and 4 GB of RAM is plenty for a home datastore.

Connect it with a dedicated backup@pbs user rather than root, and turn on client-side encryption:

pvesm set pbs01 --encryption-key autogen

Every chunk is then encrypted before it leaves the node. Download that key immediately and store it somewhere that is not the cluster, such as a password manager or a printed QR code. Without the key, every encrypted backup is unrecoverable. Losing it is the one mistake with no undo.

Running both is a sensible shape: PBS nightly for everything, plus vzdump to the NAS for the few guests you want as single portable files.

4. Retention that lets you sleep

keep-daily=7 does not mean "keep seven days". It means "keep the last backup from each of the last seven days that have a backup". If the job failed for a month and then ran once, that one run can satisfy every keep rule at once, and pruning deletes the older history. The rules keep the newest backup per calendar bucket; they never promise coverage of time.

Retention also does not protect you from a bad backup: if the guest was already corrupted, you just have seven copies of the corruption. That is why weekly and monthly buckets matter. Set retention on the storage or the PBS prune job, not per job, check it in the prune simulator, and take a protected backup before every risky change so pruning cannot touch it.

5. Off-site: the copy that survives the house

Three realistic options: an encrypted copy in Backblaze B2 via rclone, a PBS sync job to a friend's box over Tailscale, or a USB disk rotated to work. The USB disk is cheap and fast to restore from, but it is not automatic, and that is its problem.

For B2, put an rclone crypt remote on top of the bucket with a key scoped to that bucket, sync the dump directory nightly with a bandwidth limit during the day, add a lifecycle rule so hidden versions expire, and run rclone check monthly. Store the two crypt passwords with your PBS key, outside the homelab. And read the current B2 price from Backblaze's own pricing page rather than from any guide, including this one.

The trap here is the off-site copy that was set up once and never checked: an expired app key, a friend's box that was powered off, a bucket that filled up. Off-site is where "no news is good news" does the most damage.

6. Restore testing: the only proof

"Verified" means different things at each layer. A job reporting OK means it finished writing. zstd -t means the archive is complete and decompresses. A PBS verify job means the chunks still match their hashes. None of them means the guest boots.

Once a quarter, run four drills, each restored to a new ID with the network unplugged, then destroyed:

  1. A VM from PBS. Does it boot, and is last night's data there?
  2. A container from a vzdump archive on the NAS (second tool, second storage).
  3. A single file from PBS using File Restore. This is the restore you will do most often.
  4. Something from off-site. This is the only drill that proves the copy that survives the house.
qmrestore pbs01:backup/vm/101/2026-10-08T01:30:00Z 9101 \
  --storage local-zfs --unique 1
qm set 9101 --net0 virtio,bridge=vmbr0,link_down=1
qm start 9101

Write each drill down: date, what, from where, result. A drill nobody wrote down did not happen.

7. Alerts for the jobs that quietly stop

Alerting only on failure has a blind spot: a job that never runs never fails. The alert you need is "nothing succeeded recently".

Use the Proxmox notification system (VE 8.1+) for warnings and errors, then add a dead-man's switch: a check URL, from a service like healthchecks.io or a self-hosted Uptime Kuma push monitor, that your job pings on success. vzdump's hook script makes it a few lines in /etc/vzdump.conf. Set the check's period to a day with a grace of a few hours, and a night the job does not run becomes a phone notification by breakfast. Do the same for the rclone sync.

Finally, a weekly backup-age report that lists the newest backup of every guest and flags any older than two days, or any guest with no backup at all. That catches the "selected VMs" trap no matter how it sneaks back in.

The short version

  • An inventory with a tested restore path per row
  • One vzdump or PBS job in Selection mode All, on storage that is not the host
  • PBS on its own hardware, encrypted, key saved outside the cluster
  • Retention you have actually checked in the simulator
  • An off-site copy that is automatic and monitored
  • Quarterly restore drills, written down
  • A dead-man's switch, so silence becomes an alert

More articles