Plugin SD-side que intercepta datos de backup en tiempo real y los replica a filesystem local o montado en red — archivos disponibles inmediatamente para instant recovery, sin job de restore tradicional. Mirror, retención versionada, multi-site fan-out, BLAKE3 skip-unchanged, AES-256-GCM at rest, RPO/RTO compliance reporting.
Documento técnico complementario a la página del plugin PodHeitor BRC.
1. El problema: instant recovery exige restore
En Bacula Community puro, el camino para que un archivo respaldado quede disponible en sitio DR exige (a) ejecutar un job de backup, (b) replicar el volumen Bacula a otro SD, (c) ejecutar un job de restore. Tiempo total: minutos a horas según el tamaño. Para SLAs de DR sub-minuto, eso es impracticable.
PodHeitor BRC invierte: los archivos se replican durante el backup, no después. El SD plugin intercepta el stream de datos antes del write al volumen y forkea una copia hacia un filesystem destino — local, NFS, SMB, o disco DR. Resultado: el archivo está disponible para uso inmediato en el destino, mientras el backup Bacula tradicional continúa para retención long-term.
2. Arquitectura — cdylib SD + Rust backend
┌──────────┐ ┌──────────────┐ ┌──────────────────┐ ┌───────────────┐
│ File │───▶│ Storage │───▶│ Rust cdylib │───▶│ Rust Backend │
│ Daemon │ │ Daemon │ │ (SD Plugin v13) │ │ (binary) │
└──────────┘ └──────────────┘ └──────────────────┘ └───────┬───────┘
│
┌─────────────────────┼──────────┐
▼ ▼ ▼
┌──────────────┐ ┌─────────────┐ ┌──────────┐
│ File Writer │ │ RPO/RTO │ │Dashboard │
│ (target FS) │ │ Reports │ │ JSON │
└──────────────┘ └─────────────┘ └──────────┘
podheitor-replica-sd.so— cdylib Rust puro cargado porbacula-sd. Implementa el Bacula SD Plugin API v13 binary contract en clean-room Rust. Ningún source o header de Bacula es copiado o linkeado.podheitor-replica-sd-backend— binario standalone que lee bloques de volumen del FIFO configurado, parsea records Bacula, y dirige toda la lógica de replicación / retención / encryption / dashboard.- Config —
/opt/bacula/etc/podheitor-replica.conf(key=value)
Ambos componentes son 100% Rust. Build del package exige solo cargo — sin compilador C, sin source tree de Bacula.
3. Tres pilares — B · R · C
| Pilar | Capacidad |
|---|---|
| B — Backup | Full / Incremental / Differential nativos. Fidelidad de metadatos (ACL, xattr, sparse, ownership, timestamps). Modo FIFO zero-volume. |
| R — Replication | Modos mirror y retención. Multi-site fan-out. BLAKE3 skip-unchanged. Bandwidth throttling. Consistency groups. Failover automation. |
| C — Conversion | Stream decompression (zlib/LZ4). Encryption AES-256-GCM at rest. RPO/RTO compliance reporting (JSON + Markdown). |
4. Modos de replicación
| Mode | Comportamiento | Caso de uso |
|---|---|---|
mirror |
Réplica 1:1 del dataset; delete_removed=yes remueve huérfanos en Full |
Warm DR site, dev/test refresh |
retention |
Versiones históricas por archivo, controlado por retention_versions=N |
Compliance, audit trail, time-travel |
5. BLAKE3 skip-unchanged
Con skip_unchanged=yes, el backend computa BLAKE3 del archivo destino antes de escribir. Si el hash coincide, el write se skipea — el filesystem destino no recibe I/O innecesario.
- BLAKE3 elegido por throughput: ~6 GB/s/core en x86_64 con AVX-512, vs ~1 GB/s de SHA-256.
- Crítico en mirror para datasets grandes donde la mayoría de archivos no cambian.
- Combine con
verify_after=yespara verificación BLAKE3 post-replicación (cross-check).
6. FIFO mode — zero local I/O overhead
Con fifo_path= apuntando a un named pipe, el backend lee bloques de volumen directamente del FIFO en vez de espejar vía filesystem local. Resultado: cero overhead de I/O local en el SD host — los bytes van del socket FD directamente al destino de replicación, sin tocar disco.
Use case: SD con poco I/O budget (bound en IOPS de ingest), replicando a SAN destino. El FIFO mode evita el round-trip «graba al volumen → lee del volumen → escribe al destino».
7. Multi-site fan-out
El parámetro targets acepta múltiples destinos separados por ;, con per-target options:
targets = /mnt/dr-site-a;/mnt/dr-site-b:bwlimit=1M;/mnt/dr-site-c:bwlimit=500K
Cada target corre en su propia task tokio; los bandwidth limits son per-target. Falla en un sitio no bloquea los otros — reportado en job log y métricas.
8. Encryption at rest — AES-256-GCM
Con encrypt_key= seteado a una clave 64-char hex (256 bits), el backend cifra cada archivo con AES-256-GCM antes de grabar al destino. Nonce se deriva de path + timestamp; tag de autenticación es appended. Ataques de tampering se detectan en el restore.
Importante: la clave queda en podheitor-replica.conf (mode 0600). Para producción, integre con KMS vía encrypt_key_cmd= (out-of-band lookup).
9. RPO/RTO compliance reporting
Con rpo_report_dir= seteado, el backend emite reportes JSON + Markdown por job:
| Métrica | Cómputo |
|---|---|
| RPO observado | now() - last_successful_replication por archivo |
| RPO SLA | sla_rpo_secs (default 14400 = 4h) |
| RTO estimado | Tamaño del dataset / banda destino + overhead de mount/check |
| RTO SLA | sla_rto_secs (default 3600 = 1h) |
| SLA breach | Archivos que excedieron el RPO/RTO target |
Output Markdown es directamente consumible en audit reports; JSON alimenta dashboards Grafana o Bacularis.
10. Snapshot integration — pre-replication
Con snapshot_backend=lvm|zfs|btrfs, el backend toma snapshot del filesystem destino antes de iniciar la replicación. Si el job falla mid-write, el rollback restaura el estado consistente.
lvm—lvcreate --snapshot --name podheitor-pre-{jobid}zfs—zfs snapshot pool/dataset@podheitor-pre-{jobid}btrfs—btrfs subvolume snapshot
11. Failover automation
Hooks operacionales vía healthcheck_cmd, promote_cmd, demote_cmd:
healthcheck_cmd— exit 0 = primary saludable; el backend continúa replicando.promote_cmd— invocado cuando healthcheck falla N veces; promueve réplica a primary (mount, IP takeover, DNS update).demote_cmd— invocado en failback; demueve el primary anterior.
12. Anti-patterns documentados
- No use
delete_removed=yessin snapshot backend. En modo mirror, un Full mal-ejecutado puede borrar archivos genuinos. Snapshot LVM/ZFS es la red de seguridad. - No corra FIFO mode sin dimensionar el pipe. El default Linux de 64 KB puede ser bottleneck — use
fcntl F_SETPIPE_SZo aumente/proc/sys/fs/pipe-max-size. - No confíe en
skip_unchanged=yesaislado para integrity. Colisión BLAKE3 es teóricamente posible (astronómicamente improbable); combine converify_after=yesen datasets críticos. - No corra encryption sin KMS en producción. Clave en archivo de config es PoC-grade.
13. License posture
El plugin se distribuye bajo LicenseRef-PodHeitor-Proprietary. No vincula estáticamente ningún source AGPLv3 de Bacula. La SD Plugin API v13 está reimplementada en clean-room Rust — solo el binary contract de function-pointer es honrado, sin copia de header.
¿Listo para evaluar?
Trial gratuito de 30 días para workloads de DR e instant recovery. Garantizamos al menos 50% de descuento vs Bacula Enterprise, Veeam o Commvault, con más funcionalidades incluidas.
Heitor Faria — Fundador, PodHeitor International
✉ [email protected]
☎ +1 (789) 726-1749 · +55 (61) 98268-4220 (WhatsApp)
🔗 Página del plugin PodHeitor BRC
Disponível em:
Português (Portugués, Brasil)
English (Inglés)
Español