Proxmox Backup Server (PBS)¶
PBS does image-level backups of Proxmox VMs and LXCs with deduplication and snapshot verification. I run it as a small VM backed by an external USB drive, which keeps the backup target independent from the hypervisor's own storage. Full Proxmox setup is in Proxmox VE.
Step 1: Mount the USB drive to the host¶
For an all-purpose external drive (mine is 22 TB) shared by any VM, mount it on the host and expose it to VMs via Virtiofs — that pattern is described in Proxmox VE → Device passthrough and shared directories. Proxmox's UI still doesn't mount drives cleanly, so I use Cockpit for this step.
Step 2: Create a Directory Mapping¶
At the Datacenter level, add a Directory Mapping — e.g. PBS-Directory — pointing at a subfolder of the mounted drive, such as /mnt/external22TB/backups. A subfolder keeps the mapping clean if you create other mappings for other purposes.
Step 3: Create the PBS VM¶
Grab the installer ISO: click local storage under your node → ISO Images → Download from URL, using the link from the PBS downloads page.
VM sizing: 10 GB storage, 2 GB RAM, 2 CPUs.
Step 4: Mount the storage into the VM¶
Use raw-block passthrough, not virtiofs, for backup storage
The PBS datastore used to be a virtiofs share. It failed vzdump about 50% of the 03:00 UTC window with os error 23 (ENFILE, too many open files). Every file operation through the FUSE layer goes through virtiofsd, and a datastore that holds many files open hits the descriptor ceiling. Migrated to raw-block passthrough on 2026-08-29 and the failures stopped. The rule: prefer raw-block passthrough over virtiofs for backup-critical external storage. The story is in The stale mount that ate half the backup windows.
If you must use virtiofs for a shared drive, know the recovery path: a stale FUSE daemon plus a wedged guest transport. qm reset is not a guest reboot for virtiofs purposes — it leaves the vhost-user channel at "Connection refused". Only qm stop plus qm start spawns a fresh virtiofsd.
For a shared drive, Hardware → Add → Virtiofs, select the PBS-Directory mapping. Then in the PBS web UI (VM IP, port 8007) open the console and mount:
Persist in /etc/fstab:
Then in the PBS UI: Add Datastore → name it backup-local, type Local, path /mnt/pbs-backup, set your prune schedule. Verify the datastore shows the true physical drive size, then under Options set Verify New Snapshots to Yes — this checks snapshots after they're taken.
Step 5: Create a user for Proxmox VE to use¶
Configuration → Access Control → Add — e.g. user proxmox with a password. On the user's Permissions tab, add a permission at path /datastore with role DatastoreAdmin.
Step 6: Add PBS as Proxmox storage¶
Back in Proxmox VE: Datacenter → Storage → Add → Proxmox Backup Server:
- id:
pbs-backup-local - Server: the PBS VM's IP
- User:
proxmox@pbs+ password - Datastore:
/datastore/backup-local
It now appears under your other storages in the file tree.
Step 7: Schedule the backup job¶
Datacenter → Backup → Add, select storage pbs-backup-local, pick a schedule, select the VMs/LXCs to back up. Done.
The job that actually runs¶
On the Powerspec node the live job is backup-562b83c1-cc80225a: VMID 100, the GPU VM, mode: snapshot, schedule 03:00, storage pbs-backup-local, notification-mode: notification-system. Snapshot mode rather than suspend or stop, so the guest is not interrupted.
The datastore backup-local is verify-new = 1 and gc-schedule = daily, and the prune policy is keep-daily 3, keep-weekly 3, keep-monthly 3, keep-yearly 1.
CLI-created datastores need the notification mode opted in
notification-mode = notification-system is what makes events fire on a datastore. A datastore created through the UI gets it; a CLI-created one does not, and then no notifications fire at all. This is the kind of thing you only notice when a backup fails silently.
Notifications¶
PBS notifications are a separate system from Proxmox VE. They live in /etc/proxmox-backup/notifications.cfg, with secrets in notifications-priv.cfg at mode 600. There is no /etc/pve/ directory on a dedicated PBS box.
The builtin default-matcher routes everything except a successful prune to mail-to-root. I added a Gotify path on top of that:
- endpoint
gateway-gotify→http://192.168.5.8:2212 - matcher
gotify-backups→exact:typein {gc, prune, verify, sync, package-updates}, modeany, targetgateway-gotify
The CLI, worth knowing because the gotify endpoint takes the app token as a string, not the numeric app id:
proxmox-backup-manager notification endpoint gotify create gateway-gotify \
--server http://192.168.5.8:2212 --token <app-token>
proxmox-backup-manager notification matcher create gotify-backups \
--match-field exact:type=gc --match-field exact:type=prune \
--mode any --target gateway-gotify
The notification types PBS can emit on 4.1.0: gc, prune, verify, sync, package-updates, acme, tape-backup, tape-load, test. There are no verify or sync jobs configured yet, so only gc and prune fire.
See also¶
- Proxmox VE
- Backups — file/DB-level backup strategy (Kopia, pg_dump)
- Blog post: Proxmox Backup Server to USB Drive