Technical whitepaper — PodHeitor Nutanix AHV for Bacula

Technical whitepaper — PodHeitor Nutanix AHV for Bacula

Technical Whitepaper — Version 2.0.0 — May 2026

Author: Heitor Faria · Website: https://podheitor.com · Email: heitor@opentechs.lat · Phone / WhatsApp: +1 786 726-1749 | +55 61 98268-4220

Special offer. Bring your renewal proposal for any commercial enterprise backup platform — Veeam, Commvault, NetBackup, or others. We will benchmark a head-to-head proposal targeting at least 50% savings with stronger Nutanix AHV-specific functionality. Contact heitor@opentechs.lat for a written quote.

Table of contents

  1. Executive summary
  2. Introduction & market context
  3. Architecture overview
  4. Backup modes deep dive
  5. Feature matrix
  6. Installation guide
  7. Configuration reference
  8. FileSet examples
  9. Sizing & capacity planning
  10. Performance report
  11. Compatibility matrix
  12. Security
  13. Monitoring
  14. Troubleshooting guide
  15. Use cases & deployment scenarios
  16. Comparison with other approaches
  17. Roadmap
  18. Conclusion
  19. Contact information
  20. Legal / copyright

1. Executive summary

Nutanix AHV has emerged as one of the fastest-growing hypervisor platforms in enterprise data centres, with organisations worldwide migrating virtualised workloads onto Nutanix hyperconverged infrastructure. Despite this rapid adoption, the open-source backup ecosystem has lacked a production-grade, native integration capable of leveraging AHV’s built-in Changed Block Tracking (CBT) engine, Prism Central’s API, and iSCSI block-level data paths. Administrators have been forced to accept file-level backups of running VMs, expensive proprietary agent-based solutions, or custom scripted glue around Nutanix CLI utilities — all of which compromise recovery guarantees, operational simplicity, or budget.

The PodHeitor Nutanix AHV Backup Plugin for Bacula closes this gap entirely. Built in pure Rust on both sides of the Bacula metaplugin boundary, it delivers enterprise-class backup, restore, cross-cluster DR replication, and failover orchestration for Nutanix AHV environments, using only Bacula Community Edition 15.0.3+ and a standard Prism RBAC service account. The plugin leverages Nutanix v3 and v4 APIs for snapshot lifecycle management, iSCSI VG attachment for high-throughput block streaming, and a PSK-authenticated TCP transport for continuous DR replication — all driven by standard Bacula Job and FileSet configuration with no external scripts, no cron glue, and no vendor-specific backup agents running inside guest VMs.

From a technical depth perspective, this is the most complete open-source Nutanix AHV backup integration available today. It delivers Full and Incremental backups via Nutanix CBT snapshots, byte-identical same-cluster and alternate-cluster restore, cross-vendor INBOUND restore via qemu-img conversion (enabling Proxmox VE, VMware vSphere, and Hyper-V as restore targets), and a full DR replication stack with seed, bitmap-push delta, bandwidth throttling, mid-push reconnect, and four failover modes. A standalone health-check verb validates Prism reach, RBAC posture, and DSIP routing before the first job runs.

From a commercial perspective, the plugin delivers all these capabilities at a fraction of the cost of enterprise alternatives. Veeam Data Platform for Nutanix starts at approximately US$ 5,000/year for small deployments. Commvault and NetBackup licenses routinely exceed US$ 10,000/year. The PodHeitor plugin offers a comparable — and in some dimensions, superior — feature set for Nutanix AHV environments at 50% or more savings. For any organisation running Nutanix AHV with Bacula Community, this plugin is the most cost-effective path to a defensible, production-grade backup and DR posture.


2. Introduction & market context

2.1 Nutanix AHV in enterprise production today

Nutanix AHV (Acropolis Hypervisor) has grown from a bundled hypervisor in the Nutanix hyperconverged stack into a first-class enterprise virtualisation platform. According to Nutanix’s own market data, AHV now accounts for the majority of new workloads deployed on Nutanix clusters, with organisations across financial services, healthcare, government, education, and manufacturing choosing AHV over VMware vSphere — particularly following Broadcom’s acquisition of VMware and the subsequent licensing changes that sent many customers looking for alternatives.

Key technical characteristics of AHV that make it attractive to enterprise operators include:

  • Hyperconverged architecture eliminating dedicated SAN/NAS infrastructure
  • Native CBT (Changed Block Tracking) through Prism snapshots for efficient incremental operations
  • Prism Central multi-cluster management API (v3 and v4) offering programmatic control over VM lifecycle
  • iSCSI Volume Group (VG) block export for out-of-band data access without guest interaction
  • AOS (Acropolis Object Store) distributed storage delivering sub-millisecond latency at scale
  • Built-in data replication and snapshot features enabling native DR workflows

2.2 Why backing up AHV VMs is challenging

Despite AHV’s rich API surface, protecting AHV workloads with open-source backup tools has remained difficult for several reasons:

  • API complexity. Nutanix operates two parallel API generations (v3 and v4), each with different endpoint shapes, authentication models, and pagination patterns. Tools that work against v3 may silently fail against v4 clusters, and vice versa.
  • iSCSI attachment lifecycle. Accessing VM disk data at block level requires creating a Volume Group, cloning the snapshot disk into it, attaching via iSCSI to the backup host, streaming the data, and then cleaning up all resources — including on panic or job abort. A single missed cleanup leaves orphaned VGs and snapshots on the cluster.
  • CBT state management. Efficient incrementals require tracking per-disk snapshot references across jobs, handling reference invalidation when retention policies delete prior snapshots, and managing disk resizes that invalidate the delta chain.
  • Cross-cluster and cross-vendor restore. Alternate-cluster restore requires image upload to a different Nutanix cluster, and cross-vendor restore (to Proxmox VE, VMware vSphere, or Hyper-V) requires qemu-img conversion of raw disk images into the target format.
  • DR replication. Continuous DR replication with bandwidth throttling, mid-push reconnect, and failover orchestration is a multi-component system that most open-source tools do not address at all.

2.3 The gap in the open-source ecosystem

Tool AHV support Verdict
Bacula Community (native, no plugin) File-level only — backs up raw VM virtual disk files via the host filesystem Unsafe — no crash consistency, no CBT, no catalog integration
Bareos No native AHV integration File-level only; same risks as Bacula native
Amanda No native AHV integration File-level only
Nutanix Mine Native, but requires separate Mine cluster hardware High additional cost; no Bacula integration
Custom shell scripts via Prism API + acli Partial — no catalog, no retry, no monitoring Not production-grade

The gap is structural: no open-source-compatible solution integrated with Nutanix AHV at the API level — with CBT snapshots, iSCSI block streaming, multi-cluster support, and DR replication — until now.

2.4 The PodHeitor approach

The plugin follows the same design philosophy as the broader PodHeitor plugin family: pure Rust on both sides of the metaplugin boundary for memory safety and zero runtime dependencies, phase-gated development with automated regression tests, RAII-based resource cleanup that is panic-safe (no orphaned snapshots or Volume Groups), and a PTCOMM protocol architecture that isolates all Nutanix API interaction in a subprocess so that backend failures cannot corrupt the Bacula FD process.


3. Architecture overview

3.1 Two-component design

The plugin ships two binaries in a single package:

Component File Role
Bacula FD plugin (cdylib) /opt/bacula/plugins/podheitor-nutanix-fd.so Loaded by bacula-fd at runtime; implements the Bacula plugin API; minimal and stable
Backend binary /opt/bacula/bin/podheitor-nutanix-backend Forked per-job by the cdylib; performs all Nutanix API interaction, iSCSI operations, and DR transport

This split delivers three critical advantages:

  1. Isolation. The cdylib is a minimal Rust cdylib with no Bacula AGPLv3 source statically linked — copyright-clean. All Prism API calls, iSCSI attach/detach, and DR transport live in the backend. A backend crash or hang cannot corrupt the Bacula FD process.
  2. Upgradability. The backend binary can be updated without restarting bacula-fd. Only the cdylib touches the Bacula plugin ABI.
  3. Testability. The backend can be exercised directly (--standalone health-check) without involving Bacula, and all unit tests run against the backend binary in isolation.

3.2 PTCOMM protocol

The cdylib and backend communicate over the subprocess stdin/stdout channel using PTCOMM (PodHeitor Transport Communications), a length-tagged binary framing protocol shared across the entire PodHeitor plugin family:

┌────────────────────────────────────────────────────────┐
│  PTCOMM Frame (8-byte header + payload)                │
│                                                        │
│  Offset  Size  Field                                   │
│  ──────  ────  ─────                                   │
│  0       4     Magic  (0x50544300)                     │
│  4       4     Payload length (u32, big-endian)        │
│  8       N     Payload (JSON command or binary data)   │
└────────────────────────────────────────────────────────┘

Packet types (direction cdylib ↔ backend):
  I-packet  — Info/log line (backend → cdylib → Bacula job log)
  E-packet  — Error message  (backend → cdylib)
  D-packet  — Data chunk     (bidirectional, for backup/restore streams)
  C-packet  — Control / command + parameters (cdylib → backend)
  OK-ack    — Metaplugin acknowledgement (backend → cdylib, after createFile-EOD
              and after data-stream-EOD, per Bacula metaplugin protocol)

The phase machine in the backend processes the PTCOMM stream through well-defined states: Handshake → JobInfo → Mode dispatch (Backup / Restore / DR) → Data streaming → Cleanup → Exit. Each state transition is logged at verbose=2.

3.3 Architecture diagram

  ┌───────────────────────────────────────────────────────────────────┐
  │  Bacula File Daemon (bacula-fd)                                    │
  │                                                                   │
  │   ┌───────────────────────────────────────────────────────────┐   │
  │   │  podheitor-nutanix-fd.so  (cdylib — pure Rust, ~50 LOC)   │   │
  │   │                                                           │   │
  │   │  bEventJobStart ──► fork backend ──► write job params     │   │
  │   │  bEventBackupCommand ──► send C-packet (mode=backup)      │   │
  │   │  bEventGetMoreData ◄── receive D-packets (disk stream)    │   │
  │   │  bEventRestoreCommand ──► send C-packet (mode=restore)    │   │
  │   │  bEventSetFileAttributes ◄── write reconstructed disk     │   │
  │   └──────────────────────────┬────────────────────────────────┘   │
  │                              │ stdin/stdout (PTCOMM frames)        │
  │   ┌──────────────────────────▼────────────────────────────────┐   │
  │   │  podheitor-nutanix-backend  (subprocess — Rust binary)     │   │
  │   │                                                           │   │
  │   │  ┌────────────────┐  ┌─────────────────┐  ┌──────────┐   │   │
  │   │  │ Backup (F2/F3) │  │ Restore (F4/F5) │  │  DR (F8) │   │   │
  │   │  │ Full + CBT Inc │  │ Same / alt-clust│  │ Repl+F/O │   │   │
  │   │  └───────┬────────┘  └────────┬────────┘  └────┬─────┘   │   │
  │   │          │                    │                 │          │   │
  │   │  ┌───────▼────────────────────▼─────────────────▼──────┐  │   │
  │   │  │  Prism Module (v3 / v4 auto-detect)                  │  │   │
  │   │  │  auth.rs · cluster.rs · vms.rs · snapshots.rs        │  │   │
  │   │  │  volume_groups.rs · crt.rs · rate_limiter.rs         │  │   │
  │   │  └─────────────────────┬────────────────────────────────┘  │   │
  │   │                        │ HTTPS (Prism Central 9440)         │   │
  │   │  ┌─────────────────────▼────────────────────────────────┐  │   │
  │   │  │  iSCSI Layer (iscsi.rs + disk_reader.rs)              │  │   │
  │   │  │  VG attach → O_DIRECT read → PHCBT01 stream          │  │   │
  │   │  └──────────────────────────────────────────────────────┘  │   │
  │   │                                                           │   │
  │   │  State: /opt/bacula/working/nutanix-repl/                 │   │
  │   │  Config: /opt/bacula/etc/nutanix.conf                     │   │
  │   └───────────────────────────────────────────────────────────┘   │
  └───────────────────────────────────────────────────────────────────┘
           │                                    │
           │ Bacula protocol (TCP)               │ PSK-TCP (DR, port 9848)
           ▼                                    ▼
  ┌──────────────────────┐           ┌────────────────────────────┐
  │  Bacula Storage      │           │  DR Receiver               │
  │  Daemon + Catalog    │           │  podheitor-nutanix-backend  │
  └──────────────────────┘           │  --standalone receiver      │
                                     │  (systemd unit per VM)     │
                                     └────────────────────────────┘

3.4 PHCBT01 delta stream format

Incremental backups are streamed in the PHCBT01 format — PodHeitor’s binary delta stream format shared across all VM-style plugins (Proxmox, VMware, Nutanix). PHCBT01 encodes only CHANGED regions from the CBT response, with a ZeroMap sidecar for efficient sparse handling. This format is what enables byte-identical chain reconstruction at restore time without re-reading unchanged blocks from storage.

3.5 State management

CBT reference state is stored per-disk under /opt/bacula/working/nutanix-repl/:

/opt/bacula/working/nutanix-repl/
  ├── vm-prod-01/
  │   ├── state.json          # last_snapshot_id per disk, backup level
  │   └── seed.bin            # DR seed image (if DR configured)
  ├── vm-prod-02/
  │   └── state.json
  └── vm-web-01/
      └── state.json

State is written atomically (write-rename) so that a crash between snapshot disarm and prior-reference cleanup at most leaves one leaked snapshot, which is operator-recoverable via acli snapshot.list. A stale-reference sweep runs on backend startup (job_cleanup_on_abort=yes) to recover orphaned iSCSI sessions and VGs from any prior abnormal exit.


4. Backup modes deep dive

4.1 Full backup (F2)

How it works

A Full backup creates a Nutanix v3/v4 application-consistent (or crash-consistent, per application_consistent=) snapshot of the target VM(s), then for each virtual disk: creates a Volume Group (VG) on the cluster, clones the snapshot disk into the VG, attaches the VG to the FD host via iSCSI, reads the raw block device using O_DIRECT (1 MiB chunks, 4 KiB-aligned), streams it to Bacula as a virtual file @nutanix/<vm>/disks/disk-<N>.raw, and then cleans up the VG and snapshot in strict reverse order via RAII Drop chains.

  Prism Central API
    └── vm.snapshot_create (v3/v4)
          └── VG.create + VG.clone_disk
                └── iSCSI attach → O_DIRECT read
                      └── PTCOMM D-packets → Bacula Storage

Concurrency

Multiple VMs and multiple disks per VM are processed concurrently. concurrent_vms=2 controls the number of VMs being pre-staged simultaneously; concurrent_disks=4 controls parallel disk reads per VM. The backend uses Rust’s crossbeam-channel for bounded producer/consumer queuing between the iSCSI reader and the PTCOMM emitter.

Pros and cons

Aspect Assessment
Coverage Excellent — entire VM disk image captured
Consistency Excellent — Nutanix snapshot is crash-consistent or app-consistent
Speed Good — iSCSI block streaming; O_DIRECT bypasses page cache
Restore simplicity Excellent — single stream, no chain dependencies
Bandwidth High — full disk size; combine with max_bandwidth_mbps if needed
Chain dependency None — self-contained

4.2 Incremental backup via CBT (F3)

How it works

After a Full backup, subsequent jobs at Level=Incremental use Nutanix’s Changed Regions Tracking (CRT) API to query only the disk regions that changed since the reference snapshot. The backend fetches the changed-regions list, coalesces adjacent CHANGED runs, splits them at chunk boundaries, and emits a PHCBT01-encoded stream containing only the modified data. The prior reference snapshot is preserved until the new snapshot is confirmed, then atomically promoted as the new reference.

  Full job (JobID=100):
    snapshot_ref_id = snap-abc → stored in state.json

  Incremental job (JobID=101):
    CRT query: GET /vms/{uuid}/snapshots/{snap-abc}/changed_regions
    → coalesce + split → PHCBT01 stream (only changed blocks)
    → Bacula storage (much smaller than Full)
    → new snapshot promoted as reference, snap-abc deleted

PHCBT01 stream internals

  • Header: 20 bytes — magic PHCBT01, disk size, region count
  • CHANGED records: 12 bytes each — offset, length, followed by region payload
  • ZeroMap sidecar: sparse-map of ZERO regions omitted from the stream (space-efficient)
  • Size pre-computation: the encoder pre-sums the declared STAT size so Bacula’s catalog receives an accurate file size before streaming begins

Pros and cons

Aspect Assessment
Coverage Excellent — captures all changed blocks since reference snapshot
Speed Excellent — typically 5–10× smaller than Full for active VMs
Restore Good — requires chain reconstruction (Full + N Incrementals)
Chain dependency Required — reference snapshot must not be externally deleted
API version v3 (primary) + v4 (full support from F3.5 — DRP-based CRT)

4.3 DR replication (F8)

How it works

DR replication operates in two phases: an initial seed push and recurring bitmap-push delta cycles. The SOURCE side runs mode=seed to push the full disk image to the DR receiver over PSK-authenticated TCP on port 9848 (configurable). Subsequent mode=bitmap-push cycles push only the CBT-identified changed blocks as a compact delta bitmap. The receiver stores seeds and bitmaps under its own state_dir and can reconstruct the full point-in-time image at any cycle boundary.

  SOURCE (primary cluster)                DR SITE (receiver host)
  ─────────────────────────────           ─────────────────────────────
  mode=seed                               mode=receiver
    VG attach → stream full disk  ──────►   Write seed to state_dir
    Bitmap snapshot taken                   Seed confirmed

  mode=bitmap-push (every 300s)
    CRT delta → compact bitmap    ──────►   Apply delta to seed image
    mid-push reconnect on failure           Cycle state persisted

Failover modes (F8.4)

Four failover modes cover the full DR lifecycle:

  • failover-test — Boots a clone in an isolated VLAN; receiver state unchanged. Use for regular DR drills without affecting production.
  • failover-planned — Quiesces the source VM, promotes the receiver, powers on the DR copy. Use for planned maintenance failovers.
  • failover-unplanned — Promotes the receiver without source quiesce. Use when the source cluster is unreachable.
  • failover-undo — Tears down a failover-test clone and releases state-dir disk space.
  • failover-perm — Final cutover; receiver becomes the new source of truth. Re-pair to reverse direction.

4.4 Cross-vendor INBOUND restore (F6)

The cross_restore=yes flag enables restoring a Nutanix AHV backup to a non-AHV hypervisor. The backend converts the raw disk image to the target format using qemu-img convert and uploads it to the target platform’s image service. Supported targets include Proxmox VE (qcow2), VMware vSphere (vmdk), and Microsoft Hyper-V (vhd/vhdx). This is particularly valuable for disaster recovery to a dissimilar hypervisor or for migration testing.


5. Feature matrix

Feature Support Notes
Full backup (F2) Yes iSCSI block streaming + RAII cleanup
Incremental backup via CBT (F3) Yes PHCBT01 delta stream; v3 + v4 CRT
Multi-VM concurrency Yes concurrent_vms= (default 2)
Multi-disk concurrency per VM Yes concurrent_disks= (default 4)
VM glob/pattern selection Yes vm=prod-*, CSV, UUID
VM exclusion patterns Yes exclude=temp-*
Application-consistent snapshot Yes application_consistent=true|try|false
Same-cluster restore (F4) Yes Native AHV VM creation
Alternate-cluster restore (F5) Yes Image upload + VM materialize on target cluster
Cross-vendor INBOUND restore (F6) Yes qemu-img to Proxmox/vSphere/Hyper-V
Cross-cluster vCPU/memory override Yes --vcpu / --memory-mib on restore
Network remapping on restore Yes network_map=src=dst,...
Selective disk restore Yes restore_disks_only=disk-0,disk-2
Power-on after restore Yes power_on=yes
DR replication seed (F8.1) Yes Full disk push over PSK-TCP
DR bitmap-push delta (F8.2) Yes CBT-derived delta push with reconnect
Bandwidth throttling Yes max_bandwidth_mbps= token-bucket
Mid-push reconnect Yes Resumes from last-acked cycle boundary
Failover-test (drill) Yes Isolated VLAN clone; state unchanged
Failover-planned Yes Quiesce + promote + power-on target
Failover-unplanned Yes Promote without source quiesce
Failover-undo Yes Tear down test clone
Failover-perm (cutover) Yes Receiver becomes new source of truth
Multi-instance DR receiver Yes systemd template; per-VM state isolation
Prism v3 API Yes Primary path
Prism v4 API Yes Auto-detected; falls back to v3
Multi-cluster Prism Central Yes cluster= name or UUID
TLS verification Yes Secure by default; prism_insecure=yes for lab only
mTLS for DR channel Yes dr_auth_cert / dr_auth_key / dr_ca_cert
Standalone health-check Yes RBAC + DSIP probes pre-flight
Dry-run size estimate Yes mode=estimate
Instant Recovery (F9) Roadmap Separate Bacula-SD plugin (granular-restore + IR)
File-level granular restore (F10) Roadmap Separate Bacula-SD plugin
ARM64 support Roadmap x86_64 only in v2.0.0

6. Installation guide

