Das Symptom

PBS Sync Pull zwischen zwei Proxmox Backup Servern. Konfiguriert, einmal getestet, läuft. Drei Monate später ein Blick in die Tasks:

syncjob ... error trying to connect: error:0A000086:SSL routines:
tls_post_process_server_certificate:certificate verify failed

82 von 82 Runs fehlgeschlagen. Seit Monaten. Kein Alert.

Die Ursache

Der Remote-PBS nutzt Let’s Encrypt (ACME) für sein Webinterface-Zertifikat. Let’s Encrypt Zertifikate sind 90 Tage gültig und werden typischerweise alle 60 Tage automatisch erneuert.

Bei jeder Erneuerung bekommt das Zertifikat einen neuen Fingerprint. PBS Sync verifiziert den Remote-Host aber gegen den Fingerprint in /etc/proxmox-backup/remote.cfg:

remote: my-remote-pbs
    auth-id root@pam
    fingerprint AF:31:EB:5D:15:38:92:F9:...  # <- veraltet nach Cert-Renewal
    host 10.0.0.50
    password base64encodedpassword

Neues Zertifikat → neuer Fingerprint → gespeicherter Fingerprint stimmt nicht mehr → SSL verify failed → Sync tot.

Warum fällt das nicht auf?

Weil PBS zwischen Backup-Tasks und Sync-Tasks unterscheidet. Typisches Monitoring überwacht:

  • PBS: Failed backup tasks count — zählt nur worker_type: backup
  • PBS: Last failed backup task — zeigt nur Backup-Fehler

Sync-Jobs haben worker_type: syncjob. Die fallen durch jedes Backup-Monitoring-Raster.

Bonus-Gotcha: proxmox-backup-manager task list zeigt ohne --all nur laufende Tasks. Ein gescheiterter Sync, der in 2 Sekunden abbricht, taucht nie auf:

# Zeigt nur laufende Tasks — ein schnell fehlgeschlagener Sync ist unsichtbar
proxmox-backup-manager task list

# Zeigt ALLE Tasks inkl. abgeschlossener
proxmox-backup-manager task list --all --limit 20

Der Fix

1. Fingerprint manuell aktualisieren

# Aktuellen Fingerprint vom Remote-PBS holen
openssl s_client -connect <remote-ip>:8007 </dev/null 2>/dev/null \
  | openssl x509 -noout -fingerprint -sha256

# In remote.cfg eintragen
nano /etc/proxmox-backup/remote.cfg
# fingerprint <neuer-fingerprint>

systemctl restart proxmox-backup-proxy

2. Auto-Update bei Cert-Renewal

Manuelles Fingerprint-Nachziehen alle 60 Tage? Vergisst man garantiert. Stattdessen: systemd path unit auf dem Remote-PBS, die das Zertifikat überwacht.

Auf dem Remote-PBS (der das Let’s Encrypt Zertifikat hat):

# /etc/systemd/system/pbs-cert-fingerprint.path
[Unit]
Description=Watch PBS certificate for renewal

[Path]
PathModified=/etc/proxmox-backup/proxy.pem
Unit=pbs-cert-fingerprint.service

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/pbs-cert-fingerprint.service
[Unit]
Description=Update PBS fingerprint on pull host after cert renewal

[Service]
Type=oneshot
ExecStartPre=/bin/sleep 10
ExecStart=/usr/local/bin/pbs-cert-notify-fingerprint.sh
#!/bin/bash
# /usr/local/bin/pbs-cert-notify-fingerprint.sh

NEW_FP=$(openssl x509 -in /etc/proxmox-backup/proxy.pem \
  -noout -fingerprint -sha256 2>/dev/null | sed 's/.*=//')

ssh -o ConnectTimeout=10 root@<pull-host> "
  sed -i \"s|fingerprint .*|fingerprint $NEW_FP|\" \
    /etc/proxmox-backup/remote.cfg
  systemctl restart proxmox-backup-proxy
"

echo "$(date) Fingerprint updated: $NEW_FP" >> /var/log/pbs-cert-notify.log
chmod +x /usr/local/bin/pbs-cert-notify-fingerprint.sh
systemctl daemon-reload
systemctl enable --now pbs-cert-fingerprint.path

Die path unit feuert bei jeder Änderung an proxy.pem. Der 10-Sekunden-Sleep gibt PBS Zeit, das neue Zertifikat vollständig zu laden.

Voraussetzung: SSH-Key-Auth vom Remote-PBS zum Pull-Host muss eingerichtet sein.

3. Sync-Monitoring in Zabbix

# /usr/local/bin/pbs-sync-check.sh
#!/usr/bin/env python3
import json, subprocess, sys

action = sys.argv[1] if len(sys.argv) > 1 else "status"
try:
    out = subprocess.check_output(
        ["proxmox-backup-manager", "task", "list", "--all",
         "--limit", "20", "--output-format", "json-pretty"],
        stderr=subprocess.DEVNULL
    )
    tasks = json.loads(out)
    syncs = [t for t in tasks
             if "syncjob" in t.get("upid", "") and t.get("endtime", "")]
    status = syncs[0].get("status", "unknown") if syncs else "none"
except Exception:
    status = "unknown"

if action == "status":
    print(0 if status.startswith("OK") else (2 if status == "none" else 1))
elif action == "error":
    print("" if status.startswith("OK") or status == "none" else status)
# /etc/zabbix/zabbix_agent2.d/pbs-sync-monitor.conf
UserParameter=pbs.sync.status,sudo /usr/local/bin/pbs-sync-check.sh status
UserParameter=pbs.sync.lasterror,sudo /usr/local/bin/pbs-sync-check.sh error

Trigger auf Priority High — ein fehlgeschlagener Sync ist ein fehlgeschlagenes Backup.

Namespace-Kollision: Noch ein Gotcha

Wenn du PBS Sync Pull in die Root-Namespace eines Datastores ziehst, auf dem auch lokale Backups liegen, gibt es VMID-Kollisionen. CT 101 auf Host A und CT 101 auf Host B haben dieselbe Backup-Gruppe.

PBS meldet:

sync group ct/101 failed - group lock failed

Lösung: Sync Pull in eine eigene Namespace legen:

# /etc/proxmox-backup/sync.cfg
sync: my-sync-job
    ns remote-backups       # <- eigene Namespace statt Root
    remote my-remote-pbs
    remote-ns
    remote-store my_storage_box
    store local_datastore

TL;DR

  1. Let’s Encrypt auf PBS = Fingerprint-Rotation alle ~60 Tage
  2. PBS Sync Pull verifiziert gegen gespeicherten Fingerprint → bricht ab
  3. Standard-Monitoring überwacht nur Backup-Tasks, keine Sync-Tasks
  4. task list ohne --all zeigt nur laufende Tasks
  5. Fix: systemd path unit für Auto-Fingerprint-Update + Zabbix-Monitoring für syncjob-Tasks