bolt Valebyte VPS desde $4/mes — NVMe, despliegue en 60s.

Obtener VPS arrow_forward
eco Principiante Tutorial/Cómo hacer

Instalación de Chatwoot en VPS: Docker, PostgreSQL, Redis, SSL y configuración de correo electrónico

calendar_month Oct 08, 2026 schedule 18 min de lectura visibility 35 vistas
Установка Chatwoot на VPS: Docker, PostgreSQL, Redis, SSL и настройка email
info

¿Necesitas un servidor para esta guía? Ofrecemos servidores dedicados y VPS en más de 50 países con configuración instantánea.

¿Necesitas un VPS para esta guía?

Explore otras opciones de servidores dedicados en

Instalación de Chatwoot en VPS: Docker, PostgreSQL, Redis, SSL y configuración de email

TL;DR

Chatwoot es una plataforma self-hosted para atención al cliente mediante widget de sitio web, email, Telegram, WhatsApp y otros canales. En esta guía desplegará Chatwoot en un VPS Ubuntu con Docker, conectará PostgreSQL y Redis, configurará HTTPS mediante Caddy, SMTP para correo saliente, copias de seguridad y mantenimiento seguro.

  • Para un equipo pequeño basta un VPS con 2 vCPU, 4 GB de RAM y 50–80 GB de NVMe.
  • Chatwoot se ejecuta en contenedores: aplicación web, worker en segundo plano, PostgreSQL, Redis y Caddy.
  • El certificado HTTPS de Let’s Encrypt se emite y renueva automáticamente mediante Caddy.
  • El correo saliente se configura mediante variables SMTP en el archivo .env.
  • Antes de iniciar, debe crear la base de datos con el comando db:chatwoot_prepare.
  • Datos críticos para la copia de seguridad: PostgreSQL, .env, datos de Caddy y cargas de usuarios.

Qué configuramos y por qué

Chatwoot es un sistema open-source de customer support y omnichannel inbox. Reúne las solicitudes de clientes en una sola interfaz: mensajes de chat web, email, Telegram, Facebook Messenger, Instagram, WhatsApp Business API y otras integraciones. Los operadores pueden asignarse conversaciones entre sí, utilizar etiquetas, plantillas de respuesta, automatización, SLA y una base de conocimientos.

En esta instrucción se instalará una instancia self-hosted de Chatwoot en su propio VPS. Estará disponible mediante su nombre de dominio, por ejemplo chat.example.com, a través de una conexión HTTPS segura. Los datos de conversaciones, contactos, adjuntos y configuraciones se almacenarán en su servidor, no en una cuenta SaaS ajena.

Qué funcionará después de la instalación

  • interfaz web de Chatwoot para administradores y operadores;
  • widget de chat en línea que puede añadir a un sitio web;
  • PostgreSQL 16 como base de datos principal;
  • Redis 7 para colas, caché y tareas en segundo plano;
  • Sidekiq worker para enviar email, procesar webhook y operaciones en segundo plano;
  • Caddy 2 como reverse proxy y gestor de certificados TLS;
  • envío SMTP de notificaciones, invitaciones de usuarios y respuestas desde el canal de email;
  • copias de seguridad automáticas de PostgreSQL en almacenamiento compatible con S3.

Cloud-managed o self-hosted

Criterio Servicio en la nube Chatwoot self-hosted en VPS
Velocidad de inicio Unos minutos, la infraestructura ya está preparada Debe configurar el servidor, DNS, SSL y copias de seguridad
Control de datos Los datos se encuentran con el proveedor del servicio Usted controla los datos, logs y copias de seguridad
Personalización Limitada por el plan y la interfaz Puede cambiar configuraciones, integraciones y la versión de la aplicación
Operación El servicio suele realizar las actualizaciones y copias de seguridad Las actualizaciones, seguridad y recuperación son su responsabilidad
Coste al crecer el equipo A menudo depende del número de agentes y canales Depende principalmente de los recursos del servidor y el almacenamiento

La opción self-hosted es adecuada para equipos que valoran el control de datos personales, la posibilidad de integración con sistemas internos, costes de infraestructura fijos o el alojamiento en la jurisdicción necesaria. También resulta conveniente para proyectos SaaS, agencias y servicios internos de soporte.

