LUNAROPS · OPERATIONAL UPLINK 100% UPTIME 1,247d POSTS 893 JEFF.MOON@LUNAROPS.DEV UTC --:--:--

Proxmox Backup Server In Depth

proxmoxbackuppbsdeduplicationencryptiondisaster-recoveryinfrastructure

Proxmox Backup Server In Depth

Proxmox Backup Server (PBS) is a dedicated backup solution designed specifically for Proxmox VE environments. Unlike generic backup tools bolted onto a hypervisor, PBS was built from the ground up around the specific characteristics of VM and container backups: large, structured disk images that change incrementally between snapshots.

The result is a backup system with genuinely impressive efficiency: incremental forever backups, client-side deduplication across all backups in a datastore, optional end-to-end encryption, and a verification system that continuously validates backup integrity. This post covers how it works internally, how to operate it at scale, and how to build a resilient multi-site backup architecture.


Architecture Overview

Core Components

Datastore: the primary organizational unit in PBS. A datastore is a directory on the PBS filesystem where backup data is stored. Each datastore maintains its own chunk store, catalog, and retention configuration. You might have separate datastores for different environments (production, staging) or different retention requirements.

Chunk Store: the heart of PBS’s efficiency. When PBS stores a backup, it breaks the disk image into fixed-size chunks (4 MB by default), computes a SHA-256 hash of each chunk, and stores only unique chunks. If the same 4 MB block exists in ten different backups across ten different VMs, it’s stored exactly once. This deduplication operates across all backups in a datastore — not just multiple backups of the same VM.

Backup Groups: backups are organized as type/name — for example vm/100 or ct/200. Within a group, each backup is a snapshot identified by a timestamp.

Catalog: a fast lookup index that allows PBS to list backup contents and restore individual files without loading the full backup.

Backup Types

PBS supports three backup types:

  • VM backups (vm/): QEMU virtual machine disk images
  • Container backups (ct/): LXC container filesystems
  • Host backups (host/): arbitrary directories from the PBS client — used for backing up non-Proxmox hosts with the proxmox-backup-client tool

How Incremental Backups Work

PBS uses a “dirty bitmap” approach for VM backups. QEMU maintains a dirty bitmap that tracks which 64 KB blocks have changed since the last backup. On the next backup run:

  1. PBS reads the dirty bitmap from QEMU
  2. Only reads the changed 64 KB regions from the disk
  3. Rechunks those regions into 4 MB chunks
  4. Deduplicates against the chunk store (most chunks will already exist)
  5. Writes only new unique chunks

The result: after the first full backup, subsequent backups typically transfer 1–5% of the disk size and complete in minutes regardless of disk size. A 500 GB VM with 2 GB of changes since the last backup takes roughly the same time to back up as a 50 GB VM with 2 GB of changes.


Installation and Initial Setup

Installing PBS

PBS is a separate Debian-based distribution (not installed on Proxmox VE nodes). Download the ISO from proxmox.com/downloads.

Install on dedicated hardware (or a VM on a separate host — don’t run PBS on the same host whose VMs it’s backing up). Minimum recommended specs:

  • 4 CPU cores
  • 8 GB RAM (16+ GB for large datastores)
  • Boot drive: 32 GB SSD (OS only)
  • Backup storage: sized to your backup data × dedup ratio × retention count

Initial Configuration

After installation, access the web UI at https://pbs-host:8007.

1
2
3
4
5
6
7
8
# Add the no-subscription repository if no license
echo "deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription" \
  > /etc/apt/sources.list.d/pbs-no-subscription.list

# Remove enterprise repo if no subscription
rm /etc/apt/sources.list.d/pbs-enterprise.list

apt update && apt full-upgrade

Creating a Datastore

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Via CLI
proxmox-backup-manager datastore create main /backup/main \
  --comment "Primary backup datastore"

# Or via web UI: Administration → Datastores → Add Datastore

# View datastore info
proxmox-backup-manager datastore info main

# Check disk usage
proxmox-backup-manager datastore show-stats main

Adding PBS to Proxmox VE

