Introduction

If you're running Proxmox Backup Server, you've probably already solved the easy problem: your VMs and containers get deduplicated, space-efficient backups on a schedule, and restoring one is a few clicks away. But a single PBS datastore, no matter how well it's configured, still lives in one building, on one set of disks, behind one power feed. A fire, a flood, a failed RAID controller, or a stolen drive takes your only copy of every backup with it — and "we had backups" doesn't help much if the backups burned down with the server room.

The fix is a second, independent copy of your backup data somewhere else — a different building, a different site, ideally a different city. Proxmox Backup Server has a built-in feature for exactly this: Remotes and Sync Jobs. A Remote is a saved connection to another PBS instance. A Sync Job uses that connection to replicate an entire datastore — or a filtered subset of it — from one PBS server to another, transferring only the chunks that don't already exist on the target. Run it on a schedule and you have continuous, low-bandwidth offsite replication with no third-party tools, no rsync scripts, and no manual drive rotation.

This guide covers the whole path: setting up the remote connection, creating a sync job in both pull and push direction, the permissions each direction actually requires, filtering what gets synced, throttling bandwidth so replication doesn't saturate your uplink, handling encrypted backups correctly, and verifying the offsite copy is actually good for something when you need it. We're using Proxmox Backup Server 4.x throughout — the sync-job mechanics are unchanged from 3.x, but a few flags (like resync-corrupt and per-job worker threads) are newer additions worth knowing about.

Why Sync Jobs, and Not Something Else

PBS already gives you a few different ways to get backup data off the primary server, and it's worth being clear about which problem each one solves before picking a tool:

  • Client-side encryption protects data at rest and in transit from anyone who gains access to the storage, but it doesn't put a second copy anywhere. Lose the datastore and encryption doesn't save you.
  • An S3-compatible backend (stable since PBS 4.2) moves the primary datastore itself onto object storage, which can be offsite by nature — but it changes where your only copy lives rather than creating a second copy, and it comes with its own latency and egress-cost tradeoffs.
  • File-level restore solves "I need one file back," not "my whole backup server is gone."
  • Sync Jobs solve the actual 3-2-1 backup problem: a second, independently restorable, independently located copy of the same backup data, kept in sync automatically.

None of these are mutually exclusive — a common setup is a local PBS with encryption enabled, an S3 backend for the primary datastore, and a sync job replicating to a second PBS at a different site or in a different provider's region. This guide focuses specifically on that last piece.

Prerequisites

  • Two working Proxmox Backup Server installations, each already receiving backups from Proxmox VE (or at least one with an existing datastore). Version 3.4 or later on both sides; PBS 4.x is assumed for the exact CLI output below.
  • Network reachability from one PBS instance to the other over HTTPS (TCP 8007 by default). It only needs to go one direction — see the pull-vs-push section below for which side needs the open port.
  • Root or an administrative account on both PBS instances, at least for initial setup. You'll create a scoped-down user afterward.
  • Enough spare capacity on the target datastore to hold a full copy of whatever you're replicating.

Step 1: Decide on Pull or Push

Before touching any configuration, decide which PBS instance will initiate the sync, because it changes both the network topology and the permissions setup.

