← Blog

Auto-hospedar Chatwoot con Postgres, Redis y Sidekiq

Railyard

11 de abril de 2026 · 10 min de lectura

Sigue esto en tu propio servidor. Empieza gratis, sin tarjeta

Chatwoot ofrece una bandeja de entrada compartida y un widget de chat en vivo sin una factura SaaS por agente, pero el proyecto en sí tiene cuatro piezas en movimiento: un proceso web Rails, un worker Sidekiq para tareas en segundo plano, Postgres y Redis. Si configuras mal cualquiera de ellas (un FRONTEND_URL desactualizado, un worker que no puede llegar a Redis, un certificado que nunca se emite), obtienes una pantalla de inicio de sesión que gira sin fin en lugar de una bandeja de soporte funcional. Al final de esta guía tendrás los cuatro servicios corriendo en tu propio servidor, detrás de HTTPS, con respaldos y un proceso de actualización que realmente podrás repetir.

Lo que necesitas

  • Un servidor con al menos 4 vCPU y 8 GB de RAM. La propia documentación de auto-hospedaje de Chatwoot indica 2 núcleos / 4 GB como mínimo absoluto, pero esa cifra es solo para el proceso web por sí solo. Una vez que agregas el worker Sidekiq, Postgres y Redis en la misma máquina, su documentación eleva la recomendación a 4 núcleos o más y 8 GB o más. Un Hetzner CX33 (4 vCPU, 8 GB de RAM, 80 GB NVMe) cumple con esa recomendación y actualmente cuesta 8,99 €/mes sin IVA.
  • Ubuntu 22.04 o más reciente, con acceso root o sudo.
  • Un nombre de dominio al que puedas apuntar un registro A (esta guía usa chat.example.com).
  • Opcional pero recomendado: credenciales SMTP de un proveedor de correo transaccional, para que Chatwoot pueda enviar restablecimientos de contraseña y notificaciones a los agentes. Chatwoot no viene con SMTP configurado de forma predeterminada.

Paso 1: apuntar el DNS al servidor y abrir el firewall

Crea un registro A para tu subdominio que apunte a la dirección IPv4 pública del servidor. La propagación del DNS es la razón por la que el paso de HTTPS más adelante puede fallar si te apresuras, así que hazlo primero y deja que se asiente mientras avanzas con el resto de la configuración.

En el servidor mismo, abre solo los puertos que necesitas:

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Deberías ver Status: active con esas tres reglas listadas al ejecutar ufw status.

Paso 2: instalar Docker

El despliegue Docker de Chatwoot necesita Docker Engine y el plugin de Compose. El script de instalación oficial configura ambos:

curl -fsSL https://get.docker.com | sh
usermod -aG docker $(whoami)

Cierra sesión y vuelve a entrar para que el cambio de grupo surta efecto, y luego comprueba que ambas piezas están presentes:

docker --version
docker compose version

Deberías ver una versión de Docker y una versión de Compose impresas, no un error de “command not found”.

Paso 3: generar los secretos que necesitarás

Tres valores deben existir antes de escribir el archivo compose: una clave secreta de Rails, una contraseña de Postgres y una contraseña de Redis. Genera los tres ahora, para no tener la tentación de dejar un valor por defecto:

openssl rand -hex 64   # SECRET_KEY_BASE
openssl rand -hex 24   # POSTGRES_PASSWORD
openssl rand -hex 24   # REDIS_PASSWORD

Guarda los tres resultados en algún lugar desde donde puedas copiarlos y pegarlos. Ponlos en un archivo .env junto al archivo compose en lugar de escribirlos directamente en él, para que el archivo compose en sí mismo siga siendo seguro de mantener en el control de versiones:

mkdir -p /opt/chatwoot && cd /opt/chatwoot
cat > .env <<'EOF'
SECRET_KEY_BASE=pega-el-primer-valor-aqui
POSTGRES_PASSWORD=pega-el-segundo-valor-aqui
REDIS_PASSWORD=pega-el-tercer-valor-aqui
SMTP_ADDRESS=smtp.tu-proveedor.com
SMTP_USERNAME=tu-usuario-smtp
SMTP_PASSWORD=tu-contrasena-smtp
EOF
chmod 600 .env

Paso 4: escribir el archivo Compose

