Plugin SD-side que intercepta dados de backup em tempo real e os replica para filesystem local ou montado em rede — arquivos imediatamente disponíveis para instant recovery, sem job de restore tradicional. Mirror, retenção versionada, multi-site fan-out, BLAKE3 skip-unchanged, AES-256-GCM at rest, RPO/RTO compliance reporting.
Documento técnico complementar à página do plugin PodHeitor BRC.
1. O problema: instant recovery exige restore
Em Bacula Community puro, o caminho para tornar um arquivo recuperado disponível em DR site exige (a) executar um job de backup, (b) replicar o volume Bacula para outro SD, (c) executar um job de restore. Tempo total: minutos a horas, dependendo de tamanho. Para SLAs de DR sub-minuto, isso é impraticável.
O PodHeitor BRC inverte: arquivos são replicados durante o backup, não depois. O SD plugin intercepta o stream de dados antes de gravar no volume e fork-a uma cópia para um filesystem destino — local, NFS, SMB, ou disco DR. Resultado: o arquivo está disponível para uso imediato no destino, e o backup Bacula tradicional continua para retenção long-term.
2. Arquitetura — 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 carregado pelobacula-sd. Implementa o Bacula SD Plugin API v13 binary contract em clean-room Rust. Nenhum source ou header do Bacula é copiado ou linkado.podheitor-replica-sd-backend— binário standalone que lê blocos de volume do FIFO configurado, parseia records Bacula, e dirige toda a lógica de replicação / retenção / encryption / dashboard.- Config —
/opt/bacula/etc/podheitor-replica.conf(key=value)
Ambos os componentes são 100% Rust. Build do package exige apenas cargo — sem compilador C, sem source tree do Bacula.
3. Três pilares — B · R · C
| Pilar | Capacidade |
|---|---|
| B — Backup | Full / Incremental / Differential nativos. Fidelidade de metadados (ACL, xattr, sparse, ownership, timestamps). Modo FIFO zero-volume. |
| R — Replication | Modos mirror e retenção. 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 replicação
| Mode | Comportamento | Caso de uso |
|---|---|---|
mirror |
Réplica 1:1 do dataset; delete_removed=yes remove órfãos no Full |
Warm DR site, dev/test refresh |
retention |
Versões históricas por arquivo, controlado por retention_versions=N |
Compliance, audit trail, time-travel |
5. BLAKE3 skip-unchanged
Com skip_unchanged=yes, o backend computa BLAKE3 do arquivo no destino antes de escrever. Se o hash bate, a write é skipada — o destination filesystem não recebe I/O desnecessário.
- BLAKE3 escolhido por throughput: ~6 GB/s/core em x86_64 com AVX-512, vs ~1 GB/s do SHA-256.
- Crítico em mirror para datasets grandes onde a maioria dos arquivos não mudou.
- Pareie com
verify_after=yespara verificação BLAKE3 pós-replicação (cross-check).
6. FIFO mode — zero local I/O overhead
Com fifo_path= apontando para um named pipe, o backend lê blocos de volume diretamente do FIFO em vez de espelhar via filesystem local. Resultado: zero overhead de I/O local no SD host — os bytes vão do socket FD diretamente para o destino de replicação, sem pousar em disco.
Use case: SD com pouco I/O budget (bound em IOPS de ingest), replicando para SAN destino. O FIFO mode evita o round-trip “grava no volume → lê do volume → escreve no destino”.
7. Multi-site fan-out
O parâmetro targets aceita múltiplos destinos separados por ;, com per-target options:
targets = /mnt/dr-site-a;/mnt/dr-site-b:bwlimit=1M;/mnt/dr-site-c:bwlimit=500K
Cada target roda em sua própria task tokio; bandwidth limits são per-target. Falha em um site não bloqueia os outros — relatado em job log e métricas.
8. Encryption at rest — AES-256-GCM
Com encrypt_key= setado para uma chave 64-char hex (256 bits), o backend criptografa cada arquivo com AES-256-GCM antes de gravar no destino. Nonce é derivado do path + timestamp; tag de autenticação é appended. Ataque de tampering é detectado na restauração.
Importante: a chave fica no podheitor-replica.conf (mode 0600). Para produção, integre com KMS via encrypt_key_cmd= (out-of-band lookup).
9. RPO/RTO compliance reporting
Com rpo_report_dir= setado, o backend gera relatórios JSON + Markdown a cada job:
| Métrica | Cálculo |
|---|---|
| RPO observado | now() - last_successful_replication por arquivo |
| RPO SLA | sla_rpo_secs (default 14400 = 4h) |
| RTO estimado | Tamanho do dataset / banda destino + overhead de mount/check |
| RTO SLA | sla_rto_secs (default 3600 = 1h) |
| SLA breach | Lista de arquivos que excederam RPO/RTO target |
Output Markdown é direto consumível em audit reports; JSON alimenta dashboards Grafana ou Bacularis.
10. Snapshot integration — pre-replication
Com snapshot_backend=lvm|zfs|btrfs, o backend tira um snapshot do filesystem destino antes de iniciar a replicação. Se o job falhar mid-write, rollback restaura o 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 operacionais via healthcheck_cmd, promote_cmd, demote_cmd:
healthcheck_cmd— exit 0 = primary saudável; backend continua replicando.promote_cmd— invocado quando healthcheck falha N vezes; promove réplica a primary (mount, IP takeover, DNS update).demote_cmd— invocado em failback; demove primary anterior.
12. Anti-patterns documentados
- Não use
delete_removed=yessem snapshot backend. Em modo mirror, um Full job mal-executado pode deletar arquivos genuínos. Snapshot LVM/ZFS é o net. - Não rode FIFO mode sem dimensionar o pipe. O Linux default de 64 KB pode ser bottleneck — use
fcntl F_SETPIPE_SZou aumente/proc/sys/fs/pipe-max-size. - Não confie em
skip_unchanged=yesisoladamente para integrity. BLAKE3 colisão é teoricamente possível (mesmo que astronomicamente improvável); pareie comverify_after=yesem datasets críticos. - Não rode encrypt sem KMS em produção. Chave em arquivo de config é PoC-grade.
13. License posture
O plugin distribui sob LicenseRef-PodHeitor-Proprietary. Não vincula estaticamente nenhum source AGPLv3 do Bacula. A SD Plugin API v13 é reimplementada em clean-room Rust — apenas o binary contract de função-pointer é honrado, sem header copy.
Pronto para avaliar?
Trial gratuito de 30 dias para workloads de DR e instant recovery. Garantimos no mínimo 50% de desconto vs Bacula Enterprise, Veeam ou Commvault, com mais funcionalidades inclusas.
Heitor Faria — Fundador, PodHeitor International
✉ [email protected]
☎ +1 (789) 726-1749 · +55 (61) 98268-4220 (WhatsApp)
🔗 Página do plugin PodHeitor BRC
Disponível em:
Português
English (Inglês)
Español (Espanhol)