Antes de comenzar, prepare un dominio o subdominio, por ejemplo chat.example.com. Su registro A debe apuntar a la dirección IPv4 pública del VPS. Para la emisión automática del certificado, los puertos 80 y 443 deben ser accesibles desde Internet.

Qué configuración de VPS se necesita para esta tarea

La carga de Chatwoot depende no solo del número de operadores, sino también de la cantidad de visitantes simultáneos en el chat web, el tamaño de los adjuntos, el número de canales conectados y la actividad de automatización. PostgreSQL y Sidekiq son sensibles a la falta de memoria: no se debe utilizar un servidor con 1 GB de RAM para un despliegue production.

Escenario vCPU RAM Disco NVMe Para quién es adecuado
Entorno de pruebas 2 2 GB 30 GB Pruebas, un administrador, sin gran cantidad de adjuntos
Production mínimo 2 4 GB 50–80 GB Hasta 5–10 agentes y un flujo moderado de solicitudes
Equipo de trabajo 4 8 GB 100–160 GB 10–30 agentes, canales activos y adjuntos
Alta carga 8+ 16+ GB 250+ GB Muchas conversaciones, integraciones, API y almacenamiento prolongado de medios

Una configuración inicial práctica es 2 vCPU, 4 GB de RAM, 80 GB de NVMe y una conexión desde 100 Mbit/s. Es suficiente para que PostgreSQL, Redis, Caddy, el contenedor web y el worker funcionen simultáneamente. Puede elegir un VPS con las características indicadas o un servidor equivalente de otro proveedor.

Por qué es importante tener espacio libre en disco

El disco no solo se utiliza para las imágenes Docker. El espacio lo ocupan la base de datos PostgreSQL, archivos temporales, logs de contenedores, adjuntos de conversaciones, copias de seguridad antes de enviarlas al almacenamiento externo y datos de Caddy. No planifique el disco «al límite»: mantenga al menos un 25–30% de espacio libre. Si la partición se llena, PostgreSQL puede detenerse de forma inesperada o afectar el procesamiento de transacciones.

Cuándo se necesita un dedicated en lugar de un VPS

Un servidor dedicado tiene sentido con una carga alta estable, requisitos de aislamiento de recursos, almacenamiento de gran cantidad de archivos o si Chatwoot funciona junto con otros servicios pesados. Por ejemplo, conviene considerar un dedicated con más de 50 agentes activos, decenas de miles de conversaciones al mes, almacenamiento local de archivos multimedia grandes y analítica intensiva.

Para el soporte habitual de una pequeña empresa, un VPS normalmente es mejor: es más fácil aumentar CPU, RAM y disco, es más económico al inicio y no requiere reservar recursos excesivos. No aloje Chatwoot production en un mismo servidor con una base de datos pública, tareas CI de prueba o contenedores no verificados.

Cómo elegir la ubicación

La ubicación influye en la latencia del chat web, el enrutamiento de email y los requisitos de tratamiento de datos personales. Elija una región más cercana a los operadores y a la audiencia principal. Si almacena conversaciones de clientes de la UE, revise de antemano los requisitos legales internos sobre la región de alojamiento y los acuerdos de procesamiento de datos.

Preparación del servidor

A continuación se utiliza Ubuntu Server 24.04 LTS. En 2026, es una base LTS adecuada para un despliegue Docker: cuenta con un kernel actual, soporte prolongado y un conjunto estable de paquetes. Conéctese al servidor con el usuario root proporcionado por el proveedor.

Actualice el sistema operativo

El comando instala las actualizaciones de seguridad actuales, tras lo cual el servidor se reinicia si se actualizó el kernel.

apt update && apt upgrade -y
apt autoremove -y
reboot

Después de reiniciar, vuelva a conectarse mediante SSH y cree un usuario independiente para la administración. No trabaje permanentemente con root: esto aumenta el riesgo de eliminar datos accidentalmente o ejecutar un comando peligroso sin restricciones.

adduser deploy
usermod -aG sudo deploy
mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chown -R deploy:deploy /home/deploy/.ssh

