Wiki
Copia de seguridad y recuperación
Cómo QuoteNode gestiona las copias de seguridad de base de datos y archivos: archivos cifrados con age, restauración guiada por manifiesto, kits de recuperación y perfiles de ejecución.
Copia de seguridad y recuperación
QuoteNode incluye un sistema de copias de seguridad integrado que protege tus datos comerciales frente a fallos de hardware, eliminaciones accidentales e incidentes operativos.
Qué se incluye en la copia de seguridad
Cada copia de seguridad crea un archivo que contiene:
- Volcado de la base de datos — un volcado completo de PostgreSQL en formato personalizado (
pg_dump --format=custom), que incluye todas las tablas, secuencias y restricciones. - Almacenamiento de archivos — todos los archivos subidos (imágenes de productos, logotipos de empresa) y los PDF generados, archivados como
files.tar.gzcon rutas relativas. - Manifiesto de la copia de seguridad — un archivo
backup-manifest.jsonque contiene la versión de origen, el modo de cifrado, el modo de carga útil de la base de datos, las sumas de comprobación y los metadatos de compatibilidad de restauración. - Sumas de comprobación de integridad — un archivo
checksums.sha256que contiene los hashes SHA-256 de todos los componentes del archivo.
Las tres capas de cifrado
Una copia de seguridad implica tres secretos/ajustes independientes. «Copia cifrada» es ambiguo — nombra siempre la capa:
- Identidad privada AGE — desbloquea solo el archivo externo
.tar.age. Proviene del Recovery Kit y se usa al restaurar/verificar (RESTORE_AGE_IDENTITY_FILE). No contiene ni reemplaza laDB_ENCRYPTION_KEY. DB_ENCRYPTION_KEY— descifra los camposAPP_ENCRYPTEDde la base de datos y los secretos operativos (MFA, SMTP, payloads de correo de ofertas). Respáldala por separado del archivo y nunca la pases como argumento de línea de comandos.ENCRYPT_PII— la política de almacenamiento en tiempo de ejecución del destino. No descifra un archivo; cambiarla nunca sustituye a la clave correcta ni al postprocesamiento de restauración.
Guarda tus secretos de .env / despliegue y el Recovery Kit en ubicaciones protegidas separadas.
Cifrado del archivo
Las nuevas copias de seguridad cifradas usan el cifrado por destinatario age (AGE_RECIPIENT). Es el único modelo de cifrado admitido para los archivos nuevos.
- El proceso de copia de seguridad usa únicamente un destinatario age público (
age1...) — no se necesita ninguna clave privada en el servidor para crear copias de seguridad. - Los archivos cifrados tienen la extensión
.tar.age. - La suma de comprobación SHA-256 del archivo cifrado se almacena junto al archivo para su verificación por parte del operador.
- El descifrado requiere la identidad age privada correspondiente, que se conserva exclusivamente en el kit de recuperación del operador.
- La identidad age privada en bruto nunca se almacena en la base de datos, los registros, los DTO ni los argumentos del proceso tras la confirmación de la configuración.
Copias de seguridad locales sin cifrar
Las copias de seguridad locales sin cifrar (.tar) solo se permiten cuando se cumplen todas las condiciones siguientes:
BACKUP_ARCHIVE_ENCRYPTION_MODE=NONEBACKUP_ALLOW_UNENCRYPTED_LOCAL_BACKUP=true- El destino es el almacenamiento local
BACKUP_DATABASE_PAYLOAD_MODE=APP_ENCRYPTED- El administrador ha reconocido explícitamente el riesgo en la interfaz
Los archivos sin cifrar se bloquean para el almacenamiento remoto y para las cargas útiles con PII descifradas.
Configuración (.env). El destinatario age lo genera el kit de recuperación (Administración → Seguridad → Copia de seguridad) y se almacena en la instancia; no colocas ninguna clave en el .env. Define únicamente las dos variables de modo:
BACKUP_ENABLED=true
# Second, dedicated switch — default off. Set true only on the backup-worker to run scheduled backups.
BACKUP_SCHEDULER_ENABLED=true
BACKUP_ARCHIVE_ENCRYPTION_MODE=AGE_RECIPIENT
BACKUP_DATABASE_PAYLOAD_MODE=APP_ENCRYPTED
# Alternative — encrypted archive + decrypted PII (cross-instance portability):
# BACKUP_DATABASE_PAYLOAD_MODE=PII_DECRYPTED
BACKUP_ALLOW_UNENCRYPTED_LOCAL_BACKUP=false
Para desactivar el cifrado del archivo (solo local, no recomendado — los PII siguen cifrados en la carga útil):
BACKUP_ARCHIVE_ENCRYPTION_MODE=NONE
BACKUP_ALLOW_UNENCRYPTED_LOCAL_BACKUP=true
Con
AGE_RECIPIENT, si aún no se ha generado ningún destinatario, la copia de seguridad falla de forma explícita en lugar de escribir un archivo sin proteger. La combinaciónNONE+PII_DECRYPTEDse rechaza.
Modos de carga útil de la base de datos
| Modo | Descripción |
|---|---|
APP_ENCRYPTED |
Predeterminado. Los campos PII permanecen cifrados con la clave de la aplicación DB_ENCRYPTION_KEY. Restaurar sobre la misma clave (huella coincidente) no requiere pasos adicionales; restaurar sobre una clave diferente requiere la clave de origen original (mediante PII_REKEY_OLD_KEY) para un recifrado offline; de lo contrario, la restauración se bloquea antes de cualquier cambio. |
PII_DECRYPTED |
Los campos PII se descifran en una base de datos temporal antes del archivado. Los hashes de las contraseñas de usuario permanecen sin cambios. Requiere el cifrado de archivo AGE_RECIPIENT. Útil para la portabilidad entre instancias. |
Al restaurar una copia de seguridad PII_DECRYPTED en un destino con ENCRYPT_PII=true, el proceso de restauración vuelve a cifrar automáticamente los PII con la DB_ENCRYPTION_KEY del destino antes del arranque normal de la aplicación.
Kit de recuperación
Durante la configuración, el administrador genera (o importa) un destinatario age para las copias de seguridad cifradas. El kit de recuperación es un archivo ZIP que contiene:
quotenode-age-identity.txt— la identidad age privada (se devuelve solo una vez)quotenode-age-recipient.txt— el destinatario público y la huellaquotenode-backup-verify.sh— script de verificación local (Linux/macOS)quotenode-backup-verify.ps1— script de verificación local (Windows)README.md— comandos de verificación y restauración
Crítico: La identidad age privada se devuelve solo una vez durante la generación del kit. Si se pierde, los archivos cifrados no podrán descifrarse. Guarda el kit de recuperación en una ubicación sin conexión segura.
El administrador debe confirmar que el kit se ha guardado y probado antes de que el asistente de configuración marque la copia de seguridad como lista para producción.
Verificación local de copias de seguridad
Las copias de seguridad descargadas pueden verificarse fuera de la aplicación en ejecución mediante los scripts del kit de recuperación:
scripts/quotenode-backup-verify.sh \
--archive /path/backup.tar.age \
--identity /path/quotenode-age-identity.txt \
--expected-sha256 <sha256-from-ui-or-sidecar>
El verificador:
- Comprueba la suma de comprobación SHA-256 del archivo cifrado frente al valor esperado o al archivo adjunto
.sha256. - Descifra con
age -den un directorio temporal privado. - Valida las entradas tar (rechaza rutas absolutas,
.., enlaces simbólicos y archivos de dispositivo). - Comprueba que
backup-manifest.jsonexiste y tiene una versión admitida. - Ejecuta
sha256sum -c checksums.sha256. - Ejecuta
pg_restore --list db.dumpcuandopg_restoreestá disponible. - Elimina por defecto los datos temporales descifrados (usa
--keep-decryptedpara conservarlos).
Copia de seguridad en línea (predeterminada)
Las copias de seguridad en línea se ejecutan mientras la aplicación atiende solicitudes. No hay tiempo de inactividad.
pg_dumpen formato personalizado crea una instantánea coherente a nivel transaccional sin bloquear las tablas ni las consultas.- El almacenamiento de archivos se archiva en paralelo — los archivos subidos y los PDF son inmutables tras su creación, por lo que el archivo siempre es coherente.
- PostgreSQL no necesita detenerse para obtener un volcado de base de datos coherente.
Cómo se ejecutan las copias de seguridad: elegir una topología
Hay dos formas de ejecutar de forma continua las copias de seguridad programadas. Ambas producen archivos idénticos — solo se diferencian en dónde se ejecuta la tarea de copia de seguridad.
| Topología | Cuándo usarla | Contenedores |
|---|---|---|
| Worker dedicado (predeterminado) | Producción. Las copias de seguridad se ejecutan en un contenedor backup-worker independiente, por lo que nunca compiten con el tráfico web por memoria o CPU. |
backend web + backup-worker |
| En proceso | Configuraciones propias con un solo backend y su propio archivo Compose (los paquetes de la versión no lo usan). El backend web ejecuta también las copias de seguridad — un contenedor menos que operar. | solo backend web |
La tarea de copia de seguridad en sí es el mismo pipeline de shell (pg_dump → archivado → cifrado) en ambos casos, ejecutado fuera del heap de la JVM, por lo que su coste de memoria es modesto.
Cómo seleccionar una topología
Dos variables de entorno funcionan en conjunto:
JOBS_MODEdecide qué contenedor ejecuta realmente la tarea de copia de seguridad programada.BACKUP_RUNTIME_PROFILEes una etiqueta que se registra en los registros y manifiestos de las copias de seguridad para que puedas ver, a posteriori, cómo se produjo cada copia.
| Topología | Backend web | Worker de copia de seguridad |
|---|---|---|
| Worker dedicado (predeterminado) | JOBS_MODE=web + BACKUP_RUNTIME_PROFILE=WORKER |
contenedor JOBS_MODE=backup-only |
| En proceso | JOBS_MODE=all + BACKUP_RUNTIME_PROFILE=WEB_MAINTENANCE |
(ninguno) |
Los paquetes de la versión usan la topología de worker dedicado en todas las instalaciones (servidor, LAN, portátil, NAS y Coolify): ambos archivos Compose incluyen un servicio
backup-workery fijanJOBS_MODEpor servicio. En el paquete independiente este ajuste de Compose prevalece sobre.env, así que el modo en proceso (JOBS_MODE=all+BACKUP_RUNTIME_PROFILE=WEB_MAINTENANCE) requiere un archivo Compose que mantengas tú.
Referencia de perfiles de ejecución
BACKUP_RUNTIME_PROFILE acepta cuatro valores. Los dos primeros son para las topologías continuas anteriores; los dos últimos, para copias de seguridad puntuales gestionadas por el operador.
| Perfil | Descripción |
|---|---|
WORKER |
Predeterminado. Un contenedor backup-worker permanente ejecuta las copias de seguridad programadas mediante cron. |
WEB_MAINTENANCE |
El backend web ejecuta directamente las copias de seguridad programadas. No se necesita ningún contenedor worker adicional. |
ONE_SHOT |
Un cron externo o un operador ejecuta operator/backup-one-shot.sh y finaliza. Sin worker permanente. |
OFFLINE_MAINTENANCE |
Un script automatizado anuncia la inactividad, detiene frontend/backend/backup-worker, mantiene PostgreSQL en ejecución, ejecuta la copia de seguridad, reinicia los servicios y verifica su estado. |
Copia de seguridad puntual (one-shot)
COMPOSE_PROJECT_NAME=quotenode COMPOSE_FILE=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
BACKUP_ARCHIVE_ENCRYPTION_MODE=AGE_RECIPIENT \
BACKUP_AGE_RECIPIENT=age1... \
./operator/backup-one-shot.sh
Mantenimiento sin conexión
COMPOSE_PROJECT_NAME=quotenode COMPOSE_FILE=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
BACKUP_OFFLINE_NOTICE_SECONDS=300 \
./operator/backup-offline-maintenance.sh
El script de mantenimiento sin conexión:
- Anuncia un mantenimiento programado (período de gracia configurable).
- Opcionalmente habilita una página de mantenimiento estática mientras los servicios están detenidos.
- Detiene el frontend, el backend y el backup-worker (mantiene PostgreSQL en ejecución).
- Ejecuta una copia de seguridad puntual.
- Reinicia todos los servicios.
- Verifica el estado del backend.
- Escribe un diario de mantenimiento JSONL a nivel de host.
Si el script falla en cualquier punto, una trampa de seguridad reinicia los servicios automáticamente.
Usa --dry-run para previsualizar el plan sin ejecutarlo:
./operator/backup-offline-maintenance.sh --dry-run
Programación
- Programación predeterminada: todos los días a las 2:00 (
0 0 2 * * *, configurable medianteBACKUP_CRON) - Activación (dos interruptores): las copias programadas se ejecutan solo cuando ambos
BACKUP_ENABLED=trueyBACKUP_SCHEDULER_ENABLED=trueestán definidos.BACKUP_SCHEDULER_ENABLEDes un interruptor de corte dedicado que por defecto está desactivado, de modo que activar las copias nunca provoca una primera ejecución programada sorpresa. Actívalo solo en el backup-worker (perfil de tiempo de ejecuciónWORKER/WEB_MAINTENANCE), nunca en el nivel web. - Activación manual: los administradores pueden activar una copia de seguridad inmediata desde el panel de administración o mediante la API (
POST /api/v1/admin/backup/trigger). El activador responde de inmediato (HTTP 202) mientras la copia de seguridad se ejecuta de forma asíncrona. - Protección frente a concurrencia: un bloqueo respaldado por la base de datos garantiza que solo se ejecute una copia de seguridad a la vez en todos los workers y activaciones manuales.
Para los perfiles ONE_SHOT y OFFLINE_MAINTENANCE, el planificador interno está desactivado — las copias de seguridad se gestionan externamente.
Opciones de almacenamiento
Almacenamiento local (predeterminado)
Las copias de seguridad se almacenan en BACKUP_LOCAL_DIR (predeterminado: /app/data/backups), mapeado a un volumen de Docker.
En producción, las copias de seguridad locales deben complementarse con copias remotas.
Almacenamiento remoto mediante rclone
Si BACKUP_RCLONE_REMOTE está configurado, las copias de seguridad se suben automáticamente a un destino remoto tras su creación local. rclone admite más de 70 proveedores de almacenamiento en la nube, incluidos los compatibles con S3, Google Cloud Storage, Azure Blob, SFTP y WebDAV.
Descarga de copias de seguridad
La descarga de archivos de copia de seguridad requiere autorización reforzada (step-up):
- Ve a Configuración > Copia de seguridad.
- Haz clic en Descargar en la entrada de copia de seguridad.
- Introduce tu contraseña actual (y el código TOTP si la MFA está activada).
- El sistema emite una concesión de descarga de un solo uso y de corta duración (predeterminado: 120 segundos).
- El archivo se descarga automáticamente.
El token de concesión se almacena únicamente como hash SHA-256. La creación de la concesión y la descarga se auditan y se notifica a los demás administradores.
Nota: una descarga directa sin concesión devuelve 403. Las copias de seguridad en almacenamiento remoto no se pueden descargar a través del panel de administración.
Metadatos y registro de auditoría
Cada copia de seguridad se registra en la tabla backup_logs con:
- Estado (RUNNING, SUCCESS, FAILED)
- Iniciada por (SCHEDULER o ADMIN)
- Hora de inicio/finalización
- Tamaño (bytes) y suma de comprobación SHA-256
- Destino (ruta local o URL remota)
- Versión del manifiesto y versión de la app de origen
- Modo de cifrado del archivo y huella
- Modo de carga útil de la base de datos
- Perfil de ejecución
- Estado de verificación (NOT_RUN, PASSED, FAILED, SKIPPED_TIMEOUT)
- Estado de la prueba de restauración y estado de compatibilidad de restauración
Restauración
Uso de operator/restore.sh
El script de restauración canónico gestiona el ciclo de vida completo:
COMPOSE_PROJECT_NAME=quotenode COMPOSE_FILE_PATH=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
DB_USERNAME="$(grep '^DB_USERNAME=' .env | cut -d= -f2-)" \
DB_NAME="$(grep '^DB_NAME=' .env | cut -d= -f2-)" \
DB_PASSWORD="$(grep '^DB_PASSWORD=' .env | cut -d= -f2-)" \
RESTORE_JOURNAL_DIR=$PWD/restore-journal \
RESTORE_AGE_IDENTITY_FILE=/path/to/quotenode-age-identity.txt \
[email protected] \
RESTORE_ADMIN_PASSWORD_FILE=/path/to/password \
./operator/restore.sh /path/to/backup.tar.age
El script:
- Extrae y valida el archivo (manifiesto, sumas de comprobación, seguridad de las entradas tar).
- Ejecuta comprobaciones previas (capacidad de disco, versión de PostgreSQL, conectividad con la base de datos).
- Crea una copia de seguridad de protección del destino antes de cualquier operación destructiva.
- Escribe un diario de restauración a nivel de host (JSONL, sobrevive al reemplazo de la base de datos).
- Restaura la base de datos.
- Prepara los archivos en un directorio temporal y los intercambia en su lugar.
- Conserva la identidad del destino (ID de instancia, metadatos de cifrado de copias de seguridad, estado de la licencia).
- Borra las sesiones, los enlaces públicos de ofertas y los tokens de notificación.
- Restablece o fuerza el cambio del acceso de administrador.
- Vuelve a cifrar los PII si la copia de seguridad es
PII_DECRYPTEDy el destino tieneENCRYPT_PII=true.
Restauración entre instancias
Al restaurar una copia de seguridad de una instalación diferente, el modo predeterminado es PRESERVE_TARGET_IDENTITY:
- El ID de instancia de destino, el destinatario age de las copias de seguridad, los metadatos del kit de recuperación y el estado de la licencia se conservan.
- Las sesiones, los enlaces públicos de ofertas y los tokens de notificación se borran.
- La contraseña de administrador se restablece/se fuerza su cambio.
- Los datos de negocio se reemplazan por completo (sin fusión).
Compatibilidad de restauración
La comprobación previa de restauración valida:
- Copia de seguridad más antigua en una app más nueva: permitido (compatible).
- Copia de seguridad más nueva en una app más antigua: bloqueado.
- Manifiesto ausente: bloqueado.
- Huella de clave de cifrado incorrecta para una carga útil
APP_ENCRYPTED: bloqueado antes del trabajo destructivo. PII_DECRYPTEDsin cifrado de archivo: bloqueado.
Decisiones de recuperación y acciones seguras
Las decisiones de la política de restauración provienen de un único motor y devuelven reason codes estables; un resultado bloqueado no modifica nada.
- APP_ENCRYPTED sobre una clave diferente, sin clave de origen →
SOURCE_DB_ENCRYPTION_KEY_REQUIRED. Proporciona la clave original mediantePII_REKEY_OLD_KEY(variable de entorno, nunca en argv) para hacer el rekey. - Clave de origen incorrecta →
SOURCE_DB_ENCRYPTION_KEY_MISMATCH. Proporciona la clave original correcta; no generes una de reemplazo. - Destino con PII en texto plano, sin confirmación →
PLAINTEXT_PII_TARGET_NOT_ACKNOWLEDGED. DefineRESTORE_ACKNOWLEDGE_PLAINTEXT_PII=truesolo si la PII en texto plano en reposo es intencionada. - Sin clave de origen verificada (solo PII_DECRYPTED) → los secretos operativos solo pueden RESTABLECERSE. Define
RESTORE_ACKNOWLEDGE_OPERATIONAL_SECRET_RESET=truepara aceptarlo. - Identidad AGE incorrecta / fallo de integridad → el archivo no se abre y nada se modifica.
Consecuencias del restablecimiento de secretos operativos (si se acepta): los registros MFA se restablecen y los usuarios deben volver a configurarlos; SMTP se borra y el correo saliente permanece desactivado hasta reconfigurarlo; los payloads de offer-email no recuperables se depuran y no pueden reenviarse. FEATURE_2FA_ENABLED=false es solo un break-glass de emergencia y temporal, nunca un ajuste normal.
Semántica del resultado de la restauración:
- Éxito — BD + archivos restaurados, postprocesamiento cripto hecho, y solo entonces la app puede servir tráfico.
- Rechazo antes de mutar — una política bloqueada o un preflight fallido dejan el destino sin cambios.
- Rollback exitoso — un fallo posterior a la mutación revierte BD + archivos juntos desde la copia de seguridad del destino.
- Rollback fallido — la aplicación queda deliberadamente DETENIDA con todos los artefactos de recuperación conservados; recupera desde el archivo de seguridad.
No hagas: generar una DB_ENCRYPTION_KEY de reemplazo aleatoria; pasar ningún secreto como argumento de línea de comandos; ni iniciar la aplicación web antes de que el postprocesamiento cripto haya terminado.
Garantía de acceso de administrador
La restauración garantiza el acceso de administrador mediante una de estas opciones:
RESTORE_ADMIN_PASSWORD_FILE— contraseña proporcionada por el operador (definida conforcePasswordChange=true)RESTORE_ADMIN_PASSWORD— solo para uso local/de pruebas- Token de restablecimiento de un solo uso generado automáticamente — impreso en la consola y en el diario a nivel de host
Ejecución de prueba (dry run)
RESTORE_DRY_RUN=true ./operator/restore.sh /path/to/backup.tar.age
Valida el archivo, comprueba las sumas de comprobación y el manifiesto, e informa del plan de restauración sin modificar nada.
Recuperación ante desastres — reconstrucción desde cero
Tu servidor ha desaparecido. Tienes un archivo de copia de seguridad (.tar.age o .tar) y un servidor nuevo con Docker. Así es como se restaura.
Paso 1 — Preparar el nuevo servidor
mkdir quotenode && cd quotenode
Configura docker-compose.yml y .env como se describe en la Guía de instalación.
Crítico para las copias APP_ENCRYPTED: lo más sencillo es restaurar con la misma
DB_ENCRYPTION_KEY. Restaurar sobre una clave diferente sigue funcionando si proporcionas la clave original mediantePII_REKEY_OLD_KEYpara un recifrado. Sin la clave original, los PII deAPP_ENCRYPTEDno se pueden recuperar (solo un archivoPII_DECRYPTED, cuyos secretos operativos deberán restablecerse) — nunca generes una clave de reemplazo aleatoria.
Crítico para los archivos cifrados: necesitas el archivo de identidad privada del kit de recuperación (
quotenode-age-identity.txt) para descifrar el archivo.
Paso 2 — Copiar la copia de seguridad y el script de restauración
scp backup.tar.age user@new-server:~/quotenode/
# operator/restore.sh comes with the release package (the release that created the backup, or a later one)
curl -fsSLO https://quotenode.dev/releases/v0.9.8-alpha/quotenode-deploy-v0.9.8-alpha.tar.gz
tar -xzf quotenode-deploy-v0.9.8-alpha.tar.gz --strip-components=1
Paso 3 — Ejecutar la restauración
# Only a successful restore starts the remaining services (the restore itself starts PostgreSQL, the backend and
# the frontend). On failure nothing else starts and the restore's exit status is kept: read its message.
# Default installations keep PII unencrypted at rest (ENCRYPT_PII=false); a restore into such a target requires the
# explicit RESTORE_ACKNOWLEDGE_PLAINTEXT_PII acknowledgement below, for this command only. A target with
# ENCRYPT_PII=true in .env does not use it.
export COMPOSE_PROJECT_NAME=quotenode
COMPOSE_FILE_PATH=$PWD/docker-compose.yml COMPOSE_ENV_FILE=$PWD/.env \
DB_USERNAME="$(grep '^DB_USERNAME=' .env | cut -d= -f2-)" \
DB_NAME="$(grep '^DB_NAME=' .env | cut -d= -f2-)" \
DB_PASSWORD="$(grep '^DB_PASSWORD=' .env | cut -d= -f2-)" \
RESTORE_JOURNAL_DIR=$PWD/restore-journal \
RESTORE_AGE_IDENTITY_FILE=./quotenode-age-identity.txt \
[email protected] \
RESTORE_ADMIN_PASSWORD_FILE=./admin-password \
RESTORE_ACKNOWLEDGE_PLAINTEXT_PII=true \
./operator/restore.sh --fresh-install backup.tar.age \
&& docker compose up -d
Si la restauración informa de un fallo, no inicies QuoteNode a mano: arrancaría una instalación vacía o restaurada a medias. Lee el mensaje, corrige la causa (por ejemplo, el archivo de identidad o DB_ENCRYPTION_KEY) y vuelve a ejecutar el bloque. Si la restauración indica que dejó la aplicación detenida con los artefactos de recuperación conservados, sigue Decisiones de recuperación y acciones seguras más arriba.
Paso 4 — Verificar
Abre tu dominio e inicia sesión. Todos los clientes, ofertas, productos y configuraciones deberían estar exactamente como estaban en el momento de la copia de seguridad.
Recuperación ante desastres probada
La ruta completa de backup → restauración aislada se ejercita de extremo a extremo como una prueba automatizada de recuperación ante desastres (escenarios A–G): restauración con la misma clave, recifrado a una clave diferente, confirmación de PII en texto plano, restablecimiento de secretos operativos, rechazo por identidad incorrecta y rollback posterior a la restauración. Se ejecuta contra un PostgreSQL real en un entorno desechable y verifica las garantías de rollback y de claves descritas arriba.
Retención de copias de seguridad
- Local: se conservan las
BACKUP_RETENTION_DAILY(predeterminado: 7) copias de seguridad correctas más recientes. - Remoto: configura políticas de ciclo de vida en tu proveedor de almacenamiento.
- Las copias de seguridad con PII descifradas deberían tener una retención más estricta debido a su naturaleza sensible.
Tiempo de espera de la copia de seguridad
Cada copia de seguridad tiene un tiempo de espera configurable (predeterminado: 30 minutos mediante BACKUP_TIMEOUT_MINUTES). Si se supera, la copia de seguridad se termina y se registra como FAILED.
Estrategia recomendada
- Activa las copias de seguridad automáticas diarias con cifrado
AGE_RECIPIENTy almacenamiento remoto. - Genera un kit de recuperación durante la configuración y guárdalo en una ubicación sin conexión segura.
- Verifica tu kit de recuperación frente a una copia de seguridad real usando los scripts de verificación incluidos.
- Prueba periódicamente los procedimientos de restauración — una copia de seguridad que nunca se ha probado no es una copia de seguridad.
- Descarga una copia de seguridad al menos una vez al mes a una ubicación sin conexión (requiere autorización reforzada).
- Supervisa el estado de las copias de seguridad en el panel de administración — aparecen avisos para las copias obsoletas, fallidas o sin cifrar.
- Conserva al menos 7 días de historial de copias de seguridad (el valor predeterminado).