Cómo implementar Chatwoot self-hosted en producción: guía Docker Swarm 2026

📅 Publicado 2 may 2026 ⏱ Lectura ~14 min 🔧 Por operadores, no reseñadores

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:

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:

ServicioQué haceRecursos típicos
chatwoot (rails app)Aplicación principal1-2 vCPU, 1.5GB RAM
chatwoot-sidekiqBackground jobs (emails, notificaciones)1 vCPU, 1GB RAM
postgresBase de datos principal1-2 vCPU, 2GB RAM, SSD
redisQueue + cache + websockets0.5 vCPU, 512MB RAM
traefikReverse proxy + SSL automático0.2 vCPU, 256MB RAM
postgres-backupBackup automático cada 6hsolo cuando corre
monitoring (opcional)Prometheus + Grafana1 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:

  1. VPS Linux (Ubuntu 22.04 LTS preferido), mínimo 4GB RAM + 80GB SSD.
  2. Dominio apuntado al VPS con A record (ej: chat.tuempresa.cl).
  3. Puertos 80 + 443 abiertos en firewall.
  4. Docker Engine + docker-compose v2 instalados.
  5. Docker Swarm inicializado: docker swarm init
  6. Acceso SMTP para envío de emails (recomendado: SES, SendGrid, Postmark).
  7. 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:

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:

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

ConceptoCosto 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 mensualUSD 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 WhatsApp

Preguntas 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.