Héberger Rocket.Chat avec Docker Compose
Hébergez Rocket.Chat sur un VPS avec Docker Compose : le jeu de réplicas MongoDB à un nœud requis, le TLS, les sauvegardes et chaque panne corrigée.
Ce que vous allez construire
Une messagerie d'équipe privée que vous possédez entièrement : Rocket.Chat tourne sur votre propre VPS sous Docker Compose, protégé par le TLS, avec chaque message stocké dans une base de données MongoDB que vous pouvez sauvegarder et déplacer. Rocket.Chat est l'alternative open source mature à Slack et Teams : canaux, messages directs, fils de discussion, partage de fichiers, voix et vidéo, le tout sur du matériel que vous louez et contrôlez. L'application est un seul conteneur qui démarre en quelques minutes. Tout ce qui pose vraiment problème vit dans la base de données à côté, c'est pourquoi la majeure partie de ce guide parle de MongoDB, et en particulier de l'unique exigence qui surprend tout le monde la première fois : Rocket.Chat ne fonctionne pas avec un MongoDB autonome. Il lui faut un jeu de réplicas, même si ce « jeu » ne compte qu'un seul nœud.
Prérequis, et le calcul de RAM que personne ne vous explique
Dimensionnez la machine honnêtement. Le plancher réaliste pour une petite équipe est de 2 vCPU et 4 Go de RAM. Le processus Node.js de Rocket.Chat réclame à lui seul environ 1 à 1,5 Go, et le cache WiredTiger de MongoDB s'accapare par défaut à peu près la moitié de la RAM restante. Sur un VPS de 2 Go, les deux tiennent au démarrage puis entrent en collision dès que le trafic réel arrive : MongoDB agrandit son cache, Node agrandit son tas, le noyau n'a plus de pages disponibles, et le tueur de mémoire insuffisante (out-of-memory killer) abat le processus le plus gros, en général mongod. Le conteneur affiche Killed, Docker le redémarre, et vous obtenez un serveur de discussion qui décroche toutes les quelques minutes sous une charge qu'il devrait encaisser sans effort. 2 Go conviennent pour faire un essai à deux personnes ; ce n'est pas un serveur d'équipe. Commencez à 4 Go, et prévoyez 8 Go si vous attendez des dizaines d'utilisateurs simultanés, des appels vidéo, ou un historique de fichiers qui grandit.
Il vous faut également trois choses en place avant de commencer. Un nom de domaine avec un enregistrement A pointant vers l'IP publique du VPS : les fonctions temps réel et les clients mobiles de Rocket.Chat ont besoin d'un nom d'hôte stable, pas d'une simple IP. Les ports 80 et 443 ouverts à la fois sur le pare-feu du serveur et sur le pare-feu réseau de votre hébergeur, qui est un contrôle distinct sur la plupart des panneaux. Et un VPS KVM Ubuntu 24.04 tout neuf avec root ou sudo. Si vous hésitez encore sur le fait qu'un serveur de discussion soit le bon premier service à faire tourner, le guide de ce qui vaut la peine d'être auto-hébergé en 2026 présente les compromis.
Installer le moteur Docker et le plugin Compose
Utilisez le dépôt apt officiel de Docker, pas le paquet docker.io fourni par Ubuntu ni l'ancien binaire Python autonome docker-compose. Le Compose moderne est un plugin Docker que vous invoquez avec docker compose, avec une espace, pas un trait d'union. L'ancien docker-compose v1 est en fin de vie et gère mal la syntaxe de healthcheck et de dépendances ci-dessous.
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] 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
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginConfirmez que les deux éléments sont présents :
sudo docker version
sudo docker compose versionLe fait que docker compose version affiche quelque chose comme Docker Compose version v2.x est la vérification qui compte. S'il échoue avec docker: 'compose' is not a docker command, le plugin ne s'est pas installé et vous allez rencontrer des pannes déroutantes plus tard : corrigez cela ici.
Le fichier compose : MongoDB en jeu de réplicas à un seul nœud
C'est la partie que les gens ratent, alors lisez-la lentement. Rocket.Chat utilise les change streams de MongoDB pour transmettre les nouveaux messages aux clients connectés en temps réel, et les change streams ne sont disponibles que sur un jeu de réplicas. Pointez Rocket.Chat vers un simple mongod autonome et il se connectera, échouera à ouvrir un change stream, et bouclera indéfiniment sur des redémarrages. La solution n'a rien d'exotique : vous faites tourner un seul conteneur MongoDB ordinaire, mais vous le démarrez avec --replSet puis vous initialisez un jeu à un seul membre.
Créez un répertoire de travail et un compose.yml :
services:
mongodb:
image: mongo:8.0
restart: always
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--oplogSize", "128"]
volumes:
- mongodb_data:/data/db
- mongodb_config:/data/configdb
healthcheck:
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 10s
retries: 12
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:8.5.1
restart: always
depends_on:
mongodb:
condition: service_healthy
environment:
MONGO_URL: "mongodb://mongodb:27017/rocketchat?replicaSet=rs0"
MONGO_OPLOG_URL: "mongodb://mongodb:27017/local?replicaSet=rs0"
ROOT_URL: "https://chat.example.com"
PORT: "3000"
ports:
- "127.0.0.1:3000:3000"
volumes:
mongodb_data:
mongodb_config:Plusieurs choix ici sont délibérés. Le port de Rocket.Chat est publié sur 127.0.0.1:3000, pas sur 0.0.0.0 : l'application elle-même n'a pas de TLS, donc seul le proxy inverse sur la même machine doit pouvoir l'atteindre ; l'attacher à toutes les interfaces mettrait une page de connexion en clair directement sur l'internet public. MongoDB n'est pas du tout publié sur l'hôte ; il n'est joignable que via le réseau interne de Compose sous le nom mongodb, qui est exactement le nom d'hôte utilisé par MONGO_URL. MONGO_URL porte ?replicaSet=rs0 : retirez-le et le pilote traite le serveur comme autonome même s'il s'agit d'un jeu de réplicas, et les change streams échouent quand même. MONGO_OPLOG_URL pointe vers la base local où réside l'oplog ; le Rocket.Chat moderne préfère les change streams, mais le définir est sans danger et satisfait d'anciens chemins de code. Le depends_on utilise condition: service_healthy, donc Compose attend que MongoDB réponde à un ping avant même de démarrer Rocket.Chat : c'est à cela que sert le healthcheck.
Épinglez de vraies étiquettes de version sur les deux images, mongo:8.0 et une version explicite de Rocket.Chat comme 8.5.1 ici, et n'utilisez jamais :latest, qui transforme un docker pull non surveillé en mise à niveau accidentelle et non migrable. Vérifiez la version stable actuelle de Rocket.Chat et les versions de MongoDB qu'elle prend en charge avant d'épingler. Rocket.Chat publie un document d'information lisible par machine pour chaque version : curl -s https://releases.rocket.chat/8.5.1/info | jq '{compatibleMongoVersions, lts}' renvoie compatibleMongoVersions: ["8.0"] pour la 8.5.1, donc mongo:8.0 est le seul moteur pris en charge, plus un indicateur lts qui vous dit si cette version est une build à support long terme qui mérite d'être épinglée pour un serveur que vous préférez ne pas avoir à surveiller.
Initialiser le jeu de réplicas
Démarrez la pile :
sudo docker compose up -dRocket.Chat va commencer à planter immédiatement et Docker ne cessera de le redémarrer : c'est normal, parce que le jeu de réplicas n'existe pas encore. Créez-le une seule fois, à la main :
sudo docker compose exec mongodb mongosh --eval 'rs.initiate({_id: "rs0", members: [{_id: 0, host: "mongodb:27017"}]})'Un résultat correct est { ok: 1 }. En quelques secondes, le nœud unique s'élit lui-même primaire ; confirmez avec :
sudo docker compose exec mongodb mongosh --quiet --eval 'rs.status().members[0].stateStr'Vous devez voir PRIMARY. Le détail le plus important de toute cette page est l'argument host: "mongodb:27017". Si vous lancez un rs.initiate() nu sans liste de membres, MongoDB annonce le jeu de réplicas sous le nom d'hôte interne du conteneur, un hash aléatoire comme a1b2c3d4e5f6. Rocket.Chat, qui se connecte depuis son propre conteneur, ne peut pas résoudre ce nom, donc le pilote MongoDB échoue sur le DNS et boucle indéfiniment en journalisant MongoServerSelectionError: getaddrinfo ENOTFOUND a1b2c3d4e5f6. Initialisez toujours avec le nom de service explicite qui correspond à votre MONGO_URL.
Premier démarrage : regardez-le monter
Une fois le jeu primaire, le prochain redémarrage de Rocket.Chat se connecte proprement et lance ses migrations de première exécution. Suivez les journaux :
sudo docker compose logs -f rocketchatLa ligne que vous attendez est la bannière de démarrage :
+--------------------------------------------+
SERVER RUNNING
Rocket.Chat Version: 8.5.1
NodeJS Version: 22.22.3 - x64
+--------------------------------------------+Le premier démarrage est lent : l'application exécute des migrations de base de données et construit des index, alors accordez-lui une minute ou deux avant de vous inquiéter. Si le journal répète plutôt MongoServerSelectionError: Server selection timed out after 30000 ms avec une description de topologie de type ReplicaSetNoPrimary, le jeu de réplicas n'est pas initialisé ; s'il répète getaddrinfo ENOTFOUND sur un hash aléatoire, il a été initialisé avec le mauvais hôte. Dans les deux cas, revenez d'une étape. Une fois que vous voyez SERVER RUNNING, Rocket.Chat écoute sur 127.0.0.1:3000 et il est temps de placer un vrai nom d'hôte et le TLS devant lui.
Placez-le derrière le TLS
N'exposez jamais Rocket.Chat en HTTP simple. Connectez-vous une seule fois via http:// et vous avez remis votre mot de passe administrateur à toute personne sur le chemin. Terminez le TLS dans un proxy inverse sur la même machine et transférez vers 127.0.0.1:3000. Deux choses comptent : le proxy doit transmettre les en-têtes de mise à niveau WebSocket, parce que Rocket.Chat fonctionne en temps réel et casse sans eux, et le ROOT_URL du conteneur doit correspondre exactement à l'adresse HTTPS publique que les utilisateurs saisissent.
Commencez par un bloc serveur nginx en HTTP simple qui fait proxy vers l'application et transmet les en-têtes de mise à niveau. Enregistrez-le sous /etc/nginx/sites-available/rocketchat, créez un lien symbolique vers sites-enabled, et rechargez :
server {
listen 80;
server_name chat.example.com;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Laissez-le sur le port 80 pour l'instant : un bloc avec listen 443 ssl; et sans certificat ne passera même pas sudo nginx -t. Rechargez nginx (sudo nginx -t && sudo systemctl reload nginx), puis émettez le certificat. Le chemin le plus propre sur Ubuntu est les certificats TLS Let's Encrypt avec Certbot et nginx : certbot --nginx réécrit le bloc ci-dessus sur place, en ajoutant listen 443 ssl;, les lignes ssl_certificate, et une redirection automatique de 80 vers 443, et il programme le renouvellement pour vous. Si vous faites déjà tourner plusieurs conteneurs derrière un seul proxy, Traefik avec TLS automatique pour de nombreuses applications Docker est l'option plus soignée : ajoutez des labels de routeur et de service au service rocketchat et Traefik demande et renouvelle le certificat pour vous, sans aucun bloc nginx. Dans les deux cas, réglez ROOT_URL sur https://chat.example.com dans compose.yml et relancez sudo docker compose up -d pour que le conteneur prenne en compte le changement. Si vous voulez que le serveur ne soit joignable que depuis votre propre réseau plutôt que depuis l'internet public, placez devant lui un VPN WireGuard auto-hébergé sur le VPS et attachez le proxy à l'adresse du tunnel.
L'assistant de configuration initiale
Rendez-vous sur https://chat.example.com et Rocket.Chat vous guide à travers un court assistant. D'abord, le compte administrateur : un nom réel, un nom d'utilisateur, un e-mail et un mot de passe fort ; c'est le seul compte qui existe, alors ne le perdez pas. Ensuite, les informations sur l'organisation et le serveur : nom, secteur, taille, le nom du site et la langue par défaut ; c'est cosmétique, remplissez-le et passez à la suite. Puis le choix qui compte vraiment : enregistrer cet espace de travail auprès de Rocket.Chat Cloud, ou le garder autonome (standalone).
L'enregistrement active les notifications push mobiles via la passerelle de Rocket.Chat et la place de marché de modules complémentaires, au prix d'une relation de plan de contrôle avec le cloud de Rocket.Chat. Le mode autonome garde le serveur entièrement privé et sans dépendance, mais les notifications push iOS et Android cessent de fonctionner, parce qu'Apple et Google ne laissent pas une application construite soi-même détenir les certificats push : les applications officielles passent par la passerelle cloud. Choisissez le mode autonome si la confidentialité est tout l'enjeu et que vos utilisateurs vivent dans l'application web ; choisissez l'enregistrement si le push mobile n'est pas négociable. Vous pouvez changer d'avis plus tard dans l'espace Admin.
Verrouillez-le avant d'inviter qui que ce soit
Rocket.Chat est livré avec l'inscription ouverte activée : par défaut, le formulaire d'inscription est réglé sur Public, donc quiconque trouve l'URL peut créer un compte. Sur un nom d'hôte public, c'est une porte ouverte. Allez dans Admin → Settings → Accounts → Registration et réglez Registration Form sur Disabled, pour créer les comptes à la main ou par lien d'invitation, ou sur Secret URL. Pendant que vous y êtes, désactivez Allow Anonymous Read et Allow Anonymous Write sauf si vous voulez spécifiquement un canal public en lecture seule.
Décidez aussi où vont les fichiers téléversés. Le stockage File Upload par défaut est GridFS, qui range chaque image et pièce jointe dans MongoDB lui-même. C'est simple, mais cela signifie que votre base de données, et chaque mongodump que vous prenez, grossit sans limite à mesure que les gens collent des captures d'écran. Dans Admin → Settings → File Upload vous pouvez basculer le stockage vers le système de fichiers local ou un bucket compatible S3, et fixer une taille maximale de fichier raisonnable. Pour une petite équipe, GridFS convient ; sachez simplement que vos sauvegardes s'alourdissent avec le temps.
Sauvegardes avec mongodump
Toutes vos données vivent dans le volume mongodb_data. Ne vous contentez pas de copier le volume sous une base de données en cours d'exécution : prenez un dump cohérent avec mongodump, redirigé vers un fichier sur l'hôte :
sudo docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > rocketchat-$(date +%F).archive.gzCette unique archive gzip est tout votre espace de travail : utilisateurs, canaux, messages, réglages, et si vous avez laissé les fichiers sur GridFS, les fichiers aussi. Si vous avez déplacé les fichiers vers le système de fichiers ou S3, sauvegardez ce stockage séparément. Restaurez sur une pile neuve en initialisant d'abord le jeu de réplicas, puis :
sudo docker compose exec -T mongodb mongorestore --archive --gzip --drop < rocketchat-2026-07-15.archive.gzCopiez l'archive hors de la machine : stockage objet, un autre serveur, n'importe où la mort du VPS n'emporte pas la sauvegarde avec elle, et lancez le dump depuis cron chaque nuit. Une sauvegarde que vous n'avez jamais restaurée est un espoir, pas une sauvegarde ; entraînez-vous à la restauration une fois sur un VPS jetable pour savoir qu'elle marche avant d'en avoir besoin.
Mises à niveau : épinglez les étiquettes, lisez les notes, respectez la matrice Mongo
Deux règles rendent les mises à niveau ennuyeuses. Premièrement, mettez Rocket.Chat à niveau une version majeure à la fois. Il exécute des migrations de schéma au démarrage et refuse délibérément de sauter des majeures ; essayez de passer de 6.x directement à 8.x et il s'arrête avec une erreur de migration plutôt que de corrompre vos données. Faites passer l'étiquette d'image à la dernière version de la majeure suivante, lisez les notes de cette version pour les changements incompatibles, lancez docker compose up -d, et regardez les journaux finir la migration avant de continuer. Deuxièmement, respectez la matrice de support de MongoDB. Chaque version de Rocket.Chat prend en charge un ensemble précis de versions de MongoDB, et curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions vous dit lesquelles. Quand vous déplacez MongoDB, disons de 7.0 à 8.0, avancez d'une majeure à la fois et réglez la version de compatibilité des fonctionnalités après chaque saut. Sur MongoDB 8.0, cette commande exige un confirm: true explicite, sinon elle refuse avec un message vous disant de la relancer avec l'indicateur de confirmation :
sudo docker compose exec mongodb mongosh --eval 'db.adminCommand({setFeatureCompatibilityVersion: "8.0", confirm: true})'Prenez un mongodump avant chaque mise à niveau de l'un ou l'autre composant. C'est toute la police d'assurance.
Modes de défaillance, avec les chaînes exactes
Rocket.Chat boucle sur des redémarrages juste après docker compose up, et docker compose logs rocketchat se remplit d'un MongoServerSelectionError. MongoDB tourne mais le pilote ne peut pas sélectionner de primaire, et la chaîne exacte vous dit quelle erreur vous avez faite. Server selection timed out after 30000 ms avec un type de topologie ReplicaSetNoPrimary signifie que vous n'avez jamais lancé rs.initiate() : le jeu n'a pas encore de configuration. getaddrinfo ENOTFOUND suivi d'un hash aléatoire signifie que vous avez initialisé sans le host: "mongodb:27017" explicite, donc MongoDB a annoncé un nom d'hôte de conteneur non résoluble. Diagnostiquez avec sudo docker compose exec mongodb mongosh --eval 'rs.status()' : s'il échoue avec MongoServerError: no replset config has been received, initialisez le jeu ; s'il montre un membre dont le name est un hash aléatoire, réinitialisez avec le nom de service.
L'interface web se charge mais la connexion tourne indéfiniment et n'aboutit jamais. Ouvrez la console du navigateur et vous verrez WebSocket connection to 'wss://chat.example.com/websocket' failed. C'est presque toujours une incohérence de ROOT_URL ou un proxy qui ne transmet pas les en-têtes de mise à niveau. Confirmez que ROOT_URL est égal à l'adresse publique exacte, y compris https://, et que votre bloc location nginx définit Upgrade et Connection "upgrade" avec proxy_http_version 1.1. Changez l'un ou l'autre et relancez docker compose up -d.
Un conteneur n'arrête pas de mourir et docker compose ps l'affiche en Restarting. docker compose logs se coupe au milieu d'une ligne et sudo dmesg | tail montre Out of memory: Killed process 12345 (mongod) de la part de l'oom-killer ; le code de sortie est 137. La machine est à court de RAM. La vraie solution est un VPS plus gros, 4 Go minimum. En dépannage, ajoutez du swap et plafonnez le cache de MongoDB avec --wiredTigerCacheSizeGB 1 dans son command, mais le swap ne fait que retarder le prochain OOM sous charge réelle :
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfiledocker compose up échoue avec Error response from daemon: driver failed programming external connectivity ... bind: address already in use. Quelque chose occupe déjà le port 3000, souvent un conteneur Rocket.Chat précédent qui ne s'est pas arrêté proprement, ou une autre application. Trouvez-le avec sudo ss -ltnp | grep :3000, arrêtez ce processus ou conteneur, ou changez le côté hôte du mappage en 127.0.0.1:3001:3000 et mettez à jour le proxy_pass de votre proxy en conséquence.
FAQ
Rocket.Chat a-t-il vraiment besoin d'un jeu de réplicas MongoDB ?
Oui, même pour un seul serveur avec un unique nœud de base de données. Rocket.Chat délivre les messages en temps réel grâce aux change streams de MongoDB, et les change streams sont une fonction réservée aux jeux de réplicas : un mongod autonome ne peut pas en ouvrir. Vous n'avez pas besoin de plusieurs machines ; vous faites tourner un conteneur MongoDB démarré avec --replSet rs0 et vous initialisez un jeu à un seul membre avec rs.initiate(). Sautez cette étape et le pilote ne trouve jamais de primaire, donc Rocket.Chat boucle sur des redémarrages avec MongoServerSelectionError: Server selection timed out et ne termine jamais son démarrage.
Combien de RAM faut-il pour un Rocket.Chat auto-hébergé ?
Prévoyez 4 Go comme minimum pratique et 8 Go pour une équipe active. Le processus Node de Rocket.Chat utilise environ 1 à 1,5 Go et MongoDB s'approprie à peu près la moitié de la RAM restante pour son cache WiredTiger, donc sur une machine de 2 Go les deux entrent en collision et le tueur de mémoire insuffisante termine mongod sous la moindre charge réelle, affichant Killed dans les journaux et le code de sortie 137. Deux Go suffisent seulement à évaluer le logiciel avec deux ou trois utilisateurs de test.
Comment placer Rocket.Chat derrière HTTPS ?
Faites tourner sur le même VPS un proxy inverse qui termine le TLS et transfère vers 127.0.0.1:3000, et réglez le ROOT_URL du conteneur sur votre adresse https:// publique. Le proxy doit transmettre les en-têtes de mise à niveau WebSocket sinon la connexion restera bloquée. Certbot avec nginx est la configuration la plus simple pour une seule application ; Traefik est plus propre si vous faites tourner plusieurs conteneurs derrière un seul proxy et que vous voulez une gestion automatique des certificats.
Comment sauvegarder un Rocket.Chat auto-hébergé ?
Prenez un dump cohérent de la base de données avec mongodump plutôt que de copier le volume : docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > backup.archive.gz. Cette archive contient les utilisateurs, les canaux, les messages et les réglages, ainsi que les fichiers téléversés si vous avez laissé le stockage sur GridFS. Copiez-la hors du serveur, automatisez-la chaque nuit avec cron, et répétez un mongorestore sur une machine jetable pour savoir que la restauration fonctionne vraiment.
Comment mettre à niveau Rocket.Chat sans casser MongoDB ?
Mettez Rocket.Chat à niveau une version majeure à la fois : il exécute des migrations au démarrage et refuse de sauter des majeures, et lisez les notes de chaque version avant de faire passer l'étiquette d'image épinglée. Vérifiez quelles versions de MongoDB votre version cible prend en charge avec curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions, et quand vous déplacez MongoDB, avancez d'une majeure à la fois et réglez setFeatureCompatibilityVersion avec confirm: true après chaque saut. Prenez toujours un mongodump d'abord.