Technical whitepaper — PodHeitor OracleDB for Bacula

Five backup modes (dump / rman / rman_sbt / cdp / replicate), pure-Rust libobk-rs.so SBT v2, Oracle 11g R2 → 23ai, anti-ransomware canary, and Bacularis-driven restore with no SSH on the Oracle host.

Technical companion to the PodHeitor OracleDB plugin page.

1. The problem: Bacula Enterprise’s Oracle plugin is Perl wrapped around RMAN

The Bacula Enterprise 18.2.3 Oracle plugin is Perl + shell + a proprietary C libobk.so, with restore driven by bs_oracle_restore.pl over SSH + a shell menu on the Oracle host. That brings three problems:

  • SSH on the Oracle host for every restore — adds attack surface, requires out-of-band operational access from Bacula, and breaks the audit trail.
  • No native DR replication — DR via Bacula Enterprise requires a separate license (Active Data Guard).
  • No CDP, no anti-ransomware, no Prometheus — modern features absent.

The PodHeitor OracleDB Plugin delivers five native modes, Bacula-driven restore (RestoreObject + pluginrestoreconf), pure-Rust libobk-rs.so, and Oracle 11g R2 → 23ai coverage.

2. Architectural model

The FD plugin loader is a pure-Rust cdylib (no Bacula AGPLv3 source statically linked); the backup engine and the libobk-rs SBT v2 runtime ship as PodHeitor-Proprietary Rust binaries.

bacula-fd → podheitor-oracle-fd.so (Rust cdylib)
              │ PTCOMM
              ▼
            podheitor-oracle-backend (Rust)
              ├─ Oracle Data Pump (expdp / legacy 11g exp)
              ├─ RMAN driver (zero-staging FIFO + multi-channel)
              ├─ libobk-rs.so SBT v2 (RMAN writes straight to Bacula)
              ├─ CDP daemon (continuous archivelog shipping)
              ├─ Replicate driver (DUPLICATE FROM ACTIVE DATABASE / archivelog-apply)
              ├─ TDE wallet handler + ASM topology probe
              └─ Anti-ransomware canary sampler

v1.1.0 removed the legacy C++ shim. The FD plugin loader is built from the plugin-oracle crate in the PodHeitor Rust cdylib workspace and ships as a pure-Rust cdylib. No Bacula AGPLv3 source is statically linked. The PluginInfo string "Bacula AGPLv3" is retained purely as an ABI compatibility token expected by bacula-fd‘s plugin-license gate.

3. Five backup modes

Mode Function
mode=dump Oracle Data Pump (expdp) on 12c+, legacy exp on 11g. Schema, tablespace or full database.
mode=rman RMAN to local staging, then streamed to Bacula SD. Zero-staging FIFO option.
mode=rman_sbt RMAN writes directly to Bacula via libobk-rs.so SBT v2 — no local staging.
mode=cdp Continuous archivelog shipping daemon with RPO tracking and Prometheus metrics.
mode=replicate DR replication via RMAN DUPLICATE FROM ACTIVE DATABASE (EE) or archivelog-apply (SE2).

4. libobk-rs.so — pure-Rust SBT v2

Oracle SBT (System Backup to Tape) is the official interface through which RMAN writes to an external “media manager.” Traditionally that’s a C libobk.so shipped by the backup vendor. PodHeitor rewrites it in Rust:

sudo ln -sf /opt/bacula/lib/libobk-rs.so "$ORACLE_HOME/lib/libobk.so"

From there on, any RMAN command of the form BACKUP DATABASE PLUS ARCHIVELOG; with device type sbt writes directly into the PodHeitor backend via PTCOMM socket, which writes straight to the Bacula SD through the FD — no intermediate disk, no custom scripting. Multi-channel RMAN (ALLOCATE CHANNEL c1, c2, c3 ...) maps to a multi-producer mpsc in the backend.

5. Bacula-driven restore (the differentiator)

Traditional Bacula Enterprise + Oracle restore requires SSH on the Oracle host and use of the bs_oracle_restore.pl menu. PodHeitor does it all via RestoreObject (Bacularis form) + pluginrestoreconf in bconsole:

* restore client=oracle-fd
… (select jobs, mark, done) …
Plugin Restore Options:
  action          = pitr
  target_time     = 2026-04-25_15:30:00
  preview_first   = yes
  verify_after    = yes
* yes

No SSH to the Oracle host. No shell menu. No bs_oracle_restore.pl. Full audit trail in the Bacula catalog.