Copie su clave pública SSH al archivo de autorización. Ejecute el comando en el ordenador local y sustituya la dirección IP del servidor.

ssh-copy-id deploy@SERVER_IP

Compruebe el acceso en una segunda terminal. No cierre la sesión root actual hasta asegurarse de que la clave funciona.

ssh deploy@SERVER_IP
sudo whoami

La salida esperada del segundo comando es root. Después de la comprobación, desactive el acceso del usuario root y la autenticación por contraseña. Primero guarde una copia de seguridad de la configuración SSH.

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo sed -i 's/^#\?PermitRootLogin./PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PasswordAuthentication./PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload ssh

Instale utilidades básicas y protección contra intentos de contraseña

Los paquetes siguientes serán necesarios para diagnóstico, descarga de archivos, trabajo con repositorios y protección SSH. Incluso con la autenticación por contraseña desactivada, Fail2ban resulta útil como nivel adicional de control.

sudo apt install -y ca-certificates curl gnupg git jq \
  ufw fail2ban unattended-upgrades apt-transport-https \
  software-properties-common

Configure el firewall. Solo se abren SSH, HTTP y HTTPS. PostgreSQL en el puerto 5432 y Redis en el puerto 6379 no deben exponerse al exterior: los contenedores interactuarán únicamente en la red Docker interna.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Cree una configuración local mínima de Fail2ban para SSH. Los valores significan: bloquear una IP durante una hora si realiza cinco intentos fallidos en diez minutos.

sudo tee /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
EOF

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Cree el directorio de trabajo

Todos los archivos del stack estarán en /opt/chatwoot. Esta ruta es cómoda para realizar copias de seguridad, migrar y comprobar. No almacene secretos en el directorio personal si hay varios administradores en el servidor.

sudo mkdir -p /opt/chatwoot
sudo chown -R deploy:deploy /opt/chatwoot
cd /opt/chatwoot

Instalación del software, paso a paso

Para la instalación se utilizan Docker Engine 27+ y Docker Compose Plugin v2. En producción, no instale PostgreSQL ni Redis directamente mediante apt si planea ejecutarlos en Docker: mezclar ambos métodos complica el diagnóstico de red, las actualizaciones y las copias de seguridad.

Instale Docker Engine desde el repositorio oficial

Primero añada la clave y el repositorio de Docker para Ubuntu.

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

El siguiente comando añade el repositorio correspondiente a la arquitectura y la versión de Ubuntu.

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update

Instale Docker Engine, Compose Plugin y los componentes necesarios de la red de contenedores.

sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

sudo systemctl enable --now docker
sudo usermod -aG docker deploy

Cierre la sesión SSH y vuelva a conectarse para que se aplique el grupo docker. Después, compruebe las versiones.

exit
ssh deploy@SERVER_IP
docker --version
docker compose version
docker run --rm hello-world

En 2026, utilice Docker Engine 27 o posterior y Docker Compose v2 como referencia. Si el comando docker run devuelve un mensaje de bienvenida, el demonio funciona correctamente.

Cree la estructura de datos persistentes

Los volúmenes con nombre de Docker sobreviven a la recreación de contenedores, pero para Caddy y los archivos adjuntos locales es más conveniente crear directorios explícitamente. El directorio storage será utilizado por Chatwoot para el almacenamiento local de archivos.

cd /opt/chatwoot
mkdir -p caddy/data caddy/config storage backups
chmod 700 backups
find /opt/chatwoot -maxdepth 2 -type d -print

Genere los secretos

Chatwoot utiliza SECRET_KEY_BASE para firmar sesiones y proteger los datos criptográficos de la aplicación. La pérdida de esta clave puede cerrar las sesiones de los usuarios, y su divulgación genera un riesgo de compromiso de las sesiones. Genere dos valores aleatorios y no los envíe por mensajería ni los incluya en repositorios.

openssl rand -hex 64
openssl rand -hex 32

El primer valor se utilizará como SECRET_KEY_BASE, el segundo como contraseña de PostgreSQL. En la siguiente sección se incluirán en el archivo .env, cuyos permisos estarán restringidos.

Compruebe el DNS antes del inicio

