Rocket.Chat на своём сервере: развёртывание и настройка
Развёртывание Rocket.Chat на своём сервере даёт компании корпоративный мессенджер, который полностью остаётся под контролем ИТ-службы: переписка, файлы и учётные записи не уходят во внешние облака и остаются в периметре компании. В этой статье мы проходим весь путь инженера: от расчёта ресурсов под 50, 200 и 500 сотрудников до развёртывания через Docker Compose с MongoDB replica set, интеграции с Active Directory и LDAP, харденинга по официальному руководству безопасности, резервного копирования и обновлений без простоя пользователей.

Развёртывание Rocket.Chat на своём сервере даёт полный контроль над расположением данных: переписка, история сообщений и файлы остаются в инфраструктуре заказчика и не уходят во внешние облака. Платформа поддерживает сквозное шифрование переписки.
Содержание
Когда Rocket.Chat подходит корпоративу: критерии выбора и сравнение с Matrix и Mattermost
Rocket.Chat на своём сервере — это разворачивание открытой коммуникационной платформы, разработанной на TypeScript, внутри корпоративного периметра, где весь трафик, история сообщений и файлы остаются на инфраструктуре заказчика. Платформа поддерживает три модели поставки — self-hosted, облачную и air-gapped (полностью изолированную), — и именно последние две интересуют корпоративного клиента в России, который должен соблюдать ФЗ-152 и внутренние регламенты по обработке данных.
Мы рекомендуем выбирать Rocket.Chat, когда заказчику нужны три вещи одновременно: полноценный мессенджер с каналами, тредами и звонками; встроенные средства идентификации, сквозного шифрования и ролевого доступа; расширяемость за счёт публичных приложений из Rocket.Chat Marketplace и интеграции с внешними системами. Если хотя бы один из этих критериев не критичен, имеет смысл сравнить решение с Mattermost и Matrix — об этом у нас отдельный разбор с сравнением Matrix, Mattermost и Rocket.Chat.
Коротко критерии выбора, по которым мы принимаем решение на проектах:
- организация хочет уйти со Slack или Microsoft Teams на свой сервер, но не готова к жёсткой федерации Matrix;
- нужен веб-клиент и мобильные приложения «из коробки», без сборки форков;
- ИБ требует SSO через Active Directory и журналирование действий администраторов;
- предполагается интеграция с Jira, GitLab, Zabbix и собственными API через webhooks и Apps-Engine.
Mattermost — корпоративный мессенджер, исторически ориентированный на разработчиков, — выигрывает у Rocket.Chat, когда команде нужна минимальная установка на одном узле и Postgres вместо MongoDB. Matrix, децентрализованный протокол обмена сообщениями с реализациями вроде Synapse и Element, мы выбираем, когда требуется межорганизационная федерация серверов и независимость от одного вендора. Rocket.Chat побеждает там, где важны готовый каталог приложений, омниканальность (live chat для сайта, мессенджеры клиентов) и админка, понятная корпоративному ИТ-отделу без обучения.
На наших проектах в банковском и производственном секторе Rocket.Chat закрывает сразу два сценария: внутренний корпоративный чат и обращение клиентов через виджет на сайте. Это снимает с заказчика необходимость держать отдельную платформу для службы поддержки и отдельную систему для сотрудников.