6. Advanced features

Feature Bacula Enterprise Oracle 18.2.3 PodHeitor v1.1.0
Language Perl + shell + C libobk.so Pure Rust (cdylib + musl static-pie)
Oracle versions 11g R2 → 21c 11g R2 → 23ai
libobk implementation Proprietary, bconsole callback libobk-rs.so Rust cdylib
Backup modes dump, rman, rman_sbt dump, rman, rman_sbt, cdp, replicate
Restore automation bs_oracle_restore.pl (SSH + menu) RestoreObject / pluginrestoreconf
Native DR replication ❌ (separate license) mode=replicate
CDP / continuous archivelog mode=cdp daemon
Anti-ransomware canary ✅ block-hash mass-change detector
Prometheus observability /metrics HTTP endpoint
cgroups v2 I/O throttle
SBOM + CVE audit make audit + make sbom

7. Anti-ransomware canary

The canary=on flag enables a sampler that computes hashes of sample blocks during backup. When %-changed between runs spikes abruptly above the baseline (typical of ransomware encryption), the plugin emits a PODHEITOR-ORACLE-AUDIT warning to the job log and (if configured) aborts the backup — protecting the backup window from being used to overwrite the last good backup.

8. Live validation (Phase F1 → F20)

Phase What was validated Result
F1 Topology discovery (version, CDB/PDB, DG role, RAC detection) 7/7 checks
F2 Data Pump expdp — PHTEST schema 416 KB 1m27s
F3 RMAN non-SBT 2-channel — 9 pieces / 451 MB 43 s
F4 RMAN SBT via libobk-rs — PTCOMM socket + multi-channel mpsc live
F5 BCT auto-enable + SCN chain validation live
F6 RESTORE PREVIEW 4 s, SCN 2090220–2090264 live
F8 Data Guard role gate (prefer_standby=no proceeds, =yes skips) live
F10 VALIDATE DATABASE 16.8 s zero corrupt; DBVERIFY 131k pages 0 fail live
F11 CDP daemon + Prometheus /metrics + cgroups v2 throttle live
F12 archivelog_apply T1 PASS; duplicate_active T2 PASS live (partial)
F13 Canary sampler + PODHEITOR-ORACLE-AUDIT in job log live
F14 RPM install on OL9.6, full backup job 4989 — T OK 26m10s live
F16–F18 bacula-fd integration, full restore PITR (job 4956: 477 MB / 19 s) live
F20 cargo audit 0 CVEs; cargo deny all-pass; DEB 568 KB + SHA256SUMS OK

Environment: Oracle 23ai FREE, VM oracle-23ai-lab, Bacula FD 15.0.3, 523 cargo tests green.

9. Minimum configuration

# /opt/bacula/etc/podheitor-oracle.conf
sid          = ORCL
mode         = rman_sbt
oracle_home  = /u01/app/oracle/product/19c/dbhome_1
oracle_user  = oracle
auth         = os
channels     = auto
compress     = zstd:3
bct          = auto
archivelog   = include
# Symlink libobk-rs into Oracle home (rman_sbt mode only)
sudo ln -sf /opt/bacula/lib/libobk-rs.so "$ORACLE_HOME/lib/libobk.so"

# Offline validation
/opt/bacula/bin/podheitor-oracle-backend --dry-run /opt/bacula/etc/podheitor-oracle.conf

# Reload FD
sudo systemctl restart bacula-fd

10. Known limitations (v1.1.0)

Item Status Reason
F8.b RAC 2-node per-node parallel Code complete, no live test Requires Oracle Grid Infrastructure + EE RAC
F12.b managed standby apply_loop Code complete, no live test Requires Oracle EE or SE + DG option
F19 Oracle 11g XE live test Deferred Oracle XE 11.2 EOL (2020-12-31); requires manual OTN binary
Windows FD Not planned Linux only

11. License posture

Single-licensed under PodHeitor-Proprietary (SPDX: LicenseRef-PodHeitor-Proprietary). All shipped components (FD cdylib, Rust backend, libobk-rs) are 100% original PodHeitor implementations. No Bacula AGPLv3 source is statically linked in any artifact in this package, and no Bacula Enterprise source has been used or reverse-engineered.

Ready to evaluate?

30-day free trial for production Oracle DB fleets (11g R2 → 23ai). Guaranteed at minimum 50% discount vs Bacula Enterprise, Veeam or Commvault, with more capabilities included (CDP, native replication, anti-ransomware canary).

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

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

Leave a Reply