Technical whitepaper — PodHeitor Hyper-V for Bacula

Direct VHDX access without Export-VM, change tracking via RCT (Resilient Change Tracking), near-CDP RCT-Push replication, cross-hypervisor conversion (vSphere/Proxmox → Hyper-V), and multi-adapter architecture.

Technical companion to the PodHeitor Hyper-V plugin page.

1. The problem: Hyper-V backup without a plugin is expensive or fragile

Production Hyper-V VMs present three fundamental problems to stock Bacula:

  • VHDX is locked while the VM is running — direct file reading is impossible without a production checkpoint. Stock Bacula doesn’t know about this.
  • Export-VM doubles storage — requiring an Export-VM before backup doubles the fleet on disk and doesn’t scale.
  • No native change tracking in Bacula — every “incremental” degrades to re-reading the entire VHDX. 2 GB modified within 100 GB becomes 100 GB transferred.

The PodHeitor Hyper-V Plugin tackles all three with in-place VHDX reading (zero extra staging), block-level RCT via WMI, and near-CDP delta replication to secondary sites.

2. Architectural model

The plugin uses the PodHeitor pattern of cdylib + standalone backend, with PTCOMM on stdin/stdout. On Windows the cdylib is a DLL (podheitor-hyperv-fd.dll) loaded by bacula-fd, and the backend is podheitor-hyperv-backend.exe.

Bacula FD (Windows)
  └─ podheitor-hyperv-fd.dll  (metaplugin adapter)
       │  PTCOMM (stdin/stdout)
       ▼
     podheitor-hyperv-backend.exe (Rust)
       ├─ Get-VM / Checkpoint-VM (PowerShell + WMI)
       ├─ Msvm_VirtualSystemReferencePointService (RCT API)
       ├─ Direct VHDX reader (no Export-VM)
       ├─ CBT delta encoder (proprietary binary format)
       ├─ RCT-Push replication driver
       └─ Cross-hypervisor convert (qemu-img.exe wrapper)

2.1 Multi-adapter design

A single backend engine serves multiple cdylib DLLs, each with a distinct Bacula namespace:

cdylib DLL Bacula namespace Function
podheitor-hyperv-fd.dll @hyperv/ Native Hyper-V backup/restore
podheitor-vsphere-fd.dll @vsphere/ Restore VMware backups → Hyper-V
podheitor-proxmox-fd.dll @proxmox_/ Restore Proxmox/KVM backups → Hyper-V

Operationally: one Bacula FD host can be the destination for migration from any hypervisor — no re-provisioning, no installing three different products.

3. Direct VHDX + RCT — why it matters

Problem PodHeitor approach
VHDX locked at runtime Production checkpoint freezes the parent VHDX — consistent reads
Inconsistent app state VSS quiesce via Hyper-V Integration Services — application-consistent
Export-VM doubles disk Plugin reads VHDX in-place, zero extra space
Whole VHDX re-sent RCT (Resilient Change Tracking) flags dirty regions; only those go
Slow incremental on big disks 100 GB with 2 GB modified → 2 GB transferred
Manual snapshot management Plugin creates and removes checkpoint automatically, even on failure
No file catalog Bacula catalog tracks every file — granular restore possible

4. RCT — Resilient Change Tracking

RCT is the native Microsoft API (Windows Server 2016+) for virtual disk change tracking. The plugin consumes it via WMI:

  • Reference points are persistent markers (survive Hyper-V host reboot) registered with Msvm_VirtualSystemReferencePointService.
  • On every incremental/differential, the plugin asks Hyper-V for the diff between two reference points and gets a list of {offset, length} extents that changed.
  • The plugin reads only those extents from the VHDX and wraps them in the proprietary CBT delta format (binary stream with offset header).
  • On restore, the cdylib applies the deltas in chronological order over the full base.

When RCT isn’t available (legacy generation 1, old host), the plugin automatically falls back to full VHDX streaming rather than failing — documented behavior as Gen1 fallback.