Расчёт ресурсов и подготовка сервера под 50, 200 и 500 сотрудников
Расчёт ресурсов под Rocket.Chat на своём сервере мы строим не от количества лицензий, а от профиля нагрузки: средней дневной активности (DAU), количества одновременно открытых клиентов, числа интеграций и объёма прикладываемых файлов. Сервер в первую очередь упирается в MongoDB и пиковую память Node.js-процессов, а не в CPU, поэтому при планировании сначала считаем диск и оперативную память, а уже потом ядра.
Для команды до пятидесяти сотрудников мы по нашему опыту берём один узел уровня бюджетного бизнес-сервера: несколько ядер, оперативная память среднего объёма, SSD-диск с запасом под полугодовую переписку и вложения. На такой конфигурации MongoDB живёт на той же машине, что и приложение, а резервные копии выгружаются на отдельное хранилище по сети. Этого достаточно, пока DAU не превышает примерно треть штата и интеграции ограничены типовыми (почтовые уведомления, webhook от трекера задач).
Для двухсот сотрудников мы выносим MongoDB на отдельный сервер и разворачиваем replica set из трёх узлов — это требование самой платформы для production-режима, и без него Rocket.Chat будет работать, но обновления между мажорными версиями станут болезненными. Приложение масштабируем горизонтально: два контейнера за обратным прокси Nginx, общий S3-совместимый бакет для uploads, отдельный том для логов. На этом уровне уже имеет смысл выделить ресурсы под микросервисы корпоративной редакции (presence, stream-hub, DDP-streamer), если планируется такая поставка.
Для пятисот сотрудников и более мы закладываем кластер: три узла MongoDB в replica set с отдельным арбитром по необходимости, минимум три экземпляра приложения, выделенный TURN-сервер для голосовых и видеозвонков, отдельная нода для интеграций и омниканальности. Здесь же мы заранее планируем отдельный сервер мониторинга — Prometheus с node-exporter и mongodb-exporter — и алерты на репликацию, иначе незаметное отставание secondary-узла превращается в потерю сообщений после сбоя primary.
Не делайте одну распространённую ошибку — мы сталкивались с этим у нового клиента: установка Rocket.Chat на виртуалку с тонким диском (thin provisioning) и снапшотами гипервизора без согласования с MongoDB. После трёх месяцев работы база раздулась, снапшот не удалялся, и виртуальная машина однажды утром просто остановилась по нехватке места на датасторе. С тех пор мы для MongoDB используем только толстый (eager-zeroed) диск и отдельный том под журнал.
Подготовку ОС мы выполняем по короткому списку: свежее ядро LTS-дистрибутива, синхронизация времени через chrony, отключение swap для узлов MongoDB, открытые порты только для обратного прокси и SSH с ключевой аутентификацией. Учётные записи администраторов разводим по разным группам, общий root по SSH запрещаем.

