Files
PVE-Backup-Report/README.fr.md
T

8.9 KiB

📄 PVE Backup Report

Version Python License Docker Sécurité

Outil Python pour générer un rapport quotidien des sauvegardes Proxmox VE vers Proxmox Backup Server.

L'application collecte les données via les API PVE/PBS, calcule la couverture des VM/CT, récupère les dernières sauvegardes connues et génère un rapport PDF avec WeasyPrint. Le rendu PDF inclut une page de garde, une table des matières, des KPI de synthèse, les stockages PBS, les jobs de sauvegarde, la couverture VM/CT, la rétention PBS et les anomalies de collecte.

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.
  • 🕒 Récupération des dernières sauvegardes connues via les tâches PVE.
  • 🗄️ Collecte optionnelle des datastores, namespaces, prune jobs et snapshots PBS.
  • ⚠️ 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é par PVE_API_TOKEN_ID.
  • Proxmox Backup Server : attribuer uniquement le rôle Audit à l'utilisateur et au token API utilisé par chaque PBS<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 --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 --generate-pdf

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 --generate-pdf

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 exemple https://pve.example.invalid:8006.
  • 🔑 PVE_API_TOKEN_ID : identifiant complet du token, par exemple backup-report@pve!report.
  • 🔒 PVE_API_TOKEN_SECRET : secret du token.
  • 🛡️ PVE_VERIFY_TLS : laisser true en production ; utiliser PVE_CA_BUNDLE pour 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 log vzdump pour extraire le détail par VM/CT.
  • 🗺️ PBS_HOSTNAMES : mapping manuel optionnel des serveurs PBS sous la forme adresse=nom-affiche,adresse2=nom-affiche2.
  • 🗄️ PBS<number>_* : configurations optionnelles des API PBS, par exemple PBS01_*, 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.