5. RCT-Push replication (near-CDP)

With mode=rct-push, the plugin runs continuous replication cycles directly to a secondary Hyper-V host, bypassing the Bacula SD per cycle.

Parameter Default Function
push_interval 300 Cycle interval (seconds)
push_cycles 1 Number of cycles (0 = infinite)
rpo_seconds 900 Target Recovery Point Objective
dr_host Destination Hyper-V host
dr_port 9847 Receiver TCP port
dr_psk Pre-shared key (HMAC) for the channel
bandwidth 0 Throttle in bytes/s (0 = unlimited)
max_restore_points 5 Restore points retained on DR
push_apply_remote no Apply deltas directly on DR (bypass Bacula SD)
network_map Network mapping for failover (src=dst,...)
reip_rules Re-IP at failover (vm:ip/mask/gw,...)

With push_apply_remote=yes, the channel goes directly from source FD to DR, no trip through Bacula SD — useful when goal is purely DR and not centralized retention. With =no, deltas go through the SD (cataloged) and are reapplied on DR in the next cycle.

6. Cross-hypervisor conversion (vSphere / Proxmox → Hyper-V)

Restore VMs backed up by sister PodHeitor plugins directly into Hyper-V — no manual disk reconversion.

Source Adapter DLL Conversion
VMware vSphere podheitor-vsphere-fd.dll VMDK / raw → VHDX (via qemu-img.exe)
Proxmox / KVM podheitor-proxmox-fd.dll raw / qcow2 → VHDX (via qemu-img.exe)

VM configuration translation (network adapters, boot order, Gen1/Gen2 detection) is automatic. Prerequisite: qemu-img.exe in %BACULA_DIR%tools or in %PATH%; temporary disk space ~1.5× the compressed VM size.

7. Granular restore (file-level)

Compatible with PodHeitor Granular Restore:

  1. Browse the Bacula catalog (BVFS) to locate VM VHDX files.
  2. Restore only the base VHDX + relevant CBT deltas to the Storage Daemon.
  3. Reconstruct the full disk state by applying CBT deltas onto the base VHDX.
  4. Mount the guest filesystem (NTFS, ext4, XFS, etc.) via libguestfs or qemu-nbd.
  5. Browse and extract individual files.

8. Validated platforms

OS Plugin version Tested scenarios
Windows Server 2016 Datacenter 1.2.0 Full, Incremental, Restore, RCT-Push, Cross-Hypervisor
Windows Server 2025 Standard 1.2.0 Full, Incremental, Restore, RCT-Push
Bacula FD 15.0.3 All scenarios above

9. Documented anti-patterns

  • Do not disable quiesce on stateful-app VMs. Without VSS quiesce the snapshot is crash-consistent — restore may boot, but DBs may need recovery.
  • Do not run two concurrent plugin jobs against the same VM. RCT reference points are per-VM globals; concurrency creates reference-point churn.
  • Don’t trust RCT on Gen1 VMs or hosts < Windows Server 2016. The plugin transparently falls back to full VHDX streaming, but the operator must know to size bandwidth/storage.

10. License posture

Plugin under LicenseRef-PodHeitor-Proprietary. No Bacula AGPLv3 source is statically linked into the cdylib DLL. Binding is via the bacula-fd-abi crate (pure PodHeitor) with independent extern "C" declarations.

Ready to evaluate?

30-day free trial for production Hyper-V fleets. Guaranteed at minimum 50% discount vs Bacula Enterprise, Veeam or Commvault, with more capabilities included.

Heitor Faria — Founder, PodHeitor International
[email protected]
☎ +1 (789) 726-1749 · +55 (61) 98268-4220 (WhatsApp)
🔗 PodHeitor Hyper-V plugin page

Disponível em: pt-brPortuguês (Portuguese (Brazil))enEnglishesEspañol (Spanish)

Leave a Reply