Pull (the default, and the recommended pattern for most offsite setups): the target PBS — the offsite one — reaches out to the source PBS and pulls the datastore contents. This means only the source site needs a reachable port, and the offsite server can sit behind NAT or a firewall with no inbound rules at all, only outbound access to the primary site. For a typical "office/datacenter primary, offsite secondary" layout, this is the safer default: the box you care least about exposing (the offsite one, possibly at a colo or a relative's house) never needs to accept inbound connections.

Push: the source PBS initiates the connection and pushes data out to the remote. This is useful when the offsite target is the one that's hard to reach inbound — for example, replicating into a cloud-hosted PBS instance behind a provider's firewall, or into a datastore you don't want to expose to the primary network at all. Push mode has one important wrinkle: pushed content is always owned by the user configured in the remote, not by whoever configured the sync job, and Proxmox's own documentation is explicit that you should create a dedicated remote configuration — with a dedicated, minimally-privileged user on the target — for each individual push sync job, rather than reusing one broad "sync" account across jobs.

The rest of this guide walks through the pull direction first, since that's what most offsite-replication setups use, then covers what changes for push.

Step 2: Get the Remote Server's Fingerprint

Adding a remote requires the target's TLS certificate fingerprint so PBS can verify it's talking to the right server. Grab it from the remote (source) server:

proxmox-backup-manager cert info

Look for the line labeled Fingerprint (sha256) and copy the whole colon-separated value. If you'd rather not touch the CLI, the same fingerprint is shown in the PBS web interface on the Dashboard, under "Show Fingerprint."

Step 3: Create the Remote

On the server that will be doing the pulling (the offsite/target PBS, in the pull scenario), add a remote pointing at the source:

proxmox-backup-manager remote create primary-site \
  --host pbs-primary.example.com \
  --userid sync@pbs \
  --password 'a-strong-password' \
  --fingerprint 64:d3:ff:3a:50:38:53:5a:9b:f7:50:...:ab:fe

A few notes on this:

  • The userid here is a user (or API token) that exists on the remote server — the one you're pulling from — not on the local machine. Create a dedicated PBS user for this rather than using root@pam; something like sync@pbs with only the permissions it needs (see the permissions table below).
  • The name you give the remote (primary-site above) is just a local label you'll reference later when creating the sync job — it doesn't need to match anything on the remote end.
  • Prefer an API token over a plain password where possible. PBS supports scoped API tokens the same way Proxmox VE does, and a token can be revoked independently of the account's login credentials.

Equivalently, in the web interface: go to Configuration → Remotes, click Add, and fill in the same fields.

You can confirm it saved correctly and check connectivity with:

proxmox-backup-manager remote list
proxmox-backup-manager remote scan primary-site

If you need to change the host or credentials later:

proxmox-backup-manager remote update primary-site --host new-hostname.example.com

Step 4: Set Up Permissions on the Source

The account you referenced in the remote (sync@pbs) needs specific ACLs on the source server, not on the target. For a pull sync job, the minimum is:

PermissionPathWhy
Remote.Read/remote/{remote}/{remote-store}Lets the pulling server read from that datastore over the API
Datastore.Backup/datastore/{store} (target side, minimum)Allows writing synced snapshots into the local target datastore
Datastore.Prunetarget datastoreOnly needed if remove-vanished is enabled, so deleted-upstream snapshots can be cleaned up locally
Datastore.Modifytarget datastoreOnly needed if the synced snapshots' owner differs from the account running the job

Set these with proxmox-backup-manager acl update on the relevant server, e.g.:

proxmox-backup-manager acl update /datastore/local sync@pbs --role DatastoreReader

For push-direction jobs the requirements flip and get stricter: the account needs Remote.Audit on the remote plus Remote.DatastoreBackup on the target namespace, Datastore.Read/Datastore.Audit on the source, and — again — Proxmox's guidance is to use a dedicated remote/user per push job rather than a shared one, since pushed content always inherits the ownership of that remote's configured user.

Step 5: Create the Sync Job

With the remote and permissions in place, create the actual sync job on the pulling (target) server:

proxmox-backup-manager sync-job create offsite-nightly \
  --remote primary-site \
  --remote-store local \
  --store offsite \
  --schedule 'Wed 02:30' \
  --remove-vanished true

Breaking down what each flag does:

  • --remote — the remote connection created in Step 3.
  • --remote-store — the datastore name on the source that you're pulling from.
  • --store — the local datastore that will receive the copy.
  • --schedule — a calendar event string. 'Wed 02:30' runs every Wednesday at 2:30 AM; PBS's calendar-event syntax also supports things like daily, *-*-* 03:00, or mon,wed,fri 01:00 for finer control.
  • --remove-vanished — if a backup group or snapshot is deleted (pruned) on the source, this deletes it locally too, keeping the offsite copy a true mirror rather than an ever-growing superset. Leave it off if you want the offsite copy to retain snapshots even after they're pruned upstream — effectively a longer retention window offsite.

Or do the same thing from Datastore → Sync Jobs in the web UI, which exposes the same fields in a form.

Run it once manually before trusting the schedule:

proxmox-backup-manager sync-job run offsite-nightly

and check on configured jobs with:

proxmox-backup-manager sync-job list

Filtering What Gets Synced

You don't have to replicate everything in a datastore. --group-filter lets you scope a sync job down:

# Only sync container backups
proxmox-backup-manager sync-job create ct-only-sync \
  --remote primary-site --remote-store local --store offsite \
  --group-filter type:ct

# Only a specific VM
proxmox-backup-manager sync-job update offsite-nightly \
  --group-filter group:vm/100

# Everything except a range of VMIDs
proxmox-backup-manager sync-job update offsite-nightly \
  --group-filter exclude:regex:'^vm/1\d{2,3}$'

Filters can be combined: includes and excludes both present means "matching includes, minus matching excludes." No filters at all means everything in scope syncs. This is useful when your offsite link is limited and you only want your production-critical VMs replicated, while dev/test containers stay local-only.

Namespaces

If you're using PBS namespaces to separate backups by tenant, environment, or purpose, sync jobs respect them via --remote-ns (the starting point on the remote) and --ns (where it lands locally), plus --max-depth to control recursion. Leaving max-depth unset recurses through all namespaces under the starting point if the remote supports namespaces; setting it to 0 syncs only the groups directly in that namespace with no recursion. If a namespace exists on the remote but not locally, PBS creates it automatically, provided the syncing account has the permissions to do so.

Throttling Bandwidth

An initial sync of a multi-terabyte datastore over a residential or budget offsite link can otherwise flood the connection for hours. Rate-limit it:

proxmox-backup-manager sync-job update offsite-nightly \
  --rate-in 20MiB \
  --burst-in 100MiB

rate-in/rate-out cap sustained throughput; burst-in/burst-out set the token-bucket size so short bursts aren't held to the sustained rate. For high-latency links (satellite, long-haul WAN), raising --worker-threads (1–32, default 1) lets multiple groups sync in parallel, which helps work around HTTP/2 head-of-line blocking on a single slow connection — at the cost of proportionally higher memory and connection usage on both ends, so scale it up gradually rather than jumping straight to 32.

Encrypted Backups and Sync

If backups are client-side encrypted, sync jobs handle keys differently depending on direction:

  • Pull: associate decryption keys with the job using --associated-key (repeatable for multiple keys, useful when key rotation means recent and older snapshots use different keys):
    proxmox-backup-manager sync-job update offsite-nightly \
      --associated-key key0 --associated-key key1
  • Push: you can encrypt previously-unencrypted snapshots server-side before pushing, using --active-encryption-key. Snapshots that are already encrypted are pushed as-is and are never re-encrypted in transit.

You can also restrict a job to only touch snapshots that meet a bar with --verified-only (already passed a PBS verify job) or --encrypted-only — useful if you only want your offsite copy to hold backups you've confirmed are both intact and encrypted, rather than replicating everything indiscriminately. One caveat worth knowing: snapshots with only partial encryption are skipped by a push sync job when encrypted-only is set, so mixed-encryption groups need a closer look before relying on that flag.

One flag worth calling out from newer PBS releases is resync-corrupt, which re-syncs snapshots that previously failed verification instead of silently skipping them forever — handy if a bad snapshot got fixed upstream (via re-backup or manual repair) and you don't want to hunt it down and force a manual sync of just that group.

Verifying the Offsite Copy Is Actually Good

A sync job that runs successfully every night for months tells you data moved — it doesn't tell you the data is restorable. Two things close that gap:

  • Run PBS's own verify jobs against the offsite datastore on its own schedule, independent of verification on the source. A snapshot that verified fine on the primary can still land corrupted offsite due to a transfer or storage issue, and only a verify run on the target side will catch that.
  • Periodically do a real test restore from the offsite copy — not just a file-level browse, an actual VM restore into a scratch VMID — and boot it. This is the only way to confirm the whole chain (sync, storage, and restore path) actually works end to end, and it's worth putting on a recurring calendar reminder rather than leaving it to "we'll find out if we ever need it."

Restoring From the Offsite Server in an Emergency

If the primary site is actually down, you restore directly from the offsite PBS the same way you'd restore from any PBS datastore: add the offsite PBS as storage in a Proxmox VE cluster (temporary or standby) under Datacenter → Storage → Add → Proxmox Backup Server, then restore VMs/containers from it through the normal GUI or pve-restore/pct restore workflow. Because sync jobs replicate full, independently-restorable snapshots — not some kind of delta that only makes sense alongside the primary — the offsite datastore behaves exactly like a standalone PBS server for restore purposes. Nothing about the restore process cares that the data arrived via a sync job rather than a direct backup.

Troubleshooting

  • Sync job fails with a certificate/fingerprint error: the remote's TLS certificate changed (renewed cert, reinstalled server) since you added it. Re-fetch the fingerprint with proxmox-backup-manager cert info on the remote and update it with proxmox-backup-manager remote update.
  • Permission denied pulling a datastore: almost always an ACL gap on the source — double check Remote.Read is actually granted on /remote/{remote}/{remote-store} for the account the remote is configured with, not just a broader role that looks like it should cover it.
  • Job runs but nothing new appears offsite: check whether a group filter is scoping the job more narrowly than expected — a leftover --group-filter from testing is a common cause of "it's running but only syncing three VMs."
  • Very slow initial sync: expected for a first full sync of a large datastore over a WAN link; subsequent runs are far faster since only new/changed chunks transfer. Increase worker-threads modestly on high-latency links, and confirm rate-in/rate-out aren't set lower than intended from an earlier throttling test.
  • Snapshots keep reappearing after being deleted: if remove-vanished isn't set, pruning on the source never removes anything from the target — that's expected behavior, not a bug, and is often the desired setup for extending offsite retention beyond the source's prune policy.

Best Practices

  • Treat this as one leg of a proper 3-2-1 strategy — three copies, two different media/systems, one offsite — not a replacement for verify jobs, monitoring, or the primary backup schedule itself.
  • Use pull direction and a dedicated, minimally-privileged remote user whenever the network layout allows it, so the offsite server never needs an open inbound port.
  • Schedule sync jobs to run after the primary backup and prune windows complete, not overlapping them, so you're never syncing a datastore mid-prune.
  • Rate-limit the initial full sync explicitly rather than letting it run wide open on a shared internet link, especially outside a maintenance window.
  • Put verify jobs and a test-restore reminder on the offsite datastore on your calendar — a sync job with no verification is just moving bytes, not guaranteeing recoverability.

Frequently Asked Questions

Do both PBS instances need to be the same version?
No, but keep both at 3.4 or later, and avoid pairing a very old and very new release together — sync relies on API compatibility between the two, and Proxmox recommends running current versions on both ends where practical.

Can I sync to more than one offsite server?
Yes — create additional remotes and sync jobs for each destination. There's no built-in limit on the number of sync jobs targeting or sourcing from a given datastore, though each adds its own load and bandwidth usage.

Does a sync job re-transfer everything every time it runs?
No. After the first full sync, subsequent runs only transfer chunks that don't already exist on the target, which is why incremental runs are typically fast even for large datastores.

Is push or pull "more secure"?
Neither is inherently more secure — they shift where the open network path and the credentials live. Pull keeps the offsite server free of inbound rules; push keeps the primary server from needing to trust an inbound connection from the remote site. Pick based on which side you're more comfortable exposing.

What happens to the protected flag on manually-protected snapshots?
It isn't synced. A snapshot marked protected on the source to prevent pruning will not automatically be protected on the target — set that flag independently on the offsite copy if you need it there too.

Conclusion

Sync Jobs turn Proxmox Backup Server from "a good backup target" into "a real disaster-recovery story." The setup is a one-time investment — a remote connection, an ACL, a scheduled job — and after that it runs unattended, moving only what's changed. Pair it with independent verify jobs and an occasional real test restore on the offsite side, and a lost building stops being a lost backup history.