El peor momento para descubrir que tus respaldos están “seguros” es durante una restauración. El segundo peor es
durante una auditoría en la que alguien pregunta, con calma, por qué los volcados de la base de datos de producción están en un almacenamiento de objetos
como texto sin formato con la fecha en el nombre del archivo.
Docker facilita desplegar aplicaciones. También facilita hacer un respaldo equivocado, cifrarlo en
el lugar incorrecto y luego descubrir que tu proceso de restauración depende de un secreto que vivía en la máquina
que acabas de perder. Esta es una guía para quienes administran sistemas en producción y quieren cifrado que
sobreviva desastres reales—incluyendo errores operativos.
Modelo de amenazas primero, herramientas después
“Cifrar los respaldos” no es un requisito; es un deseo vago. Los requisitos son específicos:
quién no debe leer los respaldos, qué fallas puedes tolerar, y cómo restaurarás cuando la mitad de tu infraestructura esté en llamas y la otra mitad espere control de cambios.
Comienza con tres modelos de amenaza comunes:
-
Compromiso del almacenamiento en la nube: credenciales filtradas, política de bucket incorrecta o una cuenta interna que se vuelve maliciosa.
El cifrado debería seguir impidiendo la exfiltración de datos legibles. -
Ransomware / atacante en el host: el atacante puede leer archivos locales y quizá tus scripts de respaldo.
El cifrado puede o no ayudar dependiendo de dónde vivan las claves. -
Error del operador: lo más frecuente. Alguien sube un volcado “temporal” a un lugar compartido, o rota claves sin un plan de restauración.
El cifrado debería reducir el radio de daño y las restauraciones deberían seguir siendo rutinarias.
Para entornos Docker, la verdad operacional es esta: no estás “respalando Docker.” Estás
respaldando los datos detrás de los contenedores, más suficientes metadatos para reconstruirlos. El cifrado debe
envolver el artefacto que realmente almacenas y mueves—no solo el disco, no solo el transporte, y
definitivamente no “en algún lugar de la pila que asumimos está cifrado.”
Hechos interesantes y contexto histórico
- Hecho 1: La cultura temprana de respaldos en Unix trataba las cintas como “seguridad física.” El cifrado era raro porque la cinta se guardaba en un gabinete con llave—hasta que dejó de ser así.
- Hecho 2: GPG (década de 1990) se convirtió en la herramienta por defecto para “cifrar un archivo” en operaciones porque funcionaba offline y entre plataformas, no porque fuera sencillo.
- Hecho 3: Muchas fallas de “cifrado de respaldos” son en realidad fallas de disponibilidad de claves: el texto cifrado está bien; la restauración no puede descifrar a tiempo.
- Hecho 4: Comprimir antes de cifrar es una práctica recomendada de larga data porque el cifrado destruye redundancia y hace que la compresión sea ineficaz.
- Hecho 5: El auge del almacenamiento de objetos hizo que los “respaldos fuera del sitio” fueran baratos y comunes—también provocando exposiciones públicas accidentales como titular recurrente en la industria.
- Hecho 6: La deduplicación y el cifrado han estado en guerra fría durante años: el cifrado aleatoriza los datos y puede matar la eficiencia de dedupe a menos que se diseñe con cuidado.
- Hecho 7: Un número sorprendente de equipos todavía “respalda contenedores” (imágenes) en lugar de respaldar el estado, y luego se preguntan por qué la base de datos está vacía después de la restauración.
- Hecho 8: La rotación de claves es anterior a la nube. La parte difícil siempre ha sido la compatibilidad con datos antiguos y rituales operacionales previsibles.
Una idea fiable parafraseada de Richard Cook (ingeniería de resiliencia): el éxito y el fracaso a menudo provienen del mismo trabajo cotidiano; la diferencia es el contexto
(idea parafraseada).
El cifrado de respaldos es exactamente eso. La misma pipeline que te protege puede dejarte varado—dependiendo de si la ruta de restauración fue tratada como una característica de primera clase.
Principios: cifrar sin romper restauraciones
1) Cifra el artefacto que almacenas, no la máquina que desearías tener
El cifrado de disco (LUKS, cifrado EBS en la nube, datasets ZFS cifrados) es buena higiene. Pero
los respaldos son portables por diseño. Los copiarás a otras máquinas, otros buckets, otras
regiones, quizá a un portátil durante un incidente. Por eso el cifrado debe viajar con el artefacto de respaldo.
2) La ruta de restauración es el producto
Si descifrar requiere una VPN a un centro de datos muerto, construiste una trampa. Las restauraciones deben funcionar desde un arranque en frío: host nuevo, herramientas mínimas, claves obtenibles mediante un proceso controlado pero disponible.
3) Prefiere flujos criptográficos simples sobre los ingeniosos
Las jerarquías de claves complejas y los esquemas de sobre personalizado pueden ser correctos y aun así ser in-restaurables a las 03:00.
La mayoría de los equipos rinde mejor con:
- Un archivo por artefacto de respaldo
- Comprimir luego cifrar (en streaming si es grande)
- Cifrado basado en destinatarios (sin contraseñas compartidas)
- Recuperación de claves documentada y probada
4) Separa confidencialidad de integridad, pero verifica ambas
Los modos modernos de cifrado (y herramientas como age) ofrecen cifrado autenticado: confidencialidad más integridad.
Aun así, deberías verificar la suma de comprobación del artefacto y probar el descifrado y la restauración. La corrupción silenciosa no es un buen augurio.
5) Planea la pérdida de claves, no solo el robo
La mayoría de las organizaciones se obsesiona con prevenir el robo e ignora la pérdida. La pérdida es cómo terminas con respaldos “perfectamente seguros”
que no pueden restaurarse. Tu gestión de claves debería tener:
- Al menos dos rutas de recuperación independientes (p. ej., dos operadores, o vault + break-glass)
- Rotación documentada
- Registros de acceso
- Pruebas de restauración regulares
Qué respaldar en Docker (y qué no)
Los contenedores son ganado; los volúmenes y los sistemas externos son las mascotas que realmente necesitas. En términos de Docker,
tu alcance de respaldo suele ser:
- Volúmenes con nombre (p. ej., directorio de datos de Postgres, cargas de la aplicación)
- Bind mounts donde vive estado (cuidado con permisos y deriva de rutas)
- Volcados lógicos de base de datos (pg_dump, mysqldump) o respaldos físicos (pg_basebackup, xtrabackup)
- Estado de configuración: docker-compose.yml, archivos env (pero trata los secretos con cuidado), configuraciones de proxy inverso
- Secretos: no en git, no en el respaldo a menos que tengas una razón y una historia de protección separada
Cosas que la gente suele respaldar por error:
- Capas/imágenes de contenedor (puedes reconstruir; además las imágenes pueden contener secretos si eres descuidado)
- /var/lib/docker completo (posible, pero frágil entre versiones/controladores de almacenamiento; y es enorme)
- Caches en tiempo de ejecución (desperdicio y puede ralentizar las restauraciones)
Opinión: respalda datos y una definición de despliegue reconstruible. Si tu restauración depende de copiar
el directorio de estado del demonio Docker entre hosts, ya estás negociando con el caos.
Dónde cifrar: en reposo, en tránsito o en la pipeline
Cifrado en transporte (TLS)
Necesario, no suficiente. TLS protege los datos en tránsito, pero el endpoint sigue viendo texto plano. Si
el bucket se compromete más tarde, TLS no hizo nada.
Cifrado del lado del almacenamiento (SSE)
El cifrado estilo S3 (SSE-S3 o SSE-KMS) es útil, especialmente para cumplimiento y para
reducir el impacto de un “bucket oops”. Pero todavía significa que el proveedor de almacenamiento puede descifrar, y el objeto
se almacena en una forma que podría descifrarse con acceso a los controles adecuados. No es extremo a extremo.
Cifrado del lado del cliente (cifrar antes de subir)
Esta es la recomendación por defecto para “mantener los secretos seguros.” Cifras el artefacto de respaldo
localmente y subes el ciphertext. Incluso si tu almacenamiento se compromete, el atacante obtiene blobs cifrados.
Control de realidad: el cifrado del lado del cliente solo es tan bueno como la higiene de claves. Si el mismo host que
cifra también guarda la clave sin protección, mayormente mejoraste el papeleo de cumplimiento.
Opciones criptográficas: age, GPG, OpenSSL, SSE de S3
age: aburrido en el buen sentido
age es una herramienta moderna de cifrado de archivos diseñada para ser difícil de usar mal. El cifrado basado en destinatarios
es directo, la salida es determinista para operar, y es menos “mística” que GPG.
Úsala cuando quieras un flujo limpio y no necesites todo el ecosistema PGP.
Caso de uso: tarballs cifrados diarios, volcados de base de datos en streaming, copias fuera del sitio.
GPG: potente, con bordes afilados
gpg está en todas partes y soporta gestión de claves compleja. También tiene deuda de complejidad: modelos de confianza,
keyrings, pinentry, comportamiento del agente y confusión humana.
Caso de uso: cuando tu organización ya tiene distribución de claves PGP y necesitas interoperabilidad.
OpenSSL: flexible, pero fácil de dispararte
OpenSSL puede cifrar archivos con una frase de paso, pero los flujos basados en frases de paso son rutinariamente mal usados:
secretos compartidos, contraseñas débiles, frases incrustadas en scripts, etc. Si usas OpenSSL, usa
modos AEAD modernos y mantén las frases fuera de listas de procesos e historial de shell.
Cifrado del lado del servidor: buena línea base, no la meta
SSE ayuda, especialmente SSE-KMS con límites de IAM fuertes y registros de auditoría. Pero para escenarios de “cuenta en la nube
comprometida”, el cifrado del lado del cliente es la historia más sólida.
Broma 1: Si tu clave de cifrado de respaldos está en el mismo bucket que los respaldos, no construiste seguridad—construiste una sala de escape temática.
Gestión de claves que no te coma el fin de semana
Elige un modelo de claves que puedas operar bajo estrés
El objetivo no es “que nadie pueda nunca descifrar.” El objetivo es “solo las personas autorizadas puedan descifrar, y
puedan hacerlo durante un incidente sin improvisar.”
Patrones recomendados
-
Cifrado basado en destinatarios (preferido): recipients de age o claves públicas GPG. Cifra a múltiples destinatarios
(p. ej., clave del equipo de ops + clave break-glass). Sin contraseñas compartidas. Sin cuello de botella humano único. -
Clave break-glass almacenada offline: QR impreso en una caja fuerte, o un proceso de exportación protegido por HSM, según tu entorno.
El punto es independencia del host de producción. - Vault/KMS para distribución de claves, no necesariamente para cifrado: almacena la clave privada o una clave de datos envuelta en un sistema con control de acceso fuerte y registros de auditoría.
Qué evitar
- Contraseña única compartida en un canal de chat (ahora también está en los respaldos del chat)
- Claves almacenadas en el mismo host sin protección adicional
- Rotación de claves sin plan de re-encriptado (lo descubrirás durante la restauración)
- “Podemos preguntar a Alicia” dependencia (Alicia se va de vacaciones o se va de la empresa)
Rotación de claves: hazla sin romper restauraciones antiguas
La rotación necesita una ventana de compatibilidad. Mantén las claves privadas antiguas disponibles (bajo controles) hasta que todos
los respaldos cifrados con ellas hayan expirado. Si debes revocar acceso, re-encripta los archivos retenidos,
y registra qué ID de clave cifró cada objeto.
Pipelines prácticos de respaldo cifrado (con rutas de restauración)
Pipeline A: snapshot de volumen vía tar → comprimir → age → subir
Este es el caballo de batalla para casos de “el volumen con nombre contiene archivos”. No es consistente con la base de datos a menos
que tu aplicación lo tolere. Para bases de datos, prefiere respaldos lógicos/físicos desde la propia BD.
Pipeline B: volcado lógico de Postgres en streaming y cifrado
Para muchas organizaciones, pg_dump es el punto ideal: snapshot consistente, portable, y puedes transmitirlo para que el texto plano
no aterrice en disco. Luego lo cifras y lo envías.
Pipeline C: almacenamiento de objetos con SSE-KMS más cifrado del lado del cliente
La seguridad en capas es normal. SSE-KMS te da controles del proveedor y registros de auditoría; el cifrado del lado del cliente
te da que “el compromiso del bucket aún yield ciphertext.”
Pensamiento sobre la ruta de restauración
Para cada pipeline, documenta:
- Dónde vive el artefacto cifrado
- Cómo obtenerlo (credenciales y quién las tiene)
- Cómo obtener la clave de descifrado (primaria y break-glass)
- Cómo verificar la integridad (checksum/firmas)
- Cómo restaurar en un entorno Docker limpio
12+ tareas reales: comandos, salidas y decisiones
Estas son las comprobaciones que ejecutas cuando construyes el sistema o depuras por qué una restauración es lenta, falla, o extrañamente “exitosa” pero con datos faltantes.
Cada tarea incluye: comando, qué significa la salida y la decisión que tomas a partir de ella.
Task 1: Enumerar contenedores e identificar los con estado
cr0x@server:~$ docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
NAMES IMAGE STATUS
pg postgres:16 Up 3 days
app myco/app:2.8.1 Up 3 days
nginx nginx:1.25 Up 3 days
Significado: Buscas bases de datos, almacenes de archivos, colas—cualquier cosa con estado.
Decisión: Marca pg y probablemente app como que requieren respaldos más allá de redeployar imágenes.
Task 2: Listar volúmenes y mapearlos a contenedores
cr0x@server:~$ docker volume ls
DRIVER VOLUME NAME
local pg_data
local app_uploads
cr0x@server:~$ docker inspect pg --format '{{json .Mounts}}'
[{"Type":"volume","Name":"pg_data","Source":"/var/lib/docker/volumes/pg_data/_data","Destination":"/var/lib/postgresql/data","Driver":"local","Mode":"z","RW":true,"Propagation":""}]
Significado: pg_data es un volumen con nombre; respaldar ese directorio en crudo arriesga inconsistencia a menos que la BD esté parada o uses respaldos nativos de la BD.
Decisión: Usa pg_dump o pg_basebackup en lugar de tar el pg_data mientras está en ejecución.
Task 3: Verificar que existe la definición de Docker Compose y está versionada
cr0x@server:~$ ls -l /srv/app/docker-compose.yml
-rw-r--r-- 1 root root 2481 Jan 2 09:41 /srv/app/docker-compose.yml
Significado: Puedes recrear el stack. Sin esto, las restauraciones se convierten en arqueología.
Decisión: Pon los archivos compose en control de versiones; mantiene los secretos fuera o usa stores de secretos externos.
Task 4: Confirmar de dónde vienen los secretos (vars de entorno vs archivos)
cr0x@server:~$ docker inspect app --format '{{range .Config.Env}}{{println .}}{{end}}' | grep -E 'PASSWORD|TOKEN|SECRET' || true
DATABASE_URL=postgres://app:REDACTED@pg:5432/app
JWT_SECRET=REDACTED
Significado: Si los secretos viven en vars de entorno, pueden filtrarse vía diagnósticos, volcados de fallos y scripts demasiado informativos.
Decisión: Decide si tus respaldos deben incluir material secreto. Usualmente: no. Respalda datos; recupera secretos desde una vía controlada separada.
Task 5: Crear un par de claves age (estación de trabajo del operador o host seguro)
cr0x@server:~$ age-keygen -o /secure/keys/backup.agekey
Public key: age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j
Significado: Ahora tienes una clave pública de destinatario (segura para distribuir) y una privada (trátala como break-glass).
Decisión: Guarda la clave privada fuera del host Docker y fuera de la ubicación de los respaldos. Cifra a múltiples destinatarios si es posible.
Task 6: Cifrar un archivo de prueba pequeño y verificar que la descifrado funcione
cr0x@server:~$ printf "hello-restore\n" > /tmp/restore-test.txt
cr0x@server:~$ age -r age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j -o /tmp/restore-test.txt.age /tmp/restore-test.txt
cr0x@server:~$ age -d -i /secure/keys/backup.agekey -o /tmp/restore-test.out /tmp/restore-test.txt.age
cr0x@server:~$ cat /tmp/restore-test.out
hello-restore
Significado: La clave es válida, la herramienta funciona y la descifrado no es “problema de tu yo del futuro.”
Decisión: Incluye la instalación de age en tu entorno de restauración o conserva un binario estático conocido.
Task 7: Transmitir un volcado de Postgres y cifrarlo (sin archivo de texto plano en disco)
cr0x@server:~$ docker exec -i pg pg_dump -U postgres -d app --format=custom | age -r age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j -o /backups/app_pg.dump.age
cr0x@server:~$ ls -lh /backups/app_pg.dump.age
-rw-r--r-- 1 root root 192M Jan 3 01:00 /backups/app_pg.dump.age
Significado: Produjiste un artefacto cifrado. El volcado viajó por una tubería; el host no almacenó texto plano en reposo.
Decisión: Adopta el streaming para respaldos sensibles grandes; reduce el problema de “residuos de texto plano”.
Task 8: Validar que puedes descifrar y restaurar ese volcado en una base de datos nueva
cr0x@server:~$ docker run --rm -d --name pg-restore -e POSTGRES_PASSWORD=restore -p 5433:5432 postgres:16
d4b2f8f15c65f6b6f8b0b76d1cc9d9d2a2b0a6f0d3f0d8f9a1c2b3d4e5f6a7b8
cr0x@server:~$ age -d -i /secure/keys/backup.agekey /backups/app_pg.dump.age | pg_restore -h 127.0.0.1 -p 5433 -U postgres -d postgres --clean --if-exists
Password:
Significado: Esto demuestra la ruta de restauración de extremo a extremo, no solo el cifrado.
Decisión: Haz esto un ejercicio programado. Si no puedes restaurar en una instancia limpia, no tienes respaldos—tienes artefactos.
Task 9: Respaldar un volumen no-DB con tar + compresión + cifrado
cr0x@server:~$ docker run --rm -v app_uploads:/data:ro -v /backups:/out alpine:3.20 sh -c "cd /data && tar -cf - . | gzip -1" | age -r age1k8t6y7z8n6k5m2p9k4d3s2q1w0e9r8t7y6u5i4o3p2a1s0d9f8g7h6j -o /backups/app_uploads.tgz.age
cr0x@server:~$ file /backups/app_uploads.tgz.age
/backups/app_uploads.tgz.age: age encrypted file
Significado: Hiciste un archivo portable cifrado de datos de archivos.
Decisión: Para volúmenes de archivos esto está bien. Para bases de datos, no hagas esto mientras la BD está viva a menos que tengas un mecanismo de consistencia.
Task 10: Restaurar el tarball cifrado en un volumen vacío nuevo
cr0x@server:~$ docker volume create app_uploads_restore
app_uploads_restore
cr0x@server:~$ age -d -i /secure/keys/backup.agekey /backups/app_uploads.tgz.age | gunzip -c | docker run --rm -i -v app_uploads_restore:/restore alpine:3.20 sh -c "cd /restore && tar -xvf - | head"
./
./avatars/
./avatars/u123.png
./docs/
./docs/terms.pdf
Significado: Los datos son recuperables y aterrizan en un volumen gestionado por Docker.
Decisión: Usa un volumen de restauración primero, luego intercámbialo. Restaurar directamente en volúmenes en vivo es cómo conviertes un pequeño incidente en un incidente largo.
Task 11: Subir respaldos cifrados a almacenamiento compatible con S3 y confirmar el estado de SSE
cr0x@server:~$ aws s3 cp /backups/app_pg.dump.age s3://prod-backups/app_pg/2026-01-03/app_pg.dump.age --sse aws:kms
upload: backups/app_pg.dump.age to s3://prod-backups/app_pg/2026-01-03/app_pg.dump.age
cr0x@server:~$ aws s3api head-object --bucket prod-backups --key app_pg/2026-01-03/app_pg.dump.age --query '{Size:ContentLength,SSE:ServerSideEncryption,KMS:SSEKMSKeyId}'
{
"Size": 201326592,
"SSE": "aws:kms",
"KMS": "arn:aws:kms:us-east-1:111122223333:key/REDACTED"
}
Significado: El objeto es ciphertext de cifrado del lado del cliente, y además está protegido por SSE-KMS.
Decisión: Mantén SSE activo. No reemplazará al cifrado del lado del cliente, pero añade protecciones y trazas de auditoría.
Task 12: Generar y almacenar un manifiesto de checksum para verificaciones de integridad
cr0x@server:~$ sha256sum /backups/app_pg.dump.age /backups/app_uploads.tgz.age > /backups/manifest.sha256
cr0x@server:~$ cat /backups/manifest.sha256
2f9e0f1c0a8c5d4b3e2a1f0e9d8c7b6a5f4e3d2c1b0a9e8d7c6b5a4f3e2d1c0b /backups/app_pg.dump.age
9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b /backups/app_uploads.tgz.age
Significado: Puedes detectar corrupción o transferencias parciales antes de intentar restaurar.
Decisión: Almacena el manifiesto junto a los respaldos (y preferiblemente también en un sistema de logs separado). Verifica antes de descifrar archivos grandes.
Task 13: Verificar que el tamaño del objeto remoto coincide con el local antes de restaurar
cr0x@server:~$ aws s3 ls s3://prod-backups/app_pg/2026-01-03/app_pg.dump.age
2026-01-03 01:02:11 201326592 app_pg.dump.age
Significado: El tamaño coincide con lo esperado; no es garantía, pero detecta truncamientos obvios.
Decisión: Si el tamaño es distinto, detente. Investiga la transferencia, fallos de multipart upload, reglas de ciclo de vida o corrupción del almacenamiento.
Task 14: Comprobar postura de ciclo de vida / inmutabilidad (resistencia a ransomware)
cr0x@server:~$ aws s3api get-bucket-versioning --bucket prod-backups
{
"Status": "Enabled"
}
cr0x@server:~$ aws s3api get-object-lock-configuration --bucket prod-backups
{
"ObjectLockConfiguration": {
"ObjectLockEnabled": "Enabled",
"Rule": {
"DefaultRetention": {
"Mode": "GOVERNANCE",
"Days": 30
}
}
}
}
Significado: Versionado y object lock reducen la probabilidad de que un atacante (o un script defectuoso) borre tu único respaldo bueno.
Decisión: Si puedes habilitar inmutabilidad, hazlo. El cifrado protege confidencialidad; la inmutabilidad protege la existencia.
Task 15: Confirmar que el entorno de restauración tiene las herramientas correctas antes de empezar
cr0x@server:~$ age --version
age 1.2.0
cr0x@server:~$ pg_restore --version
pg_restore (PostgreSQL) 16.1
cr0x@server:~$ docker --version
Docker version 24.0.7, build afdd53b
Significado: La compatibilidad de la cadena de herramientas es una causa clásica de fallos en restauración, especialmente con utilidades de restauración de bases de datos.
Decisión: Mantén una imagen de restauración conocida o un runbook que especifique versiones. No descubras incompatibilidades de versiones en medio de un incidente.
Guía de diagnóstico rápido
Cuando los respaldos cifrados son “lentos” o las restauraciones “se cuelgan”, normalmente es uno de cuatro cuellos de botella: CPU, disco, red o la fase de aplicación de la base de datos.
No adivines. Comprueba en este orden y detente tan pronto como encuentres el factor limitante.
1) Confirma que estás restaurando el artefacto correcto (y está completo)
- Comprueba que el tamaño del objeto remoto coincide con lo esperado.
- Verifica el manifiesto de checksum.
- Decisión: si la integridad es dudosa, no procedas a restaurar en un objetivo en vivo.
2) Identifica qué fase es lenta: descarga, descifrado, descompresión o aplicación
- Temporiza cada segmento con pipelines simples.
- Decisión: optimiza donde realmente se gasta el tiempo; el cifrado suele culparse pero no ser el culpable.
3) Revisa saturación de CPU y el mito de falta de entropía
- Los sistemas modernos raramente “esperan entropía” para age/GPG en uso normal; la CPU es el sospechoso habitual.
- Decisión: si la CPU está al máximo, considera paralelismo o ajustes de compresión más rápidos, no cifrado más débil.
4) Revisa I/O de disco y comportamiento del sistema de archivos
- Los objetivos de restauración pueden ser más lentos que las fuentes, especialmente en almacenamiento en red.
- Decisión: restaura en almacenamiento local rápido y luego mueve/adjunta si es factible.
5) Para bases de datos: la fase de aplicación domina
pg_restorey la creación de índices pueden superar con creces los tiempos de descarga/descifrado.- Decisión: ajusta opciones de restauración (jobs, parámetros de mantenimiento) y valida configuraciones WAL/checkpoint para el entorno de restauración.
Errores comunes (síntomas → causa raíz → solución)
Mistake 1: “Decrypt failed: no identity found” durante la restauración
Síntomas: age se niega a descifrar; la restauración se bloquea inmediatamente.
Causa raíz: Cifraste al destinatario equivocado, perdiste la clave privada, o el host de restauración no tiene acceso al archivo de identidad.
Solución: Cifra a múltiples destinatarios (clave del equipo + clave break-glass). Almacena la recuperación de identidad en el runbook. Prueba la descifrado semanalmente con un artefacto pequeño.
Mistake 2: Los respaldos existen pero la restauración da estado de aplicación vacío
Síntomas: La app arranca tras la restauración pero no aparecen usuarios/archivos/datos.
Causa raíz: Respaldaste imágenes/compose pero no volúmenes ni volcados de BD; o solo restauraste uno de los componentes de estado.
Solución: Define un inventario de respaldo: BD + uploads + configuración. Ejecuta ejercicios de restauración que validen corrección a nivel de aplicación (no solo “el contenedor está arriba”).
Mistake 3: Los respaldos cifrados son enormes y lentos de mover
Síntomas: Las ventanas de transferencia se agotan; los costos de almacenamiento suben.
Causa raíz: Cifrar sin comprimir desperdicia espacio; además respaldar demasiado (logs, caches).
Solución: Comprime antes de cifrar; excluye rutas no críticas; considera compresión nativa de BD o formatos personalizados.
Mistake 4: “Usamos SSE-KMS así que estamos seguros” (hasta que la cuenta se compromete)
Síntomas: La auditoría pasa, pero el modelado de amenazas no; un IAM comprometido puede obtener y descifrar.
Causa raíz: Confiar únicamente en el cifrado del lado del servidor y asumir que IAM es inquebrantable.
Solución: Añade cifrado del lado del cliente. Trata el compromiso de la cuenta en la nube como un escenario real, no teórico.
Mistake 5: Cifrado basado en passphrase embebido en scripts
Síntomas: Cualquiera con acceso al script, lista de procesos o logs de CI puede descifrar respaldos.
Causa raíz: Conveniencia operacional ganó la pelea contra seguridad.
Solución: Pasa a cifrado basado en destinatarios. Si debes usar passphrases, recupéralas de forma segura en tiempo de ejecución y mantenlas fuera de logs e historial del shell.
Mistake 6: Respaldos en tar de volúmenes de bases de datos en vivo
Síntomas: La restauración completa pero la BD está corrupta o inconsistente; a veces “funciona” hasta que no.
Causa raíz: Captura a nivel de sistema de archivos de una base de datos en cambio sin snapshots o coordinación con la BD.
Solución: Usa pg_dump, pg_basebackup o mecanismos de snapshot coordinados con la base de datos. No tarrees directorios de BD en vivo.
Mistake 7: La rotación de claves rompe el acceso a respaldos antiguos
Síntomas: Los respaldos nuevos se descifran; los antiguos no; la retención para cumplimiento se vuelve un pasivo.
Causa raíz: Rotaste las claves y te deshiciste de las antiguas sin un plan de retención.
Solución: Mantén las claves antiguas disponibles bajo estrictos controles hasta que los respaldos antiguos expiren, o re-encripta los respaldos retenidos como parte de la rotación.
Tres micro-historias corporativas desde el campo
Micro-historia 1: El incidente causado por una suposición equivocada
Una empresa mediana ejecutaba un stack Docker Compose: Postgres, una app web y un volumen de uploads. Tenían “respaldos cifrados”
porque el disco de la VM estaba cifrado y el bucket S3 exigía SSE-KMS. El trabajo de respaldo copiaba un pg_dump nocturno al
bucket. Pasó auditorías. Todos dormían tranquilos.
Entonces las claves de acceso a la nube de un desarrollador se filtraron por un job de CI mal configurado. El atacante no necesitó romper el cifrado. Con esas claves,
listó el bucket, descargó los volcados y—porque el IAM lo permitía—los descargó. SSE-KMS hizo exactamente lo que debía: descifró para un principal autorizado.
La suposición equivocada del equipo fue sutil: “el cifrado del lado del servidor significa que el compromiso del almacenamiento no puede leer los respaldos.” Es cierto solo si el
atacante no puede convertirse en un principal que el servicio acepte. En entornos cloud, el compromiso de credenciales es todo el juego.
La solución fue cifrado del lado del cliente a una clave no accesible desde la cuenta comprometida. Cifraron los volcados con claves de destinatarios mantenidas
fuera de la cuenta cloud y subieron ciphertext. El atacante pudo robar objetos, pero eran solo ruido caro.
Micro-historia 2: La optimización que salió mal
Otra organización quería respaldos más rápidos. Notaron que la compresión tomaba tiempo y decidieron “optimizar” cifrando primero y luego comprimiendo.
La idea sonaba razonable para quienes no manejan almacenamiento: “el cifrado reduce datos; la compresión los achicará más.” Eso es al revés.
Sus artefactos se inflaron. El tiempo de transferencia se duplicó. Los costos subieron hasta que finanzas lo notó. El tiempo de restauración también empeoró,
porque ahora tenían que mover objetos más grandes antes de poder empezar la danza de descifrar y aplicar.
El problema más profundo: también perdieron cualquier chance de deduplicación en la herramienta de backup descendente, porque el cifrado aleatoriza el flujo.
Habían forzado “bytes únicos cada día”, lo que los sistemas de almacenamiento interpretan como “por favor cóbrame por todo.”
Volvieron a comprimir-antes-de-cifrar, con un nivel de compresión bajo para streaming. Los respaldos quedaron más pequeños, las transferencias se estabilizaron,
las restauraciones se aceleraron y nadie tuvo que fingir que el cambio original fue “un experimento” (lo fue).
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Un negocio regulado ejecutaba servicios Dockerizados en un par de hosts. Nada sofisticado. Hicieron una cosa poco fashion: un drill de restauración mensual.
No un ejercicio de mesa. Una restauración real en un entorno desechable, con checklist y tiempos.
Además mantenían dos rutas de descifrado: la clave normal en un sistema interno de secretos con RBAC, y una clave privada break-glass almacenada offline
con un procedimiento de recuperación documentado que requería dos personas. Era molesto, lo cual es señal de que funcionaba.
Durante un incidente—falla de almacenamiento más una reconstrucción desordenada de hosts—descubrieron que su sistema de secretos estaba temporalmente inalcanzable por trabajos de red no relacionados.
Aquí muchas organizaciones se paralizan y empiezan a improvisar. Ellos no. Invocaron la ruta break-glass, descifraron los respaldos,
restauraron Postgres y los uploads, y pusieron el negocio en marcha.
Después, el postmortem fue tranquilo. No porque tuvieran suerte, sino porque la ruta de restauración no era teórica. Había sido practicada,
cronometrada e intencionalmente aburrida.
Broma 2: Los respaldos son como paracaídas—si solo los pruebas en laboratorio, sigues haciendo “investigación”, no seguridad.
Listas de verificación / plan paso a paso
Paso a paso: implementar respaldos cifrados para un stack Docker Compose
-
Inventario del estado: lista contenedores, volúmenes, bind mounts y dependencias externas (BDs, almacenes de objetos).
Decide qué significa “restauración completa” a nivel de aplicación. -
Elige un método primario por componente:
- Postgres:
pg_dumppara portabilidad;pg_basebackuppara restauraciones grandes más rápidas (con más complejidad). - Uploads/archivos: tar+gzip desde el volumen.
- Postgres:
- Elige la herramienta y el modelo de cifrado: se recomienda age; cifra a múltiples destinatarios.
- Diseña la custodia de claves: dónde viven las claves privadas, quién puede acceder y la ruta break-glass.
- Implementa pipelines en streaming: minimiza el texto plano en disco.
- Genera metadatos de integridad: manifiestos de checksum; opcionalmente firma los manifiestos si necesitas mayor procedencia.
- Envía fuera del sitio: almacenamiento de objetos con versionado y object lock si está disponible.
- Prueba la restauración: restaura en un contenedor/volumen fresco, valida el comportamiento de la app y los conteos de datos.
- Programa drills de restauración: al menos mensuales para sistemas críticos; trimestrales mínimo para menos críticos.
- Registra y alerta sobre fallos de respaldo: el “fallo silencioso” es el estado por defecto de scripts desatendidos.
Checklist operacional: antes de rotar claves
- Lista qué objetos de respaldo están cifrados con qué clave (almacena IDs de clave/destinatarios en metadatos).
- Define ventanas de retención y asegúrate de que las claves antiguas permanezcan disponibles hasta que los datos expiren o sean re-encriptados.
- Realiza una restauración usando la ruta de “clave antigua” la semana antes de la rotación.
- Rota claves y luego realiza inmediatamente una restauración usando la ruta de “clave nueva”.
- Actualiza el runbook, no solo el código.
Checklist de incidente: necesitas restaurar ahora
- Elige el punto de restauración (RPO) y confirma que coincide con las necesidades del negocio.
- Obtén el artefacto y verifica checksum/tamaño antes de descifrar.
- Obtén la clave de descifrado vía la ruta primaria; si está bloqueada, invoca el break-glass.
- Restaura primero en objetivos limpios (volúmenes nuevos / instancia DB nueva).
- Valida a nivel de aplicación (inicios de sesión, conteo de registros, flujos críticos).
- Sólo entonces redirige el tráfico.
Preguntas frecuentes
1) ¿Debo confiar en el cifrado de disco (LUKS/EBS) para los respaldos?
No. Úsalo, pero no confíes solo en ello. El cifrado de disco protege un disco. Los respaldos se mueven. Cifra el artefacto de respaldo para que la protección viaje con él.
2) ¿Es suficiente el cifrado del lado del servidor (SSE-KMS)?
Es una base fuerte y a menudo requerida, pero no es extremo a extremo. Si un atacante obtiene acceso IAM que permita lecturas, SSE felizmente descifrará para ellos.
Añade cifrado del lado del cliente para escenarios de “compromiso de bucket/cuenta”.
3) ¿age o GPG para respaldos Docker?
Si empiezas desde cero, elige age. Es más simple y más difícil de usar mal. Usa GPG si tu organización ya tiene distribución de claves PGP y memoria operativa.
4) ¿Dónde debo guardar la clave privada para descifrar respaldos?
No en el host Docker y no al lado de los respaldos. Guárdala en un sistema de secretos controlado con registros de auditoría, más una copia offline break-glass con procedimiento de recuperación documentado.
5) ¿Los respaldos deben incluir secretos de la aplicación?
Usualmente no. Respalda datos y la configuración necesaria para redeployar, pero recupera secretos desde un sistema separado. Si debes respaldar secretos, trata ese respaldo como de mayor sensibilidad y aísla el acceso.
6) ¿Cómo evito que el texto plano aterrice en disco durante los respaldos?
Stream: dump → compress → encrypt → upload. Las tuberías son tus amigas. Valida que las herramientas intermedias no creen archivos temporales y que los logs no capturen contenido sensible.
7) ¿Los respaldos cifrados previenen ransomware?
El cifrado evita la lectura no autorizada; no evita borrados o cifrado por parte del atacante. Para resistencia a ransomware necesitas inmutabilidad (object lock, versionado, copias offline) y límites IAM fuertes.
8) ¿Por qué son lentas las restauraciones aunque el cifrado sea “rápido”?
Porque las restauraciones suelen dominarse por el tiempo de descarga, descompresión o la aplicación de la base de datos/creación de índices. Mide cada fase. Optimiza el cuello de botella real, no la herramienta sospechosa.
9) ¿A cuántos destinatarios debería cifrar?
Al menos a dos: una clave del equipo de ops (o clave de servicio) y una clave break-glass de recuperación. Más destinatarios aumentan la flexibilidad operativa pero también amplían quién puede descifrar, así que mantenlo intencional.
10) ¿Puedo respaldar /var/lib/docker y dar por terminado?
Puedes, pero probablemente no deberías. Es grande, sensible a versiones y mezcla caches con estado. Respalda volúmenes y artefactos nativos de BD; mantén el estado del demonio Docker fuera salvo que tengas una necesidad probada.
Conclusión: próximos pasos que realmente puedes hacer
Si quieres respaldos Docker cifrados que se restauren limpiamente, deja de tratar el cifrado como una casilla y trata la restauración como una característica.
El camino práctico es:
- Inventaria el estado: volúmenes, bind mounts, bases de datos y dependencias “ocultas”.
- Usa respaldos nativos de BD para bases de datos; tar para volúmenes de archivos.
- Comprime y luego cifra (en streaming cuando sea posible).
- Usa cifrado basado en destinatarios (age es una buena opción por defecto).
- Mantén las claves fuera del host; proporciona una ruta break-glass independiente y documentada.
- Haz drills de restauración rutinarios y medibles.
- Añade inmutabilidad/versionado para proteger la existencia del respaldo, no solo la confidencialidad.
Haz eso, y tu próxima restauración no será un thriller. Será trabajo. Aburrido. El mejor tipo.