SD-side Rust suite delivering three capabilities over a single core: file-level granular restore, block-level Instant Recovery (NBD/iSCSI/NFS-Datastore/SMB-VHDX), and cross-hypervisor V2V (Hyper-V↔Proxmox↔ESXi↔CloudStack↔Nutanix). Replaces Bacula Enterprise 18.2 Single Item Restore (SIR) with technical parity + cross-hypervisor differentiators SIR doesn’t cover.
Companion technical document to the PodHeitor Granular Restore plugin page.
1. The problem: Enterprise SIR is vSphere-centric
Reverse engineering of the bacula-enterprise-single-item-restore-18.2.3-26020419.el9.x86_64.rpm package showed:
- SIR uses its own C++ parsers (
vmbackend,bacula-fused) — not libguestfs. - Instant Recovery exists only for vSphere (NFS Datastore export via
vsphere-ctl --ir-mode). - IR for Hyper-V doesn’t exist. IR for Proxmox/KVM/CloudStack/Nutanix doesn’t exist.
- Cross-hypervisor V2V doesn’t exist — Hyper-V backups restore only on Hyper-V.
mount-vmJSON mode serializes a fragile proprietary format.- Local cache in
working/mount-cache— staging is not zero.
For multi-hypervisor customers (typical of hosting providers and MSPs), these gaps are blocking. PHGR closes all four: Hyper-V IR, Proxmox/KVM IR, Nutanix/CloudStack IR, and cross-hypervisor V2V.
2. Architecture — cargo workspace, three binaries, one core
ADR-001: everything in a single cargo workspace with three binaries (phgrd, phird, phgr-cli) sharing a core crate (phgr-core). Not “everything in the same binary” — it’s “one codebase, multiple operational deliverables that can be installed independently”.
| Crate | Type | Purpose |
|---|---|---|
phgr-core |
lib | Catalog, volume reader, delta/CBT, disk adapter, FS, exporters, V2V, sessions, audit |
phgrd |
bin | GR daemon (FUSE/SMB/NFS export) |
phird |
bin | IR daemon (NBD/iSCSI/NFS-Datastore + hypervisor drivers) |
phgr-cli |
bin | Interactive + scripted CLI (mount, ir, v2v, diff, verify) |
phgr-api |
bin | gRPC + REST gateway with OpenAPI |
phgr-tests |
lib | E2E test harness + lab fixtures |
3. Granular Restore — file-level, no staging
The phgrd daemon mounts Bacula volumes as a FUSE filesystem, parses VHDX/VHD/VMDK/qcow2/raw/VDI, mounts NTFS/ext2/3/4/xfs/btrfs/ReFS/FAT/exFAT/ZFS partitions, and exposes files via:
- FUSE local — mount at
/mnt/phgr/<jobid>/<disk-N>/ - SMB — dynamic share via Samba
bacula.d/include - NFS — dynamic export via
/etc/exports.d/
The Bacula volume reader is pure Rust (ADR-005) — does not link libbacsd. In v1.0, fallback to orchestrated bextract when the Rust reader doesn’t cover an encoding. Footprint in /opt/bacula/working: ≤ 2 GB for a 200 GB VHDX (lazy reads + small LRU cache, vs SIR which fully caches).
4. Instant Recovery — VM boot in ≤ 60s
The phird daemon exposes the reconstructed image as a block target so a hypervisor boots the VM immediately. Four paths:
| Hypervisor | Block | Path |
|---|---|---|
| Proxmox / KVM | Direct NBD | qm importdisk via nbd:// URL |
| VMware ESXi | NFS Datastore | Mount NFS export as datastore + register VM |
| Hyper-V | iSCSI bridge | Linux iSCSI Target → Hyper-V iSCSI initiator → New-VM with iSCSI VHDX |
| Nutanix / CloudStack | iSCSI VG attach | Temporary VG → attach VM → boot |
Writes during IR land in a separate COW overlay (qcow2 backing file). Live migration to permanent storage runs in background (Storage vMotion / qm move-disk / equivalent) — user sees no transition. Observed RTO: ≤ 60s p95 wall-clock from operator clicking “Recover” to VM boot.
5. Cross-hypervisor V2V
phgr-cli v2v converts disk format and emits native config for the target hypervisor:
| Source → Target | Disk conversion | Config emitted |
|---|---|---|
| Hyper-V → Proxmox | vhdx → qcow2 | qm create + qm set |
| VMware → Proxmox | vmdk → qcow2 | qm create |
| Proxmox → Hyper-V | qcow2 → vhdx | VMCX XML |
| VMware → Hyper-V | vmdk → vhdx | VMCX XML |
| Hyper-V → VMware | vhdx → vmdk | VMX |
| Proxmox → VMware | qcow2 → vmdk | VMX |
Conversion uses streaming qemu-img convert. Virtio drivers are injected via virt-customize when the target requires them (Linux guest moving from Hyper-V to KVM).
6. Diffs vs Bacula Enterprise SIR
| Capability | Enterprise SIR 18.2 | PHGR v1.x |
|---|---|---|
| GR Hyper-V/VMware/Xen/KVM | Yes | Yes — parity |
| GR Proxmox / CloudStack / Nutanix | Namespace exists, real support sparse | Yes — differentiator |
| IR vSphere | Yes | Yes — parity |
| IR Hyper-V | No | Yes — iSCSI bridge |
| IR Proxmox / KVM | No | Yes — direct NBD |
| IR Nutanix / CloudStack | No | Yes — iSCSI VG |
| Cross-hypervisor V2V | No | Yes |
| Zero-staging | Local cache ≥ 2 GB | FUSE direct, ≤ 2 GB / 200 GB VHDX |
| Parallelism | C++ sync | Rust async + tokio + io_uring when available |
| API | Proprietary format | gRPC + REST with OpenAPI |
| Diff between two jobs | No | Yes — audit, DR remote saving |
| Optional auto-malware scan | No | clamav/yara opt-in |
7. Signed audit log (compliance)
Every restore session emits an HMAC-chained trail: each entry includes a hash of the previous one, ensuring tampering is detectable. Covers LGPD / GDPR / PCI requirements for forensic evidence of who accessed which data.
8. Throughput targets
| Metric | Target |
|---|---|
| Granular restore on fast volume (NVMe) | ≥ 250 MB/s |
| Concurrent sessions without > 30% degradation | ≥ 4 |
| IR start (p95 wall-clock) | ≤ 60s |
Footprint in /opt/bacula/working |
≤ 2 GB for 200 GB VHDX |
| FS families supported | 8 (NTFS, ext2/3/4, xfs, btrfs, ReFS, FAT, exFAT, ZFS) |
9. Documented anti-patterns
- Don’t run
phirdfor IR without a configured COW overlay. Writes during IR go to the base image and corrupt the point-in-time backup. - Don’t expose
phgrdSMB shares publicly. The Sambabacula.d/include is for LAN — no TLS, no hardened Kerberos. Use SMB over VPN. - Don’t trust the Enterprise SIR namespace to identify source. Backups named
@HYPERV-WINAPI,@vsphereetc are hints, but the PHGR parser validates by disk-format magic number, not by path. - Don’t forget ZFS dataset cleanup when the working dir is ZFS. Sessions use clones; cleanup is automatic via
SessionGuardDrop, but force-killing the daemon leaves orphan clones.
10. License posture
PHGR is AGPLv3 with commercial dual-licensing available. Unlike FD plugins (which must avoid transitive AGPL because they run inside bacula-fd), PHGR is a standalone SD-side suite — does not link against Bacula source at any point. Volume reading uses the documented format in pure Rust, no libbacsd.
Ready to evaluate?
Free 30-day trial for multi-hypervisor customers needing Instant Recovery on Hyper-V/Proxmox/KVM/Nutanix/CloudStack or cross-hypervisor V2V. We guarantee at least 50% discount vs Bacula Enterprise SIR or Veeam Instant VM Recovery, with cross-hypervisor IR and V2V that neither offers.
Heitor Faria — Founder, PodHeitor International
✉ [email protected]
☎ +1 (789) 726-1749 · +55 (61) 98268-4220 (WhatsApp)
🔗 PodHeitor Granular Restore plugin page
Disponível em:
Português (Portuguese (Brazil))
English
Español (Spanish)