Agentless backup for Proxmox VE. KVM and LXC via native API — real incrementals, CBT via dirty bitmap, granular file restore, cross-cluster restore.
- Real incrementals via dirty bitmap — only changed blocks shipped, no full disk re-read.
- No in-VM agent — capture through PVE API, QGA integration for app-consistency.
- Granular file restore without spinning up the full VM — mount the snapshot, pull what you need.
- Cross-cluster restore — recover to a different PVE node, optionally a different storage backend.
- Coordinated ZFS / Ceph / LVM-thin snapshots — app-consistent when available, crash-consistent guaranteed.
Production-ready in 30 days, at least 50% cheaper. Free trial, signed RPMs and DEBs, direct support from Heitor Faria. Replace your Veeam, Commvault or Bacula Enterprise license without breaking the nightly window.
Table of Contents
- Executive Summary
- Introduction
- Use Cases
- Technical Architecture
- Detailed Feature Reference
- Installation Procedure
- Sizing and Configuration Guide
- Compatibility Matrix
- Parameter Reference
- Configuration Examples
- Security Model
- Competitive Comparison
- TCO and ROI Analysis
- Roadmap
- Conclusion
- Disclaimer and Contact
- Appendix
1. Executive Summary
Organizations running Proxmox VE as their virtualization platform have historically faced a significant gap in enterprise-grade data protection: either they accept the limitations of Proxmox’s native PBS (Proxmox Backup Server) tooling — with no integration into existing corporate backup frameworks — or they pay premium prices for hypervisor-agnostic solutions that carry heavy licensing fees, complex architectures, and vendor lock-in.
PodHeitor Proxmox Backup, Replication and Conversion Plugin for Bacula closes this gap decisively. It is a production-validated, commercially licensed plugin that integrates Proxmox VE virtual machine protection natively into PodHeitor Backup, one of the world’s most widely deployed open-source backup engines. The result is a unified backup platform that combines Bacula’s mature job scheduling, catalog, and retention management with crash-consistent and application-consistent VM protection, incremental-forever backups using QEMU dirty bitmaps (CBT), cross-node disaster recovery replication, instant recovery via NBD overlay, and cross-hypervisor migration from VMware vSphere and Microsoft Hyper-V to Proxmox.
The plugin has been validated in a production environment executing over 1,290 jobs — all completing with status Terminated OK — across two Proxmox VE 8.4 nodes running on Debian 12, coordinated by a PodHeitor Backup Director on Oracle Linux 9.6. Scheduling has been stress-tested at five-minute intervals, and the full DR replication path with TLS fingerprint pinning has been confirmed operational.
For C-level and IT leadership audiences, the strategic value propositions are:
- Cost reduction: Eliminate duplicated tooling. One Bacula deployment covers physical servers, VMs, databases, and now Proxmox VMs.
- Risk reduction: Validated DR replication to a secondary PVE node with automated VM provisioning and TLS-secured transport.
- Agility: Cross-hypervisor conversion enables VMware and Hyper-V workload migration to Proxmox without costly third-party migration tools.
- Compliance readiness: Application-consistent backups (quiesce/freeze via QEMU agent), comprehensive audit logging through Bacula’s catalog, and configurable retention policies.
- No additional daemon sprawl: Scheduling is handled entirely by the native Bacula scheduler — no additional cron jobs, agents, or services.
2. Introduction
2.1 The Problem
Enterprise IT environments that have adopted Proxmox VE as their primary or secondary hypervisor platform encounter a recurring challenge: data protection integration. Most corporate backup strategies are standardized around a single backup framework — commonly Bacula, Veeam, or Commvault — and extending that framework to cover Proxmox VMs typically requires one of the following compromises:
- Running Proxmox Backup Server (PBS) as a parallel system — acceptable for small environments but introduces a completely separate management plane, retention logic, and reporting workflow that does not integrate with the corporate backup catalog.
- Installing a generic file-level backup agent inside each VM — defeats the purpose of hypervisor-level backup, misses pre-snapshot quiescing, requires per-VM agent licensing, and cannot perform bare-metal or instant recovery.
- Purchasing a hypervisor-agnostic enterprise solution — Veeam, Commvault, or Veritas add significant licensing costs, may not support Proxmox officially, and introduce agent sprawl and complex architecture.
- Using the Bacula Enterprise Proxmox plugin — available but locked to the Bacula Enterprise commercial track, which carries per-front-end or per-TB licensing costs that scale unfavorably for mid-market Proxmox deployments.
2.2 The Solution
The PodHeitor Proxmox Plugin delivers a Bacula-native plugin that runs as a shared library loaded by the Bacula File Daemon on each Proxmox VE node. A high-performance Rust backend binary communicates directly with the Proxmox REST API, QEMU Monitor Protocol (QMP) sockets, and Network Block Device (NBD) interfaces — enabling full, incremental, and differential VM backups with crash consistency and optional application consistency.
Because the plugin implements the standard Bacula plugin API, it inherits the full Bacula ecosystem:
- Job scheduling, windows, and calendars
- Retention policies and volume management
- Bootstrap files and catalog-based restore
- Director-level reporting and alerting
- Multi-storage daemon support
- Cloud storage backends (S3, Azure, GCS) via existing Bacula SD configurations
2.3 Market Target
The plugin is designed for:
- Mid-to-large enterprises running Proxmox VE 8.x as their primary virtualization platform alongside PodHeitor Backup
- Service providers and MSPs managing multiple customer environments on Proxmox
- Organizations migrating from VMware or Hyper-V to Proxmox who need a migration and backup tool in one
- Organizations already running Bacula Enterprise or Community who want to extend coverage to Proxmox nodes without adopting an additional platform
3. Use Cases
3.1 Full Fleet VM Backup with Incremental-Forever Strategy
Scenario: A mid-size enterprise runs 80 VMs across two Proxmox VE nodes. The backup team must meet a 24-hour RPO and a 4-hour RTO, with 90-day retention. Storage budget is constrained.
Solution: The plugin is configured with backup_type=full for weekly Sunday jobs and backup_type=incremental for nightly jobs. On the first run, a full image-level backup captures all VM disk extents via NBD. On subsequent runs, only the dirty extents tracked by QEMU CBT bitmaps are sent to the Bacula Storage Daemon, reducing backup windows from hours to minutes.
Flow:
[Sunday 23:00]
Bacula Director triggers FileSet "Proxmox-All-VMs" with backup_type=full
-> Plugin enumerates all VMs on PVE node via REST API
-> For each VM: create consistent snapshot (quiesce=yes via QEMU agent)
-> Open NBD export for each disk
-> Stream all extents to SD -> write to volume
-> Remove snapshot, record CBT bitmap ID in catalog
[Mon-Sat 23:00]
backup_type=incremental
-> Plugin reads CBT bitmap delta since last backup
-> Only dirty extents streamed -> 5-20x smaller backup window
-> Full restore path reconstructed from base + delta chain
Result: Full backup weekly (~TB scale), incrementals in under 30 minutes nightly. 90-day retention via Bacula pool and volume management. RTO met via catalog-based restore wizard.
3.2 Disaster Recovery Replication to Secondary Site
Scenario: A financial services firm requires a secondary site that mirrors critical VMs from the primary PVE cluster. The secondary site must be able to boot VMs independently within 15 minutes of a primary site failure.
Solution: DR replication mode uses a receiver/sender architecture. The secondary PVE node runs the plugin in mode=receiver, listening on TCP port 9190. The primary node runs mode=seed (sender), which streams VM disk data over a TLS-encrypted, PSK-authenticated channel. The receiver automatically provisions the target VM in the secondary PVE cluster.
Flow:
Primary PVE (192.168.15.129) Secondary PVE (192.168.15.102)
mode=seed mode=receiver
vm=127 dr_port=9190
dr_host=192.168.15.102 target_vmid=127
dr_port=9190 storage=local-lvm
|
| TCP:9190 (PSK/TLS encrypted)
+------------------------------------------------->
Auto provision VM 127
Write disk extents
Register in PVE inventory
Result: VM 127 is available on the secondary PVE node within minutes. In a failover event, the operations team boots VM 127 on the DR node. No manual disk copy or import required.
3.3 Instant Recovery for Rapid SLA Compliance
Scenario: A production database VM fails at 09:15. The backup from 02:00 exists on the Bacula Storage Daemon. The business SLA requires service restoration within 30 minutes.
Solution: Instant Recovery (IR) mode boots the VM directly from the backup via an NBD overlay mounted on the Proxmox node. The VM is live within 2-5 minutes. In the background, the plugin migrates the VM disks from the NBD overlay to the final target storage, transparently and without service interruption.
Flow:
[09:15] VM failure detected
[09:17] Operator initiates IR restore job
[09:19] Plugin mounts NBD overlay from backup volume on SD
PVE boots VM from NBD overlay -> VM is live (read/write via overlay)
[09:20] VM available to users -- SLA met
[09:20-10:00] Background migration: disk pages copied from NBD overlay
to target_storage=local-lvm
[10:00] Migration complete. VM detached from NBD overlay.
Fully sovereign on local storage.
Result: SLA of 30 minutes met at 09:20 — 8 minutes from failure detection.
3.4 Cross-Hypervisor Migration — VMware to Proxmox
Scenario: An enterprise is exiting a VMware perpetual license agreement following Broadcom acquisition price increases. They need to migrate 40 VMs from vSphere 7 to Proxmox VE 8 with minimal downtime and without purchasing additional migration tooling.
Solution: The plugin includes a validated conversion pipeline from VMware VMDK format to Proxmox-native qcow2 or raw format. VMDK disks are exported from vSphere, and the plugin handles format translation, disk geometry normalization, and VM configuration mapping to Proxmox .conf format.
Flow:
vSphere 7 Datastore (NFS)
VMDK disks + .vmx config
|
| Direct file access / SCP
v
PodHeitor Backend Conversion Engine
+-- Parse .vmx -> generate Proxmox VM .conf
+-- Convert VMDK -> qcow2 (via internal format pipeline)
+-- Import disk images into PVE storage
+-- Register VM in PVE inventory with converted configuration
|
v
Proxmox VE 8 -- VM ready to boot
Result: 40 VMs migrated over a weekend maintenance window. Zero additional migration tool licensing costs.
3.5 Application-Consistent Backup for Databases
Scenario: A PostgreSQL database cluster runs inside a Proxmox VM. The DBA team requires application-consistent backups — WAL logs checkpointed and the filesystem quiesced before snapshot — to guarantee clean restore without replay failures.
Solution: The quiesce=yes parameter instructs the plugin to invoke the QEMU Guest Agent’s guest-fsfreeze-freeze command before creating the Proxmox snapshot and guest-fsfreeze-thaw after. This ensures all in-flight filesystem writes are committed before the snapshot is taken.
Flow:
Plugin -> QMP socket -> QEMU Agent: guest-fsfreeze-freeze
Wait: all FS buffers flushed, PostgreSQL checkpoint issued
Plugin -> PVE REST API: POST /nodes/{node}/qemu/{vmid}/snapshot
Snapshot created at consistent state
Plugin -> QMP socket -> QEMU Agent: guest-fsfreeze-thaw
VM continues normal operation
Plugin -> NBD: open disk export from snapshot
Stream data to Bacula SD
Result: PostgreSQL restores from backup without requiring WAL replay. Restore testing confirms clean database startup directly from backup image.
3.6 Automated Multi-Tenant MSP Environment
Scenario: A managed service provider hosts VMs for 30 customers on a shared Proxmox cluster. Each customer has different backup windows, retention requirements, and DR destinations.
Solution: Bacula’s native multi-client architecture maps naturally. Each customer group is a separate Bacula Client pointing to a dedicated PVE node, with separate FileSets, Schedules, Pools, and Storage Daemons. The plugin’s vm= parameter accepts VMID ranges or name patterns, enabling customer-scoped backup jobs without modifying any global configuration.
Result: 30 independent backup streams, managed from a single Bacula Director, with per-customer reporting, retention, and DR — all without per-customer agent licensing.
4. Technical Architecture
4.1 Component Overview
+---------------------------------------------------------------------+
| Bacula Director (RHEL/OL 9.6) |
| +--------------+ +--------------+ +--------------------------+ |
| | Scheduler | | Catalog | | Job/Pool/Volume Mgmt | |
| | (native) | | (PostgreSQL) | | | |
| +--------------+ +--------------+ +--------------------------+ |
+----------------------------+----------------------------------------+
| Bacula Protocol (TCP 9102)
v
+---------------------------------------------------------------------+
| Bacula File Daemon (Proxmox VE Node, Debian 12) |
| +----------------------------------------------------------------+ |
| | podheitor-proxmox-fd.so (plugin FD) | |
| | Loaded by bacula-fd at startup | |
| | Implements: Bacula plugin API (backup/restore/events) | |
| +----------------------------+-----------------------------------+ |
+--------------------------------+------------------------------------+
| Internal Protocol (stdin/stdout pipe)
v
+---------------------------------------------------------------------+
| podheitor-proxmox-backend (Rust binary, high performance) |
| |
| +--------------+ +--------------+ +---------------------------+ |
| | PVE REST | | QMP Client | | NBD Client | |
| | API Client | | (Unix sock) | | (TCP 10809) | |
| | HTTPS:8006 | | QEMU Guest | | Disk extent stream | |
| | TLS pinned | | Agent cmds | | CBT dirty bitmaps | |
| +--------------+ +--------------+ +---------------------------+ |
| |
| +---------------------------------------------------------------+ |
| | DR Transport Engine | |
| | TCP:9190 -- PSK/TLS encrypted | |
| | Receiver: auto VM provisioning + disk write | |
| | Sender: disk delta stream + handshake | |
| +---------------------------------------------------------------+ |
+---------------------------------------------------------------------+
| |
| HTTPS:8006 (TLS pinned) | QMP Unix socket
v v
Proxmox VE REST API QEMU Monitor (per-VM)
- VM lifecycle mgmt - guest-fsfreeze-freeze/thaw
- Snapshot create/delete - disk info queries
- Storage management - bitmap management
- Node enumeration
4.2 The Plugin FD (podheitor-proxmox-fd.so)
The shared library is loaded by the Bacula File Daemon on the Proxmox VE node. Its responsibilities are:
- Registering the plugin with the FD at load time
- Parsing the FileSet
Plugin =string and extracting key-value parameters - Spawning the Rust backend process with job parameters
- Forwarding Bacula backup/restore events to the backend
- Proxying data blocks between the FD data stream and the backend’s output
This modular design means the performance-critical and feature-rich logic is entirely in the Rust backend binary, which can be updated and tested independently of the FD.
4.3 The Rust Backend (podheitor-proxmox-backend)
The backend binary — built in Rust for native memory safety and zero GC pauses — is the core engine, structured around five primary subsystems:
| Subsystem | Responsibility |
|---|---|
| PVE API Client | Authenticated HTTPS client for the Proxmox REST API. Handles token lifecycle, TLS fingerprint pinning, VM enumeration, snapshot management, storage queries. |
| QMP Client | Unix domain socket client for QEMU Monitor Protocol. Issues guest-fsfreeze-freeze/thaw, query-block, and bitmap management commands. |
| NBD Engine | TCP client for Network Block Device protocol (TCP 10809). Handles connection negotiation, extent queries (for CBT), and raw block data streaming. |
| DR Transport | Custom TCP protocol on port 9190. PSK or certificate-based TLS. Implements receiver and sender roles. |
| Conversion Engine | VMDK/OVF and VHDX parser and converter. Generates Proxmox-native .conf files and translates disk formats to qcow2 or raw. |
4.4 Data Flow: Incremental Backup
Backend reads CBT bitmap from QEMU (via QMP/NBD bitmap query)
|
v Dirty extent list (offset, length pairs)
Backend opens NBD export for snapshot disk
|
v For each dirty extent:
Read block from NBD -> compress (LZ4/zstd) -> write to Bacula data stream
|
v Bacula data stream
Plugin FD forwards to Bacula SD over network
|
v
SD writes to configured Volume (disk/tape/cloud)
|
v
Director updates catalog: job ID, file entries, bitmap checkpoint ID
4.5 Data Flow: DR Replication
Sender Node (primary PVE) Receiver Node (DR PVE)
-------------------------- ----------------------
Backend (mode=seed) Backend (mode=receiver)
| |
| 1. TLS handshake (PSK/cert) | Listening on :9190
+------------------------------------->|
| | 2. Validate auth token/cert
| 3. VM metadata (config, disk list) |
+------------------------------------->|
| | 4. Provision VM in PVE inventory
| 5. Disk data stream (extents) |
+------------------------------------->|
| | 6. Write extents to storage
| 7. Completion + bitmap checkpoint |
+------------------------------------->|
| | 8. Finalize VM, mark ready
5. Detailed Feature Reference
5.1 VM Backup — Full, Incremental, Differential
The plugin supports three backup levels aligned with the Bacula job type model:
Full: All disk extents for all selected VMs are streamed from the PVE node to the Bacula Storage Daemon. A consistent snapshot is created on the PVE side before reading, ensuring crash consistency. If quiesce=yes, the QEMU guest agent is invoked to freeze filesystems before snapshot creation.
Incremental: After a full backup, QEMU CBT (Changed Block Tracking) dirty bitmaps record which 64KB disk extents have been written since the last backup. The plugin queries these bitmap extents via NBD and streams only the changed blocks. This can reduce backup data volume by 90-98% for typical workloads.
Differential: Similar to incremental, but the bitmap reference point is always the last full backup rather than the last job. This simplifies restore chains (full + one differential) at the cost of slightly larger differential backups compared to incrementals.
5.2 VM Replication DR — Cross-Node Replication
The DR replication subsystem is designed for zero-additional-tool disaster recovery. It requires:
- A second Proxmox VE node (DR site)
- Network connectivity on TCP port 9190 between nodes
- The plugin installed on both nodes
Auto VM provisioning on the receiver means operators do not need to manually create the target VM — the plugin creates the VM configuration, allocates storage, and registers the VM in the Proxmox inventory automatically. Subsequent replication runs stream only changed extents.
5.3 Cross-Hypervisor Conversion
Validated conversion paths:
| Source | Target | Status |
|---|---|---|
| VMware vSphere (VMDK) | Proxmox VE (qcow2/raw) | Validated in production |
| Microsoft Hyper-V (VHDX) | Proxmox VE (qcow2/raw) | Validated in production |
| Proxmox VE (qcow2) | Proxmox VE (raw) | Native |
The conversion engine handles disk format translation, VM configuration mapping, storage driver normalization, and post-conversion Proxmox .conf file generation.
5.4 TLS Security — SHA-256 Fingerprint Pinning
The plugin communicates with the Proxmox API over HTTPS:8006. Rather than requiring a full PKI deployment or disabling TLS verification, the plugin implements SHA-256 fingerprint pinning: the operator provides the known SHA-256 hash of the Proxmox node’s TLS certificate in the pve_fingerprint parameter. The backend validates this fingerprint on every connection, preventing MITM attacks even with self-signed certificates.
5.5 Instant Recovery (IR) — NBD Overlay Boot
Instant Recovery eliminates the wait for full disk restore by mounting the backup volume as an NBD export directly accessible by the PVE node. Proxmox boots the VM using this NBD-backed disk immediately. An overlay layer captures new writes, so the VM can operate normally during background migration.
Background migration copies disk extents from the NBD overlay to the final target_storage transparently. Once migration completes, the VM is fully detached from the backup volume. The original backup is preserved unmodified.
5.6 Quiesce/Freeze — Application-Consistent Backups
When quiesce=yes (default), the plugin issues guest-fsfreeze-freeze to the QEMU guest agent installed in the VM before creating the Proxmox snapshot. After the snapshot is created (typically under 1 second), guest-fsfreeze-thaw is issued and the VM resumes normal operation. The total freeze window is typically 200-800ms, imperceptible to end users.
If the guest agent is not running or not installed, the plugin falls back to crash-consistent snapshot creation and logs a warning.
5.7 Multi-Format Disk Support
| Format | Read | Write | Notes |
|---|---|---|---|
| qcow2 | Yes | Yes | Native Proxmox format, supports CBT bitmaps |
| raw | Yes | Yes | Maximum performance, no format overhead |
| vmdk | Yes | Yes (conversion) | For VMware import/export workflows |
5.8 Schedule Automation
No additional daemons, cron entries, or external schedulers are required. The plugin leverages the Bacula native scheduler entirely. The production validation environment was tested at 5-minute scheduling intervals with all jobs completing cleanly, demonstrating the plugin’s suitability for high-frequency, short-RPO requirements.
6. Installation Procedure
6.1 Prerequisites
Before installing, verify:
- PodHeitor Backup+ is installed and operational (Director, SD, FD)
- The Bacula File Daemon is running on the target Proxmox VE node
- Proxmox VE 8.0+ is running on Debian 11+
- The Proxmox API user has appropriate permissions (see Section 6.3)
- TCP port 9102 (FD) is open between Director and PVE node
- TCP port 9190 is open between PVE nodes (if using DR replication)
6.2 Installing the Plugin on the PVE Node
Step 1: Deploy binary files
# On the PVE node (Debian 12)
mkdir -p /usr/lib/bacula/plugins
# Copy the compiled shared library and backend binary
cp podheitor-proxmox-fd.so /usr/lib/bacula/plugins/
cp podheitor-proxmox-backend /usr/lib/bacula/plugins/
# Set ownership and permissions
chown root:bacula /usr/lib/bacula/plugins/podheitor-proxmox-fd.so
chown root:bacula /usr/lib/bacula/plugins/podheitor-proxmox-backend
chmod 750 /usr/lib/bacula/plugins/podheitor-proxmox-fd.so
chmod 750 /usr/lib/bacula/plugins/podheitor-proxmox-backend
Step 2: Configure the Bacula File Daemon to load the plugin
Edit /etc/bacula/bacula-fd.conf on the PVE node:
FileDaemon {
Name = proxmox-pve1-fd
FDport = 9102
WorkingDirectory = /var/lib/bacula
Pid Directory = /run/bacula
Plugin Directory = /usr/lib/bacula/plugins
Maximum Concurrent Jobs = 10
}
Step 3: Restart the Bacula File Daemon
systemctl restart bacula-fd
systemctl status bacula-fd
Step 4: Verify plugin loaded
journalctl -u bacula-fd | grep -i podheitor
# Expected: "Loaded plugin: podheitor-proxmox-fd.so"
6.3 Proxmox API User Configuration
# On the PVE node
pveum user add bacula@pam --comment "Bacula backup user"
pveum passwd bacula@pam
# Required roles
pveum aclmod / -user bacula@pam -role PVEAuditor
pveum aclmod /vms -user bacula@pam -role PVEVMAdmin
pveum aclmod /storage -user bacula@pam -role PVEDatastoreAdmin
6.4 Obtain the TLS Fingerprint
openssl x509 -in /etc/pve/pve-ssl.pem -noout -fingerprint -sha256 |
sed 's/SHA256 Fingerprint=//'
Record this value for the pve_fingerprint parameter in your FileSets.
6.5 Director Configuration
Client {
Name = proxmox-pve1-fd
Address = 192.168.15.129
FDPort = 9102
Catalog = MyCatalog
Password = "your-fd-password"
File Retention = 90 days
Job Retention = 90 days
AutoPrune = yes
}
6.6 Verify Connectivity
bconsole
*status client=proxmox-pve1-fd
# Expected: Connected, version info, and plugin list
6.7 DR Receiver Setup (Optional)
On the secondary PVE node (DR site), perform the same installation steps (6.1-6.4). No additional configuration is needed on the receiver — the plugin starts in receiver mode when mode=receiver is specified in the FileSet.
# From primary PVE node to DR PVE node
nc -zv 192.168.15.102 9190
7. Sizing and Configuration Guide
7.1 Component Sizing
Bacula Director
| Tier | CPU | RAM | Storage (Catalog) | Notes |
|---|---|---|---|---|
| Minimum | 4 vCPU | 8 GB | 500 GB | Up to 50 VMs, 30-day retention |
| Recommended | 8 vCPU | 16 GB | 2 TB | Up to 500 VMs, 90-day retention |
| Large Scale | 16 vCPU | 32 GB | 10 TB+ | 1000+ VMs, 1-year retention |
Bacula Storage Daemon
| Tier | CPU | RAM | Disk Throughput | Notes |
|---|---|---|---|---|
| Minimum | 4 vCPU | 8 GB | 500 MB/s | <10 concurrent backup streams |
| Recommended | 8 vCPU | 32 GB | 2+ GB/s | Up to 50 concurrent streams |
| Large Scale | 16+ vCPU | 64 GB | 10+ GB/s | 100+ concurrent streams |
Bacula File Daemon (on PVE Node)
| Tier | CPU | RAM | Notes |
|---|---|---|---|
| Minimum | 2 vCPU | 4 GB | Shared with PVE overhead |
| Recommended | 4 vCPU | 8 GB | Allows parallel VM backups |
Network
| Scenario | Minimum | Recommended |
|---|---|---|
| Local backup (PVE to SD on same network) | 1 Gbps | 10 Gbps |
| DR replication (cross-site) | 100 Mbps | 1 Gbps |
| WAN DR replication | 10 Mbps (with compression) | 100 Mbps |
7.2 Performance Tuning
Concurrent VM backups: Set Maximum Concurrent Jobs in the FD configuration. Each concurrent VM backup uses approximately 200-500 MB RAM in the backend for buffering.
Compression: Enable Bacula SD compression (Compression = LZ4 in FileSet Options) for CPU-bound workloads where disk throughput is the bottleneck.
Incremental interval: For very active VMs (high write rates), shorter incremental intervals (hourly) produce smaller per-job delta sizes and faster backups.
8. Compatibility Matrix
8.1 Validated Component Versions
| Component | Minimum Version | Tested Version | Validation Status |
|---|---|---|---|
| PodHeitor Backup | 15.0.0 | 15.0.3 | Validated in production |
| Proxmox VE | 8.0 | 8.4.18 | Validated in production |
| Debian (PVE host) | 11 (Bullseye) | 12 (Bookworm) | Validated in production |
| RHEL / Oracle Linux (Director) | 8 | 9.6 | Validated in production |
| Ubuntu (Director/SD) | 22.04 LTS | 24.04 LTS | Compatible (community tested) |
| PostgreSQL (Catalog) | 13 | 14+ | Validated in production |
| QEMU (via PVE) | 8.0 | 9.2 | Validated |
| Linux Kernel (PVE host) | 6.1 | 6.8 | Validated |
8.2 Source Hypervisor Compatibility (Conversion)
| Source Hypervisor | Source Version | Status |
|---|---|---|
| VMware vSphere | 6.7, 7.0, 8.0 | Validated in production |
| VMware Workstation | 16, 17 | Compatible |
| Microsoft Hyper-V | 2019, 2022 | Validated in production |
| KVM / libvirt | Any | Native (qcow2/raw) |
| VirtualBox | 7.0 | Compatible (VMDK export) |
8.3 Storage Backend Compatibility (PVE)
| Proxmox Storage Type | Backup | Restore | Instant Recovery | Notes |
|---|---|---|---|---|
| local-lvm (LVM-thin) | Yes | Yes | Yes | Recommended for production |
| local (directory) | Yes | Yes | Yes | qcow2 format |
| NFS | Yes | Yes | Limited | IR performance may vary |
| Ceph RBD | Yes | Yes | Yes | Native thin-provisioning |
| ZFS | Yes | Yes | Yes | Snapshot-friendly |
9. Parameter Reference
9.1 PVE Connection Parameters
| Parameter | Aliases | Default | Required | Description |
|---|---|---|---|---|
pve_host |
pvehost, host |
— | Yes | IP address or hostname of the PVE node |
pve_user |
pveuser, user |
root@pam |
No | PVE API username (user@realm format) |
pve_password |
pvepassword, password |
— | Yes | Password for the PVE API user |
pve_port |
pveport, port |
8006 |
No | HTTPS port for the PVE REST API |
pve_realm |
pverealm, realm |
pam |
No | Authentication realm (pam, pve, ldap) |
pve_fingerprint |
pvefingerprint, fingerprint |
— | Recommended | SHA-256 fingerprint of the PVE TLS certificate |
pve_insecure |
pveinsecure |
no |
No | Set to yes to disable TLS certificate verification (not recommended) |
9.2 VM Selection Parameters
| Parameter | Aliases | Default | Required | Description |
|---|---|---|---|---|
vm |
— | * |
No | VMID, VM name, or wildcard pattern. * selects all VMs on the node |
exclude |
— | (none) | No | Comma-separated list of VMIDs to exclude from backup |
node |
— | (hostname) | No | Target a specific PVE cluster node by name |
9.3 Backup Parameters
| Parameter | Aliases | Default | Required | Description |
|---|---|---|---|---|
mode |
— | backup |
No | Operational mode: backup, receiver, seed, incremental |
backup_type |
— | full |
No | Backup level: full, incremental, differential |
quiesce |
— | yes |
No | Issue guest-fsfreeze before snapshot for application consistency |
include_config |
— | yes |
No | Include VM configuration file in backup |
include_firewall |
— | yes |
No | Include PVE firewall rules in backup |
storage |
storageid |
bacula-store |
No | PVE storage ID where snapshots are temporarily held |
9.4 NBD Parameters
| Parameter | Aliases | Default | Required | Description |
|---|---|---|---|---|
nbd_host |
nbdhost |
auto |
No | Hostname for NBD server. auto uses the PVE node address |
nbd_port |
nbdport |
10809 |
No | TCP port for the NBD server |
9.5 DR / Replication Parameters (v1.1.0 complete set)
| Parameter | Aliases | Default | Required | Description |
|---|---|---|---|---|
mode |
— | backup |
Yes (for DR) | bitmap-push / seed (source) / receiver (DR) / daemon / failover-pre / failover-exec / failback-pre / failback-exec / reprotect / replication-status |
dr_host |
drhost |
— | Yes (source) | IP/hostname of the DR receiver PVE node |
dr_port |
drport |
9100 + (vmid % 900) |
No | TCP port for the DR transport. Default derives per-VMID (e.g. 9203 for VMID 103) |
target_vmid |
targetvmid, dr_vmid |
— | Yes (source) | VMID to use on the DR site for the replica |
target_storage |
targetstorage, dr_storage |
local-lvm |
No | PVE storage pool on DR for replica volumes |
dr_auth_token |
drauthtoken, dr_token |
— | No* | Shared-secret for PSK-mode DR transport |
dr_auth_cert |
drauthcert, dr_cert |
— | No* | PEM cert path for mutual-TLS DR transport (activates TLS mode) |
dr_auth_key |
drauthkey, dr_key |
— | No* | PEM private-key path for mutual-TLS |
dr_ca_cert |
drcacert |
(falls back to dr_auth_cert) |
No | CA cert bundle used to verify the peer |
max_restore_points |
maxrestorepoints |
3 |
No | Max restore-point snapshots retained on DR (older are auto-pruned) |
state_dir |
statedir |
/var/lib/bacula |
No | Directory for per-VM repl-state-*.json / dr-vm-state-*.json |
bitmap_granularity |
bitmapgranularity |
65536 (64 KiB) |
No | QEMU dirty-bitmap granularity in bytes (power of 2) |
cycle_interval |
cycleinterval |
300 (s) |
No | Daemon-mode: seconds between cycles |
throttle_bps |
throttlebps, throttle |
0 (off) |
No | Bandwidth cap for DR transport, bytes/sec |
verify_sample_blocks |
verifysampleblocks |
0 (off) |
No | v1.1.0: random 64 KiB blocks to hash-compare per cycle |
* dr_auth_token XOR (dr_auth_cert+dr_auth_key) — choose one auth mode.
9.6 Restore Parameters
| Parameter | Aliases | Default | Required | Description |
|---|---|---|---|---|
restore_path |
restorepath |
— | No | Local path for disk image extraction on restore |
new_vm_name |
newvmname |
— | No | Name for the restored VM (overrides original name) |
target_storage |
targetstorage |
— | No | PVE storage ID for restored VM disks |
overwrite_vmid |
overwritevmid |
— | No | VMID to overwrite on restore (destructive; use with caution) |
start_vm |
startvm, power_on |
no |
No | Automatically power on the VM after restore completes |
9.7 Instant Recovery Parameters
| Parameter | Aliases | Default | Required | Description |
|---|---|---|---|---|
ir_nbd_port |
irnbdport |
auto |
No | NBD port for the IR disk export |
ir_overlay_storage |
iroverlaystorage |
— | No | PVE storage for the write overlay during IR session |
ir_timeout |
irtimeout |
3600 |
No | IR session timeout in seconds before forced migration |
ir_auto_migrate |
irautomigrate |
no |
No | Automatically start background migration after VM boot |
10. Configuration Examples
10.1 FileSet — Full Backup of All VMs
FileSet {
Name = "Proxmox-All-VMs-Full"
Include {
Options {
signature = MD5
Compression = LZ4
}
Plugin = "podheitor-proxmox:
pve_host=192.168.15.129
pve_user=root@pam
pve_password=yourpassword
pve_fingerprint=D0:C6:19:10:DA:59:68:39:E2:4E:C4:7D:2E:A9:FB:F1:75:E3:51:12:12:D6:3C:5F:51:4B:2B:21:6C:48:DC:9E
vm=*
backup_type=full
quiesce=yes
include_config=yes
include_firewall=yes
storage=local-lvm"
}
}
10.2 FileSet — Incremental Backup
FileSet {
Name = "Proxmox-All-VMs-Incremental"
Include {
Options {
signature = MD5
Compression = LZ4
}
Plugin = "podheitor-proxmox:
pve_host=192.168.15.129
pve_user=root@pam
pve_password=yourpassword
pve_fingerprint=D0:C6:19:10:DA:59:68:39:E2:4E:C4:7D:2E:A9:FB:F1:75:E3:51:12:12:D6:3C:5F:51:4B:2B:21:6C:48:DC:9E
vm=*
backup_type=incremental
quiesce=yes
storage=local-lvm"
}
}
10.3 FileSet — DR Replication Sender
FileSet {
Name = "Proxmox-Replicate-VM127-to-pve2"
Include {
Options { signature = MD5 }
Plugin = "podheitor-proxmox:
pve_host=192.168.15.129
pve_user=root@pam
pve_password=yourpassword
pve_fingerprint=D0:C6:19:10:DA:59:68:39:E2:4E:C4:7D:2E:A9:FB:F1:75:E3:51:12:12:D6:3C:5F:51:4B:2B:21:6C:48:DC:9E
vm=127
mode=seed
dr_host=192.168.15.102
dr_port=9190
target_vmid=127
nbd_port=10809
storage=local-lvm"
}
}
10.4 FileSet — DR Receiver
FileSet {
Name = "Proxmox-DR-Receiver-pve2-VM127"
Include {
Options { signature = MD5 }
Plugin = "podheitor-proxmox:
mode=receiver
pve_host=192.168.15.102
pve_user=root@pam
pve_password=yourpassword
pve_fingerprint=16:A0:9C:94:BF:22:99:8E:29:38:DD:3C:D7:62:04:AC:20:A4:02:48:A0:2A:C7:3D:17:34:81:B4:9A:CC:C8:A2
dr_port=9190
storage=local-lvm
target_vmid=127"
}
}
10.5 Complete Job, Schedule, and Pool Example
Schedule {
Name = "ProxmoxWeeklySchedule"
Run = Full sun at 23:00
Run = Incremental mon-sat at 23:00
}
Job {
Name = "Proxmox-PVE1-Backup"
Type = Backup
Client = proxmox-pve1-fd
FileSet = "Proxmox-All-VMs-Full"
Schedule = "ProxmoxWeeklySchedule"
Storage = File-Storage
Pool = Proxmox-Pool
Messages = Standard
Priority = 10
Maximum Concurrent Jobs = 5
}
Pool {
Name = Proxmox-Pool
Pool Type = Backup
Recycle = yes
AutoPrune = yes
Volume Retention = 90 days
Label Format = "Proxmox-Vol-"
Maximum Volume Bytes = 100G
}
10.6 Instant Recovery Job
Job {
Name = "Proxmox-InstantRestore-VM127"
Type = Restore
Client = proxmox-pve1-fd
FileSet = "Proxmox-All-VMs-Full"
Storage = File-Storage
Pool = Proxmox-Pool
Messages = Standard
Where = /
Plugin Options = "
ir_nbd_port=10810
ir_overlay_storage=local
ir_timeout=7200
ir_auto_migrate=yes
target_storage=local-lvm
start_vm=yes"
}
11. Security Model
11.1 Threat Model
The plugin addresses four primary threat vectors in backup infrastructure:
- Man-in-the-Middle on PVE API: Mitigated by SHA-256 certificate fingerprint pinning
- Unauthorized backup access: Mitigated by Bacula Director authentication and FD password validation
- DR transport interception: Mitigated by PSK or mutual TLS on DR transport channel
- Credential exposure: Mitigated by Bacula’s encrypted catalog and restricted file permissions
11.2 TLS Fingerprint Pinning
Unlike traditional CA-based certificate validation, fingerprint pinning verifies the exact certificate bytes of the target server. This is particularly appropriate for Proxmox deployments where self-signed certificates are standard and the set of trusted servers is known and static.
Obtaining the fingerprint:
# Option 1: Via OpenSSL on the PVE node
openssl x509 -in /etc/pve/pve-ssl.pem -noout -fingerprint -sha256
# Option 2: Via the PVE web interface
# Dashboard -> Node -> Certificates -> Fingerprint (SHA-256)
11.3 DR Transport Security
PSK Mode (dr_auth_token): Session-level HMAC authentication using the shared token. Recommended for same-datacenter or VPN-protected cross-site replication.
Certificate TLS Mode (dr_auth_cert + dr_auth_key): Full mutual TLS. Required for untrusted network segments (public internet, co-location cross-connects).
11.4 Credential Management Best Practices
- Store PVE passwords in Bacula’s encrypted credentials store or use environment variable injection
- Use dedicated API users with minimum required privileges (see Section 6.3) rather than
root@pam - Rotate DR auth tokens on a regular schedule (quarterly recommended)
- Restrict
/usr/lib/bacula/plugins/directory permissions toroot:bacula750 - Audit Bacula Director logs for unauthorized restore attempts
11.5 Network Segmentation Recommendations
+-------------------+ TCP:9102 +--------------------+
| Bacula Director +---------------->+ PVE Node FD |
| (management net) | | (hypervisor net) |
+-------------------+ +--------------------+
| TCP:9190
v
+--------------------+
| DR PVE Node FD |
| (DR site net) |
+--------------------+
Firewall rules required:
Director -> PVE FD: TCP 9102 inbound
PVE FD -> Bacula SD: TCP 9103 outbound
PVE Primary -> PVE DR: TCP 9190 outbound
PVE DR: TCP 9190 inbound (from primary only)
12. Competitive Comparison
12.1 Feature Comparison Table
| Feature | PodHeitor Plugin | Veeam B&R | Commvault | Bacula Enterprise |
|---|---|---|---|---|
| Proxmox VE backup | Native | Limited (v12 beta) | Via agent only | Native |
| Incremental CBT | QEMU dirty bitmaps | VMware CBT | CBT | QEMU dirty bitmaps |
| Application-consistent | QEMU agent (fsfreeze) | VSS/VMware tools | VSS | QEMU agent |
| Instant Recovery | NBD overlay | Instant VM Recovery | Live Recovery | Yes |
| DR Replication | Built-in | Replication jobs | Yes | Limited |
| VMware to Proxmox migration | Validated | Not supported | Not supported | Not supported |
| Hyper-V to Proxmox migration | Validated | Not supported | Not supported | Not supported |
| TLS fingerprint pinning | Yes | Full PKI required | Full PKI required | Yes |
| Bacula integration | Native plugin | Separate product | Separate product | Native |
| No additional daemons | Yes | No | No | Yes |
| Linux-native binary | Yes (Rust, native binary) | Windows primary | Mixed | Yes |
12.2 Licensing and Cost Model
| Solution | Licensing Model | Proxmox VMs | Entry Cost |
|---|---|---|---|
| PodHeitor Plugin | Commercial flat-fee per node | Unlimited per node | Contact for pricing |
| Veeam B&R | Per-workload socket or VM | Charged per VM | High per-VM cost |
| Commvault | Per-TB or per-core | Per-agent or per-TB | Complex, high cost |
| Bacula Enterprise | Per-front-end + modules | Module licensed | Annual subscription |
| Proxmox PBS | Free / open-source | Unlimited | $0 (no Bacula integration) |
12.3 Architecture Simplicity
| Solution | New Components Required | Dedicated Server | Cross-Hypervisor |
|---|---|---|---|
| PodHeitor Plugin | .so + backend binary only | No | VMware + Hyper-V validated |
| Veeam | VBR Server + Proxy VMs | Yes (Windows) | Limited Proxmox support |
| Commvault | CommServe + MediaAgent + Agents | Yes | Yes (complex licensing) |
| Bacula Enterprise | Enterprise FD + plugin module | Director (existing) | Limited |
Key differentiator: The PodHeitor plugin requires zero new infrastructure. If PodHeitor Backup is already deployed, adding Proxmox protection is a file copy and configuration change.
12.4 Lab Evidence — v1.1.0 (2026-04-24)
The following are real log excerpts captured during the pre-GA gate run (full transcript in docs/GATE_REPORT_2026-04-24.md). They are not synthetic — the localhost-dir JobId 3448 is a real Bacula Director job on the Oracle Linux 9.6 Director at 192.168.15.105.
Seed of a 100 GB VM, source → DR
2026-04-24 00:26:43 INFO Starting seed cycle for VM 103
2026-04-24 00:26:43 INFO Connecting to DR receiver at 192.168.15.102:9203
2026-04-24 00:26:43 INFO PSK encryption established (client)
2026-04-24 00:26:47 INFO NBD export size: 107374182400 bytes (102400 MB)
2026-04-24 00:26:51 INFO Seed progress: 0.2% (256 MB) chunk 64/25600 — 3.7s
…
2026-04-24 02:00:24 INFO Seed complete for VM 103: 1 disks, 102400.00 MB in 5623.5s
On the DR side simultaneously:
2026-04-23 18:26:41 INFO Provisioning replica VM 203 (source VM 103)
2026-04-23 18:26:41 INFO Created VM 203 on node pve2
2026-04-23 18:26:42 INFO Allocated disk: local-lvm:vm-203-disk-0 for VM 203
2026-04-23 18:26:47 INFO Receiving full disk seed for scsi0: 107374182400 bytes
2026-04-23 19:59:42 INFO Full disk done for scsi0: 107374182400 bytes written
Sampled integrity verification on an incremental
2026-04-24 07:42:12 INFO Integrity verify OK for scsi0: 10 blocks, all match
2026-04-24 07:42:15 INFO Incremental complete for VM 103: 1 disks, 160 regions, 281.06 MB in 155.9s
Fifteen consecutive cycles produced 150 sample-block compares, zero mismatches (full table in docs/GATE_REPORT_2026-04-24.md).
Mutual-TLS replication cycle
2026-04-24 08:00:39 INFO TLS (mutual-cert) handshake with 192.168.15.102
2026-04-24 08:00:52 INFO Integrity verify OK for scsi0: 10 blocks, all match
2026-04-24 08:00:55 INFO Incremental complete for VM 103: 1 disks, 28 regions, 3.31 MB in 15.5s
Planned failover (boot replica on DR)
2026-04-24 01:42:51 INFO PVE POST https://127.0.0.1:8006/api2/json/nodes/pve2/qemu/203/status/start
2026-04-24 01:42:51 INFO Failover: started VM 203 on DR site
Bacula Director-driven job — real bconsole output
JobId: 3448
Job: Proxmox-Replicate-VM103-Incremental.2026-04-24_08.16.31_02
Backup Level: Full (upgraded from Incremental)
Client: "proxmoxlab-fd" 15.0.3 x86_64-pc-linux-gnu-bacula,debian,12.0
FileSet: "Proxmox-Replicate-VM103"
Non-fatal FD errors: 0
SD Errors: 0
FD termination status: OK
SD termination status: OK
Termination: Backup OK
.deb turnkey install on Debian 13 PVE 9 DR node
$ apt-get install ./podheitor-proxmox-plugin_1.1.0_amd64.deb
Setting up podheitor-proxmox-plugin (1.0.0-1) ...
$ systemctl enable --now podheitor-receiver@103.service
Created symlink '/etc/systemd/system/multi-user.target.wants/podheitor-receiver@103.service'
→ '/etc/systemd/system/podheitor-receiver@.service'.
$ ss -tlnp | grep 9203
LISTEN 0 128 0.0.0.0:9203 users:(("podheitor-proxm",pid=204793,fd=4))
Dashboard JSON emitter — real output
{
"generated_at": "2026-04-24T08:45:12+00:00",
"source_vms": {
"103": {
"source_vmid": 103, "target_vmid": 203,
"source_host": "proxmoxlab", "target_host": "192.168.15.102",
"seeded": true, "total_cycles": 17,
"rpo_actual_seconds": 132,
"last_cycle": {
"cycle_type": "incremental",
"bytes_sent": 1638400, "regions_sent": 8,
"duration_secs": 29.1, "success": true
}
}
},
"dr_vms": {
"103": {
"source_vmid": 103, "local_vmid": 203,
"provisioned": true,
"disks": [{"device":"scsi0","path":"/dev/pve/vm-203-disk-0",
"size_bytes":107374182400,"seeded":true}],
"restore_point_count": 7
}
}
}
13. TCO and ROI Analysis
13.1 Scenario: 100-VM Proxmox Environment, 3-Year TCO
Baseline assumption: Organization already runs PodHeitor Backup for file/database backup.
Option A: PodHeitor Proxmox Plugin
| Cost Item | Year 1 | Year 2 | Year 3 |
|---|---|---|---|
| Plugin license (per-node, 2 nodes) | Contact | Renewal | Renewal |
| Additional infrastructure | $0 | $0 | $0 |
| Training (Bacula-familiar staff) | Minimal | $0 | $0 |
Option B: Veeam Backup & Replication (Enterprise Plus)
| Cost Item | Notes |
|---|---|
| Per-VM license (100 VMs) | Charged annually, scales with VM count |
| Veeam Proxy server (Windows) | Hardware + OS license required |
| Staff training | New platform, new management console |
| Maintenance and support | Annual contract required |
Option C: Proxmox Backup Server Only
| Cost Item | Notes |
|---|---|
| PBS license | $0 |
| Compliance reporting gap | Risk cost: no unified audit catalog |
| DR capabilities gap | Risk cost: no enterprise DR orchestration |
13.2 ROI Drivers
Backup window reduction: Incremental CBT backups reduce backup data volume by 90-98%, cutting network bandwidth, storage I/O load, and backup window duration.
Restore time reduction: Instant Recovery eliminates the RTO gap. A 4-hour traditional restore becomes a 5-minute NBD-boot operation.
Migration cost elimination: Cross-hypervisor conversion from VMware or Hyper-V eliminates the need for dedicated migration tools, which are licensed separately in competitive products.
Consolidation savings: Eliminating a parallel PBS deployment and using Bacula as the single backup catalog reduces administrative overhead, simplifies compliance reporting, and eliminates duplicated storage allocation.
Break-even estimate: In a typical 50-VM environment migrating from Veeam, the plugin license cost is typically recovered in 3-6 months of saved Veeam renewal fees.
14. Roadmap
Version 1.1.0 — Shipped (GA, 2026-04-24) ✅
| Feature | Status |
|---|---|
| Veeam-style replication (seed + bitmap-push incremental) | ✅ |
| Sampled integrity verification (FNV-1a-64) between source and DR | ✅ |
Mutual-TLS (rustls + PEM certs + WebPkiClientVerifier) |
✅ |
| Standalone DR receiver daemon (systemd template, no bacula-fd on DR) | ✅ |
Multi-VM receiver scaling (one instance per VMID via @.service) |
✅ |
Planned failover (failover-exec) + failback (failback-pre) |
✅ |
Dashboard JSON emitter (--mode=replication-status --vm=*) |
✅ |
.deb + .rpm turnkey packages |
✅ |
Version 1.1.1 — Planned (near-term polish)
| Feature | Description | Priority |
|---|---|---|
mkcerts.sh helper |
One-shot X.509 v3 CA + DR + source cert generator | High |
| Encrypted backup streams | End-to-end AES-256 at the plugin level (backup path) | High |
| Bandwidth throttling | Per-job and per-node caps for the bitmap-push transport | High |
| Enhanced CBT reporting | Per-VM changed-block stats in Bacula catalog | Medium |
| REST API for orchestration | HTTP API for triggering backups without bconsole | Medium |
Version 1.2 — Planned
| Feature | Description | Priority |
|---|---|---|
| Multi-cluster support | Single FileSet targeting multiple PVE clusters | High |
| Proxmox Containers (LXC) | Backup and replication of LXC containers | High |
| S3-compatible direct restore | Restore directly from S3/MinIO without SD routing | Medium |
| Pre/post backup scripts | Per-VM hook scripts executed before and after backup | Medium |
Full-disk integrity verify (mode=verify-full) |
Scheduled whole-disk hash audit | Medium |
Version 2.0 — Future
| Feature | Description | Priority |
|---|---|---|
| Continuous Data Protection (CDP) | Near-real-time replication via QEMU block journal | High |
| Bacularis web integration | Native Bacularis UI panels for plugin status | High |
| Proxmox Cluster HA VMs | HA VMs followed transparently across nodes during backup | Medium |
| Kubernetes PV backup | Protection for PersistentVolumes on Proxmox-hosted Kubernetes | Medium |
| Azure/AWS import | Direct upload of converted VM images to cloud platforms | Low |
15. Conclusion
The PodHeitor Proxmox Backup, Replication and Conversion Plugin for Bacula represents a mature, production-validated solution to a real and pressing enterprise challenge: extending a unified backup strategy to Proxmox VE without adopting additional platforms, incurring disproportionate per-VM licensing costs, or compromising on DR and application consistency capabilities.
With over 1,290 production jobs completed successfully, support for incremental-forever backups via QEMU dirty bitmaps, TLS-secured DR replication with auto VM provisioning, instant recovery via NBD overlay, and validated cross-hypervisor conversion from VMware and Hyper-V — this plugin delivers enterprise-grade data protection at a fraction of the cost of competing solutions.
Organizations already running PodHeitor Backup gain full Proxmox VM protection by deploying two binary files and updating their Director configuration. There are no new servers to provision, no new management consoles to learn, and no per-VM charges to budget for.
Call to Action
Ready to evaluate the PodHeitor Proxmox Plugin in your environment?
Contact Heitor Faria to discuss your specific environment, obtain a proof-of-concept license, or schedule a technical walkthrough:
| Channel | Contact |
|---|---|
| heitor@opentechs.lat | |
| Phone (US) | +1 786 726-1749 |
| WhatsApp (BR) | +55 61 98268-4220 |
Proof-of-concept engagements are available for qualified enterprise opportunities. Reference architecture validation, installation support, and custom feature development can be arranged commercially.
Licensing
PodHeitor Proxmox Backup Plugin is proprietary software distributed by subscription. For commercial terms, technical demo, or a free 30-minute assessment, reach the team via the channels below.
Ready to evaluate?
- 💬 WhatsApp: +1 (786) 726-1749
- ✉️ Email: heitor@opentechs.lat
- 🩺 Free assessment — 30 min with Heitor Faria
16. Disclaimer and Contact
SPECIAL OFFER — BRING YOUR RENEWAL PROPOSAL
Are you currently evaluating or renewing a contract for Bacula Enterprise, Veeam, Commvault, or Netbackup?
Bring your proposal and we guarantee a minimum 50% discount — with significantly more features.
The PodHeitor Proxmox Plugin offers Proxmox-native VM backup, DR replication, instant recovery, and cross-hypervisor migration in a single product, integrated natively with PodHeitor Backup — at a fraction of the cost of legacy enterprise backup vendors.
Contact:
| Author | Heitor Faria |
| Company | PodHeitor / OpenTechs |
| heitor@opentechs.lat | |
| Phone (US) | +1 786 726-1749 |
| WhatsApp (Brazil) | +55 61 98268-4220 |
Legal Notice:
Copyright 2026 Heitor Faria — All Rights Reserved.
This whitepaper and the described product are protected by copyright. Reproduction, redistribution, or disclosure of this document or any portion thereof without written permission from Heitor Faria is prohibited.
The product described herein is licensed commercially. Evaluation, development, and redistribution rights are governed by the applicable commercial license agreement. Unauthorized use, reverse engineering, or redistribution of plugin binaries is prohibited.
All trademarks mentioned in this document (Proxmox, Bacula, VMware, Veeam, Commvault, Veritas, Red Hat, Oracle, Debian, Microsoft Hyper-V) are the property of their respective owners. Their mention does not imply any affiliation or endorsement.
17. Appendix
A. Glossary
| Term | Definition |
|---|---|
| Bacula | Open-source enterprise backup, restore, and verification program consisting of Director, Storage Daemon, File Daemon, and Console components. |
| Bacula Director | Central management component that directs backup and restore operations, maintains the catalog, and runs the scheduler. |
| Bacula File Daemon (FD) | Client-side agent installed on the system being backed up. For Proxmox backups, installed on the PVE hypervisor host. |
| Bacula Storage Daemon (SD) | Component responsible for reading and writing backup data to storage volumes. |
| Bacula plugin API | Bacula’s shared library plugin interface, allowing third-party code to extend FD functionality via dlopen. |
| CBT (Changed Block Tracking) | Mechanism by which QEMU tracks which disk extents have been written since the last backup, enabling incremental-only data transfer. |
| Internal communication channel | Internal Bacula communication protocol used between Director, FD, and SD for job control and data transfer. |
| PVE (Proxmox VE) | Proxmox Virtual Environment — open-source hypervisor platform based on KVM and LXC, with integrated management API. |
| QEMU | Open-source machine emulator and virtualizer. Proxmox VE uses QEMU/KVM for VM execution. |
| QMP (QEMU Monitor Protocol) | JSON-based protocol over a Unix domain socket for controlling and querying a running QEMU instance. |
| NBD (Network Block Device) | Protocol for exporting block devices over TCP, used by the plugin to read VM disk data from QEMU snapshots. |
| CBT Dirty Bitmap | QEMU’s per-disk data structure recording which 64KB-aligned extents have been modified since the last backup checkpoint. |
| Quiesce / Freeze | The process of pausing filesystem writes in a VM before snapshot creation to ensure data consistency. |
| QEMU Guest Agent | A daemon installed inside the VM that responds to QMP commands from the hypervisor, enabling fsfreeze/thaw for application-consistent backups. |
| Fingerprint Pinning | TLS security technique where the expected SHA-256 hash of a server’s certificate is hardcoded, preventing MITM even with self-signed certificates. |
| PSK (Pre-Shared Key) | Authentication method where a shared secret is configured on both communicating parties, used for DR transport authentication. |
| Instant Recovery (IR) | Technique for booting a VM directly from its backup volume via NBD overlay, achieving near-zero RTO before full migration to local storage. |
| RPO (Recovery Point Objective) | Maximum acceptable data loss measured in time. Shorter RPO requires more frequent backups. |
| RTO (Recovery Time Objective) | Maximum acceptable time to restore service after a failure. Instant Recovery dramatically reduces RTO. |
| TCO (Total Cost of Ownership) | Full cost of a solution over its lifetime, including licensing, infrastructure, training, and operational overhead. |
| DR (Disaster Recovery) | Policies and procedures for recovering IT infrastructure after a major failure or disaster. |
| VMDK | VMware Virtual Machine Disk format. Used by vSphere and Workstation as the native VM disk format. |
| VHDX | Virtual Hard Disk Extended format used by Microsoft Hyper-V. |
| qcow2 | QEMU Copy-On-Write version 2 — native Proxmox VE disk format with support for snapshots, encryption, and compression. |
| LVM-thin | Logical Volume Manager thin provisioning — used by Proxmox’s local-lvm storage for space-efficient VM disk allocation. |
| Bacularis | Web-based management interface for Bacula, providing a GUI for job management, catalog browsing, and reporting. |
| PBS (Proxmox Backup Server) | Proxmox’s dedicated backup server product, optimized for PVE but without integration into external backup frameworks. |
B. Reference Architecture Diagram (Production Environment)
Production Environment (Validated April 2026)
Network: 192.168.15.0/24
+--------------------------------------------------------------+
| Bacula Director + Storage Daemon |
| Oracle Linux 9.6 / RHEL 9.6 |
| PostgreSQL 14+ (Catalog) |
| PodHeitor Backup |
+------------------------+-------------------------------------+
| TCP:9102 / TCP:9103
+-------------+-------------+
v v
+----------------------+ +----------------------+
| proxmoxlab | | pve2 |
| Proxmox VE 8.4.18 | | Proxmox VE 8.4.18 |
| Debian 12 (amd64) | | Debian 12 (amd64) |
| IP: 192.168.15.129 | | IP: 192.168.15.102 |
| Bacula FD | | Bacula FD |
| podheitor plugin | | podheitor plugin |
| (mode=seed) | | (mode=receiver) |
+----------------------+ +----------------------+
| TCP:9190 (PSK/TLS) ^
+-----------------------------------+
Jobs executed: 1290+ (all T = Terminated OK)
Schedule tested: 5-minute interval
DR replication: validated with TLS fingerprint pinning
C. Frequently Asked Questions
Q: Can the plugin back up VMs that are powered off? A: Yes. Powered-off VMs are backed up from their disk images directly without requiring snapshot creation. Quiesce is automatically skipped for powered-off VMs.
Q: What happens if the QEMU guest agent is not installed in the VM? A: The plugin falls back to crash-consistent backup (snapshot without freeze). A warning is logged. The backup completes successfully; application consistency is not guaranteed but crash consistency is maintained.
Q: Can I use this plugin with Bacula Enterprise? A: The plugin implements the standard Bacula plugin API and is compatible with both PodHeitor Backup and Bacula Enterprise FD versions 15.0.0 and later.
Q: How many VMs can be backed up concurrently? A: Concurrency is limited by Maximum Concurrent Jobs on the File Daemon and available system resources on the PVE node. Tested up to 10 concurrent VM backups on a 32-core PVE node without performance degradation.
Q: Is the backup data encrypted at rest? A: Encryption at rest is handled by the Bacula Storage Daemon volume encryption configuration, which is independent of this plugin. The plugin integrates transparently with whatever SD encryption is configured.
Q: Can I restore to a different PVE node than the backup source? A: Yes. Use target_storage and new_vm_name parameters to restore to any PVE node where the plugin’s FD is installed.
Q: Does this plugin support Proxmox cluster operations (live migration during backup)? A: Currently, the plugin targets a specific node. Full cluster-aware backup following VMs across nodes is on the Version 2.0 roadmap.
D. References
- Proxmox VE REST API Documentation: https://pve.proxmox.com/pve-docs/api-viewer/
- QEMU Monitor Protocol (QMP) Reference: https://qemu-project.gitlab.io/qemu/interop/qemu-qmp-ref.html
- NBD Protocol Specification: https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md
- Bacula Plugin API Reference: https://www.bacula.org/bacula-web/developers-guide/plugin-api
- PodHeitor Backup Documentation: https://www.bacula.org/documentation/
- QEMU Changed Block Tracking (CBT): https://qemu-project.gitlab.io/qemu/interop/bitmaps.html
- Proxmox VE 8.4 Release Notes: https://pve.proxmox.com/wiki/Roadmap
End of Whitepaper
Copyright 2026 Heitor Faria — All Rights Reserved heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp)
Disponível em:
Português (Portuguese (Brazil))
English
Español (Spanish)