Initial commit
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
# 📄 PVE Backup Report
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
Python tool to generate a daily backup report for Proxmox VE against Proxmox Backup Server.
|
||||
|
||||
The application collects data via the PVE/PBS APIs, computes VM/CT coverage, retrieves the latest known backups and generates a PDF report using WeasyPrint. The PDF includes a cover page, a table of contents, summary KPIs, PBS storages, backup jobs, VM/CT coverage, PBS retention and collection anomalies.
|
||||
|
||||
## ✨ Features
|
||||
|
||||
- 📄 Timestamped daily PDF report, without overwriting previous reports.
|
||||
- 🧭 Inventory of PBS storages declared in Proxmox VE.
|
||||
- ✅ Coverage analysis for QEMU VMs and LXC containers.
|
||||
- 🕒 Retrieval of the latest known backups via PVE tasks.
|
||||
- 🗄️ Optional collection of PBS datastores, namespaces, prune jobs and snapshots.
|
||||
- ⚠️ Anomalies section for errors or partial collection data.
|
||||
- 🐳 Recommended execution with Docker, or direct CLI execution.
|
||||
|
||||
## 🐳 Usage with Docker
|
||||
|
||||
Docker is the recommended execution mode. The image includes the Python dependencies and system libraries required by WeasyPrint.
|
||||
|
||||
### 📦 Setup
|
||||
|
||||
```sh
|
||||
cp .env.example .env
|
||||
mkdir -p reports
|
||||
```
|
||||
|
||||
Then edit `.env` with your PVE cluster and PBS connection details.
|
||||
|
||||
In Docker, keep:
|
||||
|
||||
```env
|
||||
REPORT_OUTPUT_DIR=/reports
|
||||
```
|
||||
|
||||
The `compose.yaml` file mounts the local `./reports` directory into the container at `/reports`. Generated PDFs are therefore visible on the host in `./reports/`.
|
||||
|
||||
### ⚙️ Minimal configuration
|
||||
|
||||
```env
|
||||
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
|
||||
```
|
||||
|
||||
To enable PBS collection, provide the URL, token ID and secret for the relevant PBS. An incomplete configuration does not enable PBS collection.
|
||||
|
||||
Example with one PBS:
|
||||
|
||||
```env
|
||||
PBS01_NAME=nom-affiche
|
||||
PBS01_API_URL=https://backup.example.invalid:8007
|
||||
PBS01_API_TOKEN_ID=
|
||||
PBS01_API_TOKEN_SECRET=
|
||||
```
|
||||
|
||||
One or more PBS servers can be configured. To add a server, duplicate the block and increment the prefix number: `PBS02_*`, `PBS03_*`, `PBS04_*`, etc. The application automatically detects all `PBS<number>_*` blocks present in the environment.
|
||||
|
||||
### 🏗️ Build
|
||||
|
||||
```sh
|
||||
docker compose build
|
||||
```
|
||||
|
||||
### ✅ Verification
|
||||
|
||||
```sh
|
||||
docker compose run --rm pve-backup-report --check-config
|
||||
docker compose run --rm pve-backup-report --check-api
|
||||
```
|
||||
|
||||
`--check-api` tests the main PVE endpoints. If `/cluster/backup` returns `HTTP 403 - Permission check failed (/, Sys.Audit)`, the token works but is missing the `Sys.Audit` privilege on `/`.
|
||||
|
||||
### 📄 Generating the report
|
||||
|
||||
```sh
|
||||
docker compose run --rm pve-backup-report --generate-pdf
|
||||
```
|
||||
|
||||
The PDF report is written to `./reports/` with a timestamped filename and never overwrites a previous report.
|
||||
|
||||
### 🧪 Docker diagnostic commands
|
||||
|
||||
```sh
|
||||
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>
|
||||
```
|
||||
|
||||
Running the container without arguments only executes the default `pve-backup-report` command. To generate a PDF, use `--generate-pdf` explicitly.
|
||||
|
||||
### 🕒 Scheduling with cron and Docker
|
||||
|
||||
Example crontab on the host to run the report every day at 02:00:
|
||||
|
||||
```cron
|
||||
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
|
||||
```
|
||||
|
||||
Replace `/srv/pve-backup-report` with the actual path to the repository. The `cd` is important: Docker Compose finds `compose.yaml` there and the application loads `.env` from it.
|
||||
|
||||
## 💻 Direct command-line usage
|
||||
|
||||
This mode is useful for development or diagnostics outside a container. The host must have Python, the project's Python dependencies and the system libraries required by WeasyPrint.
|
||||
|
||||
### 📦 Local installation
|
||||
|
||||
```sh
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
python -m ensurepip --upgrade
|
||||
pip install -r requirements.txt
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
To run the tests:
|
||||
|
||||
```sh
|
||||
pip install -e ".[dev]"
|
||||
pytest
|
||||
```
|
||||
|
||||
### 🧰 Installed commands
|
||||
|
||||
```sh
|
||||
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
|
||||
```
|
||||
|
||||
Without an editable install, from the repository:
|
||||
|
||||
```sh
|
||||
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
|
||||
```
|
||||
|
||||
In direct local execution, `REPORT_OUTPUT_DIR` can remain `reports/` or point to any other directory writable by the current user.
|
||||
|
||||
The same `.env` file can be used in Docker and in local execution. If `REPORT_OUTPUT_DIR=/reports` is kept outside Docker and `/reports` is not accessible, the application automatically falls back to the local `reports/` directory and logs the fallback.
|
||||
|
||||
### 🕒 Scheduling with cron without Docker
|
||||
|
||||
Example using the project's virtual environment:
|
||||
|
||||
```cron
|
||||
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
|
||||
```
|
||||
|
||||
The user running the crontab must have read access to `.env` and write access to `REPORT_OUTPUT_DIR`.
|
||||
|
||||
## 🔧 Key variables
|
||||
|
||||
- 🌐 `PVE_API_URL`: URL of a reachable PVE node, e.g. `https://pve.example.invalid:8006`.
|
||||
- 🔑 `PVE_API_TOKEN_ID`: full token identifier, e.g. `backup-report@pve!report`.
|
||||
- 🔒 `PVE_API_TOKEN_SECRET`: token secret.
|
||||
- 🛡️ `PVE_VERIFY_TLS`: keep `true` in production; use `PVE_CA_BUNDLE` for an internal CA.
|
||||
- 🕒 `PVE_TASK_HISTORY_LIMIT`: number of recent PVE tasks inspected to find the latest backup.
|
||||
- 📜 `PVE_TASK_LOG_LIMIT`: number of lines retrieved per `vzdump` log to extract per-VM/CT detail.
|
||||
- 🗺️ `PBS_HOSTNAMES`: optional manual mapping of PBS servers as `address=display-name,address2=display-name2`.
|
||||
- 🗄️ `PBS<number>_*`: optional PBS API configurations, e.g. `PBS01_*`, `PBS02_*`, `PBS10_*`.
|
||||
- 🏷️ `REPORT_FILENAME_PREFIX`: prefix for the generated PDF filename.
|
||||
|
||||
## 📄 PDF output
|
||||
|
||||
`--generate-pdf` generates a timestamped PDF in `REPORT_OUTPUT_DIR`. The `Last backup` column shows the status, date, time and duration when PVE provides that information. The `PBS VM/CT backup retention <PBS>` tables are split by namespace and show the datastore, the number of PBS versions, and the oldest and most recent backup visible on each configured PBS.
|
||||
|
||||
🤖 AI Usage
|
||||
|
||||
The application was entirely coded using Codex and Claude Code. I would never have had enough time to build the application on my own in such a short period of time.
|
||||
|
||||
## ⚖️ License
|
||||
|
||||
This project is distributed under the Apache License 2.0. See the `LICENSE` file.
|
||||
Reference in New Issue
Block a user