# PDF Report [Version francaise](../fr/rapport-pdf.md) ## Objective The PDF must be readable by an operations team and usable as follow-up evidence during an audit. It must prioritize clarity, generation date, backup coverage and exceptions. Current state: PDF generation is implemented with `WeasyPrint` from an HTML/CSS template. The previous `reportlab` renderer remains present in the repository as a technical reference, but `--generate-pdf` uses the WeasyPrint renderer. The WeasyPrint report language is configurable with `REPORT_LANGUAGE=fr` or `REPORT_LANGUAGE=en`. The default value remains `fr`. Current WeasyPrint rendering state: - Complete cover page (`break-after page`): logo bar on a white background at the top, main title in blue `#1f4e79` 32pt centered, metadata bar (Generation, Version) anchored at the bottom through a flex spacer. - Footer present on every page including the cover page: document label on the left, generation date in the center, version on the right, separated from content by a horizontal line. - Page headers except on the first page: report title on the left, page number over total on the right. - Table of contents with automatic page numbers (CSS `target-counter`) and visual hierarchy: group titles in bold blue, indented subsections. - SVG icons before each section title (bar chart, server, cylinder, clock, gear, warning triangle, shield, archive, cross, grey circle with question mark for unspecified namespace) to identify each part quickly. - Section headers with blue left border and very light grey background to distinguish titles from content. - Summary section displayed as KPI cards (7 columns over 2 lines) instead of a table; "Not backed up" and "Anomalies" indicators appear in orange when greater than zero. - Tables with dark headers, alternating rows, and CSS classes applied to cells by value: green for "Active" and "Success", red/bold for "Inactive" and "Failure", amber for "Undetermined", grey italic for "not specified". - Warning messages (PBS GC running) and empty messages visually distinct from tables. - The report remains readable in black-and-white printing: styling relies on bold, italic and left border in addition to color. The final report data model can be previewed with: ```sh PYTHONPATH=src python3 -m pve_backup_report --dump-report-data ``` This command produces JSON containing the computed summary, PBS storages, backup jobs, VM/CT coverage and anomalies. Raw sensitive fields are filtered from this output, but `--dump-report-data` remains a technical audit output: it contains VM/CT names, VMIDs, PVE notes, servers, datastores, namespaces, PBS users and infrastructure metadata. Treat it as internal data. PDF generation: ```sh PYTHONPATH=src python3 -m pve_backup_report --generate-pdf ``` The file is written to `REPORT_OUTPUT_DIR` with a timestamped name. An existing report is never overwritten. ## Filename Recommended format: ```text rapport-sauvegardes-pve-YYYY-MM-DD-HHMMSS.pdf ``` Example: ```text rapport-sauvegardes-pve-2026-05-07-020000.pdf ``` The script must refuse to overwrite an existing file or generate a unique alternative name. ## Report Structure ### Cover Page Implemented structure (full page, `break-after page`): 1. **Logo bar**: Proxmox VE logo (base64 PNG) on a white background, separated by a grey line at the bottom. 2. **Title area**: `{{ title }}` in blue `#1f4e79` 32pt centered, on a white background. 3. **Spacer**: `div` with `flex: 1` absorbing empty space and pushing the metadata panel to the bottom. 4. **Metadata bar**: light grey background with blue top border, two centered items - Generation (`{{ generated_at }}`) and Version (`{{ version }}`) - separated by a vertical line. ### Table of Contents The table of contents is placed after the cover page. It is automatically fed from report section titles to make navigation in the PDF easier. ### Executive Summary Minimum indicators: - total VM count; - total CT count; - number of VM/CT with a planned backup; - number of VM/CT without planned backup; - number of undetermined VM/CT; - number of PBS storages; - number of anomalies. The summary computed in `ReportSummary` also contains: - number of active jobs; - number of inactive jobs; - number of backups to non-PBS storage; - number of backups to disabled PBS storage; ### PBS Storages Declared in PVE Expected table: | ID | Username | PBS server | Datastore | Namespace | Enabled | | --- | --- | --- | --- | --- | --- | Secrets must never appear. The `Enabled` column displays `yes` when the PBS storage is active in PVE. If the PVE `disable` field is absent, the storage is considered active; `disable=1` is displayed as `no`. ### PBS Users - Access Audit This table is placed immediately after `PBS storages declared in PVE`. Expected table: | PBS server | Auth-id | PVE storage | Datastore | Namespace | Enabled | Expiration | Email | Permissions | Comment | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | Data comes from PVE PBS storage `username` values, matched with users and effective permissions exposed by configured PBS servers. If the PVE auth-id is a token of type `user@realm!token`, the `Auth-id` column keeps the full value and user metadata is matched with `user@realm`. Secrets must never appear. Displayed permissions are only effective active privileges on the target datastore/namespace. ### PBS Storage Usage Expected table: | PBS server | Datastore | Total space | Used space | Free space | | --- | --- | --- | --- | --- | Values come from the status of datastores on each configured PBS. Sizes are displayed in readable units (`Kio`, `Mio`, `Gio`, `Tio`). ### VM/CT Backups by Namespace Backup tables are grouped under a level 1 title `VM/CT backups`. VM/CT are displayed in multiple tables, one table per namespace. The title of each table indicates the relevant namespace. Expected columns: | VMID | Name | Notes | Type | Node | VM state | Backup | PBS server | Storage | Mode | Backup schedule | Last backup | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | The `Notes` column contains notes set on the VM or CT in PVE. If no note is set or if it cannot be collected, the displayed value is `not specified`. The `Backup` column displays `Active` when an active PBS backup is planned, otherwise `Inactive`. The `Backup schedule` column contains the schedules of associated backup jobs, i.e. the value displayed in the `Schedule` column of the `Backup jobs` table. The `PBS server` column is inferred from the associated PBS storage when known. If `PBS_HOSTNAMES` contains a mapping, rendering is `IP (host-name)`. Namespace is not displayed as a column in these tables because it is already carried by the table title. Tables are sorted alphabetically by namespace, then rows are sorted alphabetically by `Backup schedule`. `VMID` is no longer the primary sort criterion. The `Mode` column translates the technical PVE job mode: - `snapshot` becomes `No interruption expected`; - `suspend` becomes `Temporary suspension`; - `stop` becomes `Stopped during backup`. The `Last backup` column displays state `Success`, `Failure` or `Undetermined`, followed by date, end time and duration of the latest known `vzdump` task for the VM/CT when this duration is available. For multi-VM/CT jobs, this information is inferred from the `vzdump` task log, not only from the global job task. The value `not specified` is expected if no completed `vzdump` task is available in accessible PVE history, for example for a VM/CT recently added to a job before its first effective backup. Rows without backup must be visually identifiable. Undetermined rows must be distinct from non-backed-up rows. ### VM/CT Backup Retention by PBS and Namespace Retention tables are grouped under a level 1 title `VM/CT backup retention`. Retention data is displayed in multiple tables, split by PBS server then namespace. Each table title indicates the PBS and relevant namespace. Expected columns: | VMID | VM/CT name | Datastore | PVE state | Version count | Expected version count | Delta | Oldest | Newest | Size | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | The `Datastore` column distinguishes two backups in the same namespace on the same PBS but stored in different datastores. The `Version count`, `Oldest`, `Newest` and `Size` columns are populated from the relevant PBS through the snapshot list for the datastore and namespace. The `Expected version count` column is computed from the active retention policy matching the same PBS server, datastore and namespace, by summing configured `keep-last`, `keep-hourly`, `keep-daily`, `keep-weekly`, `keep-monthly` and `keep-yearly` values. The `Delta` column displays `Version count - Expected version count` with a `+` or `-` sign except when the delta is zero. If no matching active policy is found, `Expected version count` and `Delta` display `not specified`. The `Size` column is the size of the newest backup visible on the relevant PBS. The `PVE state` column indicates whether the VM/CT still exists in the PVE inventory (`Active on PVE`) or no longer exists (`Not active on PVE`). Each PBS server can have multiple tables: - `VM/CT backup retention - `. Namespace is not displayed as a column in these tables because it is already carried by the table title. If the garbage collector of the relevant PBS/datastore is running when the report is generated, a warning is displayed just below the relevant table title. This warning explains that the VM/CT backup version count may appear higher than the configured version count. Each table lists only VM/CT for which at least one matching snapshot is visible on the relevant PBS. VM/CT still visible on PBS but absent from the PVE inventory remain displayed in the table and are marked `Not active on PVE`. Snapshots whose namespace does not exist in namespaces declared on PVE are excluded from these tables. Retention tables are sorted by namespace, then by VM/CT name and VMID when information is available. ### Retention Policy The `Retention policy` table is populated from configured PBS servers when their `*_API_URL`, `*_API_TOKEN_ID` and `*_API_TOKEN_SECRET` variables are set. Collection reads PBS prune jobs through `/config/prune` and displays: - PBS server; - datastore; - namespace; - schedule; - active/inactive state; - columns `Last`, `Hourly`, `Daily`, `Weekly`, `Monthly`, `Yearly`; - `max-depth`. A namespace missing in PBS is displayed as `/`, meaning the root namespace. ### VM/CT Without Backup This section must include only uncovered workloads. It must be short and directly actionable. ### Anomalies This section lists collection or interpretation issues. It can be empty, but must then indicate that no anomaly was detected. ## Readability The report must remain readable in black-and-white printing. Do not rely only on color to indicate risk. Use explicit labels: - `Planned backup`; - `Not backed up`; - `Undetermined`. ## Timestamp All displayed dates must use the configured time zone. The time zone must appear in the report. ## Retention The daily report must be kept in a persistent directory. Retention policy for generated reports is separate from PBS retention policies and must be documented in operations if added.