In each Proxmox VE cluster, add the PBS instance as a storage target:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# On the PVE cluster
pvesm add pbs pbs-main \
  --server pbs.example.com \
  --datastore main \
  --username backup@pbs!pve-token \
  --password <api-token-secret> \
  --fingerprint <tls-fingerprint>

# Get the fingerprint from PBS
proxmox-backup-manager cert info | grep Fingerprint

Or via the PVE web UI: Datacenter → Storage → Add → Proxmox Backup Server.


Deduplication Internals

Understanding PBS’s chunk store helps you make good decisions about datastore design and hardware sizing.

The Chunk Store on Disk

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Explore the chunk store structure
ls /backup/main/.chunks/
# 00/ 01/ 02/ ... ff/  (256 subdirectories, one per first byte of hash)

# Each chunk is stored as a compressed file named by its SHA-256 hash
ls /backup/main/.chunks/ab/
# abcdef1234567890...sha256hash.chunk.gz

# Count total chunks and estimate dedup ratio
find /backup/main/.chunks -name "*.chunk*" | wc -l

# PBS provides dedup statistics directly
proxmox-backup-manager datastore show-stats main
# Disk usage: 1.2 TiB
# Dedup factor: 4.3x (logical data: 5.16 TiB stored in 1.2 TiB)

What Determines Dedup Ratio?

Good dedup ratios (3–10×) come from:

  • Many similar VMs: if you have 20 web servers built from the same template, their base OS is deduplicated across all of them
  • Frequent backups: more backup snapshots means more opportunities to find duplicate chunks
  • Large, compressible data: databases, logs, and document files compress and dedup well
  • Stable data: files that don’t change between backups contribute heavily to dedup savings

Poor dedup ratios (<2×) come from:

  • Encrypted VM disks: already-encrypted data has high entropy and doesn’t compress or dedup
  • Databases with random I/O patterns: write-heavy databases scatter changes across large files
  • Video/media files: already compressed, very low dedup potential

Chunk Store Garbage Collection

When backups are deleted (by retention policy or manually), the chunks they referenced may become unreferenced if no other backup uses them. Garbage collection reclaims this space:

1
2
3
4
5
6
7
8
# Run garbage collection manually
proxmox-backup-manager garbage-collection start main

# View GC status
proxmox-backup-manager garbage-collection status main

# Schedule automatic GC (runs after retention-triggered deletions by default)
# GC is scheduled automatically when you configure retention

GC is a two-phase process:

  1. Mark phase: scan all backup manifests to find all referenced chunk hashes
  2. Sweep phase: delete any chunk files not referenced by any backup

GC can be I/O intensive on large datastores. Schedule it during off-peak hours.


Encryption

PBS supports end-to-end client-side encryption. Encryption happens on the Proxmox VE host before data is sent to PBS — the PBS server never sees unencrypted data.

Encryption Architecture

PBS uses AES-256-GCM for chunk encryption. The encryption key is generated on the client, and chunks are encrypted before being sent to the server. The key can be protected with a passphrase.

Important implications:

  • PBS server compromise doesn’t expose your data
  • You cannot recover backups without the encryption key — store it safely, separately from PBS
  • Deduplication still works across encrypted backups from the same client (same key = same encrypted chunk for same data)
  • Deduplication does NOT work across different encryption keys

Setting Up Encryption

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# On the Proxmox VE host (or backup client)
# Generate an encryption key
proxmox-backup-client key create /etc/pve/priv/backup-encryption.key
# You'll be prompted for a passphrase (recommended)

# View key information
proxmox-backup-client key show /etc/pve/priv/backup-encryption.key

# Export key for safekeeping (store this SEPARATELY from PBS)
proxmox-backup-client key export-to-file \
  /etc/pve/priv/backup-encryption.key \
  /root/backup-key-BACKUP.json
# Store /root/backup-key-BACKUP.json in a password manager, offline storage, etc.

Configure encryption in PVE backup jobs:

1
2
3
# Via web UI: Datacenter → Backup → Edit job → Encryption key field
# Or in the storage config
pvesm set pbs-main --encryption-key /etc/pve/priv/backup-encryption.key

Key Management

The encryption key file must be available on the PVE host when backups run. For automated backups, remove the passphrase or store the passphrase in a secrets manager:

