Rather than set up even more infrastructure, I run Proxmox Backup Server on the same machine that's running a Proxmox VE host.
Open a shell on your Proxmox VE host. We'll be installing PBS alongside Proxmox VE at the OS level. We will NOT run PBS inside a container.
Install the PBS apt repo signing key:
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
Add the PBS repo to apt:
# Open a new file in a text editor:
nano /etc/apt/sources.list.d/pbs-install-repo.list
# In the text editor paste in:
# Proxmox Backup Server pbs-no-subscription repository provided by proxmox.com,
# NOT recommended for production use
deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription
CTRL-X
, y
to save.
Update apt and install:
apt update
apt install proxmox-backup-server -y
The web UI should be accessible at: <server_ip>:8007
Use the same root
login as the main Proxmox VE host.
Administration -> Storage / Disks -> Directory -> Create Directory:
- Disk: Backup HDD (e.g. /dev/sdb)
- Filesystem: ex4
- Name: backups_hdd
The storage should now appear in the Datastore list in the left menu.
If your PBS instance will be backing up more than one PVE host, you should isolate them by namespace because PBS groups its backups by CT / VM ID, regardless of which host it came from.
For example: ct/101 on host 1 might be bitcoind, but ct/101 on host 2 is your media server. On each backup, PBS will overwrite your bitcoind backup with the media server's backup and vice versa. But if you specify namespaces (e.g. host1, host2), the backups become uniquely named -- host1/ct/101, host2/ct/101 -- and will be preserved separately.
Datastore -> backups_hdd -> Content -> Add NS (look to the far right):
- Specify your new namespace. I describe the PVE host machine (e.g. hpelitedesk705g4-1).
PBS won't actually delete an expired backup until garbage collection (GC) is run.
Datastore -> "backups_hdd" -> Prune & GC Jobs -> Edit:
- Schedule: once daily should be fine; time it when PBS will be idle
Once GC starts, you'll begin to see data for its "Deduplication factor" (click on "Datastore") which is a measure of how much redundant (unnecessary) data was deleted across your backups.
Datastore -> backups_hdd -> Prune & GC Jobs -> Prune Jobs -> Add:
- Namespace: "root" (probably no need to customize schedule by namespace)
- Keep: 7 daily, 4 weekly, 6 monthly (up to you, obv)
- Prune Schedule: I just do once daily when PBS will be idle
PBS is extremely efficient and only stores the incremental diffs for each new backup. So a week's worth of huge backups (e.g. a bitcoind node with the entire bitcoin block history) sounds like it should require 7x the space, but it won't be much bigger than 1x.
On PBS in Configuration -> Access Control -> User Management -> Add:
- Specify a new username (e.g. "pve_host_user") and password
Then set permissions: Datastore -> backups_hdd -> Permissions -> Add User Permission:
- Role: DatastoreAdmin
On your PBS instance, go to the Dashboard and copy the fingerprint.
On your PVE host: Datacenter -> Storage -> Add -> Proxmox Backup Server:
- ID: (e.g. "backup_server")
- Server: (IP addr of PBS machine)
- Username: root@pam (or the user you created above; e.g. pve_host_user@pbs)
- Password: (PBS machine's
root
password) - Datastore: storage location on the PBS instance (e.g. "backups_hdd")
- Namespace: "root" or the namespace you created on PBS above for this PVE host
- Fingerprint: copied from above
For each VM or CT you want to back up, create a backup schedule:
On the PVE host: Datacenter -> Backup -> Add:
- Storage: (e.g. "backup_server" specified above)
- Schedule: up to you
- Selection Mode: Include selected VMs (click the checkbox(es) for your VM/CT(s))
- Retention tab: "Keep all backups" checked (configure PBS to prune itself)
Create as many backup schedules as you need to customize how each VM / CT is backed up. Maybe one VM should have lots of daily backup history retained whereas another VM might only need occasional backups.
This will use one PBS setup as your main backup server while PBS running on a different machine simply mirrors the main PBS's backup data.
This way if the main PBS server goes down, you still have a fully-functioning backup PBS server that has a full copy of all of your backups.
On PBS in Configuration -> Access Control -> User Management -> Add:
- Specify a new username (e.g. "pbs_sync_user") and password
Then set permissions: Datastore -> backups_hdd -> Permissions -> Add User Permission:
- Role: DatastoreReader
Go to the main PBS instance's Dashboard screen and copy its fingerprint.
On the mirror PBS instance, create a "Remote" entry:
Configuration -> Remotes -> Add Remote:
- Remote ID: e.g. "main_pbs"
- Host: e.g. 192.168.1.50
- Auth ID: root@pam (or the user you created above, e.g. pbs_sync_user@pbs)
- Fingerprint: (paste fingerprint copied above)
On the mirror PBS instance:
Datastore -> backups_hdd -> Sync jobs -> Add:
- Sync Schedule: (e.g. 21:00. Once daily seems fine)
- Location: Remote
- Source Remote: the "Remote ID" entered above (e.g. "main_pbs")
- Source Datastore: the datastore you want to mirror from the main instance (also named "backups_hdd" in my setup)
- Remove vanished: checked
Test your sync by selecting it and clicking "Run now".
A variation on the above setup, but with just one PBS instance. The goal is still redundant storage (two separate HDDs).
The tradeoff of this setup is that you can't immediately use any of the backups if the one and only PBS instance goes down.
Note: It would seem easier to just configure PBS to write its backups to a ZFS mirror, but I think that isn't an option or isn't practical due to the way data is written in a ZFS.
Basic steps:
- Add your second HDD as a new Directory storage.
- Create a sync job with Location: Local.
Note: When I originally tried this, I had to create a "Remote" entry that referenced itself (i.e. Host: 127.0.0.1) in order to wire up the sync job. But it looks like there's native "Local" job support now.
On the PBS server:
proxmox-backup-client change-owner <group> <new-owner> --ns <namespace> --repository <datastore>
Where:
namespace
: omit flag or specify the namespace usedgroup
: The backup's name (e.g. "ct/205"; case sensitive!)new-owner
: e.g. pve_host_user@pbsdatastore
: e.g. backups_hdd (name of storage on PBS)