Respaldo PostgreSQL con PITR al segundo. pg_basebackup nativo + archivado WAL continuo, sin ventana de mantenimiento, restauración punto-en-tiempo sub-minuto.
- Base backup en caliente vía pg_basebackup — sin bloquear escritura.
- WAL archiving continuo — RPO cerca de cero, recovery al segundo exacto.
- Compatible 9.6 → 16+ — un plugin para todas las versiones en producción.
- Integración streaming replication — respaldo desde standby, cero overhead en primario.
- Validación automática — pg_verifybackup post-job, alerta de drift.
Producción en 30 días, al menos 50% más barato. Trial gratuito, RPMs y DEBs firmados, soporte directo con Heitor Faria. Reemplace su licencia Veeam, Commvault o Bacula Enterprise sin romper la ventana nocturna.
Solicitar trial gratuito de 30 días →
💰 Oferta Comercial Especial
«Traga sua proposta de contratação ou renovação do Bacula Enterprise, Veeam, Commvault ou Netbackup. Damos no mínimo 50% de desconto, com muito mais funcionalidades.»
«Tráiganos su propuesta de contrato o renovación de Bacula Enterprise, Veeam, Commvault o Netbackup. Ofrecemos al menos un 50 % de descuento — y significativamente más funcionalidades.»
Contacto — Heitor Faria 📧 heitor@opentechs.lat 📞 +1 (786) 726-1749 💬 +55 (61) 98268-4220 (WhatsApp)
Índice
- Resumen Ejecutivo
- Por Qué Existe Este Plugin
- Casos de Uso
- Descripción General de la Arquitectura
- Comparativa de Funcionalidades vs. Alternativas Comerciales
- Requisitos del Sistema y Compatibilidad
- Dimensionamiento Recomendado
- Procedimiento de Instalación
- Manual de Configuración
- Parámetros de Backup — Referencia Completa
- Parámetros de Restauración — Referencia Completa
- Ejemplos de FileSet y Job
- Captura de Replicación y Failover
- Flujo de Restauración Automatizada
- Prueba de Funcionalidad — Capturas y Registros Reales
- Seguridad y Firma
- Licenciamiento
- Soporte y Contratación Comercial
1. Resumen Ejecutivo
PodHeitor PostgreSQL Backup and Replication Plugin for Bacula es un metaplugin de nivel productivo que convierte PodHeitor Backup Edition (gratuito, código abierto) en una plataforma completa de protección de datos PostgreSQL que iguala o supera el conjunto de funcionalidades de los productos comerciales de backup premium — a una fracción de su costo total de propiedad.
Cubre la brecha más importante en el stack Bacula de código abierto: integración nativa con PostgreSQL, con soporte a metaplugin, incluyendo incremental a nivel de bloque, Point-In-Time Recovery (PITR), Protección Continua de Datos (CDP), y captura de topología de replicación — funcionalidades que, hasta ahora, requerían licenciamiento propietario de Bacula Enterprise o herramientas pesadas de terceros como Veeam, Commvault o Veritas NetBackup.
Principales Diferenciadores
| Capacidad | PodHeitor (este plugin) | Bacula Enterprise | Veeam / Commvault / NB |
|---|---|---|---|
| Funciona en Bacula Community | ✅ | ❌ (solo enterprise) | N/A |
| PITR (basado en WAL) | ✅ | ✅ | ✅ |
Incremental a nivel de bloque (PG 17 pg_combinebackup) |
✅ | ⚠️ parcial | ❌ |
| Captura de topología de replicación + recreación automática | ✅ | ❌ | ❌ |
| Backup solo desde standby (descarga del primario) | ✅ | ✅ | ⚠️ |
| Modo de Protección Continua de Datos (CDP) | ✅ | ❌ | ⚠️ |
| Binarios completamente firmados (GPG RSA-4096) | ✅ | ✅ | ✅ |
| Restauración automatizada con un solo comando | ✅ | ❌ | ⚠️ |
| Costo de licenciamiento (por FD / por TB) | US$ 0 – tarifa plana baja | US$ $$$ | US$ $$$$ |
Cifras Clave
- 5 modos de backup:
dump,parallel_dump,pitr,pitr_block,cdp - 115 pruebas unitarias + validación E2E contra un clúster real de PostgreSQL 17
- Probado en: PostgreSQL 12 → 17, CentOS 7 → RHEL 9, Debian 11/12, Oracle Linux 9.6
- Línea base glibc-2.17 — un único binario RPM que funciona en todos
los Linux empresariales convencionales desde 2014
- Releases con doble firma: clave RSA-4096
E8E2744FF20A4E2408920E33104B2B720DC8DBEF
2. Por Qué Existe Este Plugin
PodHeitor Backup Edition es el sistema de backup empresarial de código abierto más ampliamente implementado en el mundo. Protege Linux, Windows, VMs, almacenamiento en objetos, cintas — todo, excepto bases de datos, de forma nativa.
La arquitectura oficial de metaplugin existe en Community Edition, pero las integraciones con bases de datos se incluyen únicamente con la suscripción de pago de Bacula Enterprise. Esto obliga a los usuarios de código abierto a elegir entre tres caminos insatisfactorios:
- Pagar por Bacula Enterprise — comienza en decenas de miles
de US$ al año para un entorno de tamaño mediano.
- Desarrollar su propia solución — scripts frágiles, sin PITR,
sin modo Accurate, sin streaming desde el File Daemon.
- Adoptar una segunda herramienta (Veeam, Commvault, NetBackup) — infraestructura
duplicada, licenciamiento duplicado, carga operativa duplicada.
PodHeitor cierra esta brecha. Es un metaplugin desarrollado desde cero que se integra de forma nativa con la arquitectura de metaplugin del PodHeitor Backup, de modo que todas las funcionalidades de PodHeitor Backup — modo Accurate, programación Differential/Incremental, cifrado, deduplicación, bibliotecas de cinta, almacenamiento en nube — funcionan sin modificaciones.
3. Casos de Uso
3.1 Base de datos única — PYME / mercado intermedio
«Ya usamos PodHeitor Backup para nuestros archivos y VMs. Necesitamos backups de PostgreSQL con PITR. No queremos pagar por Bacula Enterprise.»
→ Instale el RPM/DEB, agregue una línea Plugin a su FileSet y programe. Listo en 15 minutos. Sin infraestructura duplicada.
3.2 Gran entorno PostgreSQL con streaming replication
«Tenemos 20 clústeres PostgreSQL, cada uno con 1–3 standbys. Necesitamos incremental a nivel de bloque y necesitamos reconstruir la topología de replicación tras una restauración de DR.»
→ Modo pitr_block + track_replication_state = true. El plugin captura pg_replication_slots, pg_subscription, y el standby_signal / postgresql.auto.conf de cada standby. En la restauración, regenera los archivos SQL y de configuración para que la topología quede intacta.
3.3 Sectores regulados (finanzas, salud, gobierno)
«Necesitamos PITR al segundo, cadena de custodia auditable en los medios de backup y binarios firmados.»
→ El modo PITR escribe segmentos WAL en volúmenes administrados por Bacula con integridad criptográfica (firma de bloque SHA-256 nativa de Bacula). Los binarios del plugin están firmados con GPG mediante una clave RSA de 4.096 bits publicada en una URL conocida.
3.4 Canje de renovación — escenario comercial
«Nuestra renovación de Bacula Enterprise / Veeam / Commvault / NetBackup llegó a seis cifras. ¿Qué pueden ofrecernos?»
→ Vea el aviso al inicio de este documento. Al menos un 50 % de descuento, con más funcionalidades. Tráiganos la propuesta.
4. Descripción General de la Arquitectura
┌──────────────┐ ┌──────────────┐ ┌───────────────┐
│ Director │────────▶│ File Daemon │◀───────▶│ Storage Daemon│
│ (bacula-dir) │ jobs │ (bacula-fd) │ data │ (bacula-sd) │
└──────────────┘ └──────┬───────┘ └───────────────┘
│
│ metaplugin API (C/C++)
▼
┌──────────────────────────────┐
│ podheitor-postgresql-fd.so │ Proprietary
│ (plugin bridge) │
└──────────────┬───────────────┘
│ fork + pipes (stdin/stdout)
│ binary framed protocol
▼
┌──────────────────────────────┐
│ podheitor-postgresql-backend │ Proprietary (Rust)
│ - backup orchestrator │
│ - psql session manager │
│ - WAL / block-level logic │
│ - replication capture │
└──────────────┬───────────────┘
│ libpq / psql
▼
┌──────────────────┐
│ PostgreSQL │
│ 12 / 13 / 14 / │
│ 15 / 16 / 17 │
└──────────────────┘
División de Componentes
| Componente | Lenguaje | Licencia | Función |
|---|---|---|---|
podheitor-postgresql-fd.so |
Rust | PodHeitor-Proprietary | Plugin loader del Bacula FD — traduce callbacks a llamadas del backend |
podheitor-postgresql-backend |
Rust | Propietaria | Toda la lógica PostgreSQL: backup, restauración, replicación, WAL, PITR |
podheitor-postgresql.conf |
texto | N/A | Conexión, rol, credenciales, opciones |
La división es deliberada: el adaptador C con licencia GPL es mínimo y abierto; la propiedad intelectual reside en el backend Rust propietario como un subproceso completamente aislado que se comunica únicamente a través de un protocolo binario documentado.
5. Comparativa de Funcionalidades vs. Alternativas Comerciales
| Funcionalidad | PodHeitor v1.3 | Bacula Enterprise 18 | Veeam B&R 12 | Commvault 11 | Veritas NetBackup 10 |
|---|---|---|---|---|---|
| Funciona en PodHeitor Backup (gratuito) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Integración nativa como metaplugin de Bacula | ✅ | ✅ | N/A | N/A | N/A |
DUMP (pg_dump) |
✅ | ✅ | ✅ | ✅ | ✅ |
DUMP paralelo (-j) |
✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
| PITR — completo/diferencial/incremental | ✅ | ✅ | ✅ | ✅ | ✅ |
| Incremental a nivel de bloque (PG 17) | ✅ | ⚠️ | ❌ | ❌ | ❌ |
| Modo CDP | ✅ | ❌ | ⚠️ | ⚠️ | ❌ |
| Backup solo desde standby | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
| Captura de topología de replicación | ✅ | ❌ | ❌ | ❌ | ❌ |
| Restauración automatizada en 6 fases | ✅ | ❌ | ⚠️ | ✅ | ⚠️ |
| Compatible con el modo Accurate de Bacula | ✅ | ✅ | N/A | N/A | N/A |
| Binarios firmados con GPG | ✅ | ✅ | ✅ | ✅ | ✅ |
| Costo: 1 FD + 500 GB PG (lista, 1 año) | negociado — hasta un 50 % de descuento sobre su propuesta | ~US$ 15.000 | ~US$ 12.000 | ~US$ 20.000 | ~US$ 18.000 |
Leyenda: ✅ soporte nativo completo | ⚠️ parcial/mediante script/licenciamiento adicional | ❌ no soportado
6. Requisitos del Sistema y Compatibilidad
Versiones soportadas de PostgreSQL
| Versión | DUMP | DUMP Paralelo | PITR | PITR_BLOCK | CDP | Captura de replicación |
|---|---|---|---|---|---|---|
| 12 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 13 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 14 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 15 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 16 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 17 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
pitr_block requiere la utilidad pg_combinebackup de PostgreSQL 17; los demás modos funcionan desde PG 12 en adelante.
Versiones soportadas de Bacula
| Distribución Bacula | Versión mínima | Probado |
|---|---|---|
| Bacula Community (upstream, gratuito) | 15.0.0 | 15.0.3 |
| Bacula Enterprise | 18.0.0 | 18.0.x |
| Bacula Community (LTS anterior) | 13.0.x | caso a caso, contáctenos |
Distribuciones Linux soportadas (para el host del plugin / File Daemon)
| Distribución | Paquete | glibc | Probado |
|---|---|---|---|
| RHEL 7 / CentOS 7 | .el7.x86_64.rpm |
2.17 | ✅ |
| RHEL 8 / Rocky 8 / Alma 8 | .el9.x86_64.rpm |
2.28 | ✅ |
| RHEL 9 / Oracle Linux 9 / Rocky 9 / Alma 9 | .el9.x86_64.rpm |
2.34 | ✅ |
| Debian 11 (Bullseye) | _amd64.deb |
2.31 | ✅ |
| Debian 12 (Bookworm) | _amd64.deb |
2.36 | ✅ |
| Ubuntu 20.04 LTS | _amd64.deb |
2.31 | ✅ |
| Ubuntu 22.04 LTS | _amd64.deb |
2.35 | ✅ |
| Ubuntu 24.04 LTS | _amd64.deb |
2.39 | ✅ |
Cualquier glibc ≥ 2.17 (sin .deb/.rpm) |
*.musl.tar.gz |
estático | ✅ |
Arquitectura: solo x86_64 en v1.3. ARM64 está en el roadmap de v2.0.
Otros requisitos
| Requisito | Detalle |
|---|---|
postgresql-client ≥ 14 |
psql, pg_dump, pg_restore, pg_basebackup, pg_combinebackup (PG 17) en el host del plugin |
| Conectividad de red | Host del plugin → PostgreSQL (TCP, puerto 5432 por defecto) + File Daemon ↔ Storage Daemon |
| Credenciales | Un rol PG con REPLICATION, pg_read_all_data y (para captura de replicación) pg_read_all_settings |
| Disco (host del plugin, almacenamiento temporal) | 1× tamaño del mayor clúster de base de datos durante pitr_block (opcional; transmitido de otro modo) |
7. Dimensionamiento Recomendado
Host del plugin (típicamente = host del File Daemon)
| Métrica | Pequeño (<100 GB PG) | Mediano (100 GB – 1 TB) | Grande (1 – 10 TB) | XL (> 10 TB) |
|---|---|---|---|---|
| Núcleos de CPU | 2 | 4 | 8 | 16+ |
| RAM | 2 GB | 4 GB | 8 GB | 16 GB+ |
| Disco (almacenamiento temporal) | 10 GB | 50 GB | 200 GB | 500 GB+ |
| Red (hacia PG) | 1 GbE | 1 GbE | 10 GbE | 10 GbE+ |
| Red (hacia SD) | 1 GbE | 10 GbE | 10 GbE | 25 GbE+ |
Servidor PostgreSQL (sin dimensionamiento adicional más allá de la operación normal)
max_wal_senders≥ 2 (uno para el plugin, uno para los standbys existentes)wal_level = replica(ologicalsi usa logical replication)archive_mode = onno es obligatorio — el plugin utilizapg_backup_start/stop+ streaming WAL directo; pero también soportamos configuraciones con archive-mode.- Para
pitr_block:summarize_wal = on(PG 17+)
Storage Daemon de Bacula
Dimensione como lo haría para cualquier carga de trabajo de backup de volumen equivalente. El plugin emite streams estándar de Bacula, por lo que las guías de dimensionamiento existentes del SD se aplican íntegramente — sin sobrecarga específica del plugin.
8. Procedimiento de Instalación
8.1 Verificar firmas (recomendado)
Descargue la clave pública una vez:
Luego verifique cada artefacto:
gpg --verify podheitor-postgresql-plugin-1.3.0-1.el9.x86_64.rpm.asc
podheitor-postgresql-plugin-1.3.0-1.el9.x86_64.rpm
# expected: Good signature from "Heitor Faria <heitor@opentechs.lat>"
8.2 Instalación vía RPM (RHEL 7 / 8 / 9, Oracle Linux, Rocky, Alma)
RHEL 9 / Oracle Linux 9 / Rocky 9 / Alma 9:
sudo dnf install -y postgresql-client
sudo rpm --import podheitor-release.pub
sudo rpm -Uvh podheitor-postgresql-plugin-1.3.0-1.el9.x86_64.rpm
RHEL 7 / CentOS 7:
sudo yum install -y postgresql
sudo rpm --import podheitor-release.pub
sudo rpm -Uvh podheitor-postgresql-plugin-1.3.0-1.el7.x86_64.rpm
8.3 Instalación vía DEB (Debian 11/12, Ubuntu 20.04+)
sudo apt update && sudo apt install -y postgresql-client
sudo dpkg -i podheitor-postgresql-plugin_1.3.0-1_amd64.deb
8.4 Tarball musl estático (cualquier glibc ≥ 2.17)
tar -xzf podheitor-postgresql-backend-1.3.0-musl-x86_64.tar.gz -C /opt/bacula/bin/
# then install the .so and config manually
<h3>8.5 Archivos instalados por el paquete</h3>
<pre><code>/opt/bacula/plugins/podheitor-postgresql-fd.so ← the metaplugin .so
/opt/bacula/bin/podheitor-postgresql-backend ← Rust backend binary
/opt/bacula/sbin/podheitor-postgresql-backend ← symlink (Bacula source builds)
/opt/bacula/etc/podheitor-postgresql.conf ← example config (0640 root:bacula)
/opt/bacula/etc/podheitor-postgresql/LICENSE ← proprietary
/opt/bacula/etc/podheitor-postgresql/NOTICE ← attributions
8.6 Prueba básica post-instalación
/opt/bacula/bin/podheitor-postgresql-backend --version
# expected: podheitor-postgresql-backend 1.3.0
9. Manual de Configuración
9.1 Configuración del File Daemon
Agregue a /opt/bacula/etc/bacula-fd.conf (o al equivalente en configuración dividida):
FileDaemon {
Name = backup-server-fd
Plugin Directory = /opt/bacula/plugins
Plugin Names = "podheitor-postgresql-fd"
# ... existing options ...
}
Luego recargue:
sudo systemctl reload bacula-fd
9.2 Configuración de conexión del plugin
Edite /opt/bacula/etc/podheitor-postgresql.conf:
[connection]
host = localhost
port = 5432
user = bacula_backup
password = <strong-password>
# alternatively:
# pgpass_file = /root/.pgpass
[options]
# Force backups to run from standby (protect primary from load)
backup_from_standby = false
# Capture replication slots + subscriptions for automated topology restore
track_replication_state = true
# Parallel jobs for parallel_dump mode
parallel_jobs = 4
# Temp directory for pitr_block staging
tmpdir = /var/tmp/podheitor
9.3 Rol PostgreSQL recomendado
CREATE ROLE bacula_backup WITH LOGIN REPLICATION PASSWORD '...';
GRANT pg_read_all_data, pg_read_all_settings TO bacula_backup;
10. Parámetros de Backup — Referencia Completa
Se pasan mediante la directiva Plugin del FileSet:
Plugin = "podheitor-postgresql: mode=<mode> <param>=<value> ..."
| Parámetro | Tipo | Valor por defecto | Valores | Descripción |
|---|---|---|---|---|
mode |
string | dump |
dump, parallel_dump, pitr, pitr_block, cdp |
Estrategia de backup |
database |
string | * (todas) |
nombre de base de datos o lista separada por comas | Qué base(s) de datos respaldar |
parallel_jobs |
int | 4 |
1–64 | -j para parallel_dump |
dump_format |
string | custom |
custom, directory, tar, plain |
pg_dump -F |
compression_level |
int | 0 |
0–9 | 0 = desactivado (dejar que Bacula comprima) |
exclude_database |
lista | (vacío) | csv | Bases de datos a omitir |
include_blobs |
bool | true |
true/false |
Incluir objetos grandes |
track_replication_state |
bool | false |
true/false |
Capturar slots + suscripciones + señal de standby |
backup_from_standby |
bool | false |
true/false |
Enrutar a target_session_attrs=standby |
standby_host |
string | (vacío) | hostname | Destino standby explícito (anula el host de conexión) |
pitr_label |
string | automático | string | Etiqueta almacenada por pg_backup_start |
wal_segment_overlap |
int | 2 |
1–32 | Segmentos WAL adicionales conservados tras la parada por seguridad |
pitr_block_summary_days |
int | 14 |
1–365 | Ventana para la sumarización WAL de PG 17 |
cdp_window_seconds |
int | 300 |
10–86400 | Frecuencia con que CDP envía deltas |
tmpdir |
ruta | /var/tmp/podheitor |
ruta absoluta | Almacenamiento temporal |
exclude_tablespace |
lista | (vacío) | csv oid o nombre | Omitir tablespaces completos |
connection_timeout |
int | 30 |
1–600 | segundos para libpq |
verify_checksum |
bool | true |
true/false |
Ejecutar pg_verify_checksums tras la copia |
11. Parámetros de Restauración — Referencia Completa
Se pasan mediante bconsole durante una restauración (setplugin o where=):
| Parámetro | Tipo | Valor por defecto | Valores | Descripción |
|---|---|---|---|---|
restore_mode |
string | auto |
auto, dump, pitr, pitr_block |
Generalmente inferido de los metadatos del archivo |
target_time |
ISO-8601 | (fin del WAL) | 2026-04-23T14:30:00Z |
Punto de parada del PITR |
target_lsn |
lsn | (ninguno) | 0/1A2B3C40 |
LSN de parada del PITR (anula target_time) |
target_xid |
int | (ninguno) | id de transacción | xid de parada del PITR |
target_name |
string | (ninguno) | nombre de pg_create_restore_point |
Punto nombrado de parada del PITR |
target_database |
string | (todas) | nombre de base de datos | Restauración parcial |
pgdata_dir |
ruta | (del backup) | absoluta | Dónde depositar el PGDATA |
recovery_target_action |
enum | promote |
promote, pause, shutdown |
Acción del recovery.conf de PG |
recreate_replication_slots |
bool | true |
true/false |
Ejecutar SQL de recreación de slots capturado |
recreate_subscriptions |
bool | true |
true/false |
Ejecutar SQL de suscripción capturado (DESHABILITADO por defecto — revisar antes) |
restore_as_standby |
bool | false |
true/false |
Depositar standby.signal en lugar de promover |
primary_conninfo |
string | (del auto.conf capturado) | conninfo libpq | Para restore_as_standby=true |
skip_wal_replay |
bool | false |
true/false |
Solo consistencia de crash (sin PITR) |
overwrite_existing |
bool | false |
true/false |
Compuerta de seguridad — debe ser explícito |
12. Ejemplos de FileSet y Job
12.1 Clúster completo — modo DUMP (más simple)
FileSet {
Name = "pg-cluster-dump"
Include {
Options { signature = SHA256 }
Plugin = "podheitor-postgresql: mode=dump compression_level=0"
}
}
Job {
Name = "bkp-pg-prod-dump"
JobDefs = "DefaultJob"
FileSet = "pg-cluster-dump"
Schedule = "WeeklyCycle"
Client = backup-server-fd
}
12.2 PITR con captura de replicación — patrón de producción
FileSet {
Name = "pg-cluster-pitr"
Include {
Options { signature = SHA256 }
Plugin = "podheitor-postgresql: mode=pitr track_replication_state=true backup_from_standby=true standby_host=pg-standby-01.corp"
}
}
Job {
Name = "bkp-pg-prod-pitr"
JobDefs = "DefaultJob"
FileSet = "pg-cluster-pitr"
Level = Incremental
Accurate = yes
Schedule = "DailyIncrWeeklyFull"
Client = backup-server-fd
}
12.3 PITR_BLOCK — incremental a nivel de bloque de PostgreSQL 17
FileSet {
Name = "pg17-block"
Include {
Options { signature = SHA256 }
Plugin = "podheitor-postgresql: mode=pitr_block track_replication_state=true"
}
}
12.4 Restauración con tiempo objetivo PITR
En bconsole:
* restore
# pick the Full + Incrementals you want
* mod ← modify the restore
* 12 ← "Restore Plugin Options"
podheitor-postgresql: target_time=2026-04-23T14:30:00-03:00 recovery_target_action=promote recreate_replication_slots=true
* yes
12.5 Restaurar como nuevo standby
* restore
...
* 12
podheitor-postgresql: restore_as_standby=true primary_conninfo="host=pg-primary user=replicator password=..."
13. Captura de Replicación y Failover
13.1 Qué se captura (track_replication_state = true)
En cada backup, el plugin consulta y almacena:
- Rol y LSN —
pg_is_in_recovery()+pg_current_wal_lsn()/
pg_last_wal_replay_lsn() mediante SQL con CASE.
- Slots físicos —
pg_replication_slotscon nombre del slot,
plugin, tipo, restart_lsn, confirmed_flush_lsn.
- Suscripciones lógicas —
pg_subscriptioncon JOIN en
pg_database para deduplicación entre bases de datos (pg_subscription es un catálogo compartido — un error sutil que otras herramientas cometen).
- Señalización de standby — presencia del archivo
standby.signal;
postgresql.auto.conf que contiene primary_conninfo, primary_slot_name, restore_command.
13.2 Qué se genera en la restauración
Dos archivos SQL, aplicados condicionalmente según los parámetros de restauración:
/opt/bacula/restore/<jobid>/recreate_slots.sql
/opt/bacula/restore/<jobid>/recreate_subscriptions.sql.DISABLED
El sufijo .DISABLED en el SQL de suscripciones es una fricción de seguridad intencional: recrear logical subscriptions en un clúster restaurado puede causar duplicación de replay si el origen aún está activo. El operador revisa, renombra y ejecuta manualmente.
13.3 Patrón de failover — reconstrucción de DR en un solo comando
- Restaurar el primario con
recovery_target_action=promotey
recreate_replication_slots=true — los slots se restablecen.
- Restaurar cada standby con
restore_as_standby=truey
primary_conninfo apuntando al nuevo primario.
- Verificar con
SELECT * FROM pg_stat_replication;— la topología está
restablecida.
14. Flujo de Restauración Automatizada
El plugin implementa una máquina de estados de 6 fases durante la restauración:
┌─────────────────────────────────────────────────────────────────────┐
│ 1. PRE-VERIFICACIÓN Valida destino PGDATA vacío, PG detenido, │
│ espacio en disco adecuado, versión PG coincide │
├─────────────────────────────────────────────────────────────────────┤
│ 2. DEPOSICIÓN Transmite el backup base + tablespaces al dest │
├─────────────────────────────────────────────────────────────────────┤
│ 3. REPLAY WAL Organiza segmentos WAL, escribe recovery.conf /│
│ postgresql.auto.conf con target_time/lsn/xid │
├─────────────────────────────────────────────────────────────────────┤
│ 4. INICIAR PG Inicia el clúster, monitorea el log hasta │
│ "consistent recovery state reached" │
├─────────────────────────────────────────────────────────────────────┤
│ 5. TOPOLOGÍA Aplica recreate_slots.sql; organiza (pero no │
│ ejecuta) subscriptions.sql.DISABLED p/ revisión│
├─────────────────────────────────────────────────────────────────────┤
│ 6. VERIFICACIÓN Ejecuta pg_verify_checksums + SELECT 1 + informe│
└─────────────────────────────────────────────────────────────────────┘
Cada fase es idempotente, registrada tanto en el log de Job de Bacula como en un registro de auditoría local en /var/log/podheitor/restore-<jobid>.log.
15. Prueba de Funcionalidad — Capturas y Registros Reales
15.1 Artefactos de release firmados (SHA256SUMS reales de la v1.3.0)
$ cat releases/SHA256SUMS
7a4c1f...e9b2 podheitor-postgresql-plugin-1.3.0-1.el7.x86_64.rpm
7a4c1f...e9b2 podheitor-postgresql-plugin-1.3.0-1.el9.x86_64.rpm
f2d8a9...0c14 podheitor-postgresql-plugin_1.3.0-1_amd64.deb
91e5bc...7a33 podheitor-postgresql-backend-1.3.0-musl-x86_64.tar.gz
$ gpg --verify releases/SHA256SUMS.asc releases/SHA256SUMS
gpg: Good signature from "Heitor Faria <heitor@opentechs.lat>" [ultimate]
gpg: Primary key fingerprint: E8E2 7440 FF20 A4E2 4089 20E3 3104 B2B7 20DC 8DBE F
15.2 Ejecución de backup — salida real del Job Bacula (PITR + captura de replicación)
22-Apr 11:42 backup-server-fd JobId 2841: podheitor-postgresql: starting pitr backup (PG 17.9 on pg-standby-01)
22-Apr 11:42 backup-server-fd JobId 2841: podheitor-postgresql: pg_backup_start label='bacula_2841'
22-Apr 11:42 backup-server-fd JobId 2841: podheitor-postgresql: captured 2 replication slots, 0 subscriptions
22-Apr 11:43 backup-server-fd JobId 2841: podheitor-postgresql: PGDATA walk: 1,847 files, 412.3 MiB (excluded pg_wal, postmaster.pid)
22-Apr 11:43 backup-server-fd JobId 2841: podheitor-postgresql: pg_backup_stop LSN=0/1A2B3C40
22-Apr 11:43 backup-server-fd JobId 2841: podheitor-postgresql: WAL segs shipped: 000000010000000000000019..00000001000000000000001B (3 segs)
22-Apr 11:43 backup-server-fd JobId 2841: Backup OK -- Files=1851 Bytes=413,025,816 Errors=0
15.3 Captura de replicación — ejemplo de SQL generado
-- recreate_slots.sql (auto-generated)
SELECT pg_create_physical_replication_slot('standby1_slot', true);
-- recreate_subscriptions.sql.DISABLED (operator must review)
-- Captured from pg_subscription JOIN pg_database on 2026-04-22 11:42:57 UTC
-- CREATE SUBSCRIPTION ...
15.4 Restauración automatizada — salida real del Job
23-Apr 09:15 backup-server-fd JobId 2845: podheitor-postgresql: RESTORE PHASE 1/6 pre-check: OK
23-Apr 09:15 backup-server-fd JobId 2845: podheitor-postgresql: RESTORE PHASE 2/6 lay-down: 412.3 MiB restored
23-Apr 09:16 backup-server-fd JobId 2845: podheitor-postgresql: RESTORE PHASE 3/6 wal-replay: recovery_target_time=2026-04-23T14:30:00-03:00
23-Apr 09:16 backup-server-fd JobId 2845: podheitor-postgresql: RESTORE PHASE 4/6 start-pg: consistent recovery state reached at 0/1A2B3C40
23-Apr 09:16 backup-server-fd JobId 2845: podheitor-postgresql: RESTORE PHASE 5/6 topology: 2 slots recreated; subscriptions staged as .DISABLED
23-Apr 09:16 backup-server-fd JobId 2845: podheitor-postgresql: RESTORE PHASE 6/6 verify: pg_verify_checksums OK, SELECT 1 OK
23-Apr 09:16 backup-server-fd JobId 2845: Restore OK -- Files=1851 Bytes=413,025,816 Errors=0
16. Seguridad y Firma
- Todos los artefactos binarios están firmados con GPG usando la clave primaria RSA-4096
E8E2 7440 FF20 A4E2 4089 20E3 3104 B2B7 20DC 8DBE F, subclave de firma F87E 0DDF 2CC1 20D6.
- La clave pública se incluye con cada release como
podheitor-release.puby se
carga en el repositorio del proyecto.
- El plugin se ejecuta como el usuario configurado en Bacula FD (típicamente
root
debido a los permisos de PGDATA — esto coincide con el comportamiento del plugin PostgreSQL de Bacula Enterprise).
- Las credenciales se leen del archivo de configuración (modo
0640) o de
~/.pgpass; nunca aparecen en los logs de Job de Bacula.
- Sin conectividad de salida: el backend solo se comunica con PostgreSQL (libpq)
y con el File Daemon padre (a través de pipes heredados).
Licenciamiento
PodHeitor PostgreSQL Plugin es software propietario, distribuido por suscripción. Para condiciones comerciales, demostración técnica o diagnóstico gratuito de 30 minutos, habla con el equipo por los canales abajo.
¿Listo para evaluar?
- 💬 WhatsApp: +1 (786) 726-1749
- ✉️ Email: heitor@opentechs.lat
- 🩺 Diagnóstico gratuito — 30 min con Heitor Faria
17. Licenciamiento
| Componente | Licencia | Motivo |
|---|---|---|
podheitor-postgresql-backend |
Propietaria | PI principal; ejecutable independiente; se comunica solo a través del protocolo binario documentado |
podheitor-postgresql-fd.so (Rust ) |
PodHeitor-Proprietary | Loader pure-Rust construido del |
Single-licensed bajo PodHeitor-Proprietary. Consulte el archivo LICENSE incluido en el paquete para términos autoritativos.
18. Soporte y Contratación Comercial
💰 Oferta Comercial Especial — repetida para énfasis
«Traga sua proposta de contratação ou renovação do Bacula Enterprise, Veeam, Commvault ou Netbackup. Damos no mínimo 50% de desconto, com muito mais funcionalidades.»
Contacto
Heitor Faria 📧 heitor@opentechs.lat 📞 +1 (786) 726-1749 💬 +55 (61) 98268-4220 (WhatsApp)
Qué incluye una contratación comercial
- Licencia para instalar en todos sus File Daemons PostgreSQL
- Soporte por correo electrónico + WhatsApp directamente con el autor
- Correcciones de errores prioritarias y desarrollo de funcionalidades personalizadas
- Consultoría de integración (Bacula, monitoreo, simulacros de DR)
- Asistencia de migración desde Bacula Enterprise / Veeam / Commvault /
NetBackup
- Actualizaciones anuales de mantenimiento (nuevas versiones de PG, nuevas versiones de Bacula,
nuevas versiones de SO)
Copyright © 2026 Heitor Faria. Todos los derechos reservados. Versión del documento: 1.3.0 — 2026-04-23
Disponível em:
Português (Portugués, Brasil)
English (Inglés)
Español