Esta es la parte que la mayoría de las guías pasan por alto: Chatwoot necesita exactamente las mismas variables de entorno tanto en el contenedor web como en el contenedor de Sidekiq, porque Sidekiq ejecuta la misma aplicación Rails, solo que con un proceso distinto. Si falta una sola en el worker, las tareas en segundo plano (correos, webhooks, encuestas CSAT) fallan en silencio aunque la interfaz web se vea normal.

services:
  postgres:
    image: pgvector/pgvector:0.8.7-pg16
    restart: always
    environment:
      POSTGRES_USER: chatwoot
      POSTGRES_DB: chatwoot
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:7.4.11-alpine
    restart: always
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
    volumes:
      - redis-data:/data

  rails:
    image: chatwoot/chatwoot:v4.18.0
    restart: always
    depends_on:
      - postgres
      - redis
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      RAILS_ENV: production
      NODE_ENV: production
      INSTALLATION_ENV: docker
      SECRET_KEY_BASE: ${SECRET_KEY_BASE}
      FRONTEND_URL: https://chat.example.com
      REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379
      POSTGRES_HOST: postgres
      POSTGRES_USERNAME: chatwoot
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DATABASE: chatwoot
      SMTP_ADDRESS: ${SMTP_ADDRESS}
      SMTP_PORT: "587"
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_AUTHENTICATION: plain
      SMTP_DOMAIN: example.com
      MAILER_SENDER_EMAIL: support@example.com
    command: >
      bash -c "bundle exec rails db:chatwoot_prepare && bundle exec rails s -p 3000 -b 0.0.0.0"
    volumes:
      - storage-data:/app/storage

  sidekiq:
    image: chatwoot/chatwoot:v4.18.0
    restart: always
    depends_on:
      - postgres
      - redis
    environment:
      RAILS_ENV: production
      NODE_ENV: production
      INSTALLATION_ENV: docker
      SECRET_KEY_BASE: ${SECRET_KEY_BASE}
      FRONTEND_URL: https://chat.example.com
      REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379
      POSTGRES_HOST: postgres
      POSTGRES_USERNAME: chatwoot
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DATABASE: chatwoot
      SMTP_ADDRESS: ${SMTP_ADDRESS}
      SMTP_PORT: "587"
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_AUTHENTICATION: plain
      SMTP_DOMAIN: example.com
      MAILER_SENDER_EMAIL: support@example.com
    command: bundle exec sidekiq -C config/sidekiq.yml
    volumes:
      - storage-data:/app/storage

volumes:
  postgres-data:
  redis-data:
  storage-data:

Nota que el contenedor Rails solo se enlaza a 127.0.0.1:3000, no a la interfaz pública. Caddy, que configurarás a continuación, es lo que realmente da la cara a internet; el contenedor de la aplicación nunca debería ser accesible directamente.

Reemplaza chat.example.com y support@example.com con tu dominio real antes de continuar. Verifica que el archivo se analiza correctamente:

docker compose config

Deberías ver la configuración completa resuelta impresa sin errores, y ningún ${...} sin resolver en la salida.

Paso 5: levantar la pila

docker compose up -d

El comando del contenedor rails ejecuta db:chatwoot_prepare antes de iniciar el servidor web, lo que crea la base de datos, carga el esquema y siembra los datos iniciales en el primer arranque. Observa cómo sucede:

docker compose logs -f rails

Deberías ver la salida de las migraciones seguida de Listening on http://0.0.0.0:3000. Luego confirma que los cuatro contenedores están realmente activos:

docker compose ps

Deberías ver postgres, redis, rails y sidekiq, todos en estado running o healthy, no restarting.

Paso 6: poner Caddy al frente con HTTPS automático

Instala Caddy y dale un único bloque de sitio. Caddy solicita y renueva el certificado por sí mismo la primera vez que arranca, siempre que el DNS ya apunte al servidor:

apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy

Reemplaza /etc/caddy/Caddyfile con:

chat.example.com {
	reverse_proxy localhost:3000
}

Luego recárgalo:

systemctl reload caddy

Visita https://chat.example.com en un navegador. Deberías ver un candado válido y la pantalla de configuración de Chatwoot, no una advertencia de certificado.

Paso 7: respaldar Postgres con un horario

