Бэкап и восстановление Rocket.Chat
Rocket.Chat опаснее для бэкапа, чем кажется на первый взгляд: под капотом у него MongoDB в режиме replica set, а вложенные файлы могут лежать сразу в трёх разных местах — в самой базе через GridFS, на диске или во внешнем S3-совместимом хранилище. Простой mongodump без понимания, где физически находятся файлы, даёт бэкап, из которого после аварии восстановится переписка, но пропадут все скриншоты и документы за последний год. Ниже — рабочая схема, которая закрывает оба риска.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что именно нужно бэкапить в Rocket.Chat
Self-hosted Rocket.Chat — это связка из нескольких частей, и каждая требует своего подхода:
- MongoDB — вся переписка, каналы, пользователи, права, настройки, интеграции, боты. Это ядро системы, без которого восстановление невозможно в принципе.
- Replica set конфигурация — Rocket.Chat с версии 4.x требует MongoDB именно в режиме replica set (даже на одном сервере), потому что использует change streams для realtime-обновлений. Это не деталь для галочки: без корректно настроенного replica set сервис вообще не запустится.
- Загруженные файлы — хранятся одним из трёх способов: GridFS внутри самой MongoDB (дефолт из коробки), локальная файловая система, либо внешний S3/MinIO. Способ хранения задаётся в админке (Admin → File Upload → File Upload Storage Type) и критично влияет на то, что именно нужно копировать.
- Переменные окружения и docker-compose.yml — порт, домен, SMTP, ключи для push-уведомлений, интеграция с LDAP/SSO, если настроена.
- Кастомные emoji и темы оформления — если загружались вручную, физически лежат там же, где остальные файлы (GridFS или диск).
Если файлы хранятся в GridFS — это самый простой случай: mongodump заберёт их вместе с базой автоматически, отдельно бэкапить нечего. Если файлы на диске или в S3 — нужен отдельный шаг, о нём ниже.
Бэкап MongoDB: dump с учётом replica set
Rocket.Chat в Docker Compose обычно поднимает MongoDB как отдельный сервис с именем вроде mongo. Проверьте, что replica set действительно инициализирован:
docker exec -it rocketchat-mongo mongosh --eval "rs.status()" | head -20
Если видите "ok" : 1 и список members — всё в порядке. Сам дамп снимается штатным mongodump:
docker exec rocketchat-mongo mongodump \
--uri="mongodb://localhost:27017/rocketchat?replicaSet=rs0" \
--gzip --archive=/tmp/rocketchat-$(date +%F).gz
docker cp rocketchat-mongo:/tmp/rocketchat-$(date +%F).gz \
/opt/backups/rocketchat/
Флаг --archive в связке с --gzip даёт один сжатый файл вместо дерева BSON-файлов — удобнее переносить и хранить. Для консистентного снимка на активно пишущей базе полезен флаг --oplog, который фиксирует изменения за время снятия дампа и позволяет восстановить состояние на конкретный момент, а не "размазанное" по времени дампа:
docker exec rocketchat-mongo mongodump \
--uri="mongodb://localhost:27017/rocketchat?replicaSet=rs0" \
--oplog --gzip --archive=/tmp/rocketchat-$(date +%F).gz
На небольших и средних инсталляциях (до нескольких тысяч сообщений в день) --oplog часто не критичен — дамп снимается быстро, окно рассинхронизации минимально. На нагруженных серверах с постоянным потоком сообщений и вложений лучше включать его всегда: точную разницу во времени снятия дампа стоит проверить на своей базе, она зависит от объёма данных и скорости диска.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверБэкап файлов: GridFS, диск или S3
Если файлы в GridFS — они уже в дампе выше, дополнительных действий не требуется. Это самый безопасный вариант с точки зрения консистентности бэкапа (файл и запись о нём в базе снимаются одним махом), но он раздувает размер MongoDB и делает базу медленнее на больших объёмах вложений — компромисс, о котором стоит думать заранее, а не после того как база разрослась до сотен гигабайт.
Если файлы на диске — путь задаётся переменной Uploads_FileSystemPath (по умолчанию /app/uploads внутри контейнера). Бэкапить нужно отдельно, синхронно с дампом базы:
docker cp rocketchat:/app/uploads /opt/backups/rocketchat/uploads-$(date +%F)
Важно снимать оба бэкапа (базу и файлы) в рамках одного скрипта, без большого разрыва по времени — иначе после восстановления возможна ситуация, когда в базе есть запись о файле, а самого файла на диске уже нет (или наоборот).
Если файлы в S3/MinIO — сам Rocket.Chat их не хранит вообще, достаточно бэкапить конфиг с ключами доступа и bucket-политикой, а сохранность файлов — забота S3-хранилища. Для собственного MinIO это отдельная тема, подробно она разобрана в статье про бэкап и восстановление MinIO.
Автоматизация: скрипт и хранение вне сервера
Ручной бэкап работает ровно до первого забытого вечера. Рабочий вариант — простой bash-скрипт под cron, который снимает дамп базы, файлы (если они на диске) и конфиг, упаковывает всё и синхронизирует на удалённое хранилище:
#!/bin/bash
set -euo pipefail
DATE=$(date +%F)
BACKUP_DIR="/opt/backups/rocketchat"
mkdir -p "$BACKUP_DIR"
docker exec rocketchat-mongo mongodump \
--uri="mongodb://localhost:27017/rocketchat?replicaSet=rs0" \
--oplog --gzip --archive=/tmp/rc-mongo-$DATE.gz
docker cp rocketchat-mongo:/tmp/rc-mongo-$DATE.gz "$BACKUP_DIR/"
# только если файлы на диске, а не в GridFS/S3
docker cp rocketchat:/app/uploads "$BACKUP_DIR/uploads-$DATE" 2>/dev/null || true
cp docker-compose.yml .env "$BACKUP_DIR/" 2>/dev/null || true
tar czf "$BACKUP_DIR/rocketchat-full-$DATE.tar.gz" \
-C "$BACKUP_DIR" "rc-mongo-$DATE.gz" "uploads-$DATE" docker-compose.yml .env
rclone copy "$BACKUP_DIR/rocketchat-full-$DATE.tar.gz" remote:rocketchat-backups/
find "$BACKUP_DIR" -mtime +7 -delete
Добавьте в cron:
0 3 * * * /opt/scripts/backup-rocketchat.sh >> /var/log/rocketchat-backup.log 2>&1
Правило трёх копий работает здесь так же, как и для любого другого сервиса: локальная копия для быстрого отката, копия на другом сервере или в объектном хранилище для аварии с потерей диска, и хотя бы одна копия в другой локации (другой дата-центр или страна) на случай проблем с самим хостером. Про принципы выбора площадки под архивные копии подробнее — в статье про VPS для бэкапов и архива.
Восстановление на новом сервере
Разворачиваем чистый Rocket.Chat + MongoDB тем же docker-compose.yml из бэкапа, дожидаемся, пока контейнеры поднимутся и replica set инициализируется (обычно это делает entrypoint-скрипт официального образа автоматически), после чего останавливаем сам Rocket.Chat, чтобы он не писал в базу во время restore:
docker compose stop rocketchat
Восстанавливаем дамп:
docker cp rc-mongo-2026-08-30.gz rocketchat-mongo:/tmp/restore.gz
docker exec rocketchat-mongo mongorestore \
--uri="mongodb://localhost:27017/rocketchat?replicaSet=rs0" \
--gzip --archive=/tmp/restore.gz --drop
Флаг --drop пересоздаёт коллекции перед восстановлением — без него старые данные из чистой инсталляции (например, дефолтный админ, созданный при первом запуске) останутся вперемешку с восстановленными. Если бэкап снимался с --oplog, добавьте --oplogReplay при восстановлении для точного применения журнала операций.
Если файлы хранились на диске отдельно от GridFS — возвращаем их на место до запуска сервиса:
docker cp uploads-2026-08-30/. rocketchat:/app/uploads/
Запускаем сервис и проверяем логи:
docker compose start rocketchat
docker compose logs -f rocketchat
Первый запуск после restore может занять минуту-другую — Rocket.Chat пересчитывает индексы и статистику. Зайдите в интерфейс, проверьте несколько каналов и что вложения открываются — это единственный надёжный способ убедиться, что восстановление прошло без потерь, а не просто "команда отработала без ошибок".
Частые проблемы при восстановлении
- Rocket.Chat не запускается после restore с ошибкой про replica set. Значит, дамп восстановился в базу без корректно инициализированного replica set (например, вы подняли новый MongoDB без
--replSet rs0в конфиге контейнера) или восстановление затронуло служебные коллекцииlocal. Проверьтеrs.status()перед стартом Rocket.Chat, а не после. - В базе есть ссылки на файлы, которых нет на диске. Классическая ситуация при рассинхронизации бэкапа базы и бэкапа файлов по времени. Решение — снимать оба бэкапа строго в одном скрипте, как показано выше, и после restore сверить количество файлов в
/app/uploadsс количеством записей в коллекцииrocketchat_uploads. - Версия Rocket.Chat в новом окружении новее версии, из которой снят дамп. MongoDB-схема Rocket.Chat меняется между мажорными версиями с автоматическими миграциями при старте. Восстанавливать дамп рекомендуется в контейнер с той же версией образа, что была на момент бэкапа, а уже потом обновлять — иначе миграция может отработать некорректно на "чужих" данных.
- mongorestore зависает или падает по памяти на большой базе. Для инсталляций с активным GridFS-хранилищем файлов дамп может быть в десятки гигабайт. На таких объёмах стоит закладывать сервер с запасом по RAM и диску заранее, а не разбираться с этим в момент аварии.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли бэкапить Rocket.Chat без остановки сервиса?
Дамп MongoDB через mongodump снимается на живой базе без остановки сервиса — это штатный сценарий. Останавливать Rocket.Chat нужно только на время restore, чтобы он не писал в базу поверх восстанавливаемых данных.
Что делать, если файлы хранятся в GridFS и база уже занимает 50+ ГБ?
На таком объёме стоит рассмотреть перенос файлового хранилища на S3/MinIO через админку Rocket.Chat — это разгружает MongoDB и ускоряет и бэкап, и восстановление, поскольку дамп базы становится в разы легче.
Нужен ли отдельный сервер под MongoDB, если Rocket.Chat небольшой?
Для команды до полусотни человек MongoDB и Rocket.Chat спокойно живут на одном VPS через Docker Compose. Разносить их на отдельные машины имеет смысл при росте нагрузки или когда нужен полноценный replica set из нескольких узлов для отказоустойчивости, а не только для совместимости с change streams.
Чем Rocket.Chat отличается от Mattermost в плане бэкапа?
Принципиально — типом СУБД (MongoDB вместо PostgreSQL) и требованием к replica set. Логика бэкапа та же: база + файлы + конфиг, но конкретные команды и грабли разные. Если сравниваете оба варианта для своей команды, у нас есть отдельный разбор установки Mattermost на VPS.
Как часто нужно снимать бэкап?
Для рабочего чата с активной перепиской — не реже раза в сутки, ночью, когда нагрузка минимальна. Если через Rocket.Chat идут критичные бизнес-процессы (боты, интеграции, комплаенс-архив), имеет смысл добавить дополнительный снимок в середине дня.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →