Installer Chatwoot sur un VPS avec Docker
Déployez Chatwoot avec Docker Compose et Traefik : tags figés, SMTP fonctionnel, sauvegardes de PostgreSQL et des fichiers, puis mises à niveau sûres.
Ce que vous allez déployer
Pour auto-héberger Chatwoot sur un VPS, vous exécutez quatre conteneurs : un processus web Rails, un worker d’arrière-plan Sidekiq, PostgreSQL avec l’extension pgvector et Redis. Chatwoot est un service d’assistance client open source. Vous disposez donc d’une boîte de réception d’équipe partagée et d’un widget de chat pour site web, sur un serveur que vous contrôlez. L’installation prend environ vingt minutes. Ensuite, la distribution des e-mails, les sauvegardes, les mises à niveau et le dimensionnement déterminent si le service fonctionnera encore dans un an.
Chaque conteneur a un rôle précis. Rails sert le tableau de bord des agents et l’API (application programming interface) du widget. Sidekiq exécute les tâches longues : envoi d’e-mails, interrogation des canaux connectés, exécution des règles d’automatisation et génération des rapports. Postgres stocke les conversations, les contacts, les comptes des agents et chaque paramètre modifié dans le tableau de bord. Redis stocke les files d’attente Sidekiq et le canal pub/sub ActionCable, qui transmet un nouveau message à un tableau de bord ouvert sans rechargement de la page. Ici, Redis n’est pas un simple cache temporaire, car sa perte entraîne celle des tâches en attente.
L’image Postgres du fichier compose fourni en amont est pgvector/pgvector:pg16, et non l’image postgres standard, car le schéma de Chatwoot active l’extension vector pour ses fonctionnalités d’IA. Si vous remplacez cette image par l’image Postgres standard, la première initialisation de la base de données s’arrête avec ERROR: extension "vector" is not available, car le fichier de contrôle de l’extension n’est pas présent dans cette image. Utilisez l’image fournie en amont.
Ce guide suppose que Docker et un reverse proxy fonctionnent déjà sur le serveur. Si ce n’est pas le cas, commencez par Docker Compose sur un VPS, puis revenez ici.
De combien de ressources VPS Chatwoot auto-hébergé a-t-il besoin ?
En août 2026, la page des prérequis en amont demande au minimum 4 GB de RAM et 4 CPU cores, pour jusqu’à 10,000 conversations par jour. Elle indique 8 GB et 8 cores pour jusqu’à 20,000 conversations par jour. Elle demande également au moins 1 GB de swap, avec une raison clairement précisée : éviter que la machine manque de mémoire pendant une mise à niveau. Prévoyez 5 GB à 10 GB d’espace disque pour Postgres, sans compter les fichiers téléversés.
Passons au point essentiel. Un VPS de 2 GB démarre Chatwoot et semble suffisant avec deux agents et une boîte de réception peu active. Deux problèmes se présentent. Le premier concerne Sidekiq, qui dépasse 1 GB sur un serveur chargé selon les mesures de l’éditeur. Un afflux d’e-mails ou l’exécution d’un rapport fait alors dépasser la mémoire disponible avant que Rails, Postgres et Redis aient consommé leur part. Le second concerne la mise à niveau, car db:chatwoot_prepare démarre un nouveau processus Rails pour appliquer les migrations. Le démarrage de Rails sur cette image consomme plusieurs centaines de MB avant d’effectuer la moindre opération utile.
Vous ne recevez pas d’abord un avertissement explicite. Le out-of-memory killer du kernel envoie SIGKILL au processus le plus volumineux. Docker détecte l’arrêt du container et restart: always le redémarre. docker compose ps affiche alors un container qui revient constamment à Exited (137), où 137 signifie qu’il a été tué par le signal 9. Confirmez-le avec sudo dmesg -T | grep -i "killed process", qui indique le processus sélectionné par le kernel.
Si 4 GB dépassent votre budget, utilisez une machine de 2 GB avec 2 GB de swap et acceptez une dégradation des temps de réponse sous charge, plutôt que l’arrêt complet du service. Dans tous les cas, il est utile de définir une limite de mémoire stricte pour chaque service. Le worker ne pourra ainsi pas entraîner l’arrêt de la base de données. Consultez les limites de mémoire dans Docker Compose.
Les téléversements de fichiers sont la partie qui augmente sans limite prédéfinie. Chaque capture d’écran jointe par un client est enregistrée dans le volume de stockage et y reste. Surveillez donc docker system df -v au lieu de supposer que la base de données a rempli le disque.
Récupérer le fichier Compose et figer un tag de version
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 .envLe fichier que vous venez de télécharger indique image: chatwoot/chatwoot:latest. Modifiez cette valeur avant toute autre opération.
services:
base: &base
image: chatwoot/chatwoot:v4.16.2
env_file: .env
volumes:
- storage_data:/app/storagelatest signifie que le prochain docker compose pull récupère tout ce qui a été publié ce matin-là. Il peut donc s’agir d’une version majeure avec des migrations dont vous n’avez jamais entendu parler. En pratique, les migrations de Chatwoot ne sont pas réversibles. Un changement de version accidentel nécessite donc une restauration depuis une sauvegarde, et non une annulation. Figez le tag et modifiez-le délibérément. v4.16.2 était la version actuelle en août 2026. Consultez la page des releases pour connaître le tag à figer aujourd’hui.
Le service base est une ancre YAML que rails et sidekiq fusionnent tous les deux. Modifier le tag à un seul endroit le modifie donc pour les deux services. Pendant que vous éditez le fichier, supprimez la ligne version: '3' au début. Les versions modernes de Compose l’ignorent et affichent the attribute 'version' is obsolete, it will be ignored à chaque commande.
Renseignez le fichier .env
Générez d’abord le secret. Le projet upstream demande une valeur alphanumérique, car les caractères spéciaux peuvent être altérés lorsque la valeur passe par un shell ou un analyseur YAML.
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''Définissez ensuite ces clés dans .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 et redis://redis:6379 sont les noms des services Compose. Ils sont résolus sur le réseau par défaut du projet. FRONTEND_URL n’est pas décoratif. Chatwoot construit à partir de cette valeur l’URL du script du widget et tous les liens contenus dans les e-mails sortants. Une valeur incorrecte produit donc des liens de réinitialisation du mot de passe qui pointent vers un hôte qui ne répond pas.
Voici maintenant le piège dans le fichier upstream. Le service postgres ne lit pas .env. Il contient son propre bloc environment, dans lequel POSTGRES_PASSWORD= est vide. Définir le mot de passe uniquement dans .env laisse donc la base de données sans mot de passe, tandis que l’application en utilise un. Faites pointer le service vers la même 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 lit .env depuis le répertoire du projet pour effectuer la substitution ${...}. Les deux côtés utilisent donc maintenant la même chaîne. Si cette configuration est incorrecte, Rails s’arrête avec PG::ConnectionBad: FATAL: password authentication failed for user "postgres".
Un comportement surprend presque tout le monde : l’image Postgres n’applique POSTGRES_PASSWORD que lorsqu’elle initialise un répertoire de données vide. Modifier cette valeur plus tard n’a aucun effet, car initdb ne s’exécute pas une deuxième fois. Si vous avez déjà démarré la stack une fois, modifiez la valeur directement dans la base de données.
docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"ENABLE_ACCOUNT_SIGNUP=true est temporaire. Il ouvre le formulaire d’inscription public afin que vous puissiez créer le premier compte. Définissez-le sur false et exécutez de nouveau docker compose up -d dès que votre compte existe. Sinon, toute personne qui trouve l’URL peut s’inscrire sur votre support client. Ensuite, les agents arrivent par invitation et leurs mots de passe sont stockés uniquement dans cette application. Cela convient jusqu’à ce que vous exécutiez une demi-douzaine de services et que vous en ayez assez de gérer une liste de comptes distincte dans chacun. À ce moment-là, un fournisseur d’identité auto-hébergé comme Authentik est la solution qui les remplace.
.env contient maintenant tous les secrets de cette stack en clair. Conservez donc ce fichier avec le mode 600 et ne l’ajoutez pas à git. Comment Compose lit les fichiers env et où les secrets peuvent fuiter présente les principaux pièges, notamment la différence entre env_file et environment.
Mettre Chatwoot derrière votre Traefik existant
Ne créez pas un deuxième reverse proxy pour une seule application. Si Traefik assure déjà la terminaison TLS (transport layer security) pour d’autres conteneurs sur ce serveur, Chatwoot s’y ajoute avec un bloc de labels. Si ce n’est pas encore le cas, configurez-le une fois avec Traefik devant plusieurs applications Docker Compose, puis revenez ici.
Conservez le docker-compose.yaml fourni par l’éditeur aussi proche que possible de l’original afin de pouvoir le comparer à une version plus récente, et placez vos modifications dans un fichier d’override. Compose fusionne automatiquement docker-compose.override.yaml, et répartir Compose sur plusieurs fichiers explique les règles de fusion.
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: trueUtilisez vos propres noms pour l’entrypoint et le certresolver. Le conteneur doit être connecté au même réseau Docker que Traefik, comme l’indique l’entrée proxy, et il doit également rester sur default, sans quoi il perd l’accès à Postgres et Redis. C’est cette deuxième ligne que l’on oublie souvent.
Ne modifiez pas le bloc ports:. L’éditeur le lie à 127.0.0.1:3000, qui correspond uniquement à la loopback. Il n’est donc pas accessible depuis Internet et reste utilisable pour les tests depuis l’intérieur du serveur avec curl -I http://127.0.0.1:3000.
Le tableau de bord de l’agent maintient une connexion websocket ouverte vers /cable pour recevoir les messages en temps réel. Traefik transmet la requête HTTP upgrade sans configuration supplémentaire : vous n’avez donc rien à ajouter. Si vous placez ensuite un CDN ou un autre proxy devant Traefik, autorisez les websockets à cet endroit. Le symptôme est un tableau de bord qui se charge normalement, alors que les nouveaux messages n’apparaissent qu’après une actualisation manuelle.
Initialisez la base de données et démarrez la stack
Démarrez d’abord les services de données et attendez que Postgres termine sa première initialisation.
docker compose up -d postgres redis
docker compose logs postgres | tail -n 5Attendez database system is ready to accept connections. Créez ensuite le schéma.
docker compose run --rm rails bundle exec rails db:chatwoot_prepareCette commande crée la base de données si elle n’existe pas, puis charge le schéma et les données d’initialisation par défaut. Elle affiche les lignes de migration, puis se termine correctement. Si elle reste bloquée en affichant postgres:5432 - no response, l’entrypoint attend une base de données qui n’accepte pas encore les connexions. Lors d’une première exécution, cela signifie généralement que initdb est encore en cours. Attendez, consultez les journaux Postgres, puis exécutez à nouveau la commande. Si l’exécution s’arrête sur l’extension vector, vous avez remplacé l’image pgvector par l’image Postgres standard.
docker compose up -d
docker compose ps
docker compose logs --tail 30 railsLes quatre conteneurs doivent afficher Up, et le journal Rails doit se terminer par une ligne Puma indiquant une écoute sur http://0.0.0.0:3000. Vérifiez ensuite le chemin public :
curl -sI https://support.example.com | head -n 1HTTP/2 200 signifie que toute la chaîne fonctionne. Une erreur 404 renvoyée par Traefik signifie que la règle du routeur ne correspond pas, généralement à cause d’une faute dans le nom d’hôte. Une erreur 502 signifie que Traefik a trouvé le routeur, mais ne parvient pas à joindre le conteneur. La cause est presque toujours l’absence du réseau proxy ou un loadbalancer.server.port différent de 3000.
Ouvrez l’URL, créez votre compte à /app/auth/signup, puis définissez ENABLE_ACCOUNT_SIGNUP=false et exécutez docker compose up -d pour fermer le formulaire.
Pourquoi les réinitialisations de mot de passe et les échanges par e-mail échouent sans SMTP
Sans configuration SMTP (simple mail transfer protocol), Chatwoot est un support client incapable d’envoyer des e-mails. Cela casse bien plus que les notifications. Les réinitialisations de mot de passe ne fonctionnent plus. Un administrateur bloqué hors de son compte le reste donc. Les invitations d’agents ne fonctionnent plus non plus, car une invitation est envoyée par e-mail. Répondre à un client dans une conversation par e-mail devient impossible. La conversation ne fonctionne alors que dans un seul sens. C’est l’étape que l’on oublie, avant de la découvrir au pire moment.
Le mécanisme est simple. Sans configuration SMTP, ActionMailer conserve sa valeur par défaut et tente de remettre les messages à localhost sur le port 25. Aucun serveur de messagerie ne s’exécute dans le conteneur Rails. La tâche de remise lève donc Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25. Les e-mails sont envoyés par un background job. Cette ligne apparaît donc dans le log Sidekiq, et jamais dans le log Rails. Pendant ce temps, la personne qui clique sur « mot de passe oublié » voit une confirmation rassurante, mais ne reçoit rien.
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=trueUtilisez le port 587 avec STARTTLS. La connexion est d’abord ouverte en clair, puis elle est chiffrée avant l’authentification. La plupart des fournisseurs de VPS bloquent les connexions sortantes vers le port 25 pour limiter le spam. Un relay sur le port 587 est donc généralement le seul service auquel la connexion aboutira. SMTP_DOMAIN correspond au domaine que votre serveur annonce pendant l’échange SMTP. Certains relays rejettent les connexions si ce domaine ne correspond pas à leurs attentes.
Appliquez les paramètres et surveillez le worker :
docker compose up -d rails sidekiq
docker compose logs -f sidekiqDéclenchez une réinitialisation de mot de passe depuis la page de connexion. Si l’envoi fonctionne, le log Sidekiq indique que la tâche du mailer s’est terminée normalement. En cas d’échec, il affiche la classe de l’exception, puis Sidekiq réessaie avec un délai croissant. C’est pourquoi un relay défaillant produit la même erreur toutes les quelques minutes pendant plusieurs heures.
Deux rejets sont fréquents. Aucun des deux ne constitue un bug de Chatwoot. 535 Authentication failed signifie que le nom d’utilisateur ou le mot de passe est incorrect pour ce relay. De nombreux fournisseurs exigent un mot de passe d’application plutôt que le mot de passe du compte. 550 Sender address rejected signifie que MAILER_SENDER_EMAIL est une adresse que le relay refuse d’utiliser comme expéditeur. Il doit donc s’agir d’une boîte aux lettres ou d’un domaine que vous avez vérifié auprès du fournisseur.
La réception des e-mails dans une conversation est une tâche distincte. Elle nécessite MAILER_INBOUND_EMAIL_DOMAIN et RAILS_INBOUND_EMAIL_SERVICE, ainsi qu’un serveur de messagerie qui transmette les messages entrants à Chatwoot. Louer un relay est la solution la plus rapide. Si vous préférez gérer vous-même l’ensemble du chemin de messagerie, exécuter votre propre serveur de messagerie avec Mailcow explique ce que cet engagement implique réellement.
Éléments à sauvegarder et vérification de la restauration
Une sauvegarde Chatwoot comporte quatre éléments. Si vous en oubliez un seul, la restauration devient une reconstruction.
- La base de données Postgres, qui contient les conversations, les contacts, les comptes des agents et tous les paramètres.
- Le volume
storage_data, carACTIVE_STORAGE_SERVICE=localécrit les fichiers téléversés sur le disque et conserve uniquement une ligne de référence dans Postgres. - Le fichier
.env, car il contientSECRET_KEY_BASEet les clésACTIVE_RECORD_ENCRYPTION_*. - Les fichiers Compose, car ils indiquent le tag d’image exact correspondant au schéma de votre base de données.
Si vous restaurez uniquement la base de données, toutes les conversations réapparaissent avec des pièces jointes cassées, car les lignes pointent vers des fichiers qui ne se trouvent plus sur le disque.
cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dump-T est important. Sans lui, Compose alloue un pseudo-terminal, qui réécrit les caractères de nouvelle ligne dans le flux. Vous obtenez donc un fichier de dump que pg_restore refuse. -Fc correspond au format personnalisé. Il compresse les données et permet à pg_restore de fonctionner de manière sélective.
docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/storage-$(date +%F).tgz -C /data .Le nom du volume correspond au nom de votre répertoire de projet suivi de _storage_data. Confirmez-le avec docker volume ls | grep storage_data avant de faire confiance à cette commande, car Docker crée un volume vide au lieu d’échouer lorsque le nom indiqué n’existe pas. Vous obtiendriez une archive valide et vide, sans aucune erreur. Vérifiez ensuite sa taille avec ls -lh storage-*.tgz.
Les deux fichiers se trouvent maintenant sur le même disque que les données qu’ils protègent. Cela ne vous protège donc de rien. Copiez-les hors du serveur et chiffrez-les, car un dump de base de données contient chaque message client en clair. Sauvegardes chiffrées hors site avec restic explique la planification et la gestion de la rétention.
La procédure de restauration, à exécuter avant d’en avoir besoin
Restaurez la sauvegarde sur un deuxième VPS, et non sur le serveur en production. Copiez .env, les fichiers Compose et les deux archives, puis exécutez :
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 supprime les objets existants avant le chargement. Utilisez-le uniquement avec une base de données que vous acceptez de perdre. Connectez-vous ensuite et ouvrez une conversation qui contient une pièce jointe. Si la liste des messages se charge et que le fichier se télécharge, la sauvegarde est valide.
Une restauration avec un SECRET_KEY_BASE différent invalide tous les cookies de session. Tous les utilisateurs sont donc déconnectés. Une restauration avec des clés ACTIVE_RECORD_ENCRYPTION_* différentes est plus grave : Chatwoot ne peut pas déchiffrer les colonnes contenant les identifiants des canaux et renvoie ActiveRecord::Encryption::Errors::Decryption. C’est pourquoi .env figure dans la liste des éléments à sauvegarder.
Comment mettre à niveau Chatwoot vers un nouveau tag
L’ordre des opérations compte davantage que les commandes.
- Lisez les notes de version entre votre tag et le tag cible afin d’identifier les étapes manuelles nécessaires.
- Effectuez un nouveau dump de la base de données et créez une archive du stockage. Vérifiez que la taille des deux fichiers est cohérente.
- Modifiez le tag de l’image du service
basedansdocker-compose.yaml. - Téléchargez la nouvelle image, arrêtez la stack, exécutez les migrations, puis redémarrez-la.
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose imagesTéléchargez l’image avant d’exécuter les migrations, car celles-ci doivent être lancées depuis la nouvelle image. L’ancienne image ne contient pas les nouveaux fichiers de migration. Arrêtez la stack avant d’exécuter les migrations, car l’ancien code et le nouveau schéma ne correspondent pas. Un processus Rails encore actif avec l’ancien code peut donc générer des erreurs ou écrire des lignes que le nouveau schéma n’acceptera pas. L’arrêt libère également la mémoire nécessaire à la migration. C’est la raison pour laquelle le projet recommande l’utilisation du swap.
docker compose images affiche le tag réellement utilisé par chaque conteneur. Cela permet de détecter le cas où vous avez modifié le tag sans télécharger la nouvelle image.
Ne sautez pas plusieurs versions à la fois. Pour une installation ancienne, le projet recommande de passer par les tags intermédiaires, car les migrations sont supprimées une fois intégrées au schéma de base. Une base de données très ancienne peut donc atteindre un état sans chemin de mise à niveau possible. Avancez d’une version mineure à la fois et exécutez l’étape de préparation après chaque mise à niveau.
Si Rails démarre avant l’exécution de la migration, il refuse de traiter les requêtes et journalise ActiveRecord::PendingMigrationError: Migrations are pending. Avec restart: always défini, le conteneur redémarre en boucle. docker compose ps affiche alors une durée de fonctionnement qui revient à zéro toutes les quelques secondes. Exécutez l’étape de préparation pour résoudre le problème.
Pour revenir en arrière, remettez l’ancien tag et restaurez le dump. Il n’existe pas de chemin de migration inverse fiable. C’est la raison d’être de l’étape 2.
Modes de panne et messages affichés
502 Bad Gateway de Traefik. Le routeur a trouvé une correspondance, mais le backend n’a pas répondu. Vérifiez que docker compose ps indique rails comme Up, puis exécutez docker network inspect proxy et confirmez que le conteneur rails apparaît dans la liste des conteneurs. Un conteneur qui n’est pas attaché est invisible pour Traefik : la requête correspond à un routeur, puis n’aboutit nulle part.
Le dashboard se charge, mais les nouveaux messages nécessitent un rafraîchissement. La connexion websocket vers /cable n’aboutit pas, ou FRONTEND_URL ne correspond pas à l’adresse affichée dans la barre du navigateur. En cas de différence, la page tente d’ouvrir une connexion websocket vers une autre origine, ce que le navigateur bloque.
FATAL: password authentication failed for user "postgres". Le mot de passe dans .env et celui enregistré dans le volume de données Postgres sont différents. Corrigez-le avec ALTER USER dans le conteneur en cours d’exécution, car modifier à nouveau .env ne changera pas une base de données déjà initialisée.
NOAUTH Authentication required. Redis s’exécute avec --requirepass, mais l’application s’est connectée sans mot de passe. REDIS_PASSWORD est donc absent de .env ou n’a pas été pris en compte. Testez-le directement avec docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping, qui doit renvoyer PONG.
Conteneurs qui se terminent avec le code 137. Il s’agit de SIGKILL. Sur une petite machine, cela signifie généralement que le tueur de processus du noyau déclenché par le manque de mémoire est intervenu. Ajoutez du swap, définissez des limites mémoire par service ou passez à une offre plus puissante.
FAQ
De quelle quantité de RAM un VPS Chatwoot auto-hébergé a-t-il besoin ?
En août 2026, le projet en amont demande au minimum 4 GB de RAM et 4 cœurs CPU, pour une charge annoncée allant jusqu’à 10,000 conversations par jour, et 8 GB avec 8 cœurs jusqu’à 20,000 conversations. Ajoutez au moins 1 GB de swap, car une mise à niveau lance un second processus Rails pour appliquer les migrations, ce qui épuise la mémoire des petites machines. Un VPS de 2 GB démarre et fonctionne avec quelques agents, mais Sidekiq seul peut dépasser 1 GB sous charge. Attendez-vous donc à ce que des conteneurs soient tués avec le code de sortie 137 pendant les périodes d’activité et les mises à niveau.
Pourquoi les e-mails de réinitialisation du mot de passe Chatwoot n’arrivent-ils jamais ?
Parce qu’aucun paramètre SMTP n’est configuré. ActionMailer essaie donc d’envoyer le message à localhost sur le port 25, mais aucun serveur de messagerie ne s’exécute dans le conteneur. Le job échoue dans Sidekiq avec Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25, tandis que le navigateur affiche toujours un message de succès. Définissez SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD et MAILER_SENDER_EMAIL dans .env, redémarrez les services rails et sidekiq, puis surveillez docker compose logs -f sidekiq pendant que vous déclenchez une réinitialisation.
Que faut-il sauvegarder pour restaurer Chatwoot ?
La base de données Postgres, le volume Docker storage_data, le fichier .env et les fichiers compose. La base de données seule ne suffit pas, car les fichiers téléversés se trouvent dans le volume, tandis que Postgres ne contient que des références vers ces fichiers. Une restauration de la base seule vous donnerait donc des conversations avec des pièces jointes manquantes. .env est important, car une valeur SECRET_KEY_BASE différente déconnecte tous les utilisateurs. Des clés ACTIVE_RECORD_ENCRYPTION_* différentes rendent également les colonnes chiffrées illisibles.
Comment mettre à niveau Chatwoot sans endommager la base de données ?
Effectuez une sauvegarde, modifiez le tag de l’image dans votre fichier compose, puis exécutez docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare et docker compose up -d. Effectuez d’abord le pull, car les migrations doivent être exécutées depuis la nouvelle image. Arrêtez également la stack avant l’opération, car l’ancien code utilisé avec un nouveau schéma provoque des erreurs. Sur une installation ancienne, avancez d’une version mineure à la fois, car les migrations sont supprimées lorsqu’elles sont intégrées au schéma de base.
Puis-je utiliser l’image postgres standard au lieu de pgvector ?
Non. Le schéma de Chatwoot active l’extension vector. L’image postgres standard échoue donc pendant db:chatwoot_prepare avec ERROR: extension "vector" is not available, car le fichier de contrôle de l’extension n’est pas présent dans cette image. Conservez pgvector/pgvector:pg16 du fichier compose fourni en amont, ou utilisez une autre image qui fournit pgvector pour votre version majeure de Postgres.