Todo lo que importa (conversaciones, contactos, cuentas de agentes) vive en el volumen de postgres. Un volcado diario que muevas fuera del servidor es el respaldo mínimo viable:

cat > /opt/chatwoot/backup.sh <<'EOF'
#!/bin/sh
cd /opt/chatwoot
docker compose exec -T postgres pg_dump -U chatwoot chatwoot | gzip > /opt/chatwoot/backups/chatwoot-$(date +%F).sql.gz
find /opt/chatwoot/backups -mtime +14 -delete
EOF
chmod +x /opt/chatwoot/backup.sh
mkdir -p /opt/chatwoot/backups
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/chatwoot/backup.sh") | crontab -

Copia al menos uno de esos archivos .sql.gz fuera del servidor (a almacenamiento de objetos, otra máquina, cualquier lugar que no sea este VPS), para que un disco perdido no se lleve tus respaldos con él. Ejecuta ls /opt/chatwoot/backups a la mañana siguiente; deberías ver un nuevo archivo con fecha.

Paso 8: actualizar a una nueva versión de Chatwoot

Cada actualización de Chatwoot necesita que se vuelva a ejecutar el comando de migración, igual que en el primer arranque. Descarga la nueva etiqueta, ejecuta la migración una vez, y luego reinicia los dos contenedores que usan la imagen:

docker compose pull rails sidekiq
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d rails sidekiq

Revisa de nuevo docker compose logs -f rails. Deberías ver la nueva cadena de versión en el registro de arranque y ningún error de migración.

El atajo: hacerlo con Railyard

Todo lo anterior (la instancia de Postgres, la instancia de Redis protegida con contraseña, el proceso web, el worker Sidekiq que lee exactamente las mismas variables de entorno, el volumen de almacenamiento compartido entre ambos, el HTTPS en tu dominio) también está disponible como plantilla en el catálogo de plantillas de Railyard. Elige Chatwoot ahí y los cuatro servicios llegan ya conectados entre sí: Postgres y Redis se conectan automáticamente tanto al proceso web como al worker de Sidekiq, así que no hay que copiar y pegar variables de entorno entre dos contenedores esperando no haber olvidado ninguna. De todas formas tendrás que agregar tu propio proveedor SMTP después, ya que Railyard tampoco configura uno por ti. Si prefieres partir de tu propio fork o de una versión modificada de la pila, desplegar desde un repositorio y el botón de despliegue funcionan de la misma manera. Los respaldos del servicio de Postgres se cubren en bases de datos y respaldos, y si es tu primera vez en Railyard, la guía de inicio rápido cubre la configuración de la cuenta antes que todo esto. Para una idea de cuánto cuesta un servidor así entre distintos proveedores, consulta costos de hospedaje.

Solución de problemas

“Port is already allocated” al ejecutar docker compose up. Algo más en el servidor ya está usando el puerto 3000, o ejecutaste docker compose up dos veces sin detener la primera ejecución. Verifica con ss -tlnp | grep 3000 y detén lo que esté ocupando el puerto, o cambia el lado izquierdo del mapeo de puertos del servicio rails.

La pantalla de inicio de sesión carga, pero las redirecciones o los enlaces están mal. FRONTEND_URL tiene que ser exactamente la URL HTTPS que usarán los agentes y los clientes, definida tanto en el contenedor rails como en el sidekiq. Una discrepancia (http en lugar de https, una barra diagonal final, el subdominio equivocado) rompe los enlaces de restablecimiento de contraseña, las devoluciones de llamada de los webhooks e incluso las URL de los recursos del widget, aunque la aplicación misma arranque sin problemas.

El certificado nunca se emite, los registros de Caddy muestran “challenge failed” repetidos. Esto casi siempre es cuestión de DNS, no de Caddy. El registro A aún no se ha propagado, o no apunta a la IP de este servidor. Ejecuta dig chat.example.com +short desde tu propia máquina y confirma que devuelve la IP pública real del servidor antes de recargar Caddy de nuevo.

La subida de archivos o los avatares fallan con errores de permisos. El volumen chatwoot-storage necesita ser escribible por el usuario que ejecuta el proceso Rails dentro del contenedor. Si cambiaste el montaje del volumen o estás migrando desde un montaje de enlace (bind mount), verifica los permisos con docker compose exec rails ls -la /app/storage en lugar de adivinar.