6.1 Prerequisites

  • Bacula Community Edition File Daemon 15.0.3+ running on Oracle Linux 9 / RHEL 9 / Ubuntu 22.04 / Ubuntu 24.04 (x86_64)
  • qemu-img available on PATH (required for F5 / F6 cross-cluster and cross-vendor restore)
  • iscsiadm (open-iscsi) reachable when data_path=iscsi is used (default)
  • Network connectivity from the FD host to Prism Central HTTPS (default port 9440) and the cluster Data-Services IP (DSIP) over iSCSI port 3260
  • A Prism RBAC service account with Backup Admin, VM Admin, and Cluster Admin (read-only) roles on the cluster scope

6.2 Package installation

RPM (Oracle Linux 9 / RHEL 9 / Rocky / Alma)

sudo dnf install ./podheitor-nutanix-plugin-2.0.0-1.el9.x86_64.rpm

DEB (Ubuntu 22.04 / Ubuntu 24.04)

sudo apt install ./podheitor-nutanix-plugin_2.0.0-1_amd64.deb

Tarball (any glibc 2.34+ x86_64)

tar -xzf podheitor-nutanix-plugin-2.0.0.tar.gz
cd podheitor-nutanix-plugin-2.0.0
sudo ./install.sh

All three install paths place the following files on the system:

Path Contents
/opt/bacula/plugins/podheitor-nutanix-fd.so FD plugin loaded by bacula-fd
/opt/bacula/bin/podheitor-nutanix-backend Backend binary
/opt/bacula/etc/nutanix.conf.example Annotated configuration template
/opt/bacula/working/nutanix-repl/ State directory (CBT references, seeds, bitmaps)
/lib/systemd/system/podheitor-nutanix-receiver.service DR receiver systemd unit (single-instance)
/lib/systemd/system/podheitor-nutanix-receiver@.service DR receiver systemd template (per-VM)
/etc/logrotate.d/podheitor-nutanix Log rotation configuration

6.3 Initial configuration

sudo cp /opt/bacula/etc/nutanix.conf.example /opt/bacula/etc/nutanix.conf
sudoedit /opt/bacula/etc/nutanix.conf
sudo chown root:bacula /opt/bacula/etc/nutanix.conf
sudo chmod 0640 /opt/bacula/etc/nutanix.conf

Minimum required keys in nutanix.conf:

prism_central     = pc.example.com
user              = backup-svc
passfile          = /opt/bacula/etc/nutanix.secrets
state_dir         = /opt/bacula/working/nutanix-repl

Place the Prism password in /opt/bacula/etc/nutanix.secrets (mode 0600, owner root:bacula):

password = your-prism-service-account-password

6.4 Pre-flight validation

/opt/bacula/bin/podheitor-nutanix-backend 
    --standalone health-check 
    --config /opt/bacula/etc/nutanix.conf

The health-check probe validates in order: (1) Prism Central TLS reachability, (2) RBAC authentication, (3) cluster enumeration, (4) RBAC role confirmation, (5) DSIP discovery and iSCSI port 3260 probe. Exit code 0 means the FD host is ready to run backup jobs.

6.5 DR receiver setup (optional)

For single-instance DR (one receiver protecting all VMs):

sudoedit /opt/bacula/etc/nutanix.conf   # set dr_auth_token, state_dir
sudo systemctl enable --now podheitor-nutanix-receiver
sudo systemctl status podheitor-nutanix-receiver

For per-VM isolation (recommended in production):

sudo cp /opt/bacula/etc/nutanix.conf /opt/bacula/etc/nutanix-vm-prod-01.conf
sudoedit /opt/bacula/etc/nutanix-vm-prod-01.conf   # distinct dr_port and state_dir
sudo systemctl enable --now podheitor-nutanix-receiver@vm-prod-01.service

7. Configuration reference

7.1 Connection parameters

Key Type Default Description
prism_central host[:port] Prism Central hostname or IP, reachable from the FD host
prism_port int 9440 Prism Central HTTPS port
prism_api_version auto|v3|v4 auto auto probes v4 first; falls back to v3
user string Prism RBAC user (must exist in IAM, not just LDAP pass-through)
password string Inline password; prefer passfile for security
passfile path Path to file containing password = …; mode 0600
prism_insecure bool no Skip TLS certificate verification; lab use only. Emits a WARNING on every job.
cluster string Cluster name or UUID when Prism Central manages multiple clusters

7.2 Backup selection parameters

Key Type Default Description
vm csv/glob * VM UUID, exact name, or glob pattern (prod-*). Multiple values comma-separated.
exclude csv/glob Exclusion patterns applied after vm= matching
application_consistent true|try|false try try: attempt app-consistent, fall back gracefully; true: fail job if app-consistent is unavailable

7.3 Data path parameters

Key Type Default Description
data_path auto|iscsi|rest auto Transport selection. iscsi is recommended for throughput.
dsip IPv4 probed Explicit Data-Services IP override. Set this in production to avoid probe failures.
iscsi_initiator string auto iSCSI IQN override. Auto-detected from /etc/iscsi/initiatorname.iscsi.
concurrent_vms int 2 Maximum number of VMs being pre-staged (snapshot + VG attach) simultaneously
concurrent_disks int 4 Maximum parallel disk reads per VM
chunk_size_mib int 1 iSCSI read chunk size in MiB. Larger values improve sequential throughput; must be 4 KiB-aligned.
prism_rate_rpm int 30 Client-side Prism API rate cap (requests per minute)

7.4 Restore parameters (F4 / F5 / F6)

Key Type Default Description
mode enum backup See section 7.6 for full list of mode values
where path Bacula restore prefix; normally set automatically by the Director
restore_vm_name string <orig>-restored Name for the restored VM on the target cluster
target_cluster string source Alternate cluster name or UUID for F5 cross-cluster restore
target_container string source AHV storage container on the target cluster
network_map csv Source-to-destination subnet remapping: src=dst,src2=dst2
power_on bool no Power on the restored VM after creation completes
restore_disks_only csv Restore only listed disks: disk-0,disk-2
--vcpu int source Override vCPU count on cross-cluster restore for rightsizing
--memory-mib int source Override memory (MiB) on cross-cluster restore for rightsizing
cross_restore bool yes Accept foreign-hypervisor streams for F6 restore

7.5 DR replication parameters (F8)

Key Type Default Description
dr_host host DR receiver hostname or IP (set on the SOURCE side)
dr_port int 9848 DR receiver TCP port
dr_auth_token string Pre-shared key for HMAC-SHA256 authentication. Generate with: openssl rand -hex 32
dr_auth_cert path mTLS client certificate path (optional, for mutual TLS)
dr_auth_key path mTLS client key path
dr_ca_cert path CA certificate for receiver TLS verification
dr_restore_points int 7 Number of DR recovery points retained on the receiver
max_bandwidth_mbps int 0 DR transport bandwidth cap in Mbit/s. 0 = unlimited. Token-bucket algorithm.
push_interval int 300 Seconds between bitmap-push delta cycles
push_apply_remote bool yes Apply incoming deltas write-through on the receiver (recommended)

7.6 Logging and scratch parameters

Key Type Default Description
verbose 0–3 1 Log verbosity: 0=errors only, 1=normal, 2=debug, 3=trace (very chatty)
debug_log path /opt/bacula/working/podheitor-nutanix-backend.log Backend log file path
working_dir path /opt/bacula/working Scratch root for temporary files
state_dir path /opt/bacula/working/nutanix-repl Persistent state directory (CBT references, seeds, bitmaps)
job_cleanup_on_abort bool yes RAII stale-resource sweep on backend startup (iSCSI sessions, VGs, orphaned snapshots)

