Chatwoot es una plataforma de atención al cliente de código abierto que reúne en una sola bandeja las conversaciones del chat de tu web, el correo, WhatsApp, Telegram y otros canales, con asignación a agentes, etiquetas y respuestas predefinidas. En este tutorial desplegarás Chatwoot en Ubuntu 24.04 con el archivo de Docker Compose de producción del proyecto, lo publicarás detrás de Nginx con un certificado de Let's Encrypt, crearás la cuenta de administrador y añadirás el widget de chat en vivo a una web.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 4 GB de RAM y 2 vCPU. Chatwoot ejecuta Rails, Sidekiq, PostgreSQL y Redis a la vez.
  • Unos 20 GB libres en disco para las imágenes, la base de datos y los adjuntos.
  • Un usuario no root con privilegios sudo.
  • Docker Engine y el plugin Docker Compose instalados desde el repositorio oficial de Docker.
  • Un subdominio (en esta guía, chat.your_domain) con un registro DNS A que apunte a la IP pública del servidor.
  • Los puertos 80 y 443 accesibles desde Internet.
  • Una cuenta SMTP para enviar las invitaciones a agentes y las notificaciones por correo.

Comprueba que Docker y Compose responden:

docker --version
docker compose version

Paso 1: Descargar la configuración de Chatwoot

Chatwoot mantiene un archivo de Compose de producción y una plantilla de variables de entorno en su repositorio. Crea el directorio del proyecto y descarga ambos:

sudo mkdir -p /opt/chatwoot
cd /opt/chatwoot
sudo wget -O .env https://raw.githubusercontent.com/chatwoot/chatwoot/develop/.env.example
sudo wget -O docker-compose.yaml https://raw.githubusercontent.com/chatwoot/chatwoot/develop/docker-compose.production.yaml
sudo chmod 600 .env

El archivo de Compose define cuatro servicios: rails (la aplicación web), sidekiq (tareas en segundo plano), postgres y redis. Los puertos de los cuatro se publican solo en 127.0.0.1, así que ninguno queda expuesto a Internet.

Paso 2: Configurar las variables de entorno

Genera los tres secretos que necesitas y apúntalos:

echo "SECRET_KEY_BASE: $(openssl rand -hex 64)"
echo "POSTGRES_PASSWORD: $(openssl rand -hex 24)"
echo "REDIS_PASSWORD: $(openssl rand -hex 24)"

Edita el archivo .env:

sudo nano /opt/chatwoot/.env

Busca estas variables y dales valor. Algunas ya existen en la plantilla con un valor de ejemplo o vacío; cámbialas en su sitio en lugar de duplicarlas:

SECRET_KEY_BASE=your_secret_key_base
FRONTEND_URL=https://chat.your_domain
DEFAULT_LOCALE=es
ENABLE_ACCOUNT_SIGNUP=false

POSTGRES_HOST=postgres
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=your_postgres_password

REDIS_URL=redis://redis:6379
REDIS_PASSWORD=your_redis_password

MAILER_SENDER_EMAIL=Soporte <soporte@your_domain>
SMTP_DOMAIN=your_domain
SMTP_ADDRESS=smtp.your_provider.com
SMTP_PORT=587
SMTP_USERNAME=your_smtp_user
SMTP_PASSWORD=your_smtp_password
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=true
  • FRONTEND_URL es la URL pública de la instancia. Chatwoot la usa en los enlaces de los correos y en el código del widget.
  • ENABLE_ACCOUNT_SIGNUP=false impide que cualquiera cree cuentas nuevas desde la página de registro. Tus agentes entrarán por invitación.
  • SMTP_* y MAILER_SENDER_EMAIL configuran el correo saliente.

El contenedor de PostgreSQL toma su contraseña del archivo de Compose, no de .env. Edita docker-compose.yaml:

sudo nano /opt/chatwoot/docker-compose.yaml

En el servicio postgres, pon en POSTGRES_PASSWORD el mismo valor que usaste en .env:

    environment:
      - POSTGRES_DB=chatwoot
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=your_postgres_password

Paso 3: Preparar la base de datos y arrancar Chatwoot

Antes del primer arranque hay que crear la base de datos y aplicar las migraciones. Esta tarea arranca PostgreSQL y Redis, ejecuta la preparación en un contenedor temporal y lo elimina al terminar:

cd /opt/chatwoot
sudo docker compose run --rm rails bundle exec rails db:chatwoot_prepare

La primera vez tarda unos minutos, porque descarga las imágenes y crea todas las tablas. Después arranca todos los servicios:

sudo docker compose up -d

Comprueba que los cuatro contenedores están en marcha:

sudo docker compose ps
NAME                  SERVICE    STATUS          PORTS
chatwoot-postgres-1   postgres   Up 2 minutes    127.0.0.1:5432->5432/tcp
chatwoot-rails-1      rails      Up 40 seconds   127.0.0.1:3000->3000/tcp
chatwoot-redis-1      redis      Up 2 minutes    127.0.0.1:6379->6379/tcp
chatwoot-sidekiq-1    sidekiq    Up 40 seconds

Verifica que la API responde:

curl -I http://127.0.0.1:3000/api
HTTP/1.1 200 OK

Si Rails tarda en responder o se reinicia, revisa los registros con sudo docker compose logs rails. Los errores de autenticación contra PostgreSQL indican que las contraseñas de .env y docker-compose.yaml no coinciden.

Paso 4: Configurar Nginx y HTTPS

Instala Nginx y Certbot:

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx

Crea el bloque de servidor:

sudo nano /etc/nginx/sites-available/chatwoot

Añade esta configuración. underscores_in_headers on es necesario porque la API de Chatwoot se autentica con la cabecera api_access_token, que Nginx descartaría por llevar guiones bajos. Las cabeceras Upgrade y Connection permiten el WebSocket (/cable) que actualiza las conversaciones en tiempo real:

server {
    listen 80;
    listen [::]:80;
    server_name chat.your_domain;

    underscores_in_headers on;
    client_max_body_size 40M;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_buffering off;
        proxy_read_timeout 120s;
    }
}

Activa el sitio y recarga Nginx:

sudo ln -s /etc/nginx/sites-available/chatwoot /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Si usas UFW, permite SSH y el tráfico web:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Obtén el certificado. Certbot añade la configuración TLS y la redirección a HTTPS:

sudo certbot --nginx -d chat.your_domain

Comprueba que la renovación automática funcionará:

sudo certbot renew --dry-run

Paso 5: Crear la cuenta de administrador

Abre https://chat.your_domain. En el primer acceso, Chatwoot muestra la pantalla de configuración inicial, donde indicas tu nombre, el nombre de la empresa, tu correo y una contraseña. Esa cuenta es la del superadministrador de la instalación y la del administrador de la primera cuenta de empresa.

Además del panel normal, el superadministrador tiene acceso a https://chat.your_domain/super_admin, donde se gestionan las cuentas de empresa, los usuarios y los ajustes globales de la instalación.

Paso 6: Invitar agentes y organizar el equipo

Desde el panel, en Ajustes (Settings):

  1. Abre Agentes y pulsa Añadir agente. Indica nombre, correo y rol: Administrador puede cambiar la configuración de la cuenta; Agente solo atiende conversaciones.
  2. El agente recibe un correo con el enlace para establecer su contraseña. Si no llega, revisa la configuración SMTP del paso 2.
  3. En Equipos, crea grupos (por ejemplo, Ventas y Soporte técnico) para asignar conversaciones a un equipo completo.
  4. En Etiquetas, crea las etiquetas con las que clasificaréis las conversaciones.

Paso 7: Añadir el chat en vivo a tu web

Cada canal de Chatwoot es una bandeja de entrada (inbox). Para el chat de tu web:

  1. En Ajustes, abre Bandejas de entrada y pulsa Añadir bandeja de entrada.
  2. Elige Sitio web, escribe el nombre y el dominio de tu web, y personaliza el color y el mensaje de bienvenida.
  3. Selecciona los agentes que atenderán esa bandeja.
  4. Copia el fragmento de código JavaScript que muestra Chatwoot al terminar.

Pega ese fragmento justo antes de la etiqueta </body> de tu web. El script carga el widget desde https://chat.your_domain, por lo que funciona desde cualquier dominio.

Para verificarlo, abre tu web en una ventana privada, pulsa la burbuja del chat y envía un mensaje. La conversación aparece al momento en Conversaciones del panel de Chatwoot; responde desde allí y comprueba que la respuesta llega al widget sin recargar la página. Si solo aparece al recargar, el WebSocket no está pasando por Nginx.

Paso 8: Copias de seguridad y actualizaciones

Los datos de Chatwoot están en la base de datos PostgreSQL y en el volumen storage_data, que guarda los adjuntos y avatares. Crea el directorio de copias:

sudo mkdir -p /var/backups/chatwoot
sudo chmod 700 /var/backups/chatwoot
cd /opt/chatwoot

Vuelca PostgreSQL con pg_dumpall, que incluye todas las bases de datos y roles del contenedor:

sudo docker compose exec -T postgres pg_dumpall -U postgres \
  | gzip | sudo tee "/var/backups/chatwoot/chatwoot-db-$(date +%Y%m%d).sql.gz" > /dev/null

Localiza el nombre del volumen de almacenamiento. Compose le antepone el nombre del proyecto, que es el del directorio:

sudo docker volume ls --filter name=storage_data
DRIVER    VOLUME NAME
local     chatwoot_storage_data

Copia su contenido:

sudo docker run --rm \
  -v chatwoot_storage_data:/data:ro \
  -v /var/backups/chatwoot:/backup \
  alpine tar -czf "/backup/chatwoot-storage-$(date +%Y%m%d).tar.gz" -C /data .

Guarda también una copia de .env y docker-compose.yaml, y lleva todo fuera del servidor.

Para actualizar Chatwoot, haz primero la copia de seguridad, descarga las imágenes nuevas, aplica las migraciones y vuelve a arrancar:

cd /opt/chatwoot
sudo docker compose pull
sudo docker compose down
sudo docker compose run --rm rails bundle exec rails db:chatwoot_prepare
sudo docker compose up -d

Antes de actualizar a una versión mayor, lee las notas de versión: a veces cambian variables de entorno o el archivo de Compose de producción.

Solución de problemas

  • 502 Bad Gateway: Rails todavía está arrancando o se ha detenido. Espera un minuto y revisa sudo docker compose logs rails.
  • PG::ConnectionBad o password authentication failed: la contraseña de PostgreSQL es distinta en .env y en docker-compose.yaml. Si cambiaste la del compose después del primer arranque, PostgreSQL mantiene la original guardada en su volumen.
  • Las conversaciones no se actualizan en tiempo real: falta el soporte de WebSocket en Nginx. Revisa las cabeceras Upgrade y Connection.
  • No llegan los correos de invitación: revisa las variables SMTP_* y los registros de sidekiq, que es el servicio que envía el correo (sudo docker compose logs sidekiq).

Conclusión

Ya tienes Chatwoot funcionando con HTTPS, con los registros cerrados, un equipo de agentes y el chat en vivo instalado en tu web. Como siguientes pasos, conecta un buzón de correo como bandeja de entrada para recibir los correos de soporte en el mismo panel, crea respuestas predefinidas para las preguntas frecuentes y configura reglas de automatización para asignar conversaciones por etiqueta o equipo.