Technical Whitepaper — Version 1.2.0
Author: Heitor Faria Organization: OpenTechs Contact: heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp) Copyright: © 2026 Heitor Faria — All Rights Reserved
💼 Commercial Opportunity
Bring your renewal proposal for any commercial enterprise backup platform — Veeam, Commvault, NetBackup, or others. We offer at least 50% discount with far more features.
Contact: heitor@opentechs.lat | +1 786 726-1749 | +55 61 98268-4220 (WhatsApp)
Table of Contents
- Executive Summary
- Business Problem & Use Cases
- Solution Architecture
- Technical Deep Dive
- Backup & Restore Features
- Replication Features
- Cross-Hypervisor Conversion
- Installation & Deployment
- Sizing & Capacity Planning
- Platform Compatibility
- Configuration Reference
- FileSet & Job Examples
- Security Considerations
- Performance Benchmarks
- Competitive Comparison
- Development Roadmap
1. Executive Summary
PodHeitor Hyper-V Plugin is a production-grade, open-architecture solution that extends Bacula Community Edition with enterprise-class VM protection for Microsoft Hyper-V environments. Built entirely in Rust for memory safety and native performance, it delivers three critical capabilities in a single, integrated package:
- Backup & Restore — Application-consistent, block-level VM backup using Resilient Change Tracking (RCT). No VM downtime. No extra disk space. True incremental/differential with CBT delta technology.
- Replication — Near-continuous data protection via RCT-Push replication to secondary sites. Configurable RPO from minutes to hours. Encrypted delta transport. Persistent reference points for efficient incremental cycles.
- Conversion — Cross-hypervisor migration support. Restore VMs backed up from VMware vSphere or Proxmox/KVM directly into Hyper-V with automatic disk format conversion and VM configuration translation.
Version 1.2.0 represents a fully validated, production-ready release with confirmed functionality across Windows Server 2016 and 2025 with Bacula FD 15.0.3.
Key Business Benefits
| Benefit | Detail |
|---|---|
| Zero additional licensing costs | Works with Bacula Community Edition (free, open source) |
| 50%+ cost reduction vs. competitors | Compared to commercial enterprise backup platforms |
| No agent on guest VMs | Backup runs entirely on the Hyper-V host |
| No extra disk space | Direct VHDX reading — no export, no staging area |
| Near-CDP replication | RCT-Push cycles as frequent as every 5 minutes |
| Cross-platform migration | VMware/Proxmox VMs → Hyper-V with one command |
| Rust-powered performance | Memory-safe, zero-overhead abstractions, native speed |
2. Business Problem & Use Cases
2.1 The Challenge: VM Protection at Scale
Modern IT environments rely on virtual machines for everything from domain controllers to database servers. Protecting these VMs requires:
- Consistency — Backups must capture a consistent VM state, not a mix of disk states from different points in time.
- Efficiency — Full VM re-copies on every backup are impractical for large disks. Incremental must be truly block-level.
- Speed — Backup windows are shrinking. RTO requirements demand fast, reliable restore.
- Flexibility — DR scenarios require VM replication and the ability to migrate workloads between hypervisors.
2.2 Use Cases
Use Case 1: Daily VM Backup with RCT Incrementals
An SMB runs 20 VMs on a Windows Server 2022 Hyper-V cluster. Their IT team needs:
- Nightly full backup, hourly incrementals
- Application-consistent backup for SQL Server and Exchange VMs
- Quick restore of individual VMs without restoring the entire environment
PodHeitor solution: vm=* in FileSet with quiesce=yes. Full on Sunday, Incremental hourly. RCT tracks changed blocks — only 2–5% of disk data transferred on each incremental.
Use Case 2: Near-CDP Replication to DR Site
A financial institution requires RPO < 15 minutes for critical database VMs. Their primary site runs Hyper-V; their DR site is a secondary Hyper-V cluster over a WAN link.
PodHeitor solution: mode=rct-push rpo_seconds=600 push_apply_remote=no. RCT-Push job runs every 10 minutes, transferring only changed blocks (4–20 MB per cycle for active database VMs). Bacula SD at the DR site stores all restore points.
Use Case 3: Cloud/Hypervisor Migration
A company is migrating from VMware vSphere to Hyper-V. They have 50 VMs backed up by PodHeitor vSphere plugin and need to bring them into Hyper-V.
PodHeitor solution: Install podheitor-vsphere-fd.dll alongside the Hyper-V plugin. Create Restore Jobs with FileSet pointing to @vsphere/ namespace. Backend automatically converts VMDK → VHDX and registers new VMs in Hyper-V.
Use Case 4: Ransomware Recovery
A manufacturing company is hit by ransomware on a Monday morning. Their production VM (ERP system) is encrypted. They need to restore to Saturday’s backup in under 30 minutes.
PodHeitor solution: restore client=hyperv-fd restorejob=HyperV-Restore jobid=<last_full_id> all done yes. The plugin streams VHDX and CBT deltas from the Bacula SD, applies deltas during restore, and registers the VM in Hyper-V automatically. VM is booted and operational within minutes.
Use Case 5: Cost Reduction — Migrating away from premium commercial backup
A 500-user company pays USD 80,000/year for Veeam Enterprise Plus. Their IT director wants to reduce costs while maintaining SLAs.
PodHeitor solution: Migrate to Bacula Community + PodHeitor plugin. Comparable features (block-level backup, replication, cross-hypervisor), fraction of the cost.
3. Solution Architecture
3.1 Component Overview
┌─────────────────────────────────────────────────────────────────────┐
│ Bacula Director │
│ (Linux — schedules jobs, manages catalog, orchestrates all tasks) │
└───────────────────────┬─────────────────────────────────────────────┘
│
Job schedule + control
│
┌──────────────▼──────────────────────┐
│ Bacula File Daemon (FD) │
│ (Windows Server — Hyper-V) │
│ │
│ ┌─────────────────────────────────┐ │
│ │ podheitor-hyperv-fd.dll │ │
│ │ (Metaplugin C adapter) │ │
│ │ │ │
│ │ Delegates ALL logic via PTCOMM │ │
│ │ (stdin/stdout subprocess) │ │
│ └──────────────┬──────────────────┘ │
│ │ PTCOMM protocol │
│ ┌──────────────▼──────────────────┐ │
│ │ podheitor-hyperv-backend.exe │ │
│ │ (Rust — core engine) │ │
│ │ │ │
│ │ • Hyper-V WMI/PS integration │ │
│ │ • Direct VHDX I/O │ │
│ │ • RCT change tracking │ │
│ │ • CBT delta engine │ │
│ │ • RCT-Push replication │ │
│ │ • Cross-hypervisor conversion │ │
│ │ • VHDX integrity verification │ │
│ └──────────────┬──────────────────┘ │
└─────────────────┼───────────────────┘
│ WMI / Direct file I/O
┌────────────▼──────────────────────────┐
│ Hyper-V Host │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ VM-1 │ │ VM-2 │ │ VM-N │ │
│ │ (VHDX) │ │ (VHDX) │ │ (VHDX) │ │
│ └────────┘ └────────┘ └────────┘ │
│ │
│ RCT: Msvm_VirtualSystem │
│ ReferencePointService │
└───────────────────────────────────────┘
│ network (SD port 9103)
┌────────────▼──────────────────────────┐
│ Bacula Storage Daemon │
│ (Linux — stores backup data on disk) │
└───────────────────────────────────────┘
3.2 PTCOMM Protocol
The plugin uses Bacula’s PTCOMM (Plugin Transport Communication) protocol — a standard stdin/stdout IPC mechanism used by all Bacula Metaplugins.
The C DLL (podheitor-hyperv-fd.dll) is a thin adapter that:
- Receives Bacula FD events (backup start, get file info, read file data, etc.)
- Translates them into PTCOMM commands sent to the Rust backend
- Forwards backend responses back to Bacula FD
This architecture means:
- The C DLL is ~400 KB with minimal logic
- All intelligence lives in the Rust binary
- The Rust binary can be updated independently of the DLL
- The backend can be tested standalone without Bacula
3.3 Multi-Adapter Design
A single backend binary handles three distinct plugin namespaces:
podheitor-hyperv-fd.dll → @hyperv/ (native Hyper-V)
podheitor-vsphere-fd.dll → @vsphere/ (VMware → Hyper-V)
podheitor-proxmox-fd.dll → @proxmox_/ (Proxmox → Hyper-V)
The backend detects the active namespace from the FileSet’s Plugin directive prefix and routes to the appropriate handler (backup.rs, restore.rs, convert.rs, replication.rs).
4. Technical Deep Dive
4.1 Direct VHDX Access
Windows locks VHDX files while VMs are running — a naïve CopyFile() fails. PodHeitor’s approach:
- Production checkpoint (
Checkpoint-VM -SnapshotType Production) triggers VSS quiesce inside the guest VM, ensuring application consistency (flushing SQL Server transaction logs, Exchange circular logging, etc.) - The checkpoint forks the VHDX — the running VM writes to a new AVHDX differencing disk while the parent VHDX is frozen
- PodHeitor opens the frozen parent VHDX with
FileShare.ReadWrite— now readable without locking the running VM - Data is streamed via PTCOMM to Bacula FD → SD → disk
- The production checkpoint is removed after the backup — guest VM writes are merged back
This approach:
- Requires zero extra disk space (no Export-VM staging copy)
- Causes no VM downtime (VM continues running on the differencing disk)
- Ensures application consistency via VSS
4.2 RCT (Resilient Change Tracking)
RCT is a Windows Server 2016+ feature that tracks block-level changes to VHDX disks using reference points — immutable snapshots of change tracking state stored in the VHDX metadata.
PodHeitor’s RCT flow:
Full backup:
- Create production checkpoint
- Create RCT reference point (
Msvm_VirtualSystemReferencePointService.CreateReferencePoint) - Stream full VHDX content
- Save reference point ID to
%ProgramData%PodHeitorrct<VM-GUID>.json
Incremental backup:
- Create production checkpoint
- Create new RCT reference point
- Call
GetVirtualDiskChanges(previousRef, newRef)— returns list of changed block ranges - Read only changed blocks from VHDX
- Stream as CBT delta (custom binary format)
- Update saved reference point state
The RCT state is also streamed as @hyperv/VMName/.meta/rct-state.json in each backup for disaster recovery of the state itself.
4.3 CBT Delta Format
PodHeitor uses a custom binary format for changed block data:
Header (16 bytes):
magic: [u8; 4] = b"PCBT"
version: u32 = 1
block_count: u32 = number of changed blocks
reserved: u32 = 0
Per-block entry:
offset: u64 = byte offset in original VHDX
length: u64 = byte count of this block
data: [u8; length] = raw block data
During restore, the plugin:
- Restores the base VHDX from the full backup
- For each incremental: opens the VHDX, applies each CBT block at its correct offset
- After applying all deltas, the VHDX is identical to the state at backup time
This is analogous to how VMDK redo logs or QCOW2 snapshots work, but implemented at the Bacula plugin layer.
4.4 RCT-Push Replication
For near-CDP scenarios, PodHeitor implements RCT-Push — a replication mode that:
- Runs as a Bacula Backup job (JobType=B) with
mode=rct-push - On each cycle:
- Creates a new RCT reference point on the source VM
- Calls
GetVirtualDiskChangesbetween the previous and new reference point - Streams only changed blocks (typically 4–50 MB per cycle for active VMs)
- Stores the delta in the Bacula SD as a standard backup job
- Saves the reference point state for the next cycle
Because each cycle is a standard Bacula backup job, all restore points are cataloged and browsable. Recovery from any point-in-time is supported.
4.5 Integrity Verification
Version 1.2.0 adds cryptographic integrity verification:
- During backup: SHA-256 hashes computed for each VHDX block and stored in the backup metadata
- During restore: hashes recomputed and compared — any corruption detected and reported
- Supports
VerifyReq/VerifyRespPTCOMM protocol messages for cross-side verification
5. Backup & Restore Features
5.1 Backup Levels
| Level | Description | RCT Required |
|---|---|---|
| Full | Complete VHDX + configuration files | No (creates baseline RCT reference point) |
| Incremental | Changed blocks since last backup (any level) | Yes |
| Differential | Changed blocks since last Full | Yes |
5.2 VM Selection
vm=* # All VMs
vm=SQL* # Wildcard — SQL Server VMs
vm=DC01 # Specific VM by name
vm=* exclude=Test*,Dev* # All VMs except test/dev
5.3 Restore Behavior
- Files restored to
Wheredirectory under@hyperv/VMName/...namespace - CBT delta files (
.cbt) automatically applied during restore - After restore completes: VM registered in Hyper-V via
Import-VM(ifnew_vm_nameis set, VM is registered with a new name and new GUID) - Restore to existing VM path: replaces disk files and re-registers
- Restore to new VM: creates new VM with unique GUID and name
5.4 Catalog Integration
All backed-up files appear in the Bacula catalog under @hyperv/:
@hyperv/VM-Name/disks/VM-Name_<UUID>.vhdx # VHDX disk
@hyperv/VM-Name/disks/VM-Name_<UUID>.vhdx.cbt # CBT delta (incremental)
@hyperv/VM-Name/config/ # VM configuration files
@hyperv/VM-Name/.meta/rct-state.json # RCT tracking state
This enables granular file selection in bconsole restore — restore only the VHDX without configuration, or vice versa.
6. Replication Features
6.1 RCT-Push Mode
Configured with mode=rct-push in the FileSet Plugin directive:
Plugin = "podheitor-hyperv: vm=ProductionDB mode=rct-push push_cycles=1 rpo_seconds=600"
Each Bacula job invocation performs one replication cycle:
- Query changed blocks since last reference point
- Stream deltas to Bacula SD
- Update reference point state
For near-continuous replication, schedule the job with short intervals (e.g., every 10 minutes).
6.2 Reference Point Management
Reference points are maintained on the Hyper-V host:
- Location:
%ProgramData%PodHeitorrct<VM-GUID>.json - Content: full backup reference ID, last backup reference ID, timestamps
- Also backed up to Bacula as
@hyperv/VM-Name/.meta/rct-state.json
If the reference point state is lost (e.g., after a DR failover), the next job automatically falls back to a full replication cycle.
6.3 Replication Parameters
| Parameter | Default | Description |
|---|---|---|
mode |
backup |
rct-push for replication mode |
push_cycles |
1 |
Cycles per job invocation (1 = one cycle, 0 = infinite loop) |
rpo_seconds |
900 |
Target RPO — warning logged if exceeded |
push_interval |
300 |
Sleep between cycles (if push_cycles > 1) |
push_apply_remote |
no |
Push deltas directly to DR host bypassing Bacula SD |
dr_host |
— | DR site hostname/IP for direct push |
dr_port |
9847 |
DR site receiver port |
dr_psk |
— | Pre-shared key for DR transport encryption |
bandwidth |
0 |
Bandwidth cap in bytes/sec |
max_restore_points |
5 |
Max restore points retained on DR site |
7. Cross-Hypervisor Conversion
7.1 Supported Conversions
| Source | Target | Adapter DLL | Source Format | Output Format |
|---|---|---|---|---|
| VMware vSphere (via PodHeitor vSphere plugin) | Hyper-V | podheitor-vsphere-fd.dll |
VMDK / raw CBT | VHDX |
| Proxmox / KVM (via PodHeitor Proxmox plugin) | Hyper-V | podheitor-proxmox-fd.dll |
raw / qcow2 CBT | VHDX |
7.2 Conversion Flow
- Bacula FD loads
podheitor-vsphere-fd.dll(or proxmox) - Plugin command uses prefix matching the source namespace (e.g.,
@vsphere/) - Restore job sends files from Bacula SD to FD
- Backend detects source namespace, routes to
convert.rs - Raw/VMDK disk data is written to temp file
qemu-img.exe convert -f raw -O vhdx input.raw output.vhdxcalled- VHDX registered as new Hyper-V VM via PowerShell
- Temp files cleaned up
7.3 Requirements for Conversion
qemu-img.exeinstalled (included in optional Conversion Tools section of NSIS installer)- Temporary disk space: ~1.5× the uncompressed VM disk size
- Sufficient Hyper-V disk quota for the new VHDX
8. Installation & Deployment
8.1 Prerequisites
| Component | Requirement |
|---|---|
| Hyper-V Host OS | Windows Server 2016, 2019, 2022, or 2025 |
| Hyper-V Role | Enabled (built-in) |
| Bacula FD | v15.0.x (installed and configured) |
| Administrator access | Required for installer and FD service restart |
| Network port | TCP 9102 (Bacula FD) open to Director |
8.2 NSIS Installer
The installer (PodHeitor-HyperV-Plugin-1.2.0-x64.exe) is built with NSIS and provides:
Required components (always installed):
podheitor-hyperv-backend.exe→%PROGRAMFILES%Baculapodheitor-hyperv-fd.dll→%PROGRAMFILES%Baculapluginshyperv-fileset.conf.example→%PROGRAMFILES%BaculaREADME.md,INSTALLATION_MANUAL.md,LICENSE.txt
Optional component — Conversion Tools (SEC_CONV):
podheitor-vsphere-fd.dll→%PROGRAMFILES%Baculapluginspodheitor-proxmox-fd.dll→%PROGRAMFILES%Baculapluginsqemu-img.exe→%PROGRAMFILES%Baculatools(if provided)
Optional component — Documentation:
WHITEPAPER.md,REPLICATION_PLAN.md
8.3 Silent Install
.PodHeitor-HyperV-Plugin-1.2.0-x64.exe /S
With custom install directory:
.PodHeitor-HyperV-Plugin-1.2.0-x64.exe /S /D=D:Baculaplugins
8.4 Post-Install Validation
# In bconsole on the Bacula Director:
status client=hyperv-host-fd
# Expected output should include:
# Plugin: podheitor-hyperv(1.2.0)
8.5 Rollback
# Stop FD
Stop-Service bacula-fd
# Restore previous DLL from backup
Copy-Item "C:Backuppodheitor-hyperv-fd.dll.bak" `
"$env:PROGRAMFILESBaculapluginspodheitor-hyperv-fd.dll" -Force
# Start FD
Start-Service bacula-fd
9. Sizing & Capacity Planning
9.1 Hyper-V Host — Minimum Recommended
| Workload | CPU | RAM | Storage (temp) | Network |
|---|---|---|---|---|
| Backup only (≤10 VMs) | 4 cores | 4 GB | None required | 1 Gbps |
| Backup only (≤50 VMs) | 8 cores | 8 GB | None required | 10 Gbps |
| Backup + Replication | 8 cores | 8 GB | None required | 10 Gbps |
| Conversion (import) | 8 cores | 8 GB | 2× largest VM size | 10 Gbps |
9.2 Bacula Storage Daemon
| Workload | Storage Estimate |
|---|---|
| Full backup, 100 GB VM | ~30–60 GB (compressed, typical Linux/Windows system disk) |
| Incremental, active VM | ~2–10 GB/day (typical daily change rate) |
| Replication cycles (daily) | ~5–30 GB/day (changes only via RCT) |
| Retention 30 days, 10 VMs avg 100 GB | ~2–5 TB |
9.3 Network Bandwidth
| Scenario | Typical Transfer |
|---|---|
| Full backup, 100 GB VM | 30–60 GB over backup window |
| Hourly incremental, active VM | 2–5 GB/hour (post-first-full) |
| RCT-Push cycle, 10-min interval | 4–50 MB/cycle (depending on VM activity) |
9.4 Bacula Director
No additional requirements. The Director only stores job metadata (catalog entries). Plugin operation is entirely on the FD/SD side.
10. Platform Compatibility
10.1 Validated Configurations
| Hyper-V Host OS | Hyper-V Version | Bacula FD | Plugin | Status |
|---|---|---|---|---|
| Windows Server 2016 Datacenter Eval | 10.0.14393 | 15.0.3 | 1.2.0 | ✅ Fully validated |
| Windows Server 2025 Standard | 10.0.26100 | 15.0.3 | 1.2.0 | ✅ Fully validated |
10.2 Expected Compatibility
| Hyper-V Host OS | Status | Notes |
|---|---|---|
| Windows Server 2019 | ✅ Expected | RCT available since 2016 |
| Windows Server 2022 | ✅ Expected | Full RCT support |
| Windows 10/11 Pro (client Hyper-V) | ⚠️ Untested | RCT may behave differently |
| Azure Stack HCI | ⚠️ Untested | Should work; SCVMM integration not tested |
10.3 Guest VM Compatibility
| Guest OS | quiesce=yes | quiesce=no | Notes |
|---|---|---|---|
| Windows Server (any) | ✅ | ✅ | VSS in guest via Integration Services |
| Windows 10/11 | ✅ | ✅ | VSS supported |
| Ubuntu/Debian Linux | ⚠️ | ✅ | VSS via linux-guest-agent; quiesce=no recommended |
| RHEL/CentOS Linux | ⚠️ | ✅ | Same as Ubuntu |
| FreeBSD | ❌ | ✅ | No VSS support; quiesce=no required |
| Other Linux | ❌ | ✅ | quiesce=no required |
10.4 Bacula Compatibility
| Component | Version | Status |
|---|---|---|
| Bacula FD | 15.0.x | ✅ Tested |
| Bacula Director | 15.0.x | ✅ Tested |
| Bacula SD | 15.0.x | ✅ Tested |
| Bacula FD | 14.x | ⚠️ Expected (metaplugin API stable) |
| Bacularis (web UI) | Any | ✅ All jobs manageable via Bacularis |
11. Configuration Reference
11.1 Complete Parameter Reference — Backup
| Parameter | Type | Default | Description |
|---|---|---|---|
vm |
string | * |
VM name or wildcard. * = all VMs. Multiple patterns not supported (use multiple Plugin= lines). |
exclude |
string | — | Comma-separated patterns to exclude. E.g., Test*,Dev*,Staging*. |
quiesce |
bool | yes |
Create VSS application-consistent checkpoint before reading VHDX. Set no for Linux VMs without integration services. |
online |
bool | yes |
Allow backup of running VMs via production checkpoint. Set no to skip running VMs. |
timeout |
int | 3600 |
Maximum seconds to wait for any operation (checkpoint creation, VHDX streaming). |
new_vm_name |
string | — | When restoring, register VM with this name instead of original name. |
restore_path |
string | — | Override the default restore directory. Default: Where from the Restore job. |
abort_on_error |
bool | no |
Abort entire job if any VM fails. Default: continue to next VM. |
config_file |
string | — | Path to a config file. Parameters in Plugin= directive override config file values. |
11.2 Complete Parameter Reference — Replication
| Parameter | Type | Default | Description |
|---|---|---|---|
mode |
enum | backup |
Operation mode. Values: backup, rct-push, seed, async-hvr, receiver, replication-status, daemon, failback, reprotect, failover-planned, failover-unplanned, failover-test, failover-undo, failover-permanent. |
push_interval |
int | 300 |
Seconds between replication cycles (when push_cycles > 1). |
push_cycles |
int | 1 |
Number of replication cycles per job. 0 = run indefinitely (daemon mode). |
rpo_seconds |
int | 900 |
Target RPO. Warning logged if replication cycle exceeds this. |
dr_host |
string | — | DR site hostname/IP for direct-push mode (push_apply_remote=yes). |
dr_port |
int | 9847 |
DR site receiver port. |
dr_psk |
string | — | Pre-shared key for DR transport encryption. |
bandwidth |
int | 0 |
Bandwidth cap in bytes/second. 0 = unlimited. |
max_restore_points |
int | 5 |
Maximum restore points retained at DR site. Older points pruned automatically. |
push_apply_remote |
bool | no |
When yes, deltas are applied directly on the DR host (bypassing Bacula SD as intermediary). |
network_map |
string | — | Network adapter mapping for failover scenarios. Format: src_switch=dst_switch,.... |
reip_rules |
string | — | Re-IP rules for failover. Format: vm:new_ip/mask/gw,.... |
12. FileSet & Job Examples
12.1 Backup — All VMs, Daily Full + Hourly Incremental
# FileSet
FileSet {
Name = "HyperV-AllVMs"
Include {
Options {
Signature = SHA256
Compression = LZ4
}
Plugin = "podheitor-hyperv: vm=*"
}
}
# Schedules
Schedule {
Name = "DailyFull"
Run = Full sun at 01:00
Run = Incremental mon-sat at 01:00
Run = Incremental mon-sat at 07:00
Run = Incremental mon-sat at 13:00
Run = Incremental mon-sat at 19:00
}
# Job
Job {
Name = "HyperV-Backup-AllVMs"
Type = Backup
Client = hyperv-host-fd
FileSet = "HyperV-AllVMs"
Schedule = "DailyFull"
Storage = File1
Pool = Default
Priority = 10
Messages = Standard
Write Bootstrap = /opt/bacula/working/%c.bsr
}
12.2 Backup — Grouped by Criticality
FileSet {
Name = "HyperV-Tiered"
Include {
Options { Signature = SHA256; Compression = LZ4 }
# Tier 1: application-consistent, every 4h incremental
Plugin = "podheitor-hyperv: vm=SQL* quiesce=yes timeout=7200"
Plugin = "podheitor-hyperv: vm=Exchange* quiesce=yes timeout=7200"
Plugin = "podheitor-hyperv: vm=DC* quiesce=yes"
# Tier 2: no quiesce for Linux
Plugin = "podheitor-hyperv: vm=Linux* quiesce=no"
# Exclude dev/test
Plugin = "podheitor-hyperv: vm=Web* exclude=*-dev,*-test quiesce=no"
}
}
12.3 Replication — Near-CDP (10-minute RPO)
FileSet {
Name = "HyperV-Replicate-CriticalDBs"
Include {
Options { Signature = SHA256 }
Plugin = "podheitor-hyperv: vm=SQL* mode=rct-push push_cycles=1 rpo_seconds=600 push_apply_remote=no"
}
}
Schedule {
Name = "Every10Minutes"
Run = Incremental hourly at 0:00
Run = Incremental hourly at 0:10
Run = Incremental hourly at 0:20
Run = Incremental hourly at 0:30
Run = Incremental hourly at 0:40
Run = Incremental hourly at 0:50
}
Job {
Name = "HyperV-Replicate-CriticalDBs"
Type = Backup
Level = Full
Client = hyperv-host-fd
FileSet = "HyperV-Replicate-CriticalDBs"
Schedule = "Every10Minutes"
Storage = ReplicaStorage
Pool = ReplicaPool
Messages = Standard
Priority = 5
}
12.4 Restore — Specific VM
# In bconsole:
restore client=hyperv-host-fd
restoreclient=hyperv-host-fd
restorejob=HyperV-Restore
jobid=<backup_jobid>
where=/
all done yes
12.5 Restore — As New VM (Different Name)
FileSet {
Name = "HyperV-Restore-NewVM"
Include {
Options { Signature = SHA256 }
Plugin = "podheitor-hyperv: vm=ProductionVM new_vm_name=RestoredVM-Test restore_path=D:HyperVRestored"
}
}
12.6 Cross-Hypervisor Conversion (vSphere → Hyper-V)
# Prerequisite: podheitor-vsphere-fd.dll installed on Hyper-V host
# Prerequisite: qemu-img.exe available
FileSet {
Name = "vSphere-to-HyperV"
Include {
Options { Signature = SHA256 }
Plugin = "podheitor-vsphere: vm=LinuxVM restore_path=D:HyperVConverted"
}
}
Job {
Name = "Convert-vSphere-to-HyperV"
Type = Restore
Client = hyperv-host-fd
FileSet = "vSphere-to-HyperV"
Storage = File1
Pool = Default
Where = /
Messages = Standard
}
13. Security Considerations
13.1 Authentication
- Plugin communicates locally via stdin/stdout (PTCOMM) — no network socket
- Bacula FD ↔ Director uses TLS with certificates (Bacula standard)
- Bacula FD ↔ SD uses TLS with certificates (Bacula standard)
- DR-push channel uses pre-shared key (
dr_psk) for additional encryption
13.2 Credentials
- No credentials stored in plugin code or configuration files
- Hyper-V access uses the Windows account running the Bacula FD service (typically
SYSTEMor a dedicated service account) - Recommend: create a dedicated Windows service account with Hyper-V Administrator role
13.3 Data in Transit
- All backup data travels via the standard Bacula FD → SD TLS connection
- Replication via RCT-Push uses PSK-encrypted transport when
dr_pskis configured - No unencrypted data exposure during plugin operation
13.4 OWASP Compliance
- No SQL injection risk (no database interaction in plugin code)
- No command injection (subprocess execution uses argument arrays, not shell strings)
- No hardcoded credentials
- Input validation at all system boundaries
- No path traversal (all restore paths validated against
Whereparameter)
14. Performance Benchmarks
14.1 Tested Configuration
| Component | Specification |
|---|---|
| Hyper-V Host | Windows Server 2016, Dual-Core, 4 GB RAM |
| Bacula FD | 15.0.3 |
| Bacula SD | Linux, 10 Gbps link |
| Storage | Bacula dedup storage (SD) |
| Compression | LZ4 |
14.2 Backup Performance
| Scenario | VM Size | Data Transferred | Elapsed Time | Transfer Rate |
|---|---|---|---|---|
| Full backup, Linux VM (TestVM-Linux) | ~1 GB disk (sparse) | 15.6 MB | ~10 sec | ~1.5 MB/s (SD dedup active) |
| Restore, Linux VM | 633 MB restored | ~45 sec | ~14 MB/s | Standard SD throughput |
| RCT-Push incremental cycle | 4 MB changed | 36 KB (post-dedup) | ~5 sec | Negligible |
14.3 Observations
- Dedup active: Bacula SD dedup significantly reduces stored data. The 15.6 MB backup → 633 MB restore reflects dedup compression ratio of ~40:1 for this Linux VM.
- RCT-Push efficiency: Only changed blocks transferred. For a 1 GB VM with minimal changes between cycles, each cycle transfers <10 MB of raw change data.
- Production environment: Expect 100–500 MB/s raw throughput on 10 Gbps networks with NVMe storage (not dedup).
15. Competitive Comparison
| Feature | PodHeitor + Bacula | Veeam Enterprise | Commvault | Bacula Enterprise |
|---|---|---|---|---|
| Hyper-V VM backup | ✅ | ✅ | ✅ | ✅ |
| RCT block-level incremental | ✅ | ✅ | ✅ | ✅ |
| Application-consistent (VSS) | ✅ | ✅ | ✅ | ✅ |
| Near-CDP replication | ✅ | ✅ | ✅ | ✅ |
| vSphere → Hyper-V conversion | ✅ | Partial | ✅ | ❌ |
| Proxmox → Hyper-V conversion | ✅ | ❌ | ❌ | ❌ |
| Open catalog (PostgreSQL) | ✅ | ❌ (proprietary) | ❌ | ✅ |
| Linux Director | ✅ | ❌ (Windows only) | ❌ | ✅ |
| Base license cost | Free (Bacula Community) | USD 2,500+/yr | USD 5,000+/yr | USD 3,000+/yr |
| Plugin cost | Contact for pricing | Included | Included | Included |
| Total 3-year TCO (50 VMs) | ~USD 5,000 | ~USD 25,000 | ~USD 40,000 | ~USD 20,000 |
16. Development Roadmap
Completed (v1.2.0)
- [x] Direct VHDX backup with production checkpoints
- [x] RCT block-level incremental/differential
- [x] CBT delta format + delta apply on restore
- [x] Application-consistent VSS quiesce
- [x] Automatic VM registration on restore
- [x] RCT-Push replication (near-CDP)
- [x] Cross-hypervisor conversion: vSphere → Hyper-V
- [x] Cross-hypervisor conversion: Proxmox → Hyper-V
- [x] Integrity verification (SHA-256 cross-side VerifyReq/VerifyResp)
- [x] Config file support
- [x] NSIS installer with optional Conversion Tools
- [x] Production validation on Windows Server 2016 + Bacula 15.0.3
Planned (v1.2.0)
- [ ] Failover / Failback automation (planned/unplanned failover modes)
- [ ] Reprotect after failover
- [ ] Bacularis web UI integration — dedicated Hyper-V backup dashboard
- [ ] Windows Server 2025 Hyper-V live migration awareness
- [ ] Email alerting integration (SMTP, Microsoft Teams, Slack)
- [ ] REST API for plugin status and management
Planned (v2.0.0)
- [ ] Multi-host Hyper-V cluster support (Live Migration + cluster-aware backup)
- [ ] Azure Stack HCI integration
- [ ] Hyper-V Replica integration (leverage built-in Hyper-V Replica for DR)
- [ ] Container-level backup (Windows Server Containers on Hyper-V)
- [ ] S3-compatible cloud storage target support
Conclusion
PodHeitor Hyper-V Plugin delivers enterprise-class VM protection — backup, replication and cross-hypervisor conversion — on top of Bacula Community Edition at a fraction of the cost of proprietary solutions.
With a production-validated Rust backend, direct VHDX access, RCT block-level incremental, and integrated RCT-Push replication, this plugin is ready for demanding enterprise environments.
💼 Ready to save 50%+ on your backup budget?
Bring your renewal proposal for any commercial enterprise backup platform — Veeam, Commvault, NetBackup, or others. We offer at least 50% discount with far more features.
Contact Heitor Faria: – 📧 heitor@opentechs.lat – 📞 +1 786 726-1749 – 📱 +55 61 98268-4220 (WhatsApp)
Copyright © 2026 Heitor Faria — All Rights Reserved
Disponível em:
Português (Portuguese (Brazil))
English
Español (Spanish)