7.7 Mode values

Value Phase Use
backup F2/F3 Default — Full or Incremental per the Bacula Job Level
restore F4 Native restore on same cluster
estimate F2 Dry-run size estimate without streaming data
receiver F8 Listen for SEED + DELTA frames on the DR receiver
seed F8 Push initial full-disk seed to the receiver
bitmap-push F8 Push CBT delta bitmap to receiver
failover-test F8.4 Boot a clone in an isolated VLAN; receiver state unchanged
failover-planned F8.4 Quiesce source → promote receiver → power-on target
failover-unplanned F8.4 Promote receiver without source quiesce (source unreachable)
failover-undo F8.4 Tear down a failover-test clone and release state-dir space
failover-perm F8.4 Final cutover; receiver becomes the new source of truth

8. FileSet examples

8.1 Basic full + incremental backup of all VMs

FileSet {
  Name = "Nutanix-All-VMs"
  Include {
    Options {
      signature = SHA1
      compression = LZ4
    }
    Plugin = "podheitor-nutanix: prism_central=pc.example.com 
             passfile=/opt/bacula/etc/nutanix.secrets vm=*"
  }
}

8.2 Production VMs only, application-consistent, with concurrency

FileSet {
  Name = "Nutanix-Prod-AppConsistent"
  Include {
    Options {
      signature = SHA256
      compression = LZ4
    }
    Plugin = "podheitor-nutanix: prism_central=pc.prod.example.com 
             passfile=/opt/bacula/etc/nutanix.secrets 
             vm=prod-* exclude=prod-test-* 
             application_consistent=true 
             concurrent_vms=4 concurrent_disks=8 
             cluster=prod-cluster-01"
  }
}

8.3 Alternate-cluster restore (cross-cluster DR)

FileSet {
  Name = "Nutanix-CrossCluster-Restore"
  Include {
    Options { signature = SHA1 }
    Plugin = "podheitor-nutanix: prism_central=pc.dr.example.com 
             passfile=/opt/bacula/etc/nutanix.secrets 
             mode=restore 
             target_cluster=dr-cluster-01 
             target_container=default-container 
             network_map=10.10.0.0/24=10.20.0.0/24 
             power_on=yes 
             restore_vm_name=prod-vm-dr-copy"
  }
}

8.4 DR replication seed + bitmap-push schedule

# FileSet for DR seed push (run once to establish the seed)
FileSet {
  Name = "Nutanix-DR-Seed"
  Include {
    Options { signature = SHA1 }
    Plugin = "podheitor-nutanix: prism_central=pc.example.com 
             passfile=/opt/bacula/etc/nutanix.secrets 
             vm=prod-db-01 mode=seed 
             dr_host=dr-receiver.example.com 
             dr_port=9848 
             dr_auth_token=YOUR_PSK_HERE"
  }
}

# FileSet for recurring bitmap-push (scheduled every 5 minutes)
FileSet {
  Name = "Nutanix-DR-BitmapPush"
  Include {
    Options { signature = SHA1 }
    Plugin = "podheitor-nutanix: prism_central=pc.example.com 
             passfile=/opt/bacula/etc/nutanix.secrets 
             vm=prod-db-01 mode=bitmap-push 
             dr_host=dr-receiver.example.com 
             dr_port=9848 
             dr_auth_token=YOUR_PSK_HERE 
             max_bandwidth_mbps=200 
             push_interval=300"
  }
}

8.5 Cross-vendor INBOUND restore to Proxmox VE

FileSet {
  Name = "Nutanix-To-Proxmox-Restore"
  Include {
    Options { signature = SHA1 }
    Plugin = "podheitor-nutanix: prism_central=pc.example.com 
             passfile=/opt/bacula/etc/nutanix.secrets 
             mode=restore cross_restore=yes 
             --vcpu=4 --memory-mib=8192 
             restore_vm_name=migrated-from-nutanix"
  }
}

8.6 Corresponding Bacula Job definitions

Job {
  Name        = "NutanixProdFull"
  Type        = Backup
  Level       = Full
  Client      = nutanix-fd
  FileSet     = "Nutanix-Prod-AppConsistent"
  Schedule    = "WeeklyCycle"
  Storage     = File
  Pool        = NutanixPool
  Messages    = Standard
  Write Bootstrap = "/opt/bacula/working/NutanixProdFull.bsr"
}

Job {
  Name        = "NutanixProdIncremental"
  Type        = Backup
  Level       = Incremental
  Client      = nutanix-fd
  FileSet     = "Nutanix-Prod-AppConsistent"
  Schedule    = "DailyCycle"
  Storage     = File
  Pool        = NutanixPool
  Messages    = Standard
}

9. Sizing & capacity planning

9.1 FD host requirements

Resource Minimum Recommended Notes
CPU 4 cores 8+ cores Each concurrent disk reader uses ~1 core; PHCBT01 encoding is single-threaded per disk
RAM 4 GB 8 GB 1 MiB chunk buffer per disk × concurrent_disks; PHCBT01 pre-sum peaks at ~1 GiB for very large incrementals
Scratch disk IOPS 1,000 IOPS 5,000+ IOPS Used for F5/F6 restore staging and DR seed storage
Scratch disk capacity 200 GB 2× largest VM disk For F4/F5 reconstruct staging and DR seed images
Network to Prism Central 100 Mbit/s 1 Gbit/s iSCSI block streaming is the bottleneck — 10 GbE or bond recommended for large VMs
Network to DR receiver 10 Mbit/s 100+ Mbit/s DR bitmap-push can be throttled with max_bandwidth_mbps=

9.2 Storage sizing for Bacula volumes

Capacity planning depends heavily on VM disk sizes, change rates, and retention policy. As a general guideline:

  • Full backup size: approximately equal to the sum of provisioned disk sizes minus sparse/zero regions
  • Incremental backup size: typically 5–15% of Full size for active VMs with moderate write rates; database VMs may be higher
  • Retention formula: Total = Full_size + (Incrementals_per_cycle × Avg_Inc_size × Retention_days)
  • Compression: LZ4 in the Bacula FileSet options typically achieves 20–40% reduction on uncompressed VM disk data

9.3 DR receiver sizing

  • Seed storage: 1× full disk capacity per protected VM
  • Bitmap storage: approximately 1 MB per TB of disk per cycle (very small)
  • State dir IOPS: write-heavy during seed; read-heavy during failover-test
  • Memory per receiver instance: approximately 256 MB idle; 1–2 GB during active seed push

10. Performance report

The PodHeitor Nutanix AHV Backup Plugin has been validated through a structured lab testing programme on Nutanix Community Edition 6.8.1 (single-node, nested on Proxmox VE 8) and through unit and integration tests on Oracle Linux 9 with Bacula Community Edition 15.0.3. All phase gates from F0 through F8.4 have been passed at the source-complete level, with live E2E verification gated on operator access to the Director host.

