Cómo implementar Chatwoot self-hosted en producción: guía Docker Swarm 2026
Hay 200 tutoriales de "instalá Chatwoot en 5 minutos con docker-compose". Funcionan para hacer una demo. Se rompen el primer día que un cliente real lo usa en producción. Esta guía es lo que necesitás para implementar Chatwoot self-hosted de verdad: Docker Swarm como orchestrator, Postgres + Redis dedicados, Traefik para SSL automático, backup testeado, monitoreo, y multi-tenant si vas a operar varios clientes en una sola instancia.
Por qué Docker Swarm y no docker-compose plano
La pregunta razonable: "¿no es más simple docker-compose?". Sí, es más simple — y se rompe en cuanto necesitás:
- Rolling updates sin downtime: Docker Swarm hace update de servicios uno a uno, manteniendo el pool de réplicas.
- Restart automático: si un container falla, Swarm lo reinicia. docker-compose plano no.
- Secrets management: credenciales fuera del compose file, encriptadas en el cluster.
- Networking interno: servicios se ven entre sí por nombre sin exponer puertos.
- Healthchecks que importan: si un container responde 200 pero la app está rota, Swarm lo detecta.
Si vas a operar Chatwoot en producción real, Docker Swarm es el mínimo viable. Kubernetes es overkill para PYMEs y agencias — Swarm tiene 90% del valor a 10% de la complejidad operativa.
Stack de servicios necesarios
Una instalación Chatwoot production-grade tiene estos servicios:
| Servicio | Qué hace | Recursos típicos |
|---|---|---|
| chatwoot (rails app) | Aplicación principal | 1-2 vCPU, 1.5GB RAM |
| chatwoot-sidekiq | Background jobs (emails, notificaciones) | 1 vCPU, 1GB RAM |
| postgres | Base de datos principal | 1-2 vCPU, 2GB RAM, SSD |
| redis | Queue + cache + websockets | 0.5 vCPU, 512MB RAM |
| traefik | Reverse proxy + SSL automático | 0.2 vCPU, 256MB RAM |
| postgres-backup | Backup automático cada 6h | solo cuando corre |
| monitoring (opcional) | Prometheus + Grafana | 1 vCPU, 1GB RAM |
Para 1 cliente con 5-15 agentes: VPS 4GB RAM alcanza. Para 5 clientes con 50 agentes total: VPS 8-16GB. Para escalar más, separás postgres a su propia VM.
Pre-requisitos en el VPS
Antes de empezar el deploy de Chatwoot necesitás:
- VPS Linux (Ubuntu 22.04 LTS preferido), mínimo 4GB RAM + 80GB SSD.
- Dominio apuntado al VPS con A record (ej: chat.tuempresa.cl).
- Puertos 80 + 443 abiertos en firewall.
- Docker Engine + docker-compose v2 instalados.
- Docker Swarm inicializado:
docker swarm init - Acceso SMTP para envío de emails (recomendado: SES, SendGrid, Postmark).
- Storage S3-compatible para attachments (recomendado: AWS S3, Backblaze B2, MinIO self-hosted).
Stack file (docker-stack.yml) production-ready
El stack file de Swarm define todos los servicios. Versión simplificada (con secrets, omitiendo healthchecks por brevedad):
version: '3.8'
services:
chatwoot:
image: chatwoot/chatwoot:v3.x
deploy:
replicas: 2
restart_policy: { condition: on-failure }
update_config: { parallelism: 1, delay: 30s, failure_action: rollback }
environment:
- SECRET_KEY_BASE_FILE=/run/secrets/secret_key_base
- POSTGRES_HOST=postgres
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
- REDIS_URL=redis://redis:6379
- FRONTEND_URL=https://chat.tuempresa.cl
- DEFAULT_LOCALE=es
- SMTP_ADDRESS=email-smtp.us-east-1.amazonaws.com
- SMTP_PORT=587
- SMTP_USERNAME_FILE=/run/secrets/smtp_username
- SMTP_PASSWORD_FILE=/run/secrets/smtp_password
- ACTIVE_STORAGE_SERVICE=amazon
secrets:
- secret_key_base
- db_password
- smtp_username
- smtp_password
networks: [internal, web]
postgres:
image: postgres:15
deploy:
placement:
constraints: [node.role == manager]
environment:
- POSTGRES_DB=chatwoot
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
volumes:
- postgres_data:/var/lib/postgresql/data
secrets: [db_password]
networks: [internal]
redis:
image: redis:7-alpine
volumes: [redis_data:/data]
networks: [internal]
traefik:
image: traefik:v3
ports: ["80:80", "443:443"]
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik_certs:/certs
deploy:
placement: { constraints: [node.role == manager] }
labels:
- "traefik.http.routers.chatwoot.rule=Host(`chat.tuempresa.cl`)"
- "traefik.http.routers.chatwoot.tls.certresolver=le"
networks: [web]
secrets:
secret_key_base: { external: true }
db_password: { external: true }
smtp_username: { external: true }
smtp_password: { external: true }
volumes:
postgres_data:
redis_data:
traefik_certs:
networks:
internal: { driver: overlay }
web: { driver: overlay }
Crear los secrets primero: printf "tu-secret" | docker secret create db_password -
Deploy: docker stack deploy -c docker-stack.yml chatwoot
Configuración crítica que casi todos los tutoriales saltean
1. Backup automático de Postgres
Sin backup automático, el primer crash de Postgres te puede costar el negocio del cliente. Setup mínimo:
# Container que corre cada 6 horas y sube a S3:
postgres-backup:
image: prodrigestivill/postgres-backup-local:15
environment:
- POSTGRES_HOST=postgres
- POSTGRES_DB=chatwoot
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
- SCHEDULE=@every 6h
- BACKUP_KEEP_DAYS=30
- BACKUP_KEEP_WEEKS=4
- BACKUP_KEEP_MONTHS=6
volumes:
- postgres_backups:/backups
Crítico: testear el restore al menos 1 vez/mes. Backup que nunca se restauró no es backup, es deuda técnica con falsa sensación de seguridad.
2. Monitoreo proactivo
Mínimo: healthcheck endpoint + alerta Slack/SMS si baja. Ideal: Prometheus + Grafana con dashboards de:
- Tiempo de respuesta de la app (p50, p95, p99)
- Queue depth de Sidekiq (jobs pendientes)
- Disk usage de Postgres
- Memoria + CPU de cada container
- Tasa de error 5xx
3. SSL automático con Traefik + Let's Encrypt
Las labels en el servicio Traefik del stack file se encargan de pedir el certificado a Let's Encrypt automáticamente. Renovación cada 60 días sin intervención. Si usás multi-tenant (varios dominios), Traefik también lo maneja: cada cliente tiene su propio dominio + certificado.
Multi-tenant: una instancia, varios clientes
Chatwoot soporta multi-tenant nativamente — una instancia puede servir a múltiples cuentas/clientes con isolation. Pero el setup multi-tenant en producción tiene algunos puntos críticos:
- Dominio dedicado por cliente: chat.cliente1.cl, chat.cliente2.cl. Traefik routea por host header.
- Account isolation: Chatwoot tiene el concepto de "Account" — agentes y conversaciones quedan aisladas por account.
- Recursos compartidos pero medidos: el VPS sirve a todos, pero conviene tener métricas por cliente para detectar cuál genera más carga.
- Backups segregados: el dump de postgres tiene todos los clientes — si un cliente exige sus datos extraídos, se hace via Chatwoot API + filtro por account_id.
Recomendación: para 1-3 clientes muy grandes (50+ agentes c/u), conviene 1 VPS por cliente. Para 5-15 clientes pequeños/medianos (5-20 agentes c/u), multi-tenant en 1 VPS sale más eficiente.
Errores típicos en deploy y cómo evitarlos
1. "No me llegan los emails"
99% de las veces es config SMTP mal puesta. Validar con: docker exec -it $(docker ps -q -f name=chatwoot) bundle exec rails runner "ActionMailer::Base.mail(to: 'tu@email.com', from: 'no-reply@tuempresa.cl', subject: 'Test', body: 'OK').deliver_now"
2. "WhatsApp Cloud API no funciona"
Casi siempre es webhook URL mal configurada en Meta Developer Console. Debe apuntar a: https://chat.tuempresa.cl/webhooks/whatsapp/{phone_number_id} con verify token coincidente.
3. "La app está lenta"
Casi siempre Sidekiq queue saturada (jobs pendientes). Subir réplicas de Sidekiq de 1 a 2-3, o aumentar concurrency. Si Postgres es el cuello, separarlo a su propia VM dedicada.
4. "El SSL expiró y nadie se enteró"
Solo pasa si Traefik no tiene healthcheck o no lo monitoreás. La renovación de Let's Encrypt es automática — pero si Traefik está caído cuando le toca renovar, ahí pasa. Solución: monitor + alerta sobre días-hasta-expiración del certificado.
Costo total de operación a 12 meses
| Concepto | Costo mensual |
|---|---|
| VPS 8GB RAM (DigitalOcean / Hetzner) | USD 24-32 |
| S3 bucket attachments (50GB/mes) | USD 1-3 |
| SES email (10K emails/mes) | USD 1 |
| WhatsApp Cloud API (5K conversaciones/mes) | USD 25-100 |
| Backup S3 (10GB diario) | USD 0,30 |
| Operación managed (4-8h/mes a USD 35) | USD 140-280 |
| Total mensual | USD 200-440 |
Comparable: Intercom Advanced para 20 agentes = USD 1.176/mes. Diferencial anual: USD ~10.000-12.000.
¿Necesitás implementar Chatwoot self-hosted en producción?
Operamos Chatwoot en Docker Swarm para 23 clientes activos. Implementación + operación managed para que tu equipo no se preocupe de infra, backups, ni updates.
Hablar por WhatsAppPreguntas frecuentes
¿Puedo usar Kubernetes en lugar de Docker Swarm?
Sí, Chatwoot tiene Helm chart oficial para Kubernetes. La pregunta correcta no es "¿puedo?" sino "¿necesito?". Para 1-50 agentes, Swarm es más que suficiente y 5× más fácil de operar. Si ya tenés cluster Kubernetes corriendo otras apps, agregá Chatwoot ahí. Si no, no instales Kubernetes solo para Chatwoot.
¿Qué pasa si Postgres se corrompe?
Por eso el backup automático cada 6h es no-negociable. Restore: 1) Stop chatwoot service, 2) docker exec postgres pg_restore desde último backup válido, 3) Restart chatwoot. Tiempo total con backup reciente: 15-30 minutos. Sin backup: el negocio del cliente se detuvo y vos sos el responsable. Por eso testeamos el restore mensualmente.
¿Cómo escalo si crezco a 100+ agentes?
Tres pasos en orden: 1) Subir VPS a 16-32GB RAM (cubre hasta ~100 agentes simultáneos), 2) Separar Postgres a su propia VM dedicada (libera RAM del app server), 3) Si seguís creciendo, escalar horizontalmente: agregar nodes Swarm worker para correr más réplicas de chatwoot + sidekiq. Postgres puede stay en master con réplicas read-only para reporting.
¿Multi-tenant es seguro para clientes con datos sensibles?
Chatwoot tiene account isolation a nivel aplicación — un agente del cliente A no puede ver datos del cliente B. Pero a nivel base de datos, todo está en el mismo Postgres. Para clientes con datos altamente sensibles (salud, fintech regulada, legal), recomendamos VPS dedicado por cliente — más caro (~USD 100-200/mes adicionales por cliente) pero isolation a nivel infraestructura, no solo aplicación.
¿Cuánto tiempo demora el setup completo production-ready?
Setup técnico (deploy + config + backup + monitoreo + SSL): 6-12 horas con un operador experimentado. Implementación con cliente real (training agentes, configurar inboxes, conectar WhatsApp, importar contactos, custom branding): 2-4 semanas. La diferencia importa: un setup técnico sin la implementación cliente termina como una app vacía sin uso.