Rocket.Chat z Docker Compose: instalacja na własnym VPS
Instrukcja wdrożenia Rocket.Chat przy użyciu Docker Compose. Dowiedz się, jak poprawnie skonfigurować wymagany replica set MongoDB, wdrożyć TLS oraz uniknąć błędów przy starcie.
Co budujesz
Prywatny komunikator zespołowy, którego jesteś wyłącznym właścicielem: Rocket.Chat działający na własnym VPS przy użyciu Docker Compose, z terminacją TLS, gdzie każda wiadomość przechowywana jest w bazie danych MongoDB, którą można archiwizować i przenosić. Rocket.Chat to dojrzała alternatywa open-source dla Slacka i Teams, oferująca kanały, wiadomości bezpośrednie, wątki, udostępnianie plików oraz komunikację głosową i wideo – wszystko na sprzęcie, który wynajmujesz i kontrolujesz. Nie jest to jednak jedyna wiarygodna opcja, a jeśli nadal dokonujesz wyboru, porównanie Mattermost, Rocket.Chat, Synapse i Zulip zestawia je pod kątem kwestii, które stają się problematyczne w późniejszym czasie: zużycia pamięci RAM, bazy danych, powiadomień push na urządzenia mobilne, SSO oraz aktualizacji. Aplikacja to pojedynczy kontener, który uruchamia się w kilka minut. Wszystko, co może zawieść, znajduje się w powiązanej bazie danych, dlatego większość tego przewodnika dotyczy MongoDB, a w szczególności jednego wymagania, które za pierwszym razem zaskakuje każdego: Rocket.Chat nie uruchomi się z pojedynczą instancją (standalone) MongoDB. Wymaga on zestawu replik (replica set), nawet jeśli ten „zestaw” składa się z pojedynczego węzła.
Wymagania wstępne i obliczenia pamięci RAM, o których nikt nie wspomina
Należy rzetelnie dobrać zasoby serwera. Realne minimum dla małego zespołu to 2 vCPU i 4 GB pamięci RAM. Proces Node.js aplikacji Rocket.Chat wymaga samodzielnie około 1 do 1,5 GB pamięci, a pamięć podręczna WiredTiger silnika MongoDB domyślnie zajmuje większą z wartości: 50% (całkowita pamięć RAM minus 1 GB) lub 0,256 GB. To ustawienie domyślne zakłada, że mongod ma maszynę wyłącznie dla siebie: jest obliczane na podstawie całkowitej ilości pamięci RAM i nie uwzględnia pamięci już zajętej przez Node, co na maszynie z 4 GB RAM daje 1,5 GB, a na maszynie z 2 GB RAM około 0,5 GB, doliczając do tego stertę Node, pamięć mongod poza pamięcią podręczną oraz system operacyjny. Na VPS z 2 GB RAM oba procesy uruchamiają się poprawnie, ale wchodzą w konflikt w momencie pojawienia się rzeczywistego ruchu: MongoDB powiększa pamięć podręczną, Node powiększa stertę, jądro systemu wyczerpuje strony pamięci, a mechanizm out-of-memory killer kończy proces, który zajmuje najwięcej miejsca, zazwyczaj mongod. Kontener wyświetla Killed, Docker go restartuje, a serwer czatu rozłącza się co kilka minut pod obciążeniem, które powinien bez problemu obsłużyć. 2 GB wystarczą do testów dla dwóch osób; nie jest to konfiguracja dla zespołu. Należy zacząć od 4 GB, a w przypadku oczekiwania dziesiątek jednoczesnych użytkowników, połączeń wideo lub rosnącej historii plików, zapewnić 8 GB. Należy również uwzględnić zasoby dla innych usług działających na serwerze: uruchomienie przestrzeni roboczej AFFiNE w stylu Notion na tym samym VPS dodaje cztery kolejne kontenery rywalizujące o te same zasoby, więc ich pamięć RAM musi zostać dodana do wymagań Rocket.Chat, a nie odjęta od nich.
Przed rozpoczęciem należy również zapewnić trzy elementy. Nazwę domenową z rekordem A wskazującym na publiczny adres IP serwera VPS; funkcje czasu rzeczywistego Rocket.Chat oraz klienci mobilni wymagają stabilnej nazwy hosta, a nie samego adresu IP. Otwarte porty 80 i 443 zarówno w zaporze sieciowej serwera, jak i w zaporze sieciowej dostawcy, która w większości paneli zarządzania stanowi oddzielny element. Oraz świeżą instalację Ubuntu 24.04 KVM VPS z dostępem root lub sudo. Jeśli decyzja o tym, czy serwer czatu jest odpowiednią pierwszą usługą do uruchomienia, jeszcze nie zapadła, przewodnik po tym, co warto hostować samodzielnie w 2026 roku przedstawia związane z tym kompromisy.
Instalacja silnika Docker oraz wtyczki Compose
Należy korzystać z oficjalnego repozytorium apt firmy Docker, a nie z pakietu docker.io dostarczanego przez Ubuntu czy przestarzałego, samodzielnego pliku binarnego docker-compose w języku Python. Nowoczesny Compose to wtyczka Dockera, którą wywołuje się za pomocą docker compose (ze spacją, nie z łącznikiem). Stara wersja docker-compose v1 nie jest już wspierana i błędnie obsługuje poniższą składnię healthcheck oraz zależności.
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-pluginNależy potwierdzić obecność obu komponentów:
sudo docker version
sudo docker compose versionWyświetlenie linii wersji przez docker compose version jest kluczowym testem. Bieżące wydania wyświetlają Docker Compose version v5.x (wersja v5.6.0, wydana 2 października 2026, była najnowszą na dzień 2026-10-10); starsza instalacja może nadal wyświetlać v2.x, co jest wspierane przez Docker. Docker opisuje Compose v5 jako funkcjonalnie identyczny z v2, numerując go jako v5 w celu uniknięcia pomyłek ze starszymi formatami plików compose v2 i v3, dlatego obie wersje są odpowiednie dla tego przewodnika. Jeśli wystąpi błąd docker: 'compose' is not a docker command, oznacza to, że wtyczka nie została zainstalowana, co doprowadzi do trudnych w diagnozie błędów na późniejszym etapie; należy naprawić to w tym miejscu.
Plik compose: MongoDB jako replikacja jednostanowiskowa
To jest etap, na którym często popełniane są błędy, dlatego należy zapoznać się z nim uważnie. Rocket.Chat wykorzystuje change streams w MongoDB do przesyłania nowych wiadomości do połączonych klientów w czasie rzeczywistym, a mechanizm ten jest dostępny wyłącznie w ramach zestawu replik (replica set). Skierowanie Rocket.Chat na zwykłą, samodzielną instancję mongod spowoduje nawiązanie połączenia, niepowodzenie otwarcia strumienia zmian i zapętlenie procesu restartu. Rozwiązanie nie jest skomplikowane: należy uruchomić pojedynczy, standardowy kontener MongoDB, ale z flagą --replSet, a następnie zainicjować jednoelementowy zestaw.
Utwórz katalog roboczy oraz plik 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:Kilka wyborów w tym pliku jest celowych. Port Rocket.Chat jest publikowany na 127.0.0.1:3000, a nie 0.0.0.0; sama aplikacja nie obsługuje TLS, więc dostęp do niej powinien mieć wyłącznie proxy odwrotne działające na tym samym hoście. Powiązanie jej z każdym interfejsem wystawiłoby stronę logowania przesyłaną otwartym tekstem bezpośrednio do publicznego Internetu. MongoDB nie jest w ogóle publikowane na hoście; jest dostępne tylko wewnątrz sieci Compose pod nazwą mongodb, która jest dokładnie taką nazwą hosta, jakiej używa MONGO_URL. MONGO_URL zawiera ?replicaSet=rs0, co jawnie definiuje nazwę zestawu; MongoDB zaleca to ustawienie w celu zapewnienia spójnego zachowania sterowników. Pominięcie tego parametru samo w sobie nie powoduje awarii: directConnection domyślnie przyjmuje false, więc sterownik nadal wykrywa zestaw replik i przesyła operacje do węzła głównego (primary), pod warunkiem, że zestaw został zainicjowany z nazwą hosta, którą Rocket.Chat potrafi rozwiązać, czym zajmuje się kolejna sekcja. MONGO_OPLOG_URL wskazuje na bazę danych local, w której znajduje się oplog; nowoczesny Rocket.Chat preferuje strumienie zmian, ale ustawienie to jest bezpieczne i zapewnia kompatybilność ze starszymi ścieżkami kodu. Sekcja depends_on wykorzystuje condition: service_healthy, dzięki czemu Compose czeka, aż MongoDB odpowie na ping, zanim uruchomi Rocket.Chat – do tego właśnie służy healthcheck.
Przypisz konkretne wersje (tagi) do obu obrazów, mongo:8.0 oraz konkretne wydanie Rocket.Chat, takie jak 8.5.1 w tym przykładzie. Nigdy nie używaj :latest, co zmienia bezobsługową aktualizację docker pull w przypadkową, niemożliwą do łatwego wycofania migrację. Przed przypisaniem wersji sprawdź aktualne stabilne wydanie Rocket.Chat oraz wspierane przez nie wersje MongoDB. Rocket.Chat publikuje dokument informacyjny w formacie maszynowym dla każdego wydania: curl -s https://releases.rocket.chat/8.5.1/info | jq '{compatibleMongoVersions, lts}' zwraca compatibleMongoVersions: ["8.0"] dla wersji 8.5.1, więc mongo:8.0 jest jedynym wspieranym silnikiem, wraz z flagą lts informującą, czy dane wydanie jest wersją o długoterminowym wsparciu (LTS), którą warto przypisać na serwerze, którego nie chcesz stale nadzorować. Nie każdy projekt publikuje wersjonowane obrazy; w takim przypadku przypisanie dotyczy źródła: samodzielne hostowanie trackera treningów openGym oznacza pobranie konkretnego tagu git i zbudowanie aplikacji z niego, zamiast podążania za zmieniającą się gałęzią (branch).
Inicjalizacja zestawu replik
Uruchom stos:
sudo docker compose up -dRocket.Chat zacznie natychmiast ulegać awarii, a Docker będzie go stale restartował. Jest to zachowanie oczekiwane, ponieważ zestaw replik jeszcze nie istnieje. Należy go utworzyć ręcznie:
sudo docker compose exec mongodb mongosh --eval 'rs.initiate({_id: "rs0", members: [{_id: 0, host: "mongodb:27017"}]})'Poprawnym wynikiem jest { ok: 1 }. W ciągu kilku sekund pojedynczy węzeł wybierze siebie jako węzeł główny (primary); potwierdź to poleceniem:
sudo docker compose exec mongodb mongosh --quiet --eval 'rs.status().members[0].stateStr'Oczekiwany wynik to PRIMARY. Najważniejszym szczegółem na całej tej stronie jest argument host: "mongodb:27017". Jeśli uruchomisz zwykłe rs.initiate() bez listy członków, MongoDB ogłosi zestaw replik pod wewnętrzną nazwą hosta kontenera, czyli losowym hashem typu a1b2c3d4e5f6. Rocket.Chat, łącząc się z własnego kontenera, nie może rozwiązać tej nazwy, przez co sterownik MongoDB zgłasza błąd DNS i zapętla się, logując MongoServerSelectionError: getaddrinfo ENOTFOUND a1b2c3d4e5f6. Zawsze inicjuj zestaw z jawną nazwą usługi, która odpowiada Twojemu MONGO_URL.
Pierwsze uruchomienie: monitorowanie procesu
Gdy zestaw jest główny (primary), kolejny restart Rocket.Chat przebiega poprawnie i rozpoczyna migracje przy pierwszym uruchomieniu. Monitoruj dzienniki:
sudo docker compose logs -f rocketchatWiersz, na który należy czekać, to baner startowy:
+--------------------------------------------+
SERVER RUNNING
Rocket.Chat Version: 8.5.1
NodeJS Version: 22.22.3 - x64
+--------------------------------------------+Pierwsze uruchomienie jest powolne, ponieważ aplikacja wykonuje migracje bazy danych i buduje indeksy. Należy odczekać minutę lub dwie przed podjęciem działań naprawczych. Jeśli dziennik powtarza MongoServerSelectionError: Server selection timed out after 30000 ms z opisem topologii typu ReplicaSetNoPrimary, zestaw replik nie został zainicjowany. Jeśli powtarza getaddrinfo ENOTFOUND z losowym hashem, został zainicjowany z błędnym hostem. W obu przypadkach należy wrócić do poprzedniego kroku. Gdy pojawi się SERVER RUNNING, Rocket.Chat nasłuchuje na 127.0.0.1:3000 i jest to moment na skonfigurowanie właściwej nazwy hosta oraz TLS przed aplikacją.
Zabezpieczenie za pomocą TLS
Nigdy nie udostępniaj Rocket.Chat przez nieszyfrowany protokół HTTP. Jednokrotne zalogowanie przez http:// powoduje przekazanie hasła administratora każdemu, kto znajduje się na ścieżce połączenia. Terminację TLS należy przeprowadzić na odwrotnym proxy (reverse proxy) działającym na tym samym serwerze, przekazując ruch do 127.0.0.1:3000. Dwie kwestie są kluczowe: proxy musi przekazywać nagłówki aktualizacji WebSocket, ponieważ Rocket.Chat działa w czasie rzeczywistym i bez nich przestaje funkcjonować, a parametr ROOT_URL kontenera musi być dokładnie zgodny z publicznym adresem HTTPS wpisywanym przez użytkowników.
Rozpocznij od bloku serwera nginx w trybie zwykłego HTTP, który przekazuje ruch do aplikacji i przesyła nagłówki aktualizacji. Zapisz go jako /etc/nginx/sites-available/rocketchat, utwórz dowiązanie symboliczne w sites-enabled i przeładuj konfigurację:
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;
}
}Na razie pozostaw go na porcie 80; blok z listen 443 ssl; bez certyfikatu nie przejdzie nawet weryfikacji sudo nginx -t. Przeładuj nginx (sudo nginx -t && sudo systemctl reload nginx), a następnie wystaw certyfikat. Najczystszą metodą w systemie Ubuntu jest uzyskanie certyfikatów TLS Let's Encrypt za pomocą Certbot i nginx: certbot --nginx automatycznie modyfikuje powyższy blok, dodając listen 443 ssl;, linie ssl_certificate oraz automatyczne przekierowanie z portu 80 na 443, a także harmonogram odnawiania certyfikatów. Jeśli uruchamiasz już kilka kontenerów za jednym proxy, lepszym rozwiązaniem będzie Traefik z automatycznym TLS dla wielu aplikacji Docker; dodaj etykiety routera i usługi do serwisu rocketchat, a Traefik samodzielnie wystąpi o certyfikat i będzie go odnawiał, eliminując potrzebę tworzenia bloku nginx. Niezależnie od wybranej metody, ustaw ROOT_URL na https://chat.example.com w pliku compose.yml i uruchom ponownie sudo docker compose up -d, aby kontener uwzględnił zmianę. Jeśli chcesz, aby serwer był dostępny wyłącznie z sieci lokalnej, a nie z publicznego Internetu, umieść go za własnym serwerem VPN WireGuard na VPS i powiąż proxy z adresem tunelu.
Kreator konfiguracji przy pierwszym uruchomieniu
Przejdź pod adres https://chat.example.com, aby uruchomić krótki kreator konfiguracji Rocket.Chat. Najpierw należy utworzyć konto administratora, podając imię i nazwisko, nazwę użytkownika, adres e-mail oraz silne hasło; jest to jedyne istniejące konto, dlatego należy zadbać o jego bezpieczeństwo. Następnie należy podać informacje o organizacji i serwerze, takie jak nazwa, branża, wielkość, nazwa witryny oraz domyślny język; dane te mają charakter informacyjny, więc należy je wypełnić i przejść dalej. Kolejny krok jest kluczowy: wybór między rejestracją obszaru roboczego w chmurze Rocket.Chat Cloud a trybem standalone.
Rejestracja umożliwia korzystanie z powiadomień push na urządzenia mobilne za pośrednictwem bramy Rocket.Chat oraz dostęp do sklepu z dodatkami, co wiąże się z nawiązaniem relacji z chmurą Rocket.Chat; powiadomienia przesyłane przez bramę są wliczane do miesięcznego limitu obszaru roboczego. Tryb standalone zapewnia pełną prywatność serwera i brak zależności zewnętrznych, jednak oficjalne aplikacje na iOS i Android przestają otrzymywać powiadomienia push. Wynika to z dokumentacji Rocket.Chat, według której aplikacje te współpracują wyłącznie z bramą chmurową, która nie działa w niezarejestrowanych obszarach roboczych. Rozwiązaniem tego problemu jest przygotowanie własnej, oznaczonej własną marką (white-labeled) kompilacji aplikacji mobilnej: należy wyłączyć bramę w ustawieniach Push, wkleić własne certyfikaty APNs oraz dane uwierzytelniające Firebase Cloud Messaging, a następnie nakazać użytkownikom instalację własnej aplikacji zamiast oficjalnej. Wybierz tryb standalone, jeśli priorytetem jest prywatność, użytkownicy korzystają głównie z aplikacji webowej lub jesteś przygotowany na dystrybucję własnej aplikacji mobilnej. Wybierz rejestrację, jeśli powiadomienia push w oficjalnych aplikacjach są niezbędne. Decyzję można zmienić później w panelu Admin.
Zabezpiecz instancję przed udostępnieniem
Rocket.Chat domyślnie posiada włączoną otwartą rejestrację, a formularz rejestracji jest ustawiony na Public, co oznacza, że każdy, kto zna adres URL, może utworzyć konto. W przypadku publicznego hosta stanowi to poważne zagrożenie. Należy przejść do Admin → Settings → Accounts → Registration i ustawić Registration Form na Disabled, aby tworzyć konta ręcznie lub za pomocą linków zaproszeniowych, albo na Secret URL. W tym samym miejscu należy wyłączyć Allow Anonymous Read oraz Allow Anonymous Write, chyba że wymagany jest publiczny kanał tylko do odczytu. Jeśli ręczne tworzenie kont jest zbyt czasochłonne, a Rocket.Chat nie jest jedyną usługą używaną przez zespół, warto skonfigurować logowanie OAuth w Rocket.Chat wskazujące na samodzielnie hostowany serwer Authentik SSO. Dzięki temu zarządzanie użytkownikami odbywa się centralnie, a nie w każdej aplikacji z osobna.
Należy również określić miejsce przechowywania plików. Domyślnym magazynem dla File Upload jest GridFS, który przechowuje wszystkie obrazy i załączniki bezpośrednio w bazie MongoDB. Jest to rozwiązanie proste, ale powoduje, że baza danych oraz każdy wykonywany mongodump niekontrolowanie rosną wraz z przesyłanymi zrzutami ekranu. W sekcji Admin → Settings → File Upload można zmienić magazyn na lokalny system plików lub zasobnik zgodny z S3 oraz ustawić rozsądny limit rozmiaru pliku. Jeśli zespół wymienia całe biblioteki zdjęć zamiast pojedynczych zrzutów ekranu, powinny one trafiać na dedykowany serwer plików, a artykuł PhotoPrism i Immich w porównaniu analizuje koszty pamięci RAM oraz wymagania dotyczące kopii zapasowych dla każdego z tych rozwiązań. Dla małego zespołu GridFS jest wystarczający, pod warunkiem świadomości, że kopie zapasowe będą z czasem coraz większe.
Tworzenie kopii zapasowych za pomocą mongodump
Wszystkie dane znajdują się w wolumenie mongodb_data. Nie należy kopiować wolumenu bezpośrednio z działającej bazy danych; zamiast tego należy wykonać spójny zrzut za pomocą mongodump, przesyłając go strumieniowo do pliku na hoście:
sudo docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > rocketchat-$(date +%F).archive.gzTo pojedyncze archiwum skompresowane za pomocą gzip stanowi cały obszar roboczy: użytkowników, kanały, wiadomości, ustawienia oraz pliki, jeśli przechowywane są w GridFS. Jeśli pliki zostały przeniesione do systemu plików lub S3, należy je zabezpieczyć oddzielnie. Przywracanie na nowej instancji wymaga najpierw zainicjowania zestawu replik (replica set), a następnie wykonania polecenia:
sudo docker compose exec -T mongodb mongorestore --archive --gzip --drop < rocketchat-2026-07-15.archive.gzKopię archiwum należy przechowywać poza serwerem – w pamięci obiektowej, na innym serwerze lub w dowolnym miejscu, gdzie awaria VPS nie spowoduje utraty kopii zapasowej. Proces zrzutu należy uruchamiać codziennie za pomocą cron. Kopia zapasowa, która nigdy nie została przywrócona, jest jedynie nadzieją, a nie zabezpieczeniem; należy przećwiczyć proces przywracania na testowym serwerze VPS, aby mieć pewność, że działa on poprawnie przed wystąpieniem rzeczywistej potrzeby.
Aktualizacje: przypinanie tagów, czytanie notatek, przestrzeganie macierzy MongoDB
Dwie zasady sprawiają, że aktualizacje przebiegają bezproblemowo. Po pierwsze, aktualizuj Rocket.Chat o jedną główną wersję naraz. Podczas uruchamiania przeprowadzane są migracje schematu, a dokumentacja Rocket.Chat zaleca aktualizację sekwencyjną między wersjami głównymi, ostrzegając, że pomijanie wersji może powodować poważne problemy z kompatybilnością. Nie należy polegać na zabezpieczeniach oprogramowania: dokumentacja nie gwarantuje, że przeskok bezpośrednio z 6.x na 8.x zostanie bezpiecznie odrzucony, a migracja, która nie powiedzie się w trakcie, pozostawia ustawioną blokadę i wymaga ręcznej naprawy. Zmień tag obrazu na najnowsze wydanie kolejnej wersji głównej, przeczytaj notatki do tego wydania pod kątem zmian powodujących niekompatybilność, uruchom docker compose up -d i obserwuj logi, aż migracja zostanie zakończona, zanim przejdziesz dalej. Po drugie, przestrzegaj macierzy wsparcia MongoDB. Każde wydanie Rocket.Chat wspiera określony zestaw wersji MongoDB, a curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions wskazuje, które z nich są obsługiwane. Podczas aktualizacji MongoDB, na przykład z 7.0 do 8.0, przechodź o jedną wersję główną naraz i ustawiaj wersję kompatybilności funkcji (feature-compatibility version) po każdym kroku. W MongoDB 8.0 polecenie to wymaga jawnego użycia confirm: true, w przeciwnym razie zostanie odrzucone z komunikatem nakazującym ponowne uruchomienie z flagą potwierdzenia:
sudo docker compose exec mongodb mongosh --eval 'db.adminCommand({setFeatureCompatibilityVersion: "8.0", confirm: true})'Wykonaj mongodump przed każdą aktualizacją któregokolwiek z komponentów. To jedyna gwarancja bezpieczeństwa.
Tryby awarii i dokładne komunikaty
Rocket.Chat wpada w pętlę restartów zaraz po docker compose up, a docker compose logs rocketchat zapełnia się wpisem MongoServerSelectionError. MongoDB działa, ale sterownik nie może wybrać węzła głównego (primary), a dokładny ciąg znaków wskazuje na popełniony błąd. Server selection timed out after 30000 ms z typem topologii ReplicaSetNoPrimary oznacza, że nie wykonano rs.initiate(); zestaw nie posiada jeszcze konfiguracji. getaddrinfo ENOTFOUND poprzedzone losowym hashem oznacza inicjację bez jawnego host: "mongodb:27017", przez co MongoDB rozgłosiło nierozpoznawalną nazwę hosta kontenera. Diagnozę przeprowadź za pomocą sudo docker compose exec mongodb mongosh --eval 'rs.status()': jeśli wystąpi błąd MongoServerError: no replset config has been received, zainicjuj zestaw; jeśli widoczny jest członek, którego name jest losowym hashem, zainicjuj ponownie, używając nazwy usługi.
Interfejs webowy ładuje się, ale logowanie trwa w nieskończoność i nie kończy się. Otwórz konsolę przeglądarki, gdzie widoczny będzie błąd WebSocket connection to 'wss://chat.example.com/websocket' failed. Jest to niemal zawsze niezgodność ROOT_URL lub problem z proxy, które nie przekazuje nagłówków upgrade. Potwierdź, że ROOT_URL odpowiada dokładnemu adresowi publicznemu, włącznie z https://, oraz że blok location w Nginx ustawia Upgrade i Connection "upgrade" za pomocą proxy_http_version 1.1. Po zmianie któregokolwiek z tych elementów uruchom ponownie docker compose up -d.
Kontener ciągle wyłącza się, a docker compose ps wskazuje na Restarting. docker compose logs urywa się w połowie linii, a sudo dmesg | tail pokazuje Out of memory: Killed process 12345 (mongod) pochodzące od oom-killer; kod wyjścia to 137. Serwerowi brakuje pamięci RAM. Jedynym właściwym rozwiązaniem jest większy VPS, minimum 4 GB. Jako rozwiązanie tymczasowe dodaj swap i ogranicz pamięć podręczną MongoDB za pomocą --wiredTigerCacheSizeGB w pliku command, ustawiając wartość poniżej domyślnej, na przykład 1 dla maszyny 4 GB (domyślnie 1.5) lub 0.3 dla maszyny 2 GB (domyślnie około 0.5). Pamiętaj jednak, że swap jedynie opóźnia kolejny błąd OOM przy rzeczywistym obciążeniu:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfiledocker compose up kończy się niepowodzeniem z błędem Error response from daemon: driver failed programming external connectivity ... bind: address already in use. Port 3000 jest już zajęty, często przez poprzedni kontener Rocket.Chat, który nie został poprawnie zatrzymany, lub przez inną aplikację. Zidentyfikuj proces za pomocą sudo ss -ltnp | grep :3000, zatrzymaj go lub zmień mapowanie portu po stronie hosta na 127.0.0.1:3001:3000 i zaktualizuj proxy_pass w konfiguracji proxy.
FAQ
Czy Rocket.Chat rzeczywiście wymaga zestawu replik MongoDB?
Tak, nawet w przypadku pojedynczego serwera z jednym węzłem bazy danych. Rocket.Chat dostarcza wiadomości w czasie rzeczywistym przy użyciu strumieni zmian MongoDB (change streams), a strumienie zmian są funkcją dostępną wyłącznie w zestawie replik; samodzielna instancja mongod nie może ich otworzyć. Nie potrzeba do tego wielu maszyn; wystarczy uruchomić jeden kontener MongoDB z flagą --replSet rs0 i zainicjować jednoelementowy zestaw za pomocą rs.initiate(). Pominięcie tego kroku sprawi, że sterownik nigdy nie odnajdzie węzła nadrzędnego (primary), przez co Rocket.Chat będzie zapętlał się przy uruchamianiu z błędem MongoServerSelectionError: Server selection timed out i nigdy nie zakończy procesu startu.
Ile pamięci RAM wymaga samodzielnie hostowany Rocket.Chat?
Należy zaplanować 4 GB jako praktyczne minimum oraz 8 GB dla aktywnego zespołu. Proces Node aplikacji Rocket.Chat zużywa około 1 do 1,5 GB, a domyślna pamięć podręczna WiredTiger w MongoDB zajmuje połowę wartości (całkowita pamięć RAM minus 1 GB), przy założeniu, że na serwerze nie działa nic innego. Na maszynie z 2 GB RAM pamięć podręczna, sterta Node oraz narzut samego systemu mongod wchodzą w konflikt, a mechanizm OOM killer przerywa działanie mongod przy jakimkolwiek realnym obciążeniu, co objawia się błędem Killed w logach oraz kodem wyjścia 137. Dwa GB wystarczają jedynie do przetestowania oprogramowania z kilkoma użytkownikami testowymi.
Jak umieścić Rocket.Chat za HTTPS?
Należy uruchomić reverse proxy na tym samym VPS, który zakończy połączenie TLS i przekaże ruch do 127.0.0.1:3000, a następnie ustawić zmienną ROOT_URL kontenera na publiczny adres https://. Proxy musi przekazywać nagłówki WebSocket upgrade, w przeciwnym razie logowanie zawiesi się. Certbot z nginx to najprostsza konfiguracja dla pojedynczej aplikacji; Traefik jest lepszym rozwiązaniem, jeśli uruchamiasz kilka kontenerów za jednym proxy i wymagasz automatycznego zarządzania certyfikatami.
Jak wykonać kopię zapasową samodzielnie hostowanego Rocket.Chat?
Należy wykonać spójny zrzut bazy danych za pomocą mongodump zamiast kopiowania wolumenu: docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > backup.archive.gz. To archiwum zawiera użytkowników, kanały, wiadomości i ustawienia, a także przesłane pliki, jeśli przechowywanie pozostało w GridFS. Kopię należy przenieść poza serwer, zautomatyzować jej tworzenie za pomocą cron i przeprowadzić próbne odtwarzanie mongorestore na testowej maszynie, aby upewnić się, że proces przywracania działa poprawnie.
Jak zaktualizować Rocket.Chat bez uszkodzenia MongoDB?
Rocket.Chat należy aktualizować o jedną główną wersję naraz, ponieważ podczas startu uruchamiane są migracje, a dokumentacja ostrzega, że pomijanie głównych wersji może powodować poważne problemy z kompatybilnością. Przed zmianą przypiętego tagu obrazu należy przeczytać informacje o wydaniu. Należy sprawdzić, które wersje MongoDB wspiera docelowe wydanie za pomocą curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions, a podczas aktualizacji MongoDB przechodzić przez kolejne wersje główne pojedynczo i ustawiać setFeatureCompatibilityVersion za pomocą confirm: true po każdym kroku. Zawsze należy najpierw wykonać mongodump.