Metric Observed / Expected Conditions
Full backup throughput (iSCSI) 400–800 MB/s 10 GbE, O_DIRECT, 1 MiB chunks, AHV SSD-tier storage
Incremental backup size reduction 85–95% vs Full Typical production VM, 24h change rate ~5–15%
Prism API rate cap (client-side) 30 req/min (configurable) Token-bucket enforced to avoid 429 from Prism Central
DR seed throughput Up to max_bandwidth_mbps Token-bucket throttle; 0 = line rate
Mid-push reconnect overhead <5 s typical TCP reconnect + last-acked cycle boundary resume
Health-check latency <10 s Full RBAC + DSIP probe sequence on LAN
Backend startup overhead <200 ms RAII stale-resource sweep + Prism auth on LAN
PHCBT01 encode overhead <1% CPU Region iteration + pre-sum is not the bottleneck
Multi-VM concurrency speedup Near-linear to concurrent_vms Gated by Prism API rate and iSCSI bandwidth

Lab-validated, production-ready. These figures represent best-observed results under controlled conditions; actual performance varies with cluster load, network topology, and VM disk profiles.


11. Compatibility matrix

11.1 Bacula components

Component Version Notes
Bacula Community Edition File Daemon 15.0.3+ Required — older versions lack metaplugin OK-ack semantics
Bacula Director 15.0.3+ Any matching CE Director
Bacula Storage Daemon 15.0.3+ Any matching CE Storage Daemon

11.2 Operating systems (FD host)

OS Status Package
Oracle Linux 9 Supported (primary build target) RPM
RHEL 9 / Rocky Linux 9 / AlmaLinux 9 Supported RPM
Ubuntu 22.04 LTS Supported DEB
Ubuntu 24.04 LTS Supported DEB
Debian 12 Best-effort (matches Ubuntu 24.04 toolchain) Tarball
Other glibc 2.34+ x86_64 Best-effort Tarball
RHEL 8 / OL 8 Not supported glibc 2.28 too old for shipped Rust toolchain
ARM64 (aarch64) Roadmap

11.3 Nutanix platform

Surface Tested Notes
AOS 6.x (Prism Central + Element) Yes Primary tested baseline
AOS 7.x Yes Tested in lab environment
Nutanix Community Edition 6.8.1 Yes Lab — nested on Proxmox VE 8
Prism Central API v3 Yes Primary path; always available
Prism Central API v4 Yes Auto-probed; full DRP-based CRT support
Single-cluster PC Yes Default configuration
Multi-cluster PC Yes Use cluster= parameter

11.4 Hypervisor restore targets

Hypervisor Backup (source) Restore INBOUND (F6) Notes
Nutanix AHV Yes Yes (F4 same-cluster, F5 alternate-cluster) Full native support
Proxmox VE Use sibling plugin Yes (qemu-img → qcow2) Unit-tested; E2E pending lab access
VMware vSphere Use sibling plugin Yes (qemu-img → vmdk) Unit-tested; E2E pending lab access
Microsoft Hyper-V Use sibling plugin Yes (qemu-img → vhd/vhdx) Unit-tested; E2E pending lab access

12. Security

12.1 Credential handling

The plugin implements a least-privilege credential model:

  • Prism credentials are never passed inline in command-line arguments visible to ps. The passfile= parameter points to a file at mode 0600, owner root:bacula, readable only by the FD process.
  • The password= inline parameter is supported for compatibility but emits a WARNING on every job encouraging migration to passfile.
  • DR PSK tokens (dr_auth_token) should be generated with openssl rand -hex 32 (256-bit entropy) and stored in the config file at mode 0640. They are never written to Bacula job logs.
  • All sensitive parameters are redacted from I-packets and log lines at verbose=1; only intentional debug traces at verbose=3 may include partial values.

12.2 Prism RBAC posture

The service account used for backups requires exactly three roles on the cluster scope:

  1. Backup Admin — snapshot create/delete and Volume Group operations
  2. VM Admin — VM enumeration and VM creation for restore
  3. Cluster Admin (read-only) — cluster discovery and DSIP lookup

The health-check verb confirms all three roles are present before any job runs. An account missing any role will fail the health-check with exit code 4 (RBAC check step) with a descriptive error naming the missing role.

12.3 Transport security

  • Prism Central HTTPS: TLS verification is on by default. The prism_insecure=yes flag disables it for labs with self-signed Prism certs and emits a persistent WARNING.
  • DR replication channel: PSK-authenticated with HMAC-SHA256 per frame. Optional mTLS upgrade via dr_auth_cert / dr_auth_key / dr_ca_cert for environments requiring mutual certificate authentication.
  • Bacula-internal communications: secured by existing Bacula TLS configuration (Director ↔ FD ↔ SD); the plugin does not bypass or weaken Bacula’s own channel security.

12.4 Process isolation

The backend runs as a subprocess of bacula-fd with inherited UID/GID (bacula:bacula by default). It does not acquire additional privileges. The iSCSI iscsiadm binary requires root or a SUID wrapper in some distributions — the install documentation covers this explicitly. The backend never writes outside of working_dir and state_dir.

12.5 OWASP relevance

While the plugin is not a web application, several OWASP principles apply to its design: sensitive data is never logged at default verbosity (OWASP A02 Cryptographic Failures mitigation); the Prism API client enforces TLS certificate verification by default (A02); all external inputs (plugin parameters, config file values, Prism API responses) are validated and bounded before use (A03 Injection mitigation); and the PSK-authenticated DR channel prevents unauthorised receiver impersonation (A07 Authentication Failures mitigation).


13. Monitoring

13.1 Log sources

Source Path / Command Content
Backend log /opt/bacula/working/podheitor-nutanix-backend.log All backend activity — Prism calls, iSCSI events, PHCBT01 stats, errors
FD log /opt/bacula/working/&lt;fd-host&gt;-fd.log Plugin load, PTCOMM I-packets forwarded to Director
DR receiver log (single) journalctl -u podheitor-nutanix-receiver Seed receive, bitmap-push apply, failover state transitions
DR receiver log (per-VM) journalctl -u podheitor-nutanix-receiver@vm-prod-01 Per-VM receiver activity
Bacula job log Bacula Director console / Bweb / Baculum I-packets forwarded by cdylib: backend version, phase, selected VMs, disk counts, errors

13.2 Key I-packet messages to monitor

The following I-packets are emitted at verbose=1 and appear in the Bacula job log. They are the primary operational monitoring surface:

I-packet message Meaning Action if missing
podheitor-nutanix backend up (v2.0.0) phase=F2 mode=Backup vm=… Backend started successfully Check plugin load in FD log
Prism discovery: PC=… cluster=… capability=v3|v4 Prism Central reached and API version determined Run --standalone health-check
Selected N VM(s) for backup VM glob matched N virtual machines Verify vm= pattern and Prism connectivity
Backup complete: VM=… disks=N bytes=B All disks for a VM streamed successfully Check backend log if absent
Applied PHCBT01 delta to disk-N (regions=R changed=B) Incremental CBT delta applied on restore Ensure FileSet includes v3
DR cycle complete: vm=… cycle=N bytes_pushed=B Bitmap-push cycle completed Check receiver log and network path

13.3 Prometheus / metrics integration

The backend does not expose a native Prometheus endpoint in v2.0.0. The recommended monitoring pattern uses a log-scraping exporter (e.g., mtail or grok_exporter) against the backend log. Suggested metrics to derive:

