9.0 KiB
📄 PVE Backup Report
Outil Python pour générer un rapport quotidien des sauvegardes Proxmox VE vers Proxmox Backup Server.
Documentation
✨ Fonctionnalités
- 📄 Rapport PDF quotidien horodaté, sans écrasement des rapports précédents.
- 🧭 Inventaire des stockages PBS déclarés dans Proxmox VE.
- ✅ Analyse de couverture des VM QEMU et conteneurs LXC.
- 📝 Notes PVE des VM/CT intégrées au rapport.
- 🕒 Récupération des dernières sauvegardes connues via les tâches PVE et les logs
vzdump. - 🗄️ Collecte optionnelle des datastores, namespaces, prune jobs, snapshots et espaces PBS.
- 🔐 Audit des utilisateurs PBS et permissions effectives associées aux stockages PVE.
- 📊 Rétention PBS avec nombre attendu de versions, delta et état PVE des VM/CT.
- ⚠️ Section d'anomalies pour les erreurs ou données de collecte partielles.
- 🐳 Exécution recommandée avec Docker, ou exécution directe en CLI.
🔐 Prérequis
Créer des utilisateurs ou tokens API dédiés à cette application de rapport. Ils doivent être limités aux droits d'audit/lecture seule :
- Proxmox VE : attribuer uniquement le rôle
PVEAuditorà l'utilisateur et au token API utilisé parPVE_API_TOKEN_ID. - Proxmox Backup Server : attribuer uniquement le rôle
Audità l'utilisateur et au token API utilisé par chaquePBS<number>_API_TOKEN_ID.
Ne pas utiliser de compte administrateur ou de compte avec droits d'écriture. L'application a seulement besoin de lire l'inventaire, les jobs de sauvegarde, les tâches, les datastores, les namespaces, les snapshots et les données de rétention.
🐳 Utilisation avec Docker
Docker est le mode d'exécution recommandé. L'image contient les dépendances Python et les bibliothèques système nécessaires à WeasyPrint.
📦 Préparation
cp .env.example .env
mkdir -p reports
Adapter ensuite .env avec les informations du cluster PVE et des PBS à collecter.
Dans Docker, conserver :
REPORT_OUTPUT_DIR=/reports
Le fichier compose.yaml monte le répertoire local ./reports dans le conteneur sous /reports. Les PDF générés sont donc visibles sur l'hôte dans ./reports/.
⚙️ Configuration minimale
PVE_API_URL=https://pve.example.invalid:8006
PVE_API_TOKEN_ID=backup-report@pve!report
PVE_API_TOKEN_SECRET=change-me
REPORT_OUTPUT_DIR=/reports
REPORT_TIMEZONE=Europe/Paris
PVE_VERIFY_TLS=true
Pour activer la collecte PBS, renseigner l'URL, le token ID et le secret du PBS concerné. Une configuration partielle n'active pas la collecte du PBS.
Exemple avec un PBS :
PBS01_NAME=nom-affiche
PBS01_API_URL=https://backup.example.invalid:8007
PBS01_API_TOKEN_ID=
PBS01_API_TOKEN_SECRET=
Il est possible de renseigner un ou plusieurs PBS. Pour ajouter un serveur, dupliquer le bloc en incrémentant le numéro du préfixe : PBS02_*, PBS03_*, PBS04_*, etc. L'application détecte automatiquement tous les blocs PBS<number>_* présents dans l'environnement.
🏗️ Construction
docker compose build
✅ Vérification
docker compose run --rm pve-backup-report --check-config
docker compose run --rm pve-backup-report --check-api
--check-api teste les endpoints PVE principaux. Si /cluster/backup retourne HTTP 403 - Permission check failed (/, Sys.Audit), le token fonctionne mais il lui manque le privilège Sys.Audit sur /.
📄 Génération du rapport
docker compose run --rm pve-backup-report --generate-pdf
Le rapport PDF est écrit dans ./reports/ avec un nom horodaté et n'écrase jamais un rapport précédent.
🧪 Commandes de diagnostic Docker
docker compose run --rm pve-backup-report --dump-inventory
docker compose run --rm pve-backup-report --dump-coverage
docker compose run --rm pve-backup-report --dump-report-data
docker compose run --rm pve-backup-report --dump-pbs-storage-usages
docker compose run --rm pve-backup-report --dump-pbs-users
docker compose run --rm pve-backup-report --debug-last-backup-vmid <VMID>
Lancer le conteneur sans argument exécute seulement la commande par défaut pve-backup-report. Pour générer un PDF, utiliser explicitement --generate-pdf.
🕒 Planification avec cron et Docker
Exemple de crontab côté hôte pour lancer le rapport tous les jours à 02:00 :
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 * * * cd /srv/pve-backup-report && /usr/bin/flock -n /tmp/pve-backup-report.lock /usr/bin/docker compose run --rm pve-backup-report --generate-pdf >> /var/log/pve-backup-report.log 2>&1
Adapter /srv/pve-backup-report au chemin réel du dépôt. Le cd est important : Docker Compose y trouve compose.yaml et l'application y charge .env.
💻 Utilisation directe en ligne de commande
Ce mode est utile pour le développement ou le diagnostic hors conteneur. L'hôte doit disposer de Python, des dépendances Python du projet et des bibliothèques système requises par WeasyPrint.
📦 Installation locale
python3 -m venv .venv
. .venv/bin/activate
python -m ensurepip --upgrade
pip install -r requirements.txt
pip install -e .
Pour lancer les tests :
pip install -e ".[dev]"
pytest
🧰 Commandes installées
pve-backup-report --check-config
pve-backup-report --check-api
pve-backup-report --dump-inventory
pve-backup-report --dump-coverage
pve-backup-report --dump-report-data
pve-backup-report --dump-pbs-storage-usages
pve-backup-report --dump-pbs-users
pve-backup-report --generate-pdf
pve-backup-report --debug-last-backup-vmid <VMID>
Sans installation éditable, depuis le dépôt :
PYTHONPATH=src python3 -m pve_backup_report --check-config
PYTHONPATH=src python3 -m pve_backup_report --check-api
PYTHONPATH=src python3 -m pve_backup_report --dump-inventory
PYTHONPATH=src python3 -m pve_backup_report --dump-coverage
PYTHONPATH=src python3 -m pve_backup_report --dump-report-data
PYTHONPATH=src python3 -m pve_backup_report --dump-pbs-storage-usages
PYTHONPATH=src python3 -m pve_backup_report --dump-pbs-users
PYTHONPATH=src python3 -m pve_backup_report --generate-pdf
PYTHONPATH=src python3 -m pve_backup_report --debug-last-backup-vmid <VMID>
En exécution locale directe, REPORT_OUTPUT_DIR peut rester à reports/ ou pointer vers un autre répertoire accessible par l'utilisateur courant.
Le même fichier .env peut être utilisé en Docker et en exécution locale. Si REPORT_OUTPUT_DIR=/reports est conservé hors Docker et que /reports n'est pas accessible, l'application utilise automatiquement le répertoire local reports/ et l'indique dans les logs.
🕒 Planification avec cron sans Docker
Exemple avec l'environnement virtuel du projet :
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 * * * cd /srv/pve-backup-report && /usr/bin/flock -n /tmp/pve-backup-report.lock /srv/pve-backup-report/.venv/bin/pve-backup-report --generate-pdf >> /var/log/pve-backup-report.log 2>&1
L'utilisateur qui exécute la crontab doit avoir le droit de lire .env et d'écrire dans REPORT_OUTPUT_DIR.
🔧 Variables utiles
- 🌐
PVE_API_URL: URL d'un noeud PVE joignable, par exemplehttps://pve.example.invalid:8006. - 🔑
PVE_API_TOKEN_ID: identifiant complet du token, par exemplebackup-report@pve!report. - 🔒
PVE_API_TOKEN_SECRET: secret du token. - 🛡️
PVE_VERIFY_TLS: laissertrueen production ; utiliserPVE_CA_BUNDLEpour une CA interne. - 🕒
PVE_TASK_HISTORY_LIMIT: nombre de tâches PVE récentes inspectées pour retrouver la dernière sauvegarde. - 📜
PVE_TASK_LOG_LIMIT: nombre de lignes récupérées par logvzdumppour extraire le détail par VM/CT. - 🗺️
PBS_HOSTNAMES: mapping manuel optionnel des serveurs PBS sous la formeadresse=nom-affiche,adresse2=nom-affiche2. - 🗄️
PBS<number>_*: configurations optionnelles des API PBS, par exemplePBS01_*,PBS02_*,PBS10_*. - 🏷️
REPORT_FILENAME_PREFIX: préfixe du fichier PDF généré.
📄 Sortie PDF
--generate-pdf génère un PDF horodaté dans REPORT_OUTPUT_DIR. La colonne Dernière sauvegarde affiche l'état, la date, l'heure et la durée lorsque PVE fournit cette information. Les tableaux Rétention des sauvegardes VM/CT <PBS> sont séparés par namespace et affichent le datastore, le nombre de versions PBS, la plus ancienne et la plus récente sauvegarde visibles sur chaque PBS configuré.
🤖 Utilisation de l'IA
L'application a été entièrement codée avec Codex et Claude code. Je n'aurai jamais eu le temps de coder l'application tout seul en aussi peu de temps.
⚖️ Licence
Ce projet est distribué sous licence Apache License 2.0. Voir le fichier LICENSE.