1
2
3
4
5
6
7
# Change passphrase (or remove it for automation)
proxmox-backup-client key change-passphrase \
  /etc/pve/priv/backup-encryption.key
# Enter new passphrase (leave blank to remove)

# For Vault integration, fetch key at backup time
# Store encrypted key in Vault, decrypt to temp file, backup, delete temp file

Retention Policies

Retention policies determine how many backup snapshots to keep. PBS implements a “keep” policy that’s evaluated per backup group, typically expressed as:

keep-last=N   keep the N most recent backups
keep-hourly=N keep the most recent backup for each of the last N hours
keep-daily=N  keep the most recent backup for each of the last N days
keep-weekly=N keep the most recent backup for each of the last N weeks
keep-monthly=N keep the most recent backup for each of the last N months
keep-yearly=N keep the most recent backup for each of the last N years

These combine. Proxmox evaluates which backups to keep by applying all rules and keeping any backup that satisfies at least one rule.

Configuring Retention

1
2
3
4
5
6
7
8
9
# Set retention on a datastore (applies as default to all backup groups)
proxmox-backup-manager datastore update main \
  --keep-last 3 \
  --keep-daily 7 \
  --keep-weekly 4 \
  --keep-monthly 3

# Or set per-namespace/group retention in the web UI
# Datastore → main → Options → Retention

In PVE backup jobs (via web UI: Datacenter → Backup → Add/Edit):

keep-last: 3
keep-daily: 14
keep-weekly: 8
keep-monthly: 6
keep-yearly: 2

Example of what this keeps for a daily backup:

  • The 3 most recent backups (last 3 days)
  • One backup per day for the last 14 days
  • One backup per week for the last 8 weeks (~2 months)
  • One backup per month for the last 6 months
  • One backup per year for the last 2 years

This gives good coverage with reasonable storage use. Adjust based on your RPO requirements and storage budget.

Prune vs Garbage Collection

prune marks old backup snapshots for deletion according to the retention policy. gc (garbage collection) actually reclaims the disk space by removing unreferenced chunks. Both steps are needed for space to be freed:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Prune a specific group
proxmox-backup-client prune --repository pbs.example.com:main \
  --backup-type vm --backup-id 100 \
  --keep-last 3 --keep-daily 7

# Prune all groups in a datastore (PBS server-side)
proxmox-backup-manager prune-datastore main \
  --keep-last 3 --keep-daily 7 --keep-weekly 4

# Then run GC to reclaim space
proxmox-backup-manager garbage-collection start main

Tape Support

PBS supports writing backups to tape via the Linux tape subsystem (LTO drives, tape libraries). Tape is ideal for long-term archival and air-gapped offsite storage.

Tape Hardware Setup

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# Check tape drive is detected
lsscsi -g
# [2:0:0:0]    tape    HP       Ultrium 6-SCSI   Z51U  /dev/st0   /dev/sg2

# Install mtx for tape library control
apt install mtx

# Check tape library
mtx -f /dev/sg3 status

# Create a tape changer in PBS
proxmox-backup-manager tape changer create library1 \
  --path /dev/sg3 \
  --export-slots 1

# Create a tape drive
proxmox-backup-manager tape drive create lto-drive \
  --path /dev/st0 \
  --changer library1 \
  --changer-drivenum 0

Tape Pools and Media

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Create a media pool (defines tape usage policy)
proxmox-backup-manager tape pool create offsite-pool \
  --drive lto-drive \
  --encrypt true \
  --media-set-naming-scheme "Daily-%Y-%m-%d" \
  --media-set-allocation-policy "always"  # new tape set per backup run

# Label blank tapes (must be done before use)
proxmox-backup-manager tape label --drive lto-drive --pool offsite-pool

# Load and label multiple tapes in sequence
for i in {1..10}; do
  proxmox-backup-manager tape load-tape --drive lto-drive --slot $i
  proxmox-backup-manager tape label --drive lto-drive --pool offsite-pool
done

Tape Backup Jobs