Metric name Derived from Alert threshold
nutanix_backup_bytes_total{vm,type} Backup complete: bytes=B Zero bytes = empty backup (warning)
nutanix_backup_duration_seconds{vm} Backend start / complete timestamps > 4× rolling average (anomaly)
nutanix_dr_cycle_bytes_pushed{vm} DR cycle complete: bytes_pushed=B Sustained zero = replication stalled
nutanix_dr_reconnect_total{vm} mid-push reconnect log lines > 5/hour = unstable network path
nutanix_prism_api_errors_total{endpoint} Prism API error log lines Any sustained errors
nutanix_iscsi_attach_failures_total iSCSI attach failed log lines Any = investigate DSIP / initiator

14. Troubleshooting guide

14.1 Where to look first

# Backend verbose log (most detail)
tail -100 /opt/bacula/working/podheitor-nutanix-backend.log

# Increase verbosity for active debugging
# In nutanix.conf: verbose = 2   (debug) or verbose = 3 (trace)

# Run standalone health-check
/opt/bacula/bin/podheitor-nutanix-backend 
    --standalone health-check 
    --config /opt/bacula/etc/nutanix.conf

# DR receiver status
journalctl -u podheitor-nutanix-receiver --since "1 hour ago"

14.2 Common failures and fixes

Symptom Root cause Fix
401 Unauthorized on first Prism request Service account not found in Prism IAM (may exist only in LDAP pass-through); or passfile not readable by the FD process Verify IAM user exists in Prism. Check chown root:bacula /opt/bacula/etc/nutanix.secrets &amp;&amp; chmod 0600 nutanix.secrets
403 Forbidden on snapshot create Service account missing the Backup Admin role on the cluster scope In Prism → IAM → Roles → Assignments, add Backup Admin for the cluster scope
Incremental keeps running as Full FileSet Plugin= line missing v3 key, or reference snapshot was deleted by cluster retention policy Ensure FileSet uses default (no version= key) or explicitly v3. Check backend log for reference_snapshot not found.
iSCSI attach fails: No portal available DSIP wrong or unreachable, or FD host IQN not authorised on cluster VG allowlist Pin DSIP: dsip=192.168.x.y. Add FD IQN to cluster volume-group allowlist via Prism or CHAP.
qemu-img: command not found during F5/F6 restore qemu-img not installed or not on PATH for the bacula user dnf install qemu-img (RHEL) or apt install qemu-utils (Ubuntu). Verify with sudo -u bacula which qemu-img.
DR receiver flaps in restart loop dr_auth_token mismatch between SOURCE and RECEIVER configs; state_dir not writable; port collision Confirm tokens match. Check chmod 750 /opt/bacula/working/nutanix-repl/. Run ss -tlnp | grep 9848 to detect port conflicts.
Multi-instance receiver: state crosses between VMs Two template instances sharing the same state_dir Each per-VM config must have a distinct state_dir, e.g. /opt/bacula/working/nutanix-repl/vm-prod-01/
Failover-test clone not cleaned up failover-undo not run after the DR test Run mode=failover-undo job to release the isolated VLAN clone and free state-dir disk space
TLS handshake failed on Prism connection Nutanix CE or internal cluster using self-signed certificate For lab/internal only: add prism_insecure=yes to config. For production: install a valid cert on Prism Central.
Backend exits with code 2 on startup Unknown --standalone verb or malformed Plugin= parameters Check the Plugin= line syntax against section 7. Run with verbose=3 to see the full parameter parse.

14.3 Failover state reference

Mode VM on source VM on receiver Receiver state
failover-test Untouched Boots in isolated VLAN Unchanged
failover-planned Quiesced + powered-off Powered-on Promoted; receiver becomes source-of-truth
failover-unplanned Unreachable Powered-on Promoted; receiver becomes source-of-truth
failover-undo Untouched Test clone deleted Unchanged
failover-perm (manual cleanup required) Promoted Becomes new SOURCE — re-pair to reverse

15. Use cases & deployment scenarios

15.1 Daily backup of production Nutanix VMs

An organisation running 50 production VMs on a Nutanix AHV cluster wants daily Full backups on weekends and nightly Incrementals Monday through Friday, with 30-day retention. The PodHeitor plugin is installed on a dedicated Bacula FD host with 10 GbE connectivity to the Prism DSIP. A single FileSet with vm=prod-* and concurrent_vms=4 drives the entire backup programme. The Bacula Director runs Jobs at scheduled times; incremental change rates of 5–10% per day mean weekend Full backups are the only jobs with significant storage growth. Restore testing is performed monthly using a mode=restore Job against an isolated test cluster.

15.2 Disaster recovery with continuous replication

A financial services firm requires RPO of less than 5 minutes for its 10 Tier-1 database VMs. The DR replication stack is deployed with per-VM systemd template units on a receiver host at the DR site (300 km away, connected via 100 Mbit/s MPLS). Each VM runs an independent receiver with its own state_dir, dr_port, and PSK. The push_interval=300 setting drives bitmap-push cycles every 5 minutes. Monthly failover-test drills confirm recovery capability without disrupting production.

15.3 Migration from VMware vSphere to Nutanix AHV

An enterprise migrating from a VMware vSphere environment to Nutanix AHV uses the sibling PodHeitor VMware plugin to back up vSphere VMs, then uses the Nutanix plugin’s cross_restore=yes (F6 INBOUND) path to restore converted disk images into the target AHV cluster. The --vcpu and --memory-mib overrides allow rightsizing VMs during the migration without modifying the source. This eliminates the need for a dedicated migration tool and keeps the entire workflow within the existing Bacula infrastructure.

15.4 Multi-cluster Nutanix environment

A managed service provider operates three Nutanix clusters under a single Prism Central. They use a single nutanix.conf with prism_central= pointing to PC, and separate FileSets per cluster using the cluster= parameter to scope each job to the correct cluster. Cross-cluster restore scenarios (restoring a VM from cluster A onto cluster B) use target_cluster= in the restore Job. The health-check verb is run via an Ansible playbook as part of weekly infrastructure checks.

15.5 Air-gapped environment with tape-based Bacula storage

A government agency operates an air-gapped Nutanix environment. All backups flow through a Bacula infrastructure with LTO tape storage. The PodHeitor plugin streams VM disk data through PTCOMM directly to the Bacula tape pool — no intermediate disk staging required. The max_bandwidth_mbps= parameter is used to throttle backup traffic to avoid saturating the internal network during business hours. Restores require manual tape mount, which the operator initiates via bconsole restore; the plugin handles the full reconstruct on the FD host scratch disk before uploading to AHV.


16. Comparison with other approaches