Развёртывание через Docker Compose с MongoDB replica set
Развёртывание Rocket.Chat на своём сервере мы выполняем через Docker — это один из официально рекомендуемых способов установки на собственные серверы наряду с Podman и Kubernetes. Docker Compose выбираем там, где заказчику нужен один или два узла приложения и не планируется автоматическое масштабирование на десятки подов; для кластера от пятисот пользователей мы переходим на Kubernetes с Helm-чартом от вендора.
Ключевая особенность production-инсталляции — MongoDB обязана работать в режиме replica set, даже если узел один. Без replica set Rocket.Chat откажется стартовать в современных версиях, потому что использует change streams для распространения событий между подами. Мы инициализируем replica set отдельной командой после первого запуска MongoDB и убеждаемся, что в логах нет ошибок выбора primary.
Первый запуск выполняем поэтапно: сначала поднимаем только MongoDB, инициализируем replica set и лишь затем запускаем приложение. Такое разделение фаз позволяет увидеть проблемы конфигурации БД раньше, чем приложение успеет начать запись. Мы не делаем docker compose up -d всем стеком сразу при первой установке — на наших проектах в трёх случаях из десяти Rocket.Chat успевал записать первые документы до инициализации replica set, и затем приходилось чистить базу. С тех пор разделение фаз вошло в наш стандарт.
После старта проверяем три вещи: доступность по внутреннему порту, статус replica set (rs.status() должен показать PRIMARY и health: 1) и запись логов в JSON-формате для последующей передачи в систему сбора. Только после этого мы пробрасываем сервис наружу через обратный прокси.
Все перечисленные шаги опираются на единую структуру каталога на сервере, которую мы разворачиваем заранее: файл .env с общими переменными (имя хоста, корневой URL, ключ подписи сессий, параметры SMTP), compose-файл с сервисами rocketchat и mongodb, тома из ./data для устойчивости при пересоздании контейнеров и точные теги образов вместо latest, чтобы повторное docker compose up -d после перезагрузки не подтянуло мажорное обновление. Базовая структура каталога выглядит так:
/opt/rocketchat/
├── docker-compose.yml
├── .env
├── data/
│ ├── mongo/
│ ├── mongo-config/
│ └── uploads/
└── backup/
HTTPS, обратный прокси Nginx и первичная настройка администратора
HTTPS для Rocket.Chat на своём сервере мы всегда терминируем на отдельном обратном прокси — это позволяет управлять сертификатами, заголовками безопасности и rate limit независимо от перезапусков приложения. В качестве прокси мы по умолчанию используем Nginx (HTTP-сервер и обратный прокси). Контейнер Rocket.Chat при этом слушает только на внутреннем интерфейсе и не публикует порт на внешний IP.
В конфигурации Nginx критичны три блока: проксирование WebSocket для каналов реального времени (заголовки Upgrade и Connection), увеличенные таймауты для долгоживущих соединений и ограничение размера тела запроса под максимальный размер загружаемого файла, согласованный с настройкой Rocket.Chat. Если значения расходятся, пользователи получают непонятные ошибки на полпути загрузки крупных вложений, и админ долго ищет проблему.
Сертификат для внешнего домена мы выпускаем через Let’s Encrypt (бесплатный удостоверяющий центр) с автопродлением через certbot; для закрытого контура используем корпоративный внутренний УЦ. В переменной ROOT_URL приложения обязательно указываем именно ту схему и хост, под которыми пользователи открывают сервис, иначе Rocket.Chat начнёт генерировать ссылки в письмах и пуш-уведомлениях с неправильным протоколом.
Первичная настройка администратора выполняется через мастер при первом обращении к веб-интерфейсу: задаём учётные данные владельца, наименование рабочего пространства, политику регистрации (для корпоратива — закрытая, только по приглашению или через SSO), параметры исходящей почты. Сразу после мастера мы заходим в раздел Workspace → Settings и фиксируем три вещи: запрещаем регистрацию по форме, отключаем стандартные публичные каналы по умолчанию, включаем требование подтверждения e-mail для всех новых учётных записей.
Мы не оставляем включёнными примеры интеграций и стандартного бота rocket.cat с дефолтным правом отправки в любые каналы. На одном из наших проектов этого хватило, чтобы внешний подрядчик через зарегистрированный webhook залил рекламные сообщения во внутренний канал. С тех пор мы отключаем встроенные интеграции до того, как заведём первого пользователя.
Конфигурацию обратного прокси, которая сводит воедино требования к WebSocket, таймаутам и размеру тела запроса, мы начинаем с такого серверного блока Nginx:
server {
listen 443 ssl http2;
server_name chat.example.com;
ssl_certificate /etc/letsencrypt/live/chat.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem;
client_max_body_size 200m;
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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600s;
}
}
Интеграция с Active Directory и LDAP: доменный вход, синхронизация групп и ролей
Интеграция Rocket.Chat на своём сервере с Active Directory (служба каталогов Microsoft на базе LDAP) — типовое требование корпоративного заказчика: пользователи должны входить под доменными учётными записями, а отключённый в кадровой системе сотрудник терять доступ к чату автоматически. Rocket.Chat поддерживает встроенное управление идентификацией и ролевой/атрибутивный контроль доступа, которые мы подключаем к корпоративному каталогу через стандартный модуль LDAP.
Подключение настраивается в админке в разделе LDAP. Минимально нужно задать адрес контроллера домена, шифрование (LDAPS на порту 636 либо StartTLS на 389), сервисную учётную запись с правом чтения каталога, базовый DN для поиска пользователей и фильтр. Для AD мы используем фильтр, исключающий отключённые учётные записи (userAccountControl), служебные и компьютерные объекты, чтобы не засорять список синхронизируемых пользователей.
Связку Rocket.Chat-атрибута с LDAP-атрибутом мы выстраиваем явно: username — sAMAccountName, email — mail, name — displayName, при необходимости nickname — cn. Это критично: если потом сменить маппинг, существующие пользователи могут получить дубль учётной записи. По нашему опыту, разрулить такой дубль вручную дольше, чем один раз правильно согласовать поля с владельцем каталога перед первой синхронизацией.
Для синхронизации групп мы используем механизм LDAP-групп Rocket.Chat: каждая группа из AD сопоставляется либо с ролью внутри Rocket.Chat (например, admin, bot, livechat-agent), либо с каналом, в который пользователь должен попадать автоматически. Это позволяет управлять составом чатов с той же стороны, что и доступом к другим системам — через групповые политики AD. Расписание синхронизации мы ставим раз в час; полный пересчёт ролей запускаем ночью.
Не настраивайте сразу Authentication.Background Sync = true с большим интервалом и широким фильтром на каталог в десятки тысяч записей. Мы один раз получили деградацию контроллера домена, потому что синхронизация утром совпала со входом сотрудников. С тех пор для крупных каталогов мы делаем ступенчатый запуск: сначала узкий OU, потом расширяем фильтр.
Перед включением доменного входа в админке мы всегда проверяем связку вручную — одной командой ldapsearch с сервера Rocket.Chat. Она подтверждает сразу три вещи: сеть до контроллера домена открыта, сертификат LDAPS принимается системой, фильтр находит ожидаемого пользователя. Только после успешной ручной проверки мы включаем Login with LDAP и тестируем вход одной пилотной учётной записью:
ldapsearch -H ldaps://dc.example.local -D 'CN=rocketchat,OU=Service,DC=example,DC=local' \
-W -b 'DC=example,DC=local' '(sAMAccountName=ivanov)'
Hardening и аудит безопасности: 2FA, CSP, rate limit по security-guidelines
Hardening Rocket.Chat на своём сервере мы выполняем по официальному руководству вендора (security-guidelines) и собственному чек-листу, накопленному на проектах. Платформа спроектирована безопасно по умолчанию и предоставляет управление идентификацией, сквозное шифрование и контроль доступа по ролям и атрибутам, но без явной настройки часть этих механизмов остаётся отключённой. Общие критерии выбора защищённого корпоративного мессенджера мы разбираем в отдельном обзоре безопасного мессенджера для бизнеса.
Двухфакторную аутентификацию мы делаем обязательной для всех учётных записей, не только для администраторов. В админке Workspace → Settings → Accounts → Two Factor Authentication включаем 2FA по TOTP, разрешаем резервные коды и запрещаем отказ от 2FA пользователем. Для административных операций (изменение настроек, выдача ролей, удаление каналов) включаем повторный запрос пароля и второго фактора — это страхует на случай угона активной сессии.
Заголовки безопасности задаём на стороне обратного прокси: Content-Security-Policy с разрешением только нужных доменов для медиа и шрифтов, Strict-Transport-Security с длительным max-age и includeSubDomains, X-Frame-Options для запрета встраивания, Referrer-Policy в режиме strict-origin-when-cross-origin. CSP для Rocket.Chat подбирается итеративно: первый прогон делаем в режиме Content-Security-Policy-Report-Only, собираем нарушения через report-uri, и только потом ужесточаем политику до боевого режима.
Сквозное шифрование (E2EE) включаем для каналов, в которых обсуждаются персональные данные и коммерческая тайна. На наших проектах мы не делаем E2EE глобальным по умолчанию: при включённом шифровании теряется индексация сообщений на сервере и возможность восстановить переписку администратору, что часто конфликтует с регламентом архивирования. Решение принимает заказчик, мы документируем выбор в проектной документации.
Аудит мы организуем тремя слоями: журнал действий администраторов и владельцев каналов в самом Rocket.Chat (Admin → Audit), журналы Nginx с пользовательским ID в заголовке, журналы MongoDB через auditLog. Все три потока пишем в централизованный сборщик логов и держим минимум за квартал для разбора инцидентов. На одном из проектов именно журналы Nginx позволили нам за полчаса показать заказчику, что подозрительная активность шла не от штатного пользователя, а от утёкшего токена интеграции — после чего мы отозвали токен и переподписали интеграции.
Защиту от перебора паролей мы выносим на два уровня. Внутренний rate limit Rocket.Chat ограничивает количество REST-вызовов и DDP-методов на пользователя — заводские значения мы не повышаем, а для эндпоинтов входа и сброса пароля местами снижаем. Внешний rate limit задаём на Nginx через limit_req_zone для /api/v1/login и /api/v1/users.register, чтобы перебор не доходил до приложения:
limit_req_zone $binary_remote_addr zone=rc_login:10m rate=5r/m;
location ~ ^/api/v1/(login|users\.register) {
limit_req zone=rc_login burst=10 nodelay;
proxy_pass http://127.0.0.1:3000;
}
Бэкап MongoDB и uploads, восстановление за 15 минут
Бэкап Rocket.Chat на своём сервере состоит из двух обязательных компонентов: дамп MongoDB и копия каталога uploads с файлами вложений. Без uploads восстановленная база покажет в каналах ссылки на отсутствующие файлы — формально сервис будет работать, но история окажется неполной. Мы всегда снимаем оба компонента согласованно в одном окне резервного копирования.
Файлы загрузок мы снимаем rsync или tar, в зависимости от того, лежат ли uploads на локальном томе или в S3-совместимом хранилище. Для S3 включаем версионирование объектов на стороне хранилища — это даёт бесплатное «бэкапы за период» без дополнительных скриптов и спасает от ошибочного удаления одного файла администратором.
Расписание мы строим по правилу 3-2-1, адаптированному под нагрузку: ежедневный инкрементальный бэкап с хранением на сервере резервных копий, еженедельный полный бэкап с выносом на внешний носитель или второй ЦОД, ежемесячный архив с долгим сроком хранения. Сроки хранения мы согласуем с регламентом заказчика, а не выставляем «по умолчанию» — для одного клиента нам пришлось хранить чат-историю столько же, сколько финансовую документацию.
Восстановление за пятнадцать минут возможно только при подготовленной заранее площадке: чистый сервер с тем же docker-compose.yml, той же мажорной версией Rocket.Chat, тем же DNS-именем. В случае сбоя мы поднимаем MongoDB в replica set, накатываем последний дамп командой mongorestore --oplogReplay, возвращаем каталог uploads из копии и только потом запускаем приложение и проверяем целостность истории. Цикл занимает у нас на боевых инсталляциях около четверти часа при базе среднего размера; для крупных баз он растёт пропорционально, и тогда мы переходим на восстановление из снапшота диска плюс докатку oplog — это быстрее, чем mongorestore целиком.
Не делайте бэкап только средствами гипервизора без штатного дампа MongoDB. Мы у одного клиента восстанавливали базу из снимка VM, и после старта первичный узел replica set несколько часов догонял реплики, потому что снимок был сделан без подготовки кластера. С тех пор у нас правило: гипервизорные снапшоты — это второй уровень страховки, основной бэкап — всегда mongodump --oplog плюс отдельная копия uploads. Тестовое восстановление мы проводим раз в квартал, иначе бэкап остаётся гипотезой, а не процедурой.
Сам дамп MongoDB мы снимаем штатной утилитой mongodump. Для replica set обязательно используем флаг --oplog, чтобы получить консистентный снимок на момент окончания дампа; иначе при восстановлении часть коллекций будет отставать от других на минуты. Базовая команда дампа, которую мы ставим в расписание, выглядит так:
docker compose exec mongodb mongodump \
--host 'rs0/mongodb:27017' \
--oplog \
--gzip \
--archive=/data/backup/rocketchat-$(date +%F).gz
Итог
- Для production-среды обязательно использование Docker или Kubernetes — это рекомендованные вендором методы развёртывания.
- Безопасность коммуникаций обеспечивается встроенным управлением идентификацией, ролевым доступом и опциональным сквозным шифрованием.
- Платформа написана на TypeScript — современный типизированный стек, удобный для интеграции мессенджера в продукты и его поддержки.
- Интеграция с внешними системами возможна через установку приложений из Rocket.Chat Marketplace и собственный Apps-Engine.
- Архитектура поддерживает air-gapped развёртывание для сетей с высоким уровнем изоляции.
Часто задаваемые вопросы
Ответы на часто задаваемые вопросы по теме статьи.
Константин Тютюнник — ведущий инженер IT For Prof. Специализируется на проектировании отказоустойчивых инфраструктур и внедрении self-hosted решений для крупного бизнеса. Имеет опыт миграции тысяч пользователей с проприетарных платформ на открытые стандарты.
Мы помогаем компаниям перейти на защищенные каналы связи. Закажите развертывание корпоративного мессенджера на вашем сервере с настройкой LDAP, бэкапов и отказоустойчивого кластера.




