Instalar Chatwoot en VPS con Docker y Traefik
Guía para desplegar Chatwoot mediante Docker Compose. Incluye configuración de SMTP, persistencia de Postgres, gestión de backups y actualización segura de contenedores en producción.
Lo que está construyendo
Para alojar Chatwoot en un VPS, ejecutará cuatro contenedores: un proceso web de Rails, un trabajador en segundo plano de Sidekiq, PostgreSQL con la extensión pgvector y Redis. Chatwoot es una plataforma de atención al cliente de código abierto, por lo que obtendrá una bandeja de entrada compartida para el equipo y un widget de chat para su sitio web en un servidor bajo su control. La instalación toma aproximadamente veinte minutos. Todo lo posterior, como la entrega de correo, las copias de seguridad, las actualizaciones y el dimensionamiento, es lo que determinará si el sistema seguirá funcionando dentro de un año.
Cada contenedor tiene una función específica. Rails sirve el panel de control del agente y la API (interfaz de programación de aplicaciones) del widget. Sidekiq ejecuta las tareas lentas: enviar correos electrónicos, consultar canales conectados, ejecutar reglas de automatización y generar informes. Postgres almacena las conversaciones, los contactos, las cuentas de los agentes y cada configuración que modifique en el panel. Redis mantiene las colas de Sidekiq y el canal de publicación/suscripción de ActionCable, que envía un mensaje nuevo a un panel abierto sin necesidad de recargar la página. En este caso, Redis no es una caché desechable, ya que perder su contenido implica perder los trabajos en cola.
La imagen de Postgres en el archivo compose original es pgvector/pgvector:pg16 en lugar de la imagen estándar postgres, debido a que el esquema de Chatwoot habilita la extensión vector para sus funciones de IA. Si utiliza la imagen estándar de Postgres, la primera ejecución de la base de datos se detendrá con un error ERROR: extension "vector" is not available, ya que el archivo de control de la extensión no se encuentra en esa imagen. Utilice la imagen que proporciona el desarrollador.
Esta guía asume que Docker y un proxy inverso ya funcionan en el servidor. Si no es así, comience por Docker Compose en un VPS y regrese después.
¿Cuánta capacidad de VPS necesita una instancia autohospedada de Chatwoot?
A fecha de agosto de 2026, la página de requisitos oficiales solicita 4 GB de RAM y 4 núcleos de CPU como mínimo, estimando que esto soporta hasta 10.000 conversaciones al día. Sitúa la capacidad en 8 GB y 8 núcleos para un máximo de 20.000 diarias. También requiere al menos 1 GB de swap, y explica el motivo directamente: evitar que la máquina se quede sin memoria durante una actualización. Reserve entre 5 GB y 10 GB de disco para Postgres antes de contabilizar la carga de archivos.
Ahora, la realidad técnica. Un VPS de 2 GB arrancará Chatwoot y parecerá funcionar correctamente con dos agentes y una bandeja de entrada con poco tráfico. El sistema fallará en dos puntos. El primero es Sidekiq, que según el desarrollador consume más de 1 GB en un servidor con carga; por tanto, un pico de correos o un proceso de generación de informes empujará al servidor a superar su límite de memoria antes de que Rails, Postgres y Redis hayan tomado su parte. El segundo punto es la actualización, ya que db:chatwoot_prepare inicia un proceso de Rails nuevo para aplicar las migraciones, y el arranque de Rails en esta imagen consume cientos de megabytes antes de realizar cualquier tarea útil.
No recibirá un aviso previo. El gestor de memoria (OOM killer) del kernel enviará un SIGKILL al proceso más grande, Docker detectará que el contenedor muere y restart: always lo reiniciará. docker compose ps mostrará entonces un contenedor que vuelve constantemente a Exited (137), donde 137 significa que fue terminado por la señal 9. Confirme esto con sudo dmesg -T | grep -i "killed process", que identifica el proceso que el kernel seleccionó.
Si 4 GB excede su presupuesto, utilice una máquina de 2 GB con 2 GB de swap y acepte que los tiempos de respuesta empeorarán bajo carga en lugar de que el servicio se caiga por completo. Establecer un límite estricto de memoria por servicio es recomendable en cualquier caso, para que el proceso worker no provoque la caída de la base de datos. Consulte límites de memoria en Docker Compose.
La carga de archivos es el componente que crece sin un límite definido por usted. Cada captura de pantalla que un cliente adjunta se almacena en el volumen de datos y permanece allí; por tanto, monitorice docker system df -v en lugar de asumir que es la base de datos lo que ha llenado el disco.
Obtenga el archivo compose y fije una etiqueta de versión
mkdir -p ~/chatwoot && cd ~/chatwoot
wget -O .env https://raw.githubusercontent.com/chatwoot/chatwoot/develop/.env.example
wget -O docker-compose.yaml https://raw.githubusercontent.com/chatwoot/chatwoot/develop/docker-compose.production.yaml
chmod 600 .envEl archivo que acaba de descargar indica image: chatwoot/chatwoot:latest. Cámbielo antes de realizar cualquier otra acción.
services:
base: &base
image: chatwoot/chatwoot:v4.16.2
env_file: .env
volumes:
- storage_data:/app/storagelatest significa que el siguiente docker compose pull le entregará cualquier versión publicada esa misma mañana, lo cual puede incluir una versión mayor con migraciones sobre las que no ha leído. Las migraciones de Chatwoot no son reversibles en la práctica, por lo que un salto accidental implica restaurar desde una copia de seguridad, no deshacer el cambio. Fije la etiqueta y cámbiela de forma deliberada. v4.16.2 era la versión actual en agosto de 2026; consulte la página de versiones para ver la etiqueta que debería fijar hoy.
El servicio base es un ancla YAML que rails y sidekiq heredan, por lo que cambiar la etiqueta en un solo lugar la actualiza para ambos. Mientras edita el archivo, elimine la línea version: '3' en la parte superior. Las versiones modernas de Compose la ignoran y muestran the attribute 'version' is obsolete, it will be ignored con cada comando.
Complete el archivo .env
Genere primero el secreto. El proveedor recomienda un valor alfanumérico, ya que los caracteres especiales pueden corromperse cuando el valor pasa a través de una shell o un analizador YAML.
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''A continuación, defina estas claves en .env.
SECRET_KEY_BASE=<the 63 characters you just generated>
FRONTEND_URL=https://support.example.com
FORCE_SSL=true
DEFAULT_LOCALE=en
ENABLE_ACCOUNT_SIGNUP=true
POSTGRES_HOST=postgres
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=<long random string>
POSTGRES_DATABASE=chatwoot
REDIS_URL=redis://redis:6379
REDIS_PASSWORD=<a different long random string>
RAILS_ENV=production
INSTALLATION_ENV=docker
ACTIVE_STORAGE_SERVICE=localPOSTGRES_HOST=postgres y redis://redis:6379 son los nombres de los servicios de Compose, los cuales se resuelven en la red predeterminada del proyecto. FRONTEND_URL no es un elemento decorativo. Chatwoot construye la URL del script del widget y cada enlace dentro de los correos electrónicos salientes; por lo tanto, un valor incorrecto provocará que los enlaces de restablecimiento de contraseña apunten a un host que no responde.
Ahora, la trampa en el archivo del proveedor. El servicio postgres no lee .env. Contiene su propio bloque environment con POSTGRES_PASSWORD= vacío, por lo que establecer la contraseña solo en .env deja a la base de datos sin contraseña y a la aplicación con una. Apunte el servicio a la misma variable:
postgres:
image: pgvector/pgvector:pg16
restart: always
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=chatwoot
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}Compose lee .env desde el directorio del proyecto para la sustitución de ${...}, por lo que ambos lados obtienen ahora la misma cadena. Si esto es incorrecto, Rails se detendrá con PG::ConnectionBad: FATAL: password authentication failed for user "postgres".
Un comportamiento sorprende a casi todo el mundo: la imagen de Postgres solo aplica POSTGRES_PASSWORD cuando inicializa un directorio de datos vacío. Cambiar el valor posteriormente no tiene efecto, ya que initdb nunca se ejecuta una segunda vez. Si ya ha iniciado el stack una vez, cámbielo directamente dentro de la base de datos.
docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"ENABLE_ACCOUNT_SIGNUP=true es temporal. Abre el formulario de registro público para que pueda crear la primera cuenta. Establézcalo en false y ejecute docker compose up -d de nuevo tan pronto como su cuenta exista, o cualquier persona que encuentre la URL podrá registrarse en su mesa de ayuda. A partir de ese momento, los agentes llegan mediante invitación y sus contraseñas residen solo en esta aplicación, lo cual es aceptable hasta que ejecute media docena de servicios y se canse de gestionar una lista de cuentas separada en cada uno; en ese punto, un proveedor de identidad autohospedado como Authentik es la pieza que los reemplaza.
.env contiene ahora todos los secretos de este stack en texto plano, así que manténgalo en modo 600 y fuera de git. Cómo lee Compose los archivos env y dónde se filtran los secretos cubre los riesgos, incluida la diferencia entre env_file y environment.
Ponga Chatwoot detrás de su Traefik existente
No cree un segundo proxy inverso para una sola aplicación. Si Traefik ya termina TLS (seguridad de la capa de transporte) para otros contenedores en este servidor, Chatwoot se une a él mediante un bloque de etiquetas. Si aún no lo tiene, configúrelo una vez siguiendo Traefik frente a varias aplicaciones de Docker Compose, y luego regrese aquí.
Mantenga el docker-compose.yaml del proveedor lo más parecido posible al original para poder compararlo con una versión más reciente más adelante, y coloque sus cambios en un archivo de anulación. Compose combina docker-compose.override.yaml automáticamente, y dividir Compose en varios archivos explica las reglas de combinación.
services:
rails:
networks:
- default
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.chatwoot.rule=Host(`support.example.com`)"
- "traefik.http.routers.chatwoot.entrypoints=websecure"
- "traefik.http.routers.chatwoot.tls.certresolver=letsencrypt"
- "traefik.http.services.chatwoot.loadbalancer.server.port=3000"
networks:
proxy:
external: trueUtilice sus propios nombres de entrypoint y certresolver. El contenedor debe estar en la misma red de Docker que Traefik, que es lo que hace la entrada proxy, y también debe permanecer en default o perderá la conexión con Postgres y Redis. Esa segunda línea es la que la gente suele olvidar.
Deje el bloque ports: intacto. El proveedor lo vincula a 127.0.0.1:3000, que es solo para loopback, por lo que no es accesible desde Internet y sigue siendo útil para realizar pruebas desde dentro del servidor con curl -I http://127.0.0.1:3000.
El panel de control del agente mantiene un websocket abierto a /cable para la entrega de mensajes en tiempo real. Traefik reenvía la actualización HTTP sin configuración adicional, por lo que no hay nada que añadir. Si más adelante coloca una CDN u otro proxy frente a Traefik, permita los websockets allí, ya que el síntoma es un panel de control que se carga normalmente mientras los mensajes nuevos solo aparecen después de una actualización manual.
Inicializar la base de datos e iniciar el stack
Inicie primero los servicios de datos y permita que Postgres finalice su primera ejecución.
docker compose up -d postgres redis
docker compose logs postgres | tail -n 5Espere a database system is ready to accept connections. A continuación, cree el esquema.
docker compose run --rm rails bundle exec rails db:chatwoot_prepareEsto crea la base de datos si no existe y, posteriormente, carga el esquema y los datos iniciales predeterminados. El proceso imprime las líneas de migración y finaliza correctamente. Si el proceso se queda imprimiendo postgres:5432 - no response, el punto de entrada está esperando una base de datos que aún no acepta conexiones, lo cual, en una primera ejecución, suele significar que initdb sigue trabajando. Espere, revise los registros de Postgres y vuelva a ejecutarlo. Si se detiene en la extensión vector, significa que reemplazó la imagen pgvector con la versión estándar de Postgres.
docker compose up -d
docker compose ps
docker compose logs --tail 30 railsLos cuatro contenedores deberían mostrar Up y el registro de rails debería terminar con una línea de Puma escuchando en http://0.0.0.0:3000. Luego, verifique la ruta pública:
curl -sI https://support.example.com | head -n 1HTTP/2 200 significa que toda la cadena funciona. Un error 404 de Traefik indica que la regla de enrutamiento no coincidió, generalmente debido a un error tipográfico en el nombre de host. Un error 502 significa que Traefik encontró el router pero no pudo alcanzar el contenedor, lo cual casi siempre se debe a la falta de la red proxy o a que el loadbalancer.server.port no es 3000.
Abra la URL, cree su cuenta en /app/auth/signup, configure ENABLE_ACCOUNT_SIGNUP=false y ejecute docker compose up -d para cerrar el formulario.
Por qué los restablecimientos de contraseña y las conversaciones por correo fallan sin SMTP
Chatwoot sin configuración de SMTP (Simple Mail Transfer Protocol) es una mesa de ayuda que no puede enviar correos, y esto afecta a más cosas que solo las notificaciones. Los restablecimientos de contraseña dejan de funcionar, por lo que un administrador que pierde el acceso no puede recuperarlo. Las invitaciones a agentes dejan de funcionar, ya que una invitación es un correo electrónico. Responder a un cliente en una conversación por correo deja de funcionar, por lo que la conversación solo fluye en una dirección. Este es el paso que la gente omite y del que se percata durante su peor semana.
El mecanismo es sencillo. Sin ajustes de SMTP, ActionMailer mantiene su valor predeterminado de entrega a localhost en el puerto 25. No hay ningún servidor de correo dentro del contenedor de Rails, por lo que la tarea de entrega genera Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25. El correo sale desde una tarea en segundo plano, por lo que esa línea aparece en el registro de Sidekiq y nunca en el registro de Rails. Mientras tanto, la persona que hace clic en "olvidé mi contraseña" ve una confirmación optimista y no recibe nada.
MAILER_SENDER_EMAIL=Support <support@example.com>
SMTP_DOMAIN=example.com
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=support@example.com
SMTP_PASSWORD=<the relay password>
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=trueUtilice el puerto 587 con STARTTLS, que abre la conexión en texto plano y la actualiza a cifrada antes de la autenticación. La mayoría de los proveedores de VPS bloquean el puerto 25 de salida para limitar el spam, por lo que un relay en el 587 suele ser la única opción que logrará conectar. SMTP_DOMAIN es el dominio que su servidor anuncia durante la conversación SMTP, y algunos relays rechazan cualquier discrepancia.
Aplique los ajustes y monitorice el trabajador:
docker compose up -d rails sidekiq
docker compose logs -f sidekiqInicie un restablecimiento de contraseña desde la página de inicio de sesión. Una entrega exitosa muestra que la tarea del mailer finaliza normalmente en el registro de Sidekiq. Un fallo muestra la clase de excepción, y luego Sidekiq reintenta con un retroceso exponencial creciente, razón por la cual un relay roto produce el mismo error cada pocos minutos durante horas.
Dos rechazos son comunes, y ninguno es un error de Chatwoot. 535 Authentication failed significa que el nombre de usuario o la contraseña son incorrectos para ese relay, y muchos proveedores requieren una contraseña de aplicación en lugar de la contraseña de la cuenta. 550 Sender address rejected significa que MAILER_SENDER_EMAIL es una dirección desde la cual el relay no enviará correos, por lo que debe ser un buzón o dominio que usted haya verificado con ellos.
Recibir correos en una conversación es una tarea independiente. Requiere MAILER_INBOUND_EMAIL_DOMAIN y RAILS_INBOUND_EMAIL_SERVICE, además de un servidor de correo que entregue los mensajes entrantes a Chatwoot. Contratar un relay es la vía rápida. Si prefiere gestionar toda la ruta del correo, ejecutar su propio servidor de correo con Mailcow detalla lo que implica ese compromiso.
Qué respaldar y cómo verificar que la restauración funciona
Una copia de seguridad de Chatwoot consta de cuatro partes; omitir cualquiera de ellas convierte una restauración en una reconstrucción.
- La base de datos Postgres, que contiene conversaciones, contactos, cuentas de agentes y cada configuración.
- El volumen
storage_data, ya queACTIVE_STORAGE_SERVICE=localescribe los archivos subidos al disco y solo mantiene una fila de referencia en Postgres. - El archivo
.env, ya que contieneSECRET_KEY_BASEy las clavesACTIVE_RECORD_ENCRYPTION_*. - Los archivos compose, ya que registran la etiqueta de imagen exacta con la que coincide el esquema de su base de datos.
Si restaura solo la base de datos, cada conversación volverá con archivos adjuntos rotos, porque las filas apuntan a archivos que ya no están en el disco.
cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dump-T es importante. Sin él, Compose asigna un pseudo terminal, el cual reescribe los bytes de nueva línea en el flujo, resultando en un archivo de volcado que pg_restore rechaza. -Fc es el formato personalizado, el cual comprime y permite que pg_restore trabaje de forma selectiva.
docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/storage-$(date +%F).tgz -C /data .El nombre del volumen es el nombre de su directorio de proyecto más _storage_data. Confírmelo con docker volume ls | grep storage_data antes de confiar en ese comando, ya que Docker crea un volumen vacío en lugar de fallar cuando usted nombra uno que no existe. Obtendría un archivo válido y vacío sin ningún error. Verifique el tamaño después con ls -lh storage-*.tgz.
Ambos archivos residen ahora en el mismo disco que aquello que protegen, lo cual no le protege de nada. Envíelos fuera del servidor y cifrelos, ya que un volcado de base de datos contiene cada mensaje de cliente en texto plano. Copias de seguridad externas cifradas con restic cubre el aspecto de la programación y retención.
El simulacro de restauración, ejecútelo antes de necesitarlo
Restaure en un segundo VPS, no en el de producción. Copie .env, los archivos compose y ambos archivos comprimidos, luego ejecute:
docker compose up -d postgres
docker compose exec -T postgres pg_restore -U postgres -d chatwoot --clean --if-exists < db-2026-08-10.dump
docker run --rm -v chatwoot_storage_data:/data -v "$PWD":/backup alpine \
sh -c 'rm -rf /data/* && tar xzf /backup/storage-2026-08-10.tgz -C /data'
docker compose up -d--clean --if-exists elimina los objetos existentes antes de cargar, así que apunte solo a una base de datos que esté dispuesto a perder. Luego inicie sesión y abra una conversación que tenga un archivo adjunto. Si la lista de mensajes carga y el archivo se descarga, la copia de seguridad es real.
Una restauración con un SECRET_KEY_BASE diferente invalida cada cookie de sesión, por lo que todos los usuarios cerrarán sesión. Una restauración con claves ACTIVE_RECORD_ENCRYPTION_* diferentes es peor: Chatwoot no puede descifrar las columnas que contienen las credenciales de los canales y genera ActiveRecord::Encryption::Errors::Decryption. Es por eso que .env está en la lista de respaldo.
Cómo actualizar Chatwoot a una nueva etiqueta
El orden es más importante que los comandos en sí.
- Lea las notas de la versión entre su etiqueta actual y la de destino, buscando pasos manuales obligatorios.
- Realice un volcado de base de datos y un archivo de almacenamiento nuevos, y verifique que el tamaño de ambos archivos parezca correcto.
- Edite la etiqueta de la imagen en el servicio
basedentro dedocker-compose.yaml. - Descargue la nueva imagen, detenga el stack, ejecute las migraciones y vuelva a iniciar.
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose imagesDescargue la imagen antes de migrar, ya que la migración debe ejecutarse desde la nueva imagen: la imagen antigua no contiene los nuevos archivos de migración. Detenga el stack antes de migrar, ya que el código antiguo y el nuevo esquema son incompatibles; un proceso de Rails antiguo en ejecución puede generar errores o escribir filas que el nuevo esquema no aceptará. Detener el servicio también libera la memoria necesaria para la migración, que es la razón principal por la que el desarrollador recomienda el uso de swap.
docker compose images imprime la etiqueta que cada contenedor está ejecutando realmente, lo que permite detectar casos en los que editó la etiqueta pero olvidó descargar la imagen.
No salte entre muchas versiones a la vez. El consejo del desarrollador para una instalación antigua es avanzar a través de etiquetas intermedias, ya que las migraciones se eliminan una vez que se integran en el esquema base; por lo tanto, una base de datos muy antigua puede llegar a un estado sin ruta de actualización. Avance una versión menor a la vez y ejecute el paso de preparación después de cada una.
Si Rails inicia antes de que se ejecute la migración, se negará a servir peticiones y registrará ActiveRecord::PendingMigrationError: Migrations are pending. Con restart: always configurado, el contenedor se reiniciará cíclicamente, por lo que docker compose ps mostrará un tiempo de actividad que se restablece cada pocos segundos. Ejecute el paso de preparación y el error desaparecerá.
Revertir cambios significa volver a colocar la etiqueta antigua y restaurar el volcado. No existe una ruta de migración inversa en la que pueda confiar, razón por la cual el paso 2 es fundamental.
Modos de fallo y cadenas que verá
502 Bad Gateway desde Traefik. El router coincidió pero el backend no respondió. Compruebe que docker compose ps muestra rails como Up, luego ejecute docker network inspect proxy y confirme que el contenedor rails aparece en su lista de contenedores. Un contenedor que no está adjunto es invisible para Traefik, por lo que la petición coincide con un router y luego no va a ninguna parte.
El panel de control carga pero los mensajes nuevos requieren actualizar. El websocket hacia /cable no está pasando, o FRONTEND_URL no coincide con la dirección en la barra del navegador. Una discrepancia significa que la página intenta abrir un websocket hacia un origen diferente, lo cual el navegador bloquea.
FATAL: password authentication failed for user "postgres". La contraseña en .env y la integrada en el volumen de datos de Postgres difieren. Corríjalo con ALTER USER dentro del contenedor en ejecución, ya que editar .env de nuevo no cambiará una base de datos ya inicializada.
NOAUTH Authentication required. Redis se está ejecutando con --requirepass pero la aplicación se conectó sin contraseña, por lo que REDIS_PASSWORD falta en .env o no fue detectado. Pruébelo directamente con docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping, que debería responder PONG.
Contenedores terminando con código 137. Eso es SIGKILL, y en un servidor pequeño es el asesino de memoria (OOM killer) del kernel. Añada swap, establezca límites de memoria por servicio o migre a un plan superior.
FAQ
¿Cuánta memoria RAM necesita un VPS con Chatwoot autohospedado?
A fecha de agosto de 2026, los requisitos mínimos oficiales son 4 GB de RAM y 4 núcleos de CPU para gestionar hasta 10.000 conversaciones diarias, y 8 GB con 8 núcleos para hasta 20.000. Añada al menos 1 GB de swap, ya que el proceso de actualización ejecuta un segundo proceso de Rails para aplicar migraciones y es ahí donde los servidores pequeños agotan la memoria. Un VPS de 2 GB arranca y funciona para un par de agentes, pero Sidekiq por sí solo puede superar 1 GB bajo carga; espere que los contenedores sean finalizados con el código de salida 137 durante periodos de alta actividad o durante las actualizaciones.
¿Por qué nunca llegan los correos de restablecimiento de contraseña de Chatwoot?
Porque no hay ajustes SMTP configurados, por lo que ActionMailer intenta realizar la entrega a localhost en el puerto 25 y no hay ningún servidor de correo dentro del contenedor. La tarea falla en Sidekiq con Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25 mientras el navegador sigue mostrando un mensaje de éxito. Configure SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD y MAILER_SENDER_EMAIL en .env, reinicie los servicios rails y sidekiq, y luego monitorice docker compose logs -f sidekiq mientras solicita un restablecimiento.
¿Qué debo respaldar para restaurar Chatwoot?
La base de datos Postgres, el volumen de Docker storage_data, el archivo .env y los archivos compose. La base de datos por sí sola no es suficiente, ya que los archivos subidos residen en el volumen mientras que Postgres solo contiene referencias a ellos; por tanto, una restauración solo de la base de datos dejará las conversaciones con archivos adjuntos rotos. .env es importante porque un SECRET_KEY_BASE diferente cierra la sesión de todos los usuarios, y unas claves ACTIVE_RECORD_ENCRYPTION_* distintas hacen que las columnas cifradas sean ilegibles.
¿Cómo puedo actualizar Chatwoot sin corromper la base de datos?
Realice una copia de seguridad, cambie la etiqueta de la imagen en su archivo compose y luego ejecute docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare y docker compose up -d. Descargue la imagen primero porque las migraciones deben ejecutarse desde la nueva versión, y detenga la pila primero porque el código antiguo ejecutándose contra un esquema nuevo genera errores. En instalaciones antiguas, avance una versión menor a la vez, ya que las migraciones se eliminan una vez que se integran en el esquema base.
¿Puedo usar la imagen estándar de postgres en lugar de pgvector?
No. El esquema de Chatwoot habilita la extensión vector, por lo que la imagen estándar postgres fallará durante db:chatwoot_prepare con ERROR: extension "vector" is not available, debido a que el archivo de control de la extensión no está presente en esa imagen. Mantenga pgvector/pgvector:pg16 del archivo compose original o utilice otra imagen que incluya pgvector para su versión principal de Postgres.