Capability PodHeitor Nutanix Plugin Bacula Enterprise (Nutanix) Veeam Data Platform Commvault Complete NetBackup
Backup engine Bacula Community 15.0.3+ Bacula Enterprise 15.x Veeam B&R Commvault Veritas NetBackup
CBT-based incrementals Yes Yes Yes Yes Yes
iSCSI block-level streaming Yes Yes Yes (HotAdd/NBD) Yes Yes
Native Prism API integration Yes (v3 + v4) Yes Partial Partial Partial
Cross-cluster restore Yes (F5) Yes Yes Yes Yes
Cross-vendor restore (qemu-img) Yes (F6 — Proxmox, vSphere, Hyper-V) Limited No No No
Built-in DR replication Yes (PSK-TCP, seed + delta + failover) Yes Yes (replication jobs) Yes Yes
Failover orchestration Yes (4 modes) Yes Yes (SureBackup) Yes Limited
Multi-cluster Prism Central Yes Yes Yes Yes Yes
Instant Recovery (F9) Roadmap (separate plugin) Yes Yes Yes Yes
File-level granular restore (F10) Roadmap (separate plugin) Yes Yes Yes Yes
Open-source backup engine Yes (Bacula Community) No (proprietary) No No No
Typical annual licensing cost Fraction of alternatives* ~US$ 10,000+/year ~US$ 5,000+/year ~US$ 10,000+/year ~US$ 10,000+/year
Plugin licence model Proprietary

Proprietary Proprietary Proprietary Proprietary

* Contact PodHeitor International for current pricing. The 50% savings claim is benchmarked against published list prices for comparable feature sets.

Note on Bacula Enterprise: Bacula Enterprise is a valid, mature alternative with a broader feature set (including Instant Recovery and granular restore in a single product). The PodHeitor plugin is positioned as a cost-effective alternative for organisations that have already invested in Bacula Community infrastructure and want a production-grade Nutanix AHV integration without the full Bacula Enterprise licensing commitment. The two solutions serve different budget and complexity profiles and are not direct competitors.


17. Roadmap

17.1 v2.x — Stability and ecosystem (H2 2026)

  • F7 — Cross-restore OUTBOUND: Enable Nutanix AHV VMs to be restored to other hypervisors (Proxmox VE, VMware vSphere, Hyper-V) through the export path, complementing the existing F6 INBOUND path.
  • F3.5 / F3.6 — v4 CRT stabilisation: Per-disk DRP capture is source-complete; live E2E validation on a v4-only cluster to confirm parser coverage against all GA AOS 7.x response shapes.
  • F4.5 — Image Service upload and VM creation: Complete the F4 restore path by wiring disk reconstruction to Prism Image Service upload and full VM materialise from the reconstructed image.
  • ARM64 build: Cross-compile target for aarch64 Linux to support organisations running Bacula FD on Arm-based infrastructure.
  • Prometheus exporter endpoint: Expose a /metrics HTTP endpoint on a configurable port for native Prometheus scraping without log-parsing glue.

17.2 v3.x — Advanced recovery (H1 2027)

  • F9 — Instant Recovery (iSCSI-target boot): This feature is deliberately owned by the parallel PodHeitor Bacula-SD granular-restore + IR plugin, which serves all VM-style backends from a single implementation. The Nutanix AHV plugin will integrate with it when the SD plugin reaches GA.
  • F10 — File-level granular restore: Same scope as F9 — provided by the Bacula-SD granular-restore plugin, which mounts reconstructed VM disks and exposes individual files via the Bacula restore browser.
  • Multi-tenant mode: Dedicated RBAC scopes per tenant within a shared Prism Central, enabling managed service provider deployments with strict data isolation.
  • Cloud-native target support: Direct DR replication to S3-compatible object storage as an alternative to a dedicated receiver host.

17.3 Ongoing

  • Tracking Nutanix AOS and Prism Central API releases; parser updates for any response schema changes in v4 endpoints
  • Continuous regression testing against Nutanix Community Edition lab environment
  • Performance optimisations for very large VMs (> 4 TiB single disk) and high-disk-count VMs (> 16 disks)

18. Conclusion

The PodHeitor Nutanix AHV Backup Plugin for Bacula represents a significant step forward for the open-source backup ecosystem. It brings production-grade Nutanix AHV protection — including CBT-based incrementals, multi-cluster support, cross-vendor restore, and a complete DR replication and failover stack — into the reach of any organisation running Bacula Community Edition, without requiring a full commercial backup platform migration or Bacula Enterprise licensing.

The plugin’s architecture — pure Rust on both sides of the metaplugin boundary, RAII-safe resource cleanup, PTCOMM subprocess isolation, and a phase-gated engineering discipline with 50+ automated tests — makes it a reliable foundation for mission-critical backup workflows. The standalone health-check verb, per-VM systemd DR templates, and structured I-packet logging give operations teams the visibility and control they need to maintain a defensible backup posture.

For organisations facing commercial backup platform renewals — particularly those evaluating Veeam, Commvault, or NetBackup for Nutanix AHV — the PodHeitor plugin offers a head-to-head alternative at 50% or more savings, with a feature set tailored specifically to the Nutanix platform rather than bolted onto a generic hypervisor abstraction layer.

We invite you to evaluate the plugin in your environment. Start with the standalone health-check, run a canary backup job, and compare restore accuracy and operational simplicity against your current solution. For a written commercial quote, feature comparison against your specific environment, or professional services engagement (installation, configuration, production go-live), contact Heitor Faria directly at the details below.

Special offer. Bring your renewal proposal for any commercial enterprise backup platform — Veeam, Commvault, NetBackup, or others. We will benchmark a head-to-head proposal targeting at least 50% savings with stronger Nutanix AHV-specific functionality. Contact heitor@opentechs.lat for a written quote.


19. Contact information

Channel Details
Name Heitor Faria — PodHeitor International
Website https://podheitor.com
Email heitor@opentechs.lat
Phone / WhatsApp (International) +1 786 726-1749
Phone / WhatsApp (Brazil) +55 61 98268-4220
Plugin documentation https://podheitor.com/plugins/nutanix-ahv
Support issues Email with subject: PodHeitor Nutanix Plugin Support

For enterprise engagements, Heitor Faria provides professional services including installation, integration with existing Bacula Directors, DR runbook design, and production go-live support. Retainer and per-incident support contracts are available.


20. Legal / copyright

© 2026 Heitor Faria — PodHeitor International. All Rights Reserved.

The PodHeitor Nutanix AHV Backup Plugin for Bacula is dual-licensed under LicenseRef-PodHeitor-Proprietary. The proprietary licence governs all commercial use and redistribution. Contact heitor@opentechs.lat for commercial licensing terms.

Trademarks: PodHeitor and the PodHeitor logo are trademarks of Heitor Faria / PodHeitor International. Nutanix, AHV, Prism, Prism Central, Prism Element, AOS, and Nutanix Community Edition are registered trademarks or trademarks of Nutanix, Inc. Bacula and Bacula Enterprise are trademarks of Bacula Systems SA. Veeam is a trademark of Veeam Software AG. Commvault is a trademark of Commvault Systems, Inc. NetBackup and Veritas are trademarks of Veritas Technologies LLC. VMware and vSphere are trademarks of VMware, Inc. (a Broadcom company). Proxmox VE is a registered trademark of Proxmox Server Solutions GmbH. Microsoft and Hyper-V are trademarks of Microsoft Corporation. All other trademarks are property of their respective owners.

Disclaimer: This document is provided for informational purposes. Performance figures and cost comparisons are based on lab testing and publicly available list prices at the time of publication and may vary by environment, configuration, and vendor pricing changes. PodHeitor International makes no warranty, express or implied, regarding the accuracy of third-party product information contained herein.

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

Leave a Reply