El contenedor de Sidekiq sigue reiniciándose, o las tareas nunca se procesan. Revisa primero docker compose logs sidekiq. Un worker que muere por falta de memoria (OOM) se manifiesta como un contenedor que se reinicia sin un error claro en el registro, en cuyo caso la solución es más memoria para el servidor, no un cambio de configuración. Si está activo pero las tareas nunca se ejecutan, confirma que REDIS_URL del servicio sidekiq coincide exactamente, carácter por carácter, con el del servicio rails, incluyendo la contraseña.

Nunca se envía ningún correo. Chatwoot viene sin SMTP configurado. Si omitiste las variables SMTP en el Paso 4, los restablecimientos de contraseña, las invitaciones a agentes y las notificaciones de conversación fallan todas en silencio. Agrega credenciales SMTP reales y reinicia los contenedores rails y sidekiq.

Preguntas frecuentes

¿Puedo ejecutar Chatwoot sin Sidekiq? No. Las tareas en segundo plano (envío de correo, webhooks, CSAT, reglas de automatización) dependen de él; sin él, la aplicación corre, pero gran parte de su funcionamiento se detiene en silencio.

¿Chatwoot necesita Redis para algo más además de Sidekiq? Sí, también se usa para el caché y para ActionCable (las actualizaciones en tiempo real del panel del agente), así que es necesario incluso si no crees estar usando tareas en segundo plano directamente.

¿Pueden Postgres y Redis correr en un servidor separado, más pequeño, distinto del web y el worker? Sí, y la propia documentación de Chatwoot menciona esto como una opción cuando quieres usar servicios de base de datos administrados en lugar de contenedores. Para un equipo pequeño, mantener los cuatro en una sola máquina es más simple de operar, y es lo que cubre esta guía.

¿Cuál es la diferencia entre la especificación mínima de 2 núcleos / 4 GB y la de 4 núcleos / 8 GB? La cifra más baja es solo para el proceso web. La más alta es la recomendación propia de Chatwoot una vez que Postgres, Redis y el worker Sidekiq compiten por CPU y memoria en la misma máquina, que es el caso normal de una instalación auto-hospedada.

¿Tengo que usar exactamente las etiquetas de imagen de esta guía? No, se publican etiquetas nuevas regularmente. Esta guía fija chatwoot/chatwoot:v4.18.0 porque es la versión realmente verificada de principio a fin; revisa las notas de la versión del proyecto antes de pasar a una etiqueta más reciente, y vuelve a ejecutar el paso de migración de todas formas.

Una instalación de Chatwoot que funciona son cuatro piezas pequeñas y bien entendidas que se comunican correctamente entre sí, no una sola cosa complicada. Una vez que el DNS, las variables de entorno y el paso de migración están bien, queda muy poco por mantener más allá de los respaldos y las actualizaciones de versión ocasionales.

Por qué eligen Railyard para esto

  • Tu propia cuenta en la nube. Despliega en DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, o cualquier servidor Linux por SSH, facturado directamente por tu proveedor, sin márgenes adicionales.
  • Un precio fijo por equipo. El plan Free es gratis para siempre: un servidor más un servidor de base de datos, tres apps, sin tarjeta. Pro cuesta $19 al mes por hasta cinco servidores y apps ilimitadas. Team cuesta $49 al mes con servidores ilimitados. Sin cargos por app, por despliegue, por asiento ni por gigabyte.
  • Plantillas de un clic. Despliega apps de código abierto, como bases de datos, analítica y herramientas de desarrollo, en tu propio servidor con un clic.
  • Bases de datos administradas. Postgres, MySQL y Redis, con copias de seguridad programadas y verificadas por restauración, y recuperación a un punto en el tiempo.
  • Despliegue con git push. Despliega desde GitHub, GitLab o la CLI, con HTTPS automático y lanzamientos sin tiempo de inactividad.

Evita la configuración del servidor

Elige Chatwoot en el catálogo de plantillas de Railyard para obtener los mismos cuatro servicios ya conectados y desplegados, sin tocar una terminal.

Plan gratis, sin tarjeta, y 14 días de Pro para cada equipo nuevo. Un precio fijo por equipo.