Enterprise backup solution for Proxmox VE virtual machines, containers, and physical hosts with deduplication, encryption, and incremental snapshots.
Table of Contents#
- Overview
- PVE Built-in Backup vs Proxmox Backup Server
- Proxmox Backup Server Setup
- Storage Backend Configuration
- Backing Up VMs and Containers
- Backing Up Physical Hosts
- Scheduling and Retention Policies
- Restoring Data
- Verification and Integrity Checks
- Encryption and Compression
- API Automation
- User and Permission Management
- Troubleshooting
- See Also
- Sources
1. Overview#
Proxmox provides two distinct backup mechanisms: built-in VE backup (vzdump) and Proxmox Backup Server (PBS). Both support full, incremental, and snapshot-based backups for QEMU VMs and LXC containers, but PBS adds deduplication, client-side encryption, and granular file-level restore.
Key features of PBS:
- Block-level deduplication - identical data chunks stored once across all backup jobs
- Incremental backups - only changed blocks are transferred after the initial full backup
- Client-side encryption - data encrypted before leaving the client (AES-256-GCM)
- Flexible restore - full VM/container restore, file-level restore, and live-mount
- Integrity verification - scheduled verify jobs detect bit rot and corruption
- Remote sync - replicate datastores to off-site PBS instances
2. PVE Built-in Backup vs Proxmox Backup Server#
| Feature | PVE Backup (vzdump) | Proxmox Backup Server |
|---|---|---|
| Storage format | Single file per backup (vma/tar) | Chunked, deduplicated datastore |
| Deduplication | No | Yes (variable-length chunks) |
| Incremental | No (always full, or snapshot-based) | Yes (block-level incremental) |
| Encryption | No | Yes (client-side AES-256-GCM) |
| File-level restore | Limited (extract from archive) | Native (browse and download individual files) |
| Physical host backup | No | Yes (via proxmox-backup-client) |
| Storage backends | Any PVE storage (local, NFS, CIFS, PBS) | Local directory, ZFS |
| Remote replication | PVE replication (ZFS-based) | Datastore sync to remote PBS |
| Retention management | Basic (keep-last, keep-daily, etc.) | Full GFS retention policies |
| Web UI | Integrated in PVE | Separate PBS web interface |
| Verify jobs | Manual extraction test | Automated scheduled verification |
When to use PVE backup: simple setups, quick one-off backups, storage backends without PBS support.
When to use PBS: production environments needing deduplication, encryption, compliance verification, or off-site replication.
3. Proxmox Backup Server Setup#
Installation#
PBS can be installed as a standalone ISO or added to an existing Debian system:
# Add PBS repository
echo "deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription" \
> /etc/apt/sources.list.d/pbs.list
# Import GPG key
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg \
-O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
# Install
apt update
apt install proxmox-backup-serverAccess the web UI at https://<pbs-host>:8007.
Adding PBS Storage to PVE#
In the PVE web UI: Datacenter > Storage > Add > Proxmox Backup Server
ID: pbs-store
Server: <pbs-host>
Username: backup@pbs
Datastore: <datastore-name>
Fingerprint: <pbs-tls-fingerprint>Or via CLI:
pvesm add pbs pbs-store \
--server <pbs-host> \
--username backup@pbs \
--datastore <datastore-name> \
--fingerprint <fingerprint> \
--password <password>4. Storage Backend Configuration#
PBS uses datastores to organize backup data. Each datastore is a directory on the PBS host.
Creating a Datastore#
Via the PBS web UI: Administration > Datastore > Add Datastore
Or via CLI:
proxmox-backup-manager datastore create <name> --path /path/to/datastoreStorage Backend Recommendations#
| Backend | Dedup Efficiency | Performance | Notes |
|---|---|---|---|
| ext4 on HDD | Good | Moderate | Simple, widely supported |
| ext4 on SSD | Good | High | Best for small-to-medium workloads |
| XFS | Good | High | Good for large files |
| ZFS | Good + native checksums | High | Recommended; adds scrubbing and snapshots |
| ZFS with SSD SLOG/L2ARC | Best | Highest | Optimal for production PBS |
ZFS Datastore Setup#
# Create a ZFS pool for backups
zpool create -o ashift=12 backup-pool mirror /dev/sda /dev/sdb
# Create a dataset
zfs create backup-pool/pbs-data
# Create the PBS datastore
proxmox-backup-manager datastore create main --path /backup-pool/pbs-dataDisk Space Management#
# Show datastore usage
proxmox-backup-manager datastore list
# Garbage collection (remove orphaned chunks)
proxmox-backup-client garbage-collect <datastore>5. Backing Up VMs and Containers#
From PVE Web UI#
Datacenter > Backup > Add to create a scheduled backup job, or right-click a VM/CT > Backup for an immediate backup.
Using vzdump (PVE CLI)#
# Backup a single VM (ID 100) to PBS storage
vzdump 100 --storage pbs-store --mode snapshot --compress zstd
# Backup multiple VMs
vzdump 100 101 102 --storage pbs-store --mode snapshot
# Backup all VMs on the node
vzdump --all --storage pbs-store --mode snapshotBackup modes:
| Mode | Description | Downtime |
|---|---|---|
snapshot | Live snapshot (QEMU dirty bitmap) | None |
suspend | Suspend VM, copy, resume | Brief |
stop | Stop VM, copy, start | Extended |
Using proxmox-backup-client (Direct to PBS)#
# Backup VM disk image directly
proxmox-backup-client backup vm-100-disk-0.img:/dev/vg/vm-100-disk-0 \
--repository <user>@<pbs-host>:<datastore>6. Backing Up Physical Hosts#
Install the PBS client on any Debian-based physical host:
apt install proxmox-backup-clientFile-Level Backup#
proxmox-backup-client backup root.pxar:/ \
--repository <user>@<pbs-host>:<datastore> \
--exclude /dev --exclude /proc --exclude /sys --exclude /tmp --exclude /runDisk Image Backup#
proxmox-backup-client backup disk0.img:/dev/sda \
--repository <user>@<pbs-host>:<datastore>Environment Variables#
Set these to avoid repeating connection details:
export PBS_REPOSITORY="<user>@<pbs-host>:<datastore>"
export PBS_PASSWORD="<password>"
export PBS_FINGERPRINT="<tls-fingerprint>"7. Scheduling and Retention Policies#
PVE Backup Jobs#
In PVE web UI: Datacenter > Backup > Add
Storage: pbs-store
Schedule: daily at 02:00
Mode: snapshot
Compress: zstd
Retention: keep-daily=7, keep-weekly=4, keep-monthly=6, keep-yearly=2Or via CLI:
pvesh create /cluster/backup \
--storage pbs-store \
--schedule "02:00" \
--mode snapshot \
--compress zstd \
--vmid "100,101,102" \
--prune-backups keep-daily=7,keep-weekly=4,keep-monthly=6,keep-yearly=2PBS Prune Jobs#
On PBS directly, configure prune jobs per datastore:
proxmox-backup-manager prune-job create daily-prune \
--store <datastore> \
--schedule "daily 04:00" \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--keep-yearly 2Retention Policy Explanation#
| Policy | Meaning |
|---|---|
keep-last=N | Keep the last N backups regardless of age |
keep-daily=N | Keep one backup per day for the last N days |
keep-weekly=N | Keep one backup per week for N weeks |
keep-monthly=N | Keep one backup per month for N months |
keep-yearly=N | Keep one backup per year for N years |
Policies are evaluated in order from most specific (keep-last) to least specific (keep-yearly). A backup matching any policy is kept.
8. Restoring Data#
Full VM/Container Restore (PVE)#
Via web UI: Storage > PBS > select backup > Restore
Via CLI:
# Restore VM 100 from PBS
qmrestore pbs-store:backup/vm/100/<backup-timestamp> 100
# Restore to a different VM ID
qmrestore pbs-store:backup/vm/100/<backup-timestamp> 200
# Restore LXC container
pct restore 100 pbs-store:backup/ct/100/<backup-timestamp>File-Level Restore#
PBS supports browsing and extracting individual files:
# Mount a backup for browsing
proxmox-backup-client mount <snapshot> /mnt/restore \
--repository <user>@<pbs-host>:<datastore>
# Browse and copy needed files
cp /mnt/restore/path/to/file /destination/
# Unmount
fusermount -u /mnt/restoreFrom the PBS web UI, navigate to the snapshot and use the built-in file browser.
Restore Physical Host Backup#
proxmox-backup-client restore <snapshot> root.pxar /target/path \
--repository <user>@<pbs-host>:<datastore>9. Verification and Integrity Checks#
Verify Jobs (PBS)#
Scheduled verification reads backup data, decrypts it, and validates checksums:
proxmox-backup-manager verify-job create weekly-verify \
--store <datastore> \
--schedule "weekly mon 06:00" \
--ignore-verified true \
--outdated-after 30| Parameter | Description |
|---|---|
--ignore-verified true | Skip snapshots already verified within the threshold |
--outdated-after <days> | Re-verify snapshots older than N days since last verification |
Manual Verification#
# Verify all snapshots in a datastore
proxmox-backup-manager verify <datastore>
# Verify a specific snapshot
proxmox-backup-client verify <snapshot> \
--repository <user>@<pbs-host>:<datastore>Garbage Collection#
Garbage collection removes orphaned chunks no longer referenced by any snapshot:
proxmox-backup-manager garbage-collection start <datastore>
# Schedule automatic GC
proxmox-backup-manager datastore update <datastore> \
--gc-schedule "daily 03:00"ZFS Scrubbing (If Using ZFS Backend)#
# Run a scrub to detect and repair bit rot
zpool scrub backup-pool
# Check scrub status
zpool status backup-pool10. Encryption and Compression#
Client-Side Encryption#
PBS supports AES-256-GCM encryption. The key is generated client-side; PBS never sees the plaintext.
# Generate an encryption key
proxmox-backup-client key create --kdf scrypt /path/to/encryption-key.json
# Backup with encryption
proxmox-backup-client backup root.pxar:/ \
--repository <user>@<pbs-host>:<datastore> \
--keyfile /path/to/encryption-key.json
# Back up the key itself (critical for recovery)
proxmox-backup-client key show /path/to/encryption-key.jsonStore the encryption key separately from the backup. Without the key, encrypted backups are unrecoverable.
PVE Integration with Encryption#
When adding PBS storage to PVE, specify the encryption key:
pvesm set pbs-store --encryption-key /path/to/encryption-key.jsonCompression#
PVE backup compression options:
| Algorithm | Speed | Ratio | CPU Usage |
|---|---|---|---|
none | Fastest | 1:1 | None |
lzo | Fast | Low | Low |
gzip | Medium | Medium | Medium |
zstd | Fast | High | Low-Medium |
zstd is the recommended default for its excellent speed-to-ratio balance.
11. API Automation#
PBS and PVE both expose REST APIs for automation.
PBS API#
# Authenticate and get a ticket
curl -sk -d "username=<user>@pbs&password=<pass>" \
https://<pbs-host>:8007/api2/json/access/ticket
# List datastores
curl -sk -H "Authorization: PBSAPIToken=<user>@pbs!<token-id>:<secret>" \
https://<pbs-host>:8007/api2/json/admin/datastore
# List snapshots in a datastore
curl -sk -H "Authorization: PBSAPIToken=<user>@pbs!<token-id>:<secret>" \
https://<pbs-host>:8007/api2/json/admin/datastore/<name>/snapshots
# Start garbage collection
curl -sk -X POST -H "Authorization: PBSAPIToken=<user>@pbs!<token-id>:<secret>" \
https://<pbs-host>:8007/api2/json/admin/datastore/<name>/gcPVE API for Backup Management#
# Create an API token
pveum user token add root@pam backup-automation --privsep=0
# List backup jobs
curl -sk -H "Authorization: PVEAPIToken=root@pam!backup-automation=<secret>" \
https://<pve-host>:8006/api2/json/cluster/backup
# Trigger a backup
curl -sk -X POST \
-H "Authorization: PVEAPIToken=root@pam!backup-automation=<secret>" \
-d "vmid=100&storage=pbs-store&mode=snapshot&compress=zstd" \
https://<pve-host>:8006/api2/json/nodes/<node>/vzdumpPython Automation Example#
import requests
import urllib3
urllib3.disable_warnings()
PBS_URL = "https://<pbs-host>:8007/api2/json"
HEADERS = {"Authorization": "PBSAPIToken=<user>@pbs!<token-id>:<secret>"}
# List snapshots
resp = requests.get(f"{PBS_URL}/admin/datastore/<name>/snapshots",
headers=HEADERS, verify=False)
for snap in resp.json()["data"]:
print(f"{snap['backup-type']}/{snap['backup-id']}/{snap['backup-time']}")12. User and Permission Management#
PBS Users and API Tokens#
# Create a backup user
proxmox-backup-manager user create backup@pbs --password <password>
# Create an API token
proxmox-backup-manager user generate-token backup@pbs automation
# Grant datastore access
proxmox-backup-manager acl update / DatastoreBackup --auth-id backup@pbsPBS Roles#
| Role | Permissions |
|---|---|
NoAccess | No access |
Admin | Full administrative access |
Audit | Read-only access to all configuration |
DatastoreAdmin | Full access to datastore management |
DatastoreBackup | Create and manage own backups |
DatastoreReader | Read access to datastore content |
Troubleshooting#
| Issue | Cause | Solution |
|---|---|---|
connection refused to PBS | PBS service not running or firewall | Check systemctl status proxmox-backup-proxy; open port 8007 |
Backup fails with no space left | Datastore disk full | Run GC, prune old snapshots, expand storage |
| TLS fingerprint mismatch | PBS certificate changed | Update fingerprint in PVE storage config |
| Incremental backup sends full data | Changed backup parameters or corrupted index | Check PBS logs; may need one full backup to re-baseline |
| Verify job reports errors | Bit rot or disk failure | Replace failing disk; restore affected snapshots from replica |
permission denied on backup | Insufficient PBS ACL permissions | Grant DatastoreBackup role to the backup user |
| Slow backup performance | Network bottleneck or storage I/O | Check bandwidth; use zstd compression; consider SSD cache |
vzdump lock timeout | Previous backup still running | Wait for completion or qm unlock <vmid> |