# PBS Offsite Backup Jobs: Adding Guests & Running on Correct Nodes ## When to Use When expanding offsite PBS backup coverage to include more CTs/VMs beyond the initial HA-only job, considering bandwidth constraints of the remote site. ## Key Lessons ### 1. vzdump Must Run on the Node Hosting the CT **Critical pitfall:** `vzdump --storage noris_offsite` run on proxmox1 (10.0.20.10) will silently exit 0 for any CT hosted on a different node — no backup is created, no error is logged. The CT config file (`/etc/pve/lxc/.conf`) only exists on the node where the CT runs. **Finding which node hosts a CT:** ```bash ssh root@10.0.20.10 "pvesh get /cluster/resources --type vm --output-format json" | \ python3 -c " import sys,json data=json.load(sys.stdin) for v in data: if v.get('vmid') == TARGET_VMid: print(f\"node={v['node']} status={v['status']}\") " ``` **Running backup on the correct node:** ```bash # CT108 on proxmox6 (10.0.20.60) ssh root@10.0.20.60 "vzdump 108 --storage noris_offsite --mode snapshot --compress zstd" # CT99999 on proxmox7 (10.0.20.70) ssh root@10.0.20.70 "vzdump 99999 --storage noris_offsite --mode snapshot --compress zstd" # CT104 on n5pro (10.0.20.91) ssh root@10.0.20.91 "vzdump 104 --storage noris_offsite --mode snapshot --compress zstd" ``` ### 2. Updating the Offsite Backup Job The offsite job config lives in `/etc/pve/jobs.cfg` on any PVE node (shared filesystem). Edit with sed: ```bash ssh root@10.0.20.10 " sed -i '/offsite-ha-daily/,/^$/{s/vmid 106/vmid 106,108,104,99999/}' /etc/pve/jobs.cfg " ``` Job config after update: ``` vzdump: offsite-ha-daily compress zstd enabled 1 mode snapshot schedule 02:00 storage noris_offsite vmid 106,108,104,99999 ``` ### 3. Bandwidth-Conscious Guest Selection The remote PBS at noris (213.95.54.60) has limited upload bandwidth. PBS dedup means only changed chunks are transferred after the initial full backup, but the first backup of each guest is a full upload. **Selection criteria for offsite:** | Criterion | Include | Exclude | |-----------|---------|---------| | Size < 20 GB | ✅ Small enough for initial full | | | Size > 100 GB | | ❌ Too large for WAN | | Change rate low (config, code) | ✅ Daily delta is tiny | | | Change rate high (video, media) | | ❌ Daily delta too large | | Infrastructure-critical | ✅ Traefik, Gitea, HA | | | Replaceable data | | ❌ Frigate recordings | **This homelab's offsite selection (2026-07-08):** - VM106 HA (70 GB) — already in job, critical - CT108 Gitea (1.2 GB) — added, critical code - CT99999 Traefik (3 GB) — added, critical infra - CT104 Paperless (16 GB) — added, documents **Excluded from offsite:** - CT111 Seafile (558 GB) — too large, needs separate strategy - CT120 Frigate (40 GB) — replaceable video data - CT115 Immich (20 GB) — photos, needs separate strategy - CT121/124/127 — low priority, small ### 4. Verifying Offsite Backups After running manual backups, verify on the remote PBS: ```bash ssh root@10.0.20.10 "pvesh get /nodes/proxmox1/storage/noris_offsite/content --output-format json" | \ python3 -c " import sys,json,datetime data=json.load(sys.stdin) for b in sorted(data, key=lambda x: x.get('ctime',0), reverse=True)[:10]: volid=b.get('volid','') sz=b.get('size',0)//1024//1024 dt=datetime.datetime.fromtimestamp(b.get('ctime',0)).strftime('%Y-%m-%d %H:%M') print(f'{volid:55s} {sz:>8} MB {dt}') " ``` **Note:** PBS content listing may lag by a few minutes after upload. If backups don't appear immediately, wait and re-query. ### 5. Lock Timeout on Concurrent vzdump If two vzdump jobs run simultaneously on different nodes targeting the same PBS storage, one may fail with: ``` ERROR: can't acquire lock '/var/run/vzdump.lock' - got timeout ``` This is a global lock across the PVE cluster. Retry the failed backup after the first one completes. For manual triggers, run sequentially. ## Session Reference - **2026-07-08**: Added CT108 (Gitea), CT99999 (Traefik), CT104 (Paperless) to offsite-ha-daily job. Initial full backups run manually on correct nodes. CT104 failed with lock timeout (concurrent with scheduled job), retried successfully.