1
2
3
4
5
6
7
# Create a tape backup job (copies from disk datastore to tape)
proxmox-backup-manager tape backup create \
  --store main \
  --pool offsite-pool \
  --drive lto-drive \
  --schedule "weekly" \
  --eject-media true  # eject tape after backup for offsite rotation

PBS writes backups from the disk datastore to tape in a format that supports direct restore — you don’t need to stage back to disk before restoring.


Replication Between PBS Instances

For true offsite backup protection, replicate your PBS datastore to a remote PBS instance. This is the “3rd copy” in a 3-2-1 backup strategy.

Setting Up Sync Jobs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# On the primary PBS, create a sync job that pulls from remote
# (or pushes to remote — both are supported)

# Via web UI: Datastore → main → Sync Jobs → Add

# Via CLI: sync from a remote PBS to local datastore
proxmox-backup-manager remote create offsite-pbs \
  --host pbs-offsite.example.com \
  --port 8007 \
  --userid sync@pbs \
  --password <password> \
  --fingerprint <tls-fingerprint>

proxmox-backup-manager sync-job create main-to-offsite \
  --store main \
  --remote offsite-pbs \
  --remote-store main \
  --schedule "daily" \
  --remove-vanished false \
  --comment "Daily sync to offsite PBS"

The sync job is incremental — it only transfers chunks that don’t already exist on the remote instance. After the initial full sync, daily syncs transfer only new or changed chunks, typically a small fraction of the total datastore size.

Bandwidth Limiting

1
2
3
4
5
6
7
# Limit sync bandwidth to avoid saturating the WAN link
proxmox-backup-manager sync-job update main-to-offsite \
  --rate-limit 50   # MB/s

# Or set a time-based schedule that runs during off-peak hours
proxmox-backup-manager sync-job update main-to-offsite \
  --schedule "02:00"  # run at 2 AM daily

Verifying Remote Copies

1
2
3
4
5
6
7
8
# On the remote PBS, verify backup integrity
proxmox-backup-manager verify-job create remote-verify \
  --store main \
  --schedule "weekly" \
  --ignore-verified true  # skip chunks verified in last 30 days

# View verification status
proxmox-backup-manager verify-job list

Backup Verification

PBS continuously verifies backup integrity. This is crucial — a backup that can’t be restored is not a backup.

Verification Mechanics

PBS verification:

  1. Reads every chunk referenced by the backup manifests
  2. Verifies the SHA-256 hash of each chunk matches the chunk’s filename
  3. Optionally verifies that the backup can be fully reconstructed (checks manifest completeness)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Verify all backups in a datastore
proxmox-backup-manager verify main

# Verify a specific backup group
proxmox-backup-client verify \
  --repository pbs.example.com:main \
  vm/100/2026-04-12T02:00:00Z

# Schedule automatic verification
proxmox-backup-manager verify-job create nightly-verify \
  --store main \
  --schedule "daily" \
  --ignore-verified true  # only verify chunks not verified in 30 days
  --outdated-after 30     # re-verify after 30 days

Test Restores

Verification confirms data integrity but not restorability. Periodically test full restores:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Restore a VM to a different VM ID (non-destructive test)
qmrestore pbs:backup/vm/100/2026-04-01T02:00:00Z 9100 \
  --storage local-lvm \
  --unique true  # generate new UUID and MAC address

# Start the test VM
qm start 9100

# Verify application health, then delete
qm stop 9100
qm destroy 9100

Automate this process quarterly or whenever backup software changes.


Scheduling Backup Jobs

Backup Job Configuration in PVE

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Create a backup job via CLI
pvesh create /cluster/backup \
  --id daily-vms \
  --enabled 1 \
  --schedule "02:00" \
  --storage pbs-main \
  --mode snapshot \
  --compress zstd \
  --vmid 100,101,102,103 \
  --mailnotification always \
  --mailto admin@example.com

# Or back up all VMs
pvesh create /cluster/backup \
  --id daily-all \
  --enabled 1 \
  --schedule "02:00" \
  --storage pbs-main \
  --mode snapshot \
  --compress zstd \
  --all 1 \
  --exclude 9100  # exclude test VMs

Backup modes:

  • snapshot: uses QEMU dirty bitmaps for incremental backup — fastest, recommended
  • suspend: suspends the VM briefly to take a consistent snapshot — for VMs that don’t support live snapshots
  • stop: stops the VM, backs up, restarts — slowest, most consistent

Staggering Backup Jobs

Don’t back up all VMs simultaneously. Stagger start times to avoid I/O saturation:

1
2
3
4
5
6
7
8
# Group 1: critical production VMs at 1 AM
pvesh create /cluster/backup --schedule "01:00" --vmid 100,101,102

# Group 2: secondary VMs at 2 AM
pvesh create /cluster/backup --schedule "02:00" --vmid 200,201,202

# Group 3: dev/test VMs at 3 AM
pvesh create /cluster/backup --schedule "03:00" --vmid 300,301,302

Restoring at Scale

Single VM Restore

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Via PVE web UI: Datacenter → Storage → pbs-main → Browse
# Select backup → Restore → choose target node, storage, VM ID

# Via CLI
qmrestore pbs-main:backup/vm/100/2026-04-12T02:00:00Z 100 \
  --storage local-lvm \
  --force 1  # overwrite existing VM 100

# Restore container
pct restore 200 pbs-main:backup/ct/200/2026-04-12T02:00:00Z \
  --storage local-lvm \
  --force 1

File-Level Restore

PBS can mount a VM backup as a FUSE filesystem, allowing individual file recovery without restoring the entire disk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Mount a backup for browsing
proxmox-backup-client mount \
  --repository pbs.example.com:main \
  vm/100/2026-04-12T02:00:00Z \
  /mnt/restore \
  --keyfile /etc/pve/priv/backup-encryption.key

# Browse and copy individual files
ls /mnt/restore/
# disk.img.fidx  (index file for the disk image)

# Mount the disk image as a block device
proxmox-backup-client mount \
  --repository pbs.example.com:main \
  vm/100/2026-04-12T02:00:00Z \
  /mnt/restore

# Use qemu-nbd or losetup to access partitions
qemu-nbd --connect=/dev/nbd0 /mnt/restore/disk.img.fidx
mount /dev/nbd0p1 /mnt/files
ls /mnt/files/  # browse VM filesystem

# Cleanup
umount /mnt/files
qemu-nbd --disconnect /dev/nbd0
umount /mnt/restore

Bulk Restore (Disaster Recovery)

When restoring an entire environment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# List all backups in a datastore
proxmox-backup-client list --repository pbs.example.com:main

# Restore multiple VMs in parallel
for vmid in 100 101 102 103 104; do
  qmrestore pbs-main:backup/vm/${vmid}/$(date +%Y-%m-%d)T02:00:00Z ${vmid} \
    --storage ceph-vms \
    --force 1 &
done
wait

# Start all restored VMs
for vmid in 100 101 102 103 104; do
  qm start $vmid
done

For DR scenarios where the original PVE cluster is gone, you can restore directly from a standalone PBS instance without needing PVE infrastructure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Install proxmox-backup-client on any Linux machine
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg \
  -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
echo "deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription" \
  >> /etc/apt/sources.list
apt update && apt install proxmox-backup-client

# Restore disk image to a local file
proxmox-backup-client restore \
  --repository pbs.example.com:main \
  vm/100/2026-04-12T02:00:00Z \
  disk.img.fidx \
  /tmp/vm100-disk.img

# Import to any QEMU hypervisor
qemu-img convert -f raw /tmp/vm100-disk.img -O qcow2 /var/lib/libvirt/images/vm100.qcow2

Monitoring PBS

Built-in Dashboard

PBS’s web UI shows:

  • Datastore usage and dedup ratios
  • Recent backup task status (success/failure)
  • Verification job status
  • GC and prune job history

Prometheus Integration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Enable Prometheus metrics endpoint
# PBS exposes metrics at https://pbs-host:8007/metrics

# In prometheus.yml:
scrape_configs:
  - job_name: 'proxmox-backup-server'
    scheme: https
    tls_config:
      insecure_skip_verify: true
    static_configs:
      - targets: ['pbs.example.com:8007']
    metrics_path: /metrics
    params:
      token: ['<api-token>']

Key metrics to alert on:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
groups:
  - name: pbs-alerts
    rules:
      - alert: PBSBackupFailed
        expr: proxmox_backup_task_status{type="backup", status!="OK"} == 1
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "PBS backup task failed for {{ $labels.id }}"

      - alert: PBSDatastoreNearFull
        expr: (proxmox_backup_datastore_usage_bytes / proxmox_backup_datastore_total_bytes) > 0.85
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "PBS datastore {{ $labels.store }} is {{ $value | humanizePercentage }} full"

      - alert: PBSVerificationFailed
        expr: proxmox_backup_task_status{type="verify", status!="OK"} == 1
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "PBS verification failure — backup integrity at risk"

      - alert: PBSSyncJobFailed
        expr: proxmox_backup_task_status{type="sync", status!="OK"} == 1
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "PBS sync job failed — offsite copy may be out of date"

Backup Job Notification

PBS and PVE can send email notifications on backup completion/failure:

1
2
3
4
5
6
7
8
# Configure SMTP in PVE
pvesh set /nodes/pve1/config \
  --email admin@example.com

# In backup job settings:
pvesh set /cluster/backup/daily-vms \
  --mailnotification always \
  --mailto admin@example.com

Sizing PBS Storage

Estimating Storage Requirements

Required raw storage = (total VM disk size × change rate × backup frequency × retention days) / dedup ratio

Example:
- 20 VMs averaging 100 GB each = 2 TB total disk
- 5% daily change rate = 100 GB changes/day
- Daily backups retained for 30 days
- Estimated dedup ratio: 4×

Storage = (2000 GB initial + 100 GB × 30 days) / 4 = (2000 + 3000) / 4 = 1.25 TB

Add 30% headroom: 1.25 × 1.3 = ~1.6 TB

The dedup ratio is the wildcard. Measure your actual ratio after a week of backups and adjust capacity planning accordingly.

Storage Recommendations

PBS benefits from fast storage for the chunk store metadata (small random reads/writes) and sequential throughput for chunk data:

  • Boot/OS: 32 GB SSD
  • Chunk store: ZFS on spinning HDDs works well (ZFS ARC caches hot chunks in RAM). NVMe or SATA SSD dramatically speeds up verification and restore.
  • RAM: 1 GB per TB of backup data for ZFS ARC (8 GB minimum). ZFS ARC is critical for dedup performance.

For the PBS server itself, ZFS is strongly recommended:

1
2
3
4
5
6
7
# Create ZFS pool for backup storage
zpool create backup mirror /dev/sdb /dev/sdc  # mirrored for redundancy
# or
zpool create backup raidz2 /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sde /dev/sdf

# Create dataset with appropriate settings
zfs create -o compression=zstd -o atime=off backup/main

ZFS compression (zstd) provides a second layer of space savings on top of PBS’s deduplication.


Production Checklist

Setup

  • PBS installed on dedicated hardware (not on PVE nodes being backed up)
  • Separate PBS instance at an offsite location for 3-2-1 compliance
  • ZFS on backup storage with appropriate RAIDZ or mirror level
  • TLS fingerprint pinned in PVE storage config

Encryption

  • Encryption key generated and stored in a password manager or key escrow
  • Key backup stored separately from PBS and PVE infrastructure
  • Encryption enabled on all backup jobs

Retention

  • Retention policy matches RPO requirements
  • GC scheduled after prune jobs
  • Retention policy documented and approved by stakeholders

Verification

  • Automated verification job scheduled weekly
  • Quarterly test restore documented and tracked
  • Alerts configured for verification failures

Replication

  • Sync job to offsite PBS instance configured
  • Sync job alerts on failure
  • Bandwidth limits set to avoid saturating WAN

Monitoring

  • Prometheus metrics scraped from PBS
  • Alerts for backup failure, datastore capacity, sync failure
  • Email notifications enabled for backup jobs

Proxmox Backup Server is one of the most polished open-source backup solutions available for hypervisor environments. When configured correctly — with encryption, offsite replication, automated verification, and tested restore procedures — it provides enterprise-grade backup protection at a fraction of the cost of commercial alternatives.

Comments