Antes de iniciar Caddy, el dominio ya debe resolverse a la dirección IP del servidor. Sustituya el nombre por el suyo. Si la salida muestra otra dirección o un resultado vacío, corrija el registro A en el proveedor DNS y espere a que se actualice la zona.

getent ahostsv4 chat.example.com
curl -4 ifconfig.me
echo

Configuración de Chatwoot, SSL y correo electrónico

En esta variante, todos los servicios se describen en un único archivo compose.yaml. PostgreSQL y Redis no exponen puertos en el host, por lo que no se puede conectar a ellos directamente desde Internet. Caddy es el único contenedor que recibe solicitudes externas en los puertos 80 y 443.

Cree el archivo de variables de entorno

Cree /opt/chatwoot/.env. Sustituya el dominio, el correo electrónico del administrador, las contraseñas y los parámetros SMTP. El valor de FRONTEND_URL debe comenzar obligatoriamente con https:// y no debe tener una barra al final.

cd /opt/chatwoot
nano .env
POSTGRES_DB=chatwoot_production
POSTGRES_USER=chatwoot
POSTGRES_PASSWORD=CHANGE_TO_A_LONG_RANDOM_DATABASE_PASSWORD
POSTGRES_HOST=postgres
POSTGRES_PORT=5432

REDIS_URL=redis://redis:6379
RAILS_ENV=production
NODE_ENV=production
INSTALLATION_ENV=docker
SECRET_KEY_BASE=CHANGE_TO_128_HEX_CHARACTERS_FROM_OPENSSL

FRONTEND_URL=https://chat.example.com
DEFAULT_LOCALE=ru
RAILS_LOG_TO_STDOUT=true
RAILS_SERVE_STATIC_FILES=true
ENABLE_ACCOUNT_SIGNUP=false

ACTIVE_STORAGE_SERVICE=local
LOCAL_STORAGE_PATH=/app/storage

[email protected]
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=smtp-login
SMTP_PASSWORD=CHANGE_TO_SMTP_PASSWORD
SMTP_DOMAIN=example.com
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=true
SMTP_OPENSSL_VERIFY_MODE=peer

[email protected]

Para SMTP, utilice un buzón de correo o una cuenta SMTP independientes. Los servicios de correo suelen requerir una contraseña de aplicación en lugar de la contraseña principal del buzón. El puerto 587 se utiliza con STARTTLS, el puerto 465 con TLS inmediatamente después de conectarse; para 465 normalmente se requiere una configuración adicional del adaptador, por lo que para el primer inicio elija 587.

Restrinja el acceso al archivo: solo root y el usuario deploy deben poder leerlo.

chmod 600 /opt/chatwoot/.env
ls -l /opt/chatwoot/.env

Cree la configuración de Docker Compose

A continuación se utiliza una imagen estable de Chatwoot de la rama 4.x. Antes de una actualización importante, fije una etiqueta específica, por ejemplo v4.x.y, después de revisar las notas de la versión. La etiqueta latest es conveniente para pruebas, pero en producción reduce la previsibilidad de las actualizaciones.

nano compose.yaml
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    env_file: .env
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - chatwoot_internal

  redis:
    image: redis:7.4-alpine
    restart: unless-stopped
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - chatwoot_internal

  rails:
    image: chatwoot/chatwoot:v4.0.2
    restart: unless-stopped
    env_file: .env
    command: bundle exec rails server -p 3000 -b 0.0.0.0
    entrypoint: docker/entrypoints/docker-entrypoint.sh
    volumes:
      - ./storage:/app/storage
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - chatwoot_internal

  worker:
    image: chatwoot/chatwoot:v4.0.2
    restart: unless-stopped
    env_file: .env
    command: bundle exec sidekiq -C config/sidekiq.yml
    entrypoint: docker/entrypoints/docker-entrypoint.sh
    volumes:
      - ./storage:/app/storage
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - chatwoot_internal

  caddy:
    image: caddy:2.10-alpine
    restart: unless-stopped
    env_file: .env
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy/data:/data
      - ./caddy/config:/config
    depends_on:
      - rails
    networks:
      - chatwoot_internal

volumes:
  postgres_data:
  redis_data:

networks:
  chatwoot_internal:
    driver: bridge

Si en el momento de la instalación la versión estable actual de Chatwoot es más reciente que v4.0.2, sustituya la etiqueta de los contenedores rails y worker por la misma etiqueta comprobada de la rama estable actual. Nunca actualice solo uno de estos dos contenedores: el proceso web y Sidekiq deben funcionar con la misma versión de la aplicación.

Configure Caddy y TLS

Caddy solicitará por sí mismo un certificado de Let’s Encrypt, configurará la redirección de HTTP a HTTPS y renovará el certificado. Los certificados y la cuenta ACME se guardan en ./caddy/data, por lo que no desaparecerán tras recrear el contenedor.

nano Caddyfile
CADDY_EMAIL {
  email {$CADDY_EMAIL}
}

chat.example.com {
  encode zstd gzip

  reverse_proxy rails:3000

  header {
    -Server
    Strict-Transport-Security "max-age=31536000; includeSubDomains"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "strict-origin-when-cross-origin"
  }

  log {
    output stdout
    format json
  }
}

Sustituya chat.example.com en Caddyfile por el mismo dominio indicado en FRONTEND_URL. La variable CADDY_EMAIL del archivo .env se aplica dentro de Caddy mediante la sintaxis {$CADDY_EMAIL}.

Inicie los contenedores de infraestructura y prepare la base de datos

Primero descargue las imágenes e inicie PostgreSQL con Redis. A continuación, ejecute las migraciones y la preparación inicial de la base de datos. El comando db:chatwoot_prepare crea la estructura de las tablas y aplica las migraciones.

cd /opt/chatwoot
docker compose pull
docker compose up -d postgres redis
docker compose ps

Espere al estado healthy de PostgreSQL y Redis. Después, inicie un contenedor de un solo uso con la tarea de preparación de la base de datos.

docker compose run --rm rails \
  bundle exec rails db:chatwoot_prepare

Si el comando finalizó sin errores, inicie la aplicación, el worker y el proxy inverso. El parámetro -d inicia los servicios en segundo plano.

docker compose up -d rails worker caddy
docker compose ps
docker compose logs --tail=100 caddy

Compruebe el funcionamiento

Compruebe la respuesta de Caddy desde el propio VPS. El código 200, 301 o 302 significa que la ruta responde. En la primera solicitud, Caddy puede tardar varios segundos en obtener el certificado.

curl -I http://chat.example.com
curl -I https://chat.example.com
docker compose logs --tail=100 rails
docker compose logs --tail=100 worker

Abra https://chat.example.com en el navegador. En el primer inicio, Chatwoot ofrecerá crear una cuenta de administrador y una organización. Dado que ENABLE_ACCOUNT_SIGNUP=false, el registro público se desactivará tras crear la cuenta inicial; añada nuevos agentes desde la interfaz de administración mediante invitaciones.

Compruebe SMTP y configure el canal de correo electrónico

Después de crear el administrador, vaya a la sección de configuración de la organización en la interfaz y compruebe la invitación de un nuevo agente: es una prueba sencilla del correo saliente. Si el mensaje no llega, examine primero los registros del worker, ya que el envío de correo electrónico se realiza como tarea en segundo plano.

docker compose logs -f worker

Para recibir consultas por correo electrónico, cree un inbox de tipo Email Channel en el panel de Chatwoot. El servicio mostrará una dirección de reenvío o parámetros de integración. En el proveedor de correo, configure el reenvío desde la dirección de soporte hacia esa dirección o utilice el canal de correo compatible siguiendo las instrucciones de la interfaz.

Para una buena entregabilidad del correo saliente, configure los registros DNS SPF, DKIM y DMARC en el dominio del remitente. SMTP puede funcionar técnicamente sin ellos, pero los correos de invitación y las respuestas llegarán con más frecuencia a la carpeta de spam. La dirección MAILER_SENDER_EMAIL debe pertenecer a un dominio para el que estén configurados estos registros.

Añada el widget web al sitio

Después de crear un Website Inbox, Chatwoot mostrará un fragmento de JavaScript listo para usar. Insértelo antes de la etiqueta de cierre </body> del sitio. No copie un ejemplo con el identificador de sitio de otra persona: utilice el código generado específicamente por su instancia de Chatwoot; de lo contrario, las conversaciones se asociarán al inbox incorrecto.

Copias de seguridad y mantenimiento

Un servidor en funcionamiento sin una restauración probada no puede considerarse protegido. Para Chatwoot es necesario respaldar no solo PostgreSQL: parte de los datos críticos se encuentra en la configuración y el almacenamiento local de adjuntos. Redis normalmente no es la fuente principal de datos, pero su volume puede incluirse en una copia de seguridad completa para desastres.

Qué es obligatorio conservar

  • PostgreSQL: cuentas, contactos, conversaciones, mensajes, configuraciones de inbox e integraciones.
  • Archivo .env: secretos de la aplicación, parámetros SMTP, contraseña de la base de datos, URL pública.
  • Directorio storage: adjuntos, si se utiliza ACTIVE_STORAGE_SERVICE=local.
  • Directorio caddy/data: certificados y datos ACME; se pueden restaurar de nuevo, pero es útil conservarlos.
  • compose.yaml y Caddyfile: configuración de infraestructura.

No dependa únicamente de un Docker volume como copia de seguridad. El volume se encuentra en el mismo disco y no protege ante la eliminación del VPS, un error del administrador, daños en el sistema de archivos o el bloqueo de la cuenta. Al menos una copia debe enviarse a un almacenamiento externo compatible con S3, a un VPS de backup independiente o al almacenamiento de objetos de otra cuenta.

Instale restic

Restic cifra los archivos en el lado del servidor antes de cargarlos en el almacenamiento remoto. A continuación se muestra una opción con un bucket compatible con S3. Cree el bucket con antelación y emita un access key independiente con acceso únicamente a este bucket.

sudo apt install -y restic
sudo mkdir -p /etc/restic
sudo chmod 700 /etc/restic

Cree el archivo de entorno para restic. Obtenga los valores de endpoint, bucket y claves de su proveedor S3. No añada este archivo a Git.

sudo nano /etc/restic/chatwoot.env
RESTIC_REPOSITORY=s3:https://s3.example.net/chatwoot-backups
RESTIC_PASSWORD=CHANGE_TO_A_LONG_BACKUP_ENCRYPTION_PASSWORD
AWS_ACCESS_KEY_ID=CHANGE_TO_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=CHANGE_TO_SECRET_KEY
sudo chmod 600 /etc/restic/chatwoot.env
sudo chown root:root /etc/restic/chatwoot.env

Cree el script de copia de seguridad

El script crea un dump consistente de PostgreSQL mediante pg_dump, añade las configuraciones y el almacenamiento de archivos a un archivo cifrado de restic y después elimina el archivo SQL temporal. Para instalaciones grandes es mejor mover PostgreSQL a un servicio managed independiente o configurar copias de seguridad físicas, pero un dump lógico es adecuado para la mayoría de los equipos pequeños.

sudo nano /usr/local/sbin/chatwoot-backup.sh
#!/usr/bin/env bash
set -euo pipefail

APP_DIR="/opt/chatwoot"
BACKUP_DIR="${APP_DIR}/backups"
STAMP="$(date +%F_%H-%M-%S)"
DUMP_FILE="${BACKUP_DIR}/chatwoot_${STAMP}.sql.gz"

set -a
source /etc/restic/chatwoot.env
set +a

mkdir -p "${BACKUP_DIR}"
cd "${APP_DIR}"

docker compose exec -T postgres \
  pg_dump -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" | gzip -9 > "${DUMP_FILE}"

restic backup \
  "${DUMP_FILE}" \
  "${APP_DIR}/.env" \
  "${APP_DIR}/compose.yaml" \
  "${APP_DIR}/Caddyfile" \
  "${APP_DIR}/storage" \
  "${APP_DIR}/caddy/data"

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

rm -f "${DUMP_FILE}"

El script necesita las variables de PostgreSQL de /opt/chatwoot/.env. Añada la carga de este archivo antes de ejecutar pg_dump; de lo contrario, las variables no estarán definidas en el entorno del script.

sudo sed -i '/cd "${APP_DIR}"/a set -a\nsource "${APP_DIR}/.env"\nset +a' \
  /usr/local/sbin/chatwoot-backup.sh

sudo chmod 700 /usr/local/sbin/chatwoot-backup.sh
sudo /usr/local/sbin/chatwoot-backup.sh

La primera ejecución inicializa el repositorio restic, si es necesario, o solicitará confirmación. Tras finalizar correctamente, compruebe la lista de snapshots.

sudo bash -c 'source /etc/restic/chatwoot.env && restic snapshots'

Programe la copia de seguridad mediante cron

Ejecute la copia de seguridad por la noche, por ejemplo a las 03:30. La salida se redirige a un log, que será útil para investigar errores. Una vez por semana, compruebe que realmente haya aparecido un nuevo snapshot.

sudo crontab -e
30 3   * /usr/local/sbin/chatwoot-backup.sh >> /var/log/chatwoot-backup.log 2>&1

Prueba de restauración

La presencia de archivos de backup no demuestra la posibilidad de restauración. Al menos una vez por trimestre, despliegue el dump en un servidor de prueba. Para restaurar la base de datos, detenga la aplicación, cree una base de datos vacía y cargue el dump SQL. En production, no realice una restauración sin un plan de reversión confirmado.

gunzip -c chatwoot_YYYY-MM-DD_HH-MM-SS.sql.gz | \
  docker compose exec -T postgres \
  psql -U chatwoot -d chatwoot_production

Actualizaciones de Chatwoot y contenedores

Para una instancia pequeña, utilice una maintenance window: avise a los operadores, haga una copia de seguridad, actualice la imagen, aplique las migraciones y revise los logs. Un rolling update sin tiempo de inactividad requiere varias réplicas web, storage compartido, una base de datos independiente y un balanceador; para un solo VPS normalmente es una complejidad injustificada.

cd /opt/chatwoot
sudo /usr/local/sbin/chatwoot-backup.sh
docker compose pull
docker compose run --rm rails bundle exec rails db:migrate
docker compose up -d
docker image prune -f
docker compose ps

Antes de actualizar, lea las release notes de la versión de destino. Preste especial atención a los lanzamientos major, los requisitos de PostgreSQL/Redis y los cambios en las variables de entorno. Si la actualización provoca errores, no elimine volumes ni ejecute comandos de migración arbitrarios: primero conserve los logs y vuelva a la imagen anterior.

También controle el espacio en disco y el estado de los contenedores.

df -h
docker system df
docker compose ps
docker stats --no-stream

Solución de problemas y FAQ

¿Por qué Caddy no emite un certificado SSL y aparece un ACME error en los logs?

Primero compruebe el registro A del dominio con el comando getent ahostsv4 chat.example.com: debe devolver la IP de su VPS. Después asegúrese de que el firewall permite los puertos 80 y 443, y de que ningún otro proceso ha ocupado esos puertos: sudo ss -ltnp '( sport = :80 or sport = :443 )'. Desactive también el proxy del registro DNS a través de CDN durante el diagnóstico inicial. Consulte docker compose logs caddy; allí estará la causa exacta del rechazo de ACME.

¿Por qué la página de Chatwoot devuelve 502 Bad Gateway?

El código 502 significa que Caddy funciona, pero no puede obtener respuesta del contenedor rails. Ejecute docker compose ps y asegúrese de que rails tiene el estado Up. Después lea los últimos logs: docker compose logs --tail=150 rails. Las causas frecuentes son migraciones de base de datos no ejecutadas, un SECRET_KEY_BASE incorrecto, PostgreSQL no disponible o falta de RAM. Compruebe la memoria mediante free -h y los logs kernel de OOM mediante dmesg -T | grep -i killed.

¿Por qué worker se reinicia constantemente?

El contenedor worker depende de Redis y PostgreSQL, por lo que primero compruebe su healthcheck: docker compose ps. Después abra los logs con el comando docker compose logs --tail=200 worker. Un error de conexión a Redis normalmente significa un REDIS_URL incorrecto; dentro de la red Docker use el nombre de servicio redis, no localhost. Un error de base de datos indica un POSTGRES_HOST incorrecto, la contraseña o que la tarea db:chatwoot_prepare no se ejecutó.

¿Por qué Chatwoot no envía invitaciones y notificaciones por email?

El correo lo envía Sidekiq worker, así que abra sus logs y busque el error SMTP. Compruebe la dirección del servidor, el puerto, el login, la contraseña de la aplicación y el tipo de cifrado. Para el puerto 587 normalmente se necesitan SMTP_ENABLE_STARTTLS_AUTO=true y SMTP_AUTHENTICATION=plain. Después de modificar .env, aplique la configuración con el comando docker compose up -d --force-recreate rails worker. No olvide que el proveedor de correo puede bloquear SMTP hasta que se confirme el dominio o se habilite el acceso SMTP.

¿Por qué los correos llegan a spam?

El problema normalmente no está en Chatwoot, sino en la reputación del dominio o SMTP. La dirección MAILER_SENDER_EMAIL debe coincidir con el dominio de remitente verificado. Configure SPF, DKIM y DMARC mediante el panel DNS del servicio de correo. No utilice una dirección de remitente aleatoria si el proveedor SMTP permite envíos solo desde un dominio confirmado. Compruebe los encabezados del correo en el cliente de correo: mostrarán los resultados de SPF y DKIM. Para correos transaccionales es mejor utilizar un servicio SMTP especializado.

¿Qué configuración de VPS es mínimamente adecuada?

Para una instancia production pequeña, use como mínimo 2 vCPU, 4 GB de RAM y 50 GB de NVMe. Una configuración con 2 GB de memoria puede funcionar en modo de prueba, pero durante las actualizaciones, el procesamiento de adjuntos en segundo plano y las conversaciones simultáneas aumenta el riesgo de errores OOM. Si tiene varios canales habilitados, utiliza activamente la API o almacena muchos archivos, comience con 4 vCPU, 8 GB de RAM y 100 GB de disco. Elija el disco con margen para backups y adjuntos.

¿Qué elegir: VPS o dedicated para esta tarea?

Un VPS es adecuado para la mayoría de los equipos de hasta varias decenas de operadores: es más fácil de poner en marcha, más económico y se escala fácilmente según el plan. Elija dedicated cuando haya una carga alta constante, se requiera aislamiento físico, exista un gran volumen de adjuntos locales o se alojen varios servicios críticos en un mismo host. Por sí solo, dedicated no resuelve los problemas de backups, seguridad y monitorización. Para una sola instancia de Chatwoot, es más razonable empezar con un VPS y migrar a un servidor dedicado tras medir la carga real.

¿Cómo cambiar de forma segura el dominio de Chatwoot?

Primero cree el registro DNS del nuevo dominio, después cambie FRONTEND_URL en .env y el dominio en Caddyfile. Reinicie los servicios: docker compose up -d --force-recreate rails worker caddy. Después compruebe curl -I https://new-chat.example.com. Es recomendable mantener temporalmente el dominio anterior en Caddy como un sitio independiente con redirección, para que los enlaces antiguos y los widgets ya cargados no dejen de funcionar de inmediato.

Conclusiones y próximos pasos

Ahora tiene Chatwoot self-hosted en un VPS con Docker, PostgreSQL, Redis, HTTPS mediante Caddy y SMTP para el correo del sistema. La configuración aísla los servicios internos de Internet, y las copias de seguridad permiten restaurar la base de datos y los archivos después de un fallo.

  1. Cree un inbox para el sitio y conecte el widget; después añada operadores mediante invitaciones.
  2. Configure SPF, DKIM, DMARC y pruebe la entrega de correos desde una dirección real de cliente.
  3. Conecte la monitorización del disco, memoria, disponibilidad HTTPS y éxito de los backups nocturnos.
  4. Cuando aumente la carga, mueva los adjuntos a un almacenamiento compatible con S3 y PostgreSQL a un servidor gestionado independiente o a un nodo dedicado.

¿Te fue útil esta guía?

Tus comentarios nos ayudan a mejorar nuestras guías.

Compartir esta publicación:

Envía esta guía a alguien a quien pueda resultarle útil.

Telegram VKVK WhatsApp Facebook LinkedIn XX

instalación de chatwoot en VPS: Docker, PostgreSQL, Redis, SSL y configuración de correo electrónico
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.