Auditoría de Robustez Infraestructural — CreaRack Pro SaaS
Fecha: 04-04-2026 Contexto: Evaluación post-incidentes durante sesión de hardening Objetivo: Determinar si la infraestructura actual es suficientemente robusta para producción pública Audiencia: Equipo CreaRack (Edu, Dani, Txell)
Resumen Ejecutivo
Veredicto: La infraestructura actual NO está lista para producción pública con clientes reales.
La capa de aplicación (Django, APIs, seguridad, auth) es sólida y madura. Pero la capa de infraestructura y despliegue tiene fragilidades críticas que se evidenciaron durante la sesión del 04-04-2026. El sistema funciona para uso interno/demo, pero carece de la resiliencia necesaria para garantizar SLA a clientes.
1. Lecciones Aprendidas (04-04-2026)
Incidentes del día (en orden cronológico)
| # | Incidente | Causa raíz | Tiempo caído | Severidad |
|---|---|---|---|---|
| 1 | PG 16→18: contenedor con nombre incorrecto | docker compose usa directorio como project name, no el de Dokploy | 2 min | Bajo |
| 2 | pgbouncer en prod: web no resuelve DNS | Dokploy crea containers en dokploy-network, aislada de crearack_internal donde vive pgbouncer | ~15 min | Alto |
| 3 | docker swarm leave: Dokploy destruido | Dokploy corre como servicio Swarm — sin Swarm, desaparece | ~30 min | Crítico |
| 4 | Eliminar ports: 8000: sitio caído | Dokploy/Traefik necesita el port mapping para enrutar tráfico al container | ~10 min | Alto |
| 5 | Traefik 404 persistente | Traefik cacheó error de Swarm; necesitó recreación completa + redeploy Dokploy | ~15 min | Alto |
| 6 | Dokploy DB password mismatch | Reinstalación generó nuevo Docker secret pero PG conservó password viejo | 5 min | Medio |
Patrones problemáticos identificados
1. No existe entorno de staging Todos los cambios de infraestructura van directamente a producción. No hay forma de probar un cambio de compose, una migración de DB, o un nuevo servicio sin afectar al sistema en vivo.
2. Dokploy es una caja negra No comprendemos completamente cómo Dokploy gestiona:
- Redes Docker (crea
dokploy-networkseparada) - Labels de Traefik (los inyecta en el deploy, no están en el compose)
- Dependencia con Docker Swarm (servicio Swarm, no container standalone)
- Interacción con
docker compose upmanual (conflictos de red/labels)
3. docker compose up manual vs Dokploy son incompatibles
Ejecutar docker compose -p crearack-pro-zcmvsl up -d desde SSH crea containers sin los labels de Traefik que Dokploy inyecta. Resultado: el container existe pero Traefik no lo ve → 404.
4. Sin rollback automatizado Cuando algo falla, el rollback es manual: editar compose, re-subir, redesplegar. No hay “revert to last working state” con un click.
5. Las reglas iptables son frágiles
Docker puede resetear la cadena DOCKER-USER en reinicios. netfilter-persistent ayuda pero no es 100% fiable con Docker. Cualquier docker restart puede perder reglas.
2. Auditoría de Tecnologías del Stack SaaS
2.1 Dokploy (Plataforma de Despliegue)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Versión | v0.28.8 | Proyecto relativamente joven (< 2 años) |
| Dependencia | Docker Swarm obligatorio | No se puede eliminar Swarm |
| Networking | Red propia dokploy-network | Servicios adicionales (pgbouncer) no son accesibles |
| Rollback | Manual (redeploy versión anterior) | Sin rollback automático |
| Backups | Tiene su propia PG + Redis | Se pierden si Swarm se destruye |
| Monitoreo | Sin alertas de salud | Si Dokploy cae, nadie se entera |
| HA | Single instance | Si el servidor cae, todo cae |
Evaluación: Dokploy simplifica el deploy pero añade complejidad oculta. Para un SaaS público, considerar migrar a una plataforma más madura (Coolify, CapRover) o gestionar Traefik+Docker directamente sin intermediario.
Recomendación: A corto plazo, documentar exactamente cómo Dokploy gestiona redes y labels. A medio plazo, evaluar alternativas.
2.2 Docker Swarm (Orquestación)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Uso real | Solo para Dokploy | Overhead innecesario |
| Nodos | Single node | No aporta HA |
| Autolock | Deshabilitado | Encryption keys no protegidas en restart |
| Puertos expuestos | 2377, 7946 | Superficie de ataque innecesaria |
Evaluación: Swarm está forzado por Dokploy, no por necesidad real. Un single-node Swarm no aporta resiliencia. Añade complejidad (services vs containers, secrets vs env vars, redes overlay).
Recomendación: Aceptar como dependencia de Dokploy. No tocar. Si se migra de Dokploy, eliminar Swarm.
2.3 Traefik (Reverse Proxy / SSL)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Versión | v3.6.7 | Actual ✅ |
| SSL | Let’s Encrypt ACME httpChallenge | Funcional, auto-renewal |
| Email ACME | info@crearack.com (corregido hoy) | Recibirá alertas de expiración ✅ |
| Routing | Via Docker labels (Dokploy los gestiona) | Opaco — no controlamos los labels directamente |
| Config | /etc/dokploy/traefik/ | Separada del repo — cambios manuales en servidor |
| Fallback | 404 si no encuentra ruta | Sin página de error personalizada |
| WAF | No | Sin protección contra ataques L7 |
Evaluación: Traefik funciona bien como reverse proxy pero la gestión via Dokploy lo hace opaco. Los labels se inyectan en deploy time y no son visibles en el compose.
Recomendación: Documentar la configuración de Traefik. Considerar añadir Traefik middlewares para rate limiting a nivel proxy (independiente de Django).
2.4 PostgreSQL 18 (Base de Datos)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Versión | 18.3 (migrado hoy) | Última estable ✅ |
| max_connections | 500 | Suficiente sin pgbouncer |
| Backups | pg_dump diario (Huey task 3:30 AM) + verificación ZIP | ✅ |
| RLS | 34 policies activas | ✅ Multi-tenancy |
| pg_stat_statements | Activado | ✅ Slow query tracking |
| Connection monitoring | Huey task cada 5 min, alerta 80% | ✅ |
| Replicación | No | ⚠️ Single point of failure |
| Point-in-time recovery | No (solo pg_dump diarios) | ⚠️ Hasta 24h de pérdida |
| pgbouncer | No (incompatible con Dokploy networking) | ⚠️ Sin connection pooling |
| Volumen | Docker named volume en host | ⚠️ Si disco falla, datos perdidos |
Evaluación: La DB es sólida funcionalmente pero tiene un SPOF crítico. Sin replicación, sin PITR, sin backups offsite. Un fallo de disco = pérdida total.
Recomendación:
- Inmediato: Copiar backups diarios a almacenamiento externo (Hetzner Object Storage, ~€5/mes)
- Medio plazo: Habilitar WAL archiving para PITR (minutos de pérdida vs horas)
- Largo plazo: Read replica para HA
2.5 Valkey / Redis (Cache + Broker)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Versión | 7.2 | ✅ |
| Persistencia | AOF habilitado | ✅ |
| Password | Configurado via env var | ✅ |
| Exposición | Solo red interna Docker | ✅ |
| HA | Single instance | ⚠️ Si cae, rate limiting falla (fail-open) |
| Maxmemory | 512MB + allkeys-lru | ✅ |
Evaluación: Adecuado para el volumen actual. El fail-open del rate limiter es aceptable.
2.6 VictoriaMetrics (Time-Series)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Versión | v1.106.1 | ✅ |
| Retención | 180 días | ✅ |
| Exposición | Solo red interna Docker | ✅ |
| Backups | No | ⚠️ Métricas históricas se pierden si volumen falla |
| HA | Single instance | ⚠️ |
Evaluación: Funcional para monitoreo. No es crítico para el negocio (métricas se pueden repoblar desde dispositivos).
2.7 Daphne (Servidor ASGI)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Versión | 4.2.1 | ✅ |
| WebSockets | Funcional | ✅ |
| Workers | Single process | ⚠️ No escala horizontalmente |
| Graceful shutdown | 30s stop_grace_period | ✅ |
| Server header | Oculto (middleware) | ✅ |
Evaluación: Daphne es estable pero single-process. Para escalar, considerar múltiples réplicas detrás de Traefik (requiere session affinity para WebSockets).
2.8 Hetzner Cloud (Hosting)
| Aspecto | Estado | Riesgo |
|---|---|---|
| Tipo | CCX (dedicated vCPU) | ✅ Rendimiento consistente |
| Datacenter | EU (Alemania) | ✅ GDPR compliance |
| Firewall | Hetzner Cloud Firewall activo | ✅ |
| Backups servidor | No configurados | ⚠️ |
| Snapshots | No programados | ⚠️ |
| Failover | No (single server) | ⚠️ SPOF |
Evaluación: Hetzner es fiable y económico. Pero estamos en un solo servidor sin failover ni snapshots automáticos.
Recomendación: Activar snapshots semanales de Hetzner (~€2/mes por 20GB). Proporciona rollback completo del servidor.
2.9 iptables / Firewall Host
| Aspecto | Estado | Riesgo |
|---|---|---|
| UFW | Inactivo | ⚠️ |
| iptables DOCKER-USER | 5 reglas (8000 block, 3000 restrict) | ✅ |
| Persistencia | netfilter-persistent instalado | ⚠️ Docker puede resetear en restart |
| Hetzner Cloud Firewall | Activo, 5 reglas | ✅ |
Evaluación: Doble capa funcional pero frágil. Las reglas iptables pueden perderse con reinicios de Docker.
Recomendación: Crear script /root/restore-firewall.sh que se ejecute en boot como systemd service, independiente de netfilter-persistent.
3. Matriz de Single Points of Failure (SPOF)
| Componente | SPOF | Impacto si falla | Mitigación actual | Mitigación recomendada |
|---|---|---|---|---|
| Servidor Hetzner | ✅ Sí | Todo caído | Ninguna | Snapshot semanal + plan DR |
| PostgreSQL | ✅ Sí | App inutilizable | pg_dump diario | Backup offsite + WAL archiving |
| Disco/Volumen | ✅ Sí | Pérdida total datos | pg_dump en mismo disco | Backup en Object Storage externo |
| Dokploy | ✅ Sí | No se puede desplegar | Redeploy manual via SSH | Documentar deploy manual sin Dokploy |
| Traefik | ✅ Sí | Sin HTTPS ni routing | docker start | Auto-restart (unless-stopped) ✅ |
| Valkey | ✅ Sí | Rate limit off, Huey parado | AOF persistencia | Aceptable (fail-open) |
| DNS (Cloudflare) | ❌ No | — | Cloudflare HA global | ✅ Ya mitigado |
4. Comparativa: Estado Actual vs Producción Pública
| Requisito | Estado actual | Necesario para SaaS público |
|---|---|---|
| Uptime SLA 99.9% | ❌ No garantizado | ✅ Sí |
| Backup offsite | ❌ Solo local | ✅ Sí |
| Disaster recovery plan | ❌ No existe | ✅ Sí |
| Staging environment | ❌ No existe | ✅ Sí |
| Monitoring/alertas | ⚠️ Parcial (Huey tasks) | ✅ Alertas externas (email/Slack) |
| Rollback automatizado | ❌ Manual | ✅ Sí |
| Escalado horizontal | ❌ Single instance | ⚠️ Deseable |
| Connection pooling | ❌ Revertido | ⚠️ Deseable |
| WAF | ❌ No | ⚠️ Deseable |
| Log aggregation | ❌ Solo docker logs | ⚠️ Deseable |
| SSL monitoring | ❌ Solo ACME auto-renew | ✅ Alertas de expiración |
| Load testing | ❌ Nunca realizado | ✅ Sí |
5. Plan de Fortalecimiento (Priorizado)
Fase 1 — Fundamentos (1-2 semanas)
| # | Acción | Esfuerzo | Impacto |
|---|---|---|---|
| 1 | Backup offsite: pg_dump diario → Hetzner Object Storage | 4h | Crítico |
| 2 | Snapshots Hetzner: Activar snapshots semanales del servidor | 10 min | Crítico |
| 3 | Disaster Recovery doc: Procedimiento paso a paso para restaurar desde cero | 4h | Crítico |
| 4 | Script firewall boot: systemd service que restaura iptables en cada boot | 1h | Alto |
| 5 | Dokploy doc interna: Documentar exactamente cómo gestiona redes, labels, Swarm | 2h | Alto |
Fase 2 — Observabilidad (2-4 semanas)
| # | Acción | Esfuerzo | Impacto |
|---|---|---|---|
| 6 | Uptime monitoring externo: Servicio externo (UptimeRobot, Betterstack) que alerte si crearack.com cae | 30 min | Crítico |
| 7 | Alertas email para backups: Notificación si backup falla o DB connections > 80% | 2h | Alto |
| 8 | SSL expiry alert: Monitor externo que alerte 30 días antes de expiración | 30 min | Medio |
Fase 3 — Resiliencia (1-2 meses)
| # | Acción | Esfuerzo | Impacto |
|---|---|---|---|
| 9 | Staging environment: Segundo servidor Hetzner (CX21, ~€6/mes) con Dokploy clone | 1 día | Alto |
| 10 | WAL archiving: Point-in-time recovery para PostgreSQL | 4h | Alto |
| 11 | Load testing: Pruebas con k6/locust para determinar capacidad real | 1 día | Medio |
| 12 | pgbouncer via Dokploy: Configurar pgbouncer como servicio gestionado por Dokploy | 4h | Medio |
Fase 4 — Escala (cuando haya clientes)
| # | Acción | Esfuerzo | Impacto |
|---|---|---|---|
| 13 | Read replica PostgreSQL: HA para base de datos | 1 día | Alto |
| 14 | Múltiples workers Daphne: Escalar horizontalmente detrás de Traefik | 4h | Medio |
| 15 | CDN para static/media: Cloudflare o Hetzner CDN | 4h | Medio |
| 16 | Log aggregation: Loki o similar para centralizar logs | 1 día | Medio |
6. Conclusión
La plataforma CreaRack Pro tiene una capa de aplicación madura y bien protegida (509 endpoints, RLS, CSP, rate limiting, CSRF, MFA). El código es sólido.
La capa de infraestructura es funcional pero frágil. Los incidentes del 04-04-2026 demostraron que:
- Un solo error de infraestructura puede tumbar el sistema — sin staging, cada cambio es un riesgo directo
- Dokploy simplifica pero oscurece — la interacción entre Dokploy, Swarm, Traefik y Docker Compose manual es fuente de conflictos
- No hay red de seguridad — sin backups offsite, sin monitoring externo, sin DR plan
Para uso interno/demo: El sistema actual es adecuado. Para SaaS público con clientes: Se necesitan las Fases 1 y 2 como mínimo antes de aceptar clientes de pago.
El coste estimado de las Fases 1+2 es de ~2 semanas de trabajo + ~€10/mes adicionales en infraestructura. Es una inversión pequeña comparada con el riesgo de perder datos de un cliente.
Generado por: Claude (Anthropic) + Edu Fecha: 04-04-2026
Véase también
- [[crearack-tech—reports—audit-punto-cero-04-04-2026]] — auditoría punto cero v1.0.51
- [[crearack-tech—reports—security-audit-04-04-2026]] — auditoría de seguridad crearack.com
- [[crearack-tech—guides—disaster-recovery]] — procedimiento de disaster recovery
- [[crearack-tech—guides—production-deployment]] — deploy en producción Hetzner
- [[crearack-tech—guides—capacity-planning]] — capacity planning SaaS
- [[crearack-tech—admin—dokploy-internals]] — internals de Dokploy
- [[decision—20260315—postgres-18-pgbouncer]] — ADR migración a PostgreSQL 18 + pgbouncer