Enterprise backup solution for Proxmox VE virtual machines, containers, and physical hosts with deduplication, encryption, and incremental snapshots.

Table of Contents#

  1. Overview
  2. PVE Built-in Backup vs Proxmox Backup Server
  3. Proxmox Backup Server Setup
  4. Storage Backend Configuration
  5. Backing Up VMs and Containers
  6. Backing Up Physical Hosts
  7. Scheduling and Retention Policies
  8. Restoring Data
  9. Verification and Integrity Checks
  10. Encryption and Compression
  11. API Automation
  12. User and Permission Management
  13. Troubleshooting
  14. See Also
  15. 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#

FeaturePVE Backup (vzdump)Proxmox Backup Server
Storage formatSingle file per backup (vma/tar)Chunked, deduplicated datastore
DeduplicationNoYes (variable-length chunks)
IncrementalNo (always full, or snapshot-based)Yes (block-level incremental)
EncryptionNoYes (client-side AES-256-GCM)
File-level restoreLimited (extract from archive)Native (browse and download individual files)
Physical host backupNoYes (via proxmox-backup-client)
Storage backendsAny PVE storage (local, NFS, CIFS, PBS)Local directory, ZFS
Remote replicationPVE replication (ZFS-based)Datastore sync to remote PBS
Retention managementBasic (keep-last, keep-daily, etc.)Full GFS retention policies
Web UIIntegrated in PVESeparate PBS web interface
Verify jobsManual extraction testAutomated 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-server

Access 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/datastore

Storage Backend Recommendations#

BackendDedup EfficiencyPerformanceNotes
ext4 on HDDGoodModerateSimple, widely supported
ext4 on SSDGoodHighBest for small-to-medium workloads
XFSGoodHighGood for large files
ZFSGood + native checksumsHighRecommended; adds scrubbing and snapshots
ZFS with SSD SLOG/L2ARCBestHighestOptimal 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-data

Disk 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 snapshot

Backup modes:

ModeDescriptionDowntime
snapshotLive snapshot (QEMU dirty bitmap)None
suspendSuspend VM, copy, resumeBrief
stopStop VM, copy, startExtended

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-client

File-Level Backup#

proxmox-backup-client backup root.pxar:/ \
  --repository <user>@<pbs-host>:<datastore> \
  --exclude /dev --exclude /proc --exclude /sys --exclude /tmp --exclude /run

Disk 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=2

Or 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=2

PBS 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 2

Retention Policy Explanation#

PolicyMeaning
keep-last=NKeep the last N backups regardless of age
keep-daily=NKeep one backup per day for the last N days
keep-weekly=NKeep one backup per week for N weeks
keep-monthly=NKeep one backup per month for N months
keep-yearly=NKeep 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/restore

From 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
ParameterDescription
--ignore-verified trueSkip 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-pool

10. 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.json

Store 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.json

Compression#

PVE backup compression options:

AlgorithmSpeedRatioCPU Usage
noneFastest1:1None
lzoFastLowLow
gzipMediumMediumMedium
zstdFastHighLow-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>/gc

PVE 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>/vzdump

Python 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@pbs

PBS Roles#

RolePermissions
NoAccessNo access
AdminFull administrative access
AuditRead-only access to all configuration
DatastoreAdminFull access to datastore management
DatastoreBackupCreate and manage own backups
DatastoreReaderRead access to datastore content

Troubleshooting#

IssueCauseSolution
connection refused to PBSPBS service not running or firewallCheck systemctl status proxmox-backup-proxy; open port 8007
Backup fails with no space leftDatastore disk fullRun GC, prune old snapshots, expand storage
TLS fingerprint mismatchPBS certificate changedUpdate fingerprint in PVE storage config
Incremental backup sends full dataChanged backup parameters or corrupted indexCheck PBS logs; may need one full backup to re-baseline
Verify job reports errorsBit rot or disk failureReplace failing disk; restore affected snapshots from replica
permission denied on backupInsufficient PBS ACL permissionsGrant DatastoreBackup role to the backup user
Slow backup performanceNetwork bottleneck or storage I/OCheck bandwidth; use zstd compression; consider SSD cache
vzdump lock timeoutPrevious backup still runningWait for completion or qm unlock <vmid>

See Also#

Sources#