Skip to main content
RunBook Academy

Proxmox VEXIII · Proxmox Backup ServerPBS integration

Backing up non-PVE hosts with proxmox-backup-client

Advanced⏱ ~26 min🧪 Lab requiredproxmox-backup-clientsystemd

What you'll learn

  • Back up an arbitrary Linux host into a PBS datastore from the command line
  • Handle credentials and encryption passphrases without writing secrets into a script
  • Design exclusions and archive splits that make a host restorable rather than merely copied
  • Schedule, monitor and prune host backups without a PVE cluster in the picture

Prerequisites

Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12

Not yet marked complete on this device.

Every estate has hosts that are not virtual machines on your cluster: the physical database server nobody will virtualise, the cloud instance running the public-facing thing, the build machine, the NAS, the router with a configuration you would hate to rebuild. They usually end up on a different backup product, with a different retention policy, a different restore procedure and a different set of people who know how to use it.

proxmox-backup-client puts them in the same datastore as everything else. Same deduplication, same verification, same prune and garbage-collection machinery, same restore skills. It is a standalone binary that talks to PBS directly; PVE is not involved at any point.

Installing the client

The client ships in the Proxmox repositories, and on a non-Proxmox Debian or Ubuntu host you add the client repository rather than the full PBS one.

Configuration changeclient installation on Debian 13
set -euo pipefail

apt update && apt install -y ca-certificates wget

wget -O /usr/share/keyrings/proxmox-archive-keyring.gpg \
https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg

cat > /etc/apt/sources.list.d/pbs-client.sources <<'EOF'
Types: deb
URIs: http://download.proxmox.com/debian/pbs-client
Suites: trixie
Components: main
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF

apt update && apt install -y proxmox-backup-client
proxmox-backup-client version

The repository string and the credential

Everything the client does is aimed at a repository, whose format is:

[[username@]server[:port]:]datastore

The username defaults to root@pam if unset — which, per the previous lesson, is exactly what you do not want a standalone host holding.

Configuration changeon the PBS server: an identity for this host, scoped to one namespace
set -euo pipefail

proxmox-backup-manager user create db01@pbs --comment 'Physical DB server db01'
proxmox-backup-manager user generate-token db01@pbs client

# DatastoreBackup: can write and restore its own backups; cannot prune.
for id in 'db01@pbs' 'db01@pbs!client'; do
proxmox-backup-manager acl update /datastore/store1/hosts/db01 \
  DatastoreBackup --auth-id "$id"
done
Configuration change/etc/proxmox-backup/client.env - sourced by the unit, never committed
set -euo pipefail
install -d -m 0700 /etc/proxmox-backup

umask 077
cat > /etc/proxmox-backup/client.env <<'EOF'
PBS_REPOSITORY=db01@pbs!client@pbs1.example.com:store1
PBS_NAMESPACE=hosts/db01
PBS_PASSWORD_FILE=/etc/proxmox-backup/token.secret
PBS_ENCRYPTION_PASSWORD_FILE=/etc/proxmox-backup/key.passphrase
PBS_FINGERPRINT=aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99
EOF

printf '%s\n' 'REPLACE_ME_WITH_THE_TOKEN_SECRET' > /etc/proxmox-backup/token.secret
chmod 0600 /etc/proxmox-backup/token.secret /etc/proxmox-backup/client.env

PBS_FINGERPRINT verifies the server certificate. Setting it means a client that finds itself talking to a different server — because DNS was poisoned, or because someone stood up a lookalike — refuses rather than uploading your data to it.

Encryption, and the key you must not lose

Client-side encryption is the feature that makes it reasonable to back up a sensitive host into a shared datastore, or into a datastore you do not administer.

Configuration changecreate an encryption key, then get it out of the building
set -euo pipefail

proxmox-backup-client key create /etc/proxmox-backup/db01.key
chmod 0600 /etc/proxmox-backup/db01.key

# A printable copy for the safe. This is the escrow that matters.
proxmox-backup-client key paperkey /etc/proxmox-backup/db01.key \
> /root/db01-paperkey.txt

The backup itself

Read-only / Safea first backup, run by hand
set -euo pipefail
set -a; . /etc/proxmox-backup/client.env; set +a

proxmox-backup-client backup \
root.pxar:/ \
--keyfile /etc/proxmox-backup/db01.key \
--exclude /proc --exclude /sys --exclude /dev --exclude /run \
--exclude /tmp --exclude /var/tmp \
--exclude /var/lib/postgresql \
--exclude /mnt --exclude /media

proxmox-backup-client snapshot list

Three design decisions are embedded in that command and they are the difference between a copy and a restorable host.

Split archives by restore unit, not by directory tidiness. An archive is the granularity at which you restore. Anything you might want to recover without touching the rest deserves its own archive:

Read-only / Safemultiple archives in one snapshot
set -euo pipefail
set -a; . /etc/proxmox-backup/client.env; set +a

proxmox-backup-client backup \
system.pxar:/ \
data.pxar:/srv/data \
dbdump.pxar:/var/backups/pgdump \
--keyfile /etc/proxmox-backup/db01.key \
--exclude /proc --exclude /sys --exclude /dev --exclude /run \
--exclude /srv/data --exclude /var/backups/pgdump

Exclusions belong in two places. Pseudo-filesystems and caches go on the command line, where they are visible in the unit file and in review. Anything application-specific is better expressed as a .pxarexclude file in the directory it concerns, where it lives next to the thing it describes and survives a rewrite of the backup script. Patterns are one per line, # introduces a comment, ! reverses a pattern into an inclusion, a leading / anchors to the current directory and a pattern without one matches in subdirectories too.

A live database directory is not a backup of the database. The exclusion of /var/lib/postgresql above is deliberate: what is included is /var/backups/pgdump, produced by a dump that runs before the backup. Copying running database files with a file-level tool produces exactly the crash consistency problem from xiii-pbs-backup-modes, without even the benefit of a coordinated snapshot.

Scheduling it

There is no backup job scheduler outside PVE, and that is fine, because systemd already is one.

Configuration change/etc/systemd/system/pbs-backup.service
set -euo pipefail

cat > /etc/systemd/system/pbs-backup.service <<'EOF'
[Unit]
Description=Back up this host to Proxmox Backup Server
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/proxmox-backup/client.env
ExecStartPre=/usr/local/sbin/pre-backup-dump.sh
ExecStart=/usr/bin/proxmox-backup-client backup \
system.pxar:/ data.pxar:/srv/data dbdump.pxar:/var/backups/pgdump \
--keyfile /etc/proxmox-backup/db01.key \
--exclude /proc --exclude /sys --exclude /dev --exclude /run \
--exclude /srv/data --exclude /var/backups/pgdump
Nice=10
IOSchedulingClass=idle
EOF

cat > /etc/systemd/system/pbs-backup.timer <<'EOF'
[Unit]
Description=Nightly PBS backup

[Timer]
OnCalendar=*-*-* 01:30:00
RandomizedDelaySec=1800
Persistent=true

[Install]
WantedBy=timers.target
EOF

systemctl daemon-reload
systemctl enable --now pbs-backup.timer
systemctl list-timers pbs-backup.timer

RandomizedDelaySec matters more than it looks: forty hosts with an OnCalendar of 01:30 all connect at 01:30 and turn a manageable load into a thundering herd against one datastore. Persistent=true runs a missed backup after the host comes back, which is the behaviour you want on a machine that is not always on.

Read-only / Safestale-backup detector - run it on the PBS server itself
set -euo pipefail
STORE=store1
MAX_AGE_HOURS=36

# snapshot list prints one line per snapshot; the group is the first column.
# Keep only the newest line per group and compare its timestamp to now.
proxmox-backup-client snapshot list --repository "$STORE" \
| awk 'NR>2 {print $2}' \
| sort -t/ -k1,2 -k3,3r \
| awk -F/ '!seen[$1"/"$2]++ {print $0}' \
| while read -r snap; do
  when=$(printf '%s' "$snap" | sed 's|.*/||')
  age=$(( ( $(date +%s) - $(date -d "$when" +%s) ) / 3600 ))
  if [ "$age" -gt "$MAX_AGE_HOURS" ]; then
    printf 'STALE %-40s %s h old\n' "$snap" "$age"
  fi
done

Restoring a host

Destructiverestore paths, in increasing order of commitment
set -euo pipefail
set -a; . /etc/proxmox-backup/client.env; set +a

proxmox-backup-client snapshot list

# 1. Browse, decide, extract selectively.
proxmox-backup-client catalog shell 'host/db01/2026-08-11T01:30:00Z' data.pxar

# 2. Mount read-only and copy out what you need.
mkdir -p /mnt/restore
proxmox-backup-client mount 'host/db01/2026-08-11T01:30:00Z' data.pxar /mnt/restore
# ... copy ...
umount /mnt/restore

# 3. Restore a whole archive into a staging directory.
proxmox-backup-client restore 'host/db01/2026-08-11T01:30:00Z' \
data.pxar /srv/staging/db01-restore/

Knowledge check

Knowledge check · 4 questions

  1. Q1. A scheduled host backup needs the token secret. Which mechanism is the most defensible for a production host with a secret manager available?

  2. Q2. Because PBS stores the chunks, a client-side encryption key that is lost can be recovered by the PBS administrator.

  3. Q3. Which of these are sound reasons to split a host backup into several named archives rather than one? Select all that apply.

  4. Q4. Forty hosts each run a systemd timer with OnCalendar set to 01:30. What single directive most improves this?

Passing score: 75%. Answers are checked in this browser.