MAATRIX / Блог / Бэкап и восстановление Mattermost

Бэкап и восстановление Mattermost

MAATRIX

Mattermost — это не одна база данных, которую достаточно продампить раз в сутки. Это связка PostgreSQL, файлового хранилища с вложениями и аватарками, конфига с интеграциями и плагинов, каждый из которых может держать собственные настройки. Если бэкапить только базу, после аварии вы получите рабочий чат без единого прикреплённого файла и без настроенных webhook'ов — и объяснять команде, почему пропали все скриншоты за полгода, придётся вам. Ниже — рабочая схема бэкапа и восстановления, которую можно повторить на своём сервере за один вечер.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что входит в бэкап Mattermost и почему это не просто одна база

Self-hosted Mattermost состоит из нескольких частей, и каждая бэкапится по-своему:

  • PostgreSQL — вся переписка, каналы, пользователи, права, настройки команд. Это ядро системы.
  • Data directory (data/ при файловом хранилище) — прикреплённые файлы, аватарки, экспорты комплаенса, эмодзи. Если вы используете S3-совместимое хранилище вместо локального диска, эту часть бэкапит уже сам S3-провайдер, но конфиг с ключами доступа всё равно нужен.
  • config.json — адрес SMTP, настройки SSO/LDAP, webhook'и, лицензия Enterprise (если есть), параметры плагинов.
  • Каталог plugins/ и client/plugins/ — установленные плагины и их собственные данные (например, Mattermost Playbooks хранит часть состояния в базе, но бинарники плагинов — на диске).
  • Bleve-индекс поиска (если включён, data/bleve-indexes) — по желанию, его можно не бэкапить: индекс перестраивается командой mattermost search index rebuild, это дольше, но не критично.

Из всего списка обязательны первые три пункта. Без них полноценное восстановление невозможно — с ними сервер поднимается за 10-15 минут даже на чистой машине.

Бэкап PostgreSQL: дамп базы данных

Если Mattermost развёрнут через Docker Compose (самый частый вариант), дамп снимается через pg_dump внутри контейнера базы:

docker exec -t mattermost-postgres pg_dump \
  -U mmuser -d mattermost -F c -f /tmp/mattermost.dump

docker cp mattermost-postgres:/tmp/mattermost.dump \
  /opt/backups/mattermost/mattermost-$(date +%F).dump

Формат -F c (custom) даёт сжатый дамп, который восстанавливается через pg_restore и позволяет накатывать данные выборочно — это удобнее, чем плоский SQL-дамп из pg_dump без флагов. На базе среднего размера (2-5 ГБ активной переписки) дамп в custom-формате обычно в 3-5 раз компактнее сырых данных за счёт сжатия, но точную цифру для вашей базы стоит проверить на своих данных — зависит от объёма текста и вложений, которые в базе не хранятся.

Если PostgreSQL стоит не в Docker, а установлен на хост напрямую — команда та же, просто без docker exec:

pg_dump -U mmuser -h localhost -d mattermost -F c \
  -f /opt/backups/mattermost/mattermost-$(date +%F).dump

Про саму установку и настройку PostgreSQL под продакшн-нагрузку есть отдельный разбор: как установить и настроить PostgreSQL на VPS — там же про пулы соединений и базовый тюнинг, которые пригодятся, если Mattermost растёт и упирается в лимиты подключений.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Бэкап файлового хранилища, конфига и плагинов

Файлы бэкапятся простым архивом. Если Mattermost в Docker и данные примонтированы через volume:

docker run --rm \
  -v mattermost_app-data:/data:ro \
  -v /opt/backups/mattermost:/backup \
  alpine tar czf /backup/mm-data-$(date +%F).tar.gz -C /data .

Так можно снять архив, не останавливая контейнер и не блокируя приложение — том монтируется в отдельный служебный контейнер только на чтение. Конфиг и плагины копируются отдельно, они обычно весят немного:

docker cp mattermost-app:/mattermost/config/config.json \
  /opt/backups/mattermost/config-$(date +%F).json

docker run --rm \
  -v mattermost_app-plugins:/plugins:ro \
  -v /opt/backups/mattermost:/backup \
  alpine tar czf /backup/mm-plugins-$(date +%F).tar.gz -C /plugins .

Если используете S3-хранилище для файлов (в config.json это блок FileSettings.DriverName: "amazons3"), сам файловый бэкап вам не нужен — но config.json бэкапить всё равно обязательно, иначе после восстановления сервер не будет знать, куда стучаться за файлами. При этом ключи доступа к S3 в конфиге лучше держать через переменные окружения или secrets, а не хранить бэкап конфига с открытым ключом там, куда есть доступ у посторонних.

Docker-compose окружение: где что лежит

Типовой docker-compose.yml для Mattermost выглядит так — держите его под рукой, он пригодится и для бэкапа, и для восстановления на чистом сервере:

services:
  postgres:
    image: postgres:16-alpine
    container_name: mattermost-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: mmuser
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: mattermost
    volumes:
      - db-data:/var/lib/postgresql/data

  mattermost:
    image: mattermost/mattermost-team-edition:10.5
    container_name: mattermost-app
    restart: unless-stopped
    depends_on:
      - postgres
    environment:
      MM_SQLSETTINGS_DATASOURCE: "postgres://mmuser:${DB_PASSWORD}@postgres:5432/mattermost?sslmode=disable"
    ports:
      - "8065:8065"
    volumes:
      - app-config:/mattermost/config
      - app-data:/mattermost/data
      - app-logs:/mattermost/logs
      - app-plugins:/mattermost/plugins
      - app-client-plugins:/mattermost/client/plugins

volumes:
  db-data:
  app-config:
  app-data:
  app-logs:
  app-plugins:
  app-client-plugins:

Версию образа фиксируйте явно (не latest) — так вы точно знаете, какую версию поднимаете при восстановлении, и не ловите миграцию схемы базы «между делом». Перед доступом к серверу извне обычно ставят nginx как reverse proxy с TLS — про это отдельно: Nginx как reverse proxy на Ubuntu 24.04.

Автоматизация: скрипт + cron + хранение вне сервера

Ручной бэкап рано или поздно забывается сделать перед важным обновлением. Собираем всё в один скрипт:

#!/bin/bash
# /opt/scripts/mattermost-backup.sh
set -euo pipefail

DATE=$(date +%F)
BACKUP_DIR=/opt/backups/mattermost
mkdir -p "$BACKUP_DIR"

docker exec -t mattermost-postgres pg_dump \
  -U mmuser -d mattermost -F c -f /tmp/mattermost.dump
docker cp mattermost-postgres:/tmp/mattermost.dump \
  "$BACKUP_DIR/db-$DATE.dump"

docker cp mattermost-app:/mattermost/config/config.json \
  "$BACKUP_DIR/config-$DATE.json"

docker run --rm \
  -v mattermost_app-data:/data:ro \
  -v "$BACKUP_DIR":/backup \
  alpine tar czf "/backup/data-$DATE.tar.gz" -C /data .

# синхронизация на удалённое хранилище
rclone sync "$BACKUP_DIR" remote:mattermost-backups --min-age 1h

# ротация: локально держим 7 дней, на удалённом — политика хранилища
find "$BACKUP_DIR" -type f -mtime +7 -delete

Ставим в cron на ежедневный ночной запуск:

0 3 * * * /opt/scripts/mattermost-backup.sh >> /var/log/mm-backup.log 2>&1

Флаг --min-age 1h в rclone нужен, чтобы не синхронизировать файл, который ещё дописывается — на практике это редко бывает проблемой при таком скрипте, но привычка полезная. Хранить бэкапы только на том же сервере, что и сам Mattermost, — плохая идея: если диск умрёт или сервер станет недоступен, бэкап пропадёт вместе с оригиналом. Для переноса на внешнее S3-совместимое хранилище или другой сервер стоит посмотреть restic — он умеет дедупликацию и шифрование из коробки: restic в Docker Compose.

Восстановление из бэкапа: пошагово

Разворачиваем на новом сервере (или после аварии на текущем) в том же порядке, что и бэкапили, только в обратную сторону.

  1. Поднимаем контейнеры без старта Mattermost, чтобы база успела создаться:
docker compose up -d postgres
sleep 5
  1. Восстанавливаем базу данных:
docker cp db-2026-08-30.dump mattermost-postgres:/tmp/restore.dump
docker exec -t mattermost-postgres pg_restore \
  -U mmuser -d mattermost --clean --if-exists /tmp/restore.dump

Флаги --clean --if-exists нужны, если в целевой базе уже что-то есть (например, вы восстанавливаетесь после неудачного апдейта) — тогда pg_restore сначала снесёт существующие объекты и накатит бэкап поверх чистого места. На абсолютно новой базе эти флаги не мешают.

  1. Возвращаем файлы и конфиг в соответствующие volume:
docker run --rm \
  -v mattermost_app-data:/data \
  -v /opt/backups/mattermost:/backup \
  alpine tar xzf /backup/data-2026-08-30.tar.gz -C /data

docker cp config-2026-08-30.json mattermost-app:/mattermost/config/config.json
  1. Стартуем Mattermost:
docker compose up -d mattermost
docker logs -f mattermost-app
  1. Проверяем, что сервис поднялся и авторизация работает, зайдя в веб-интерфейс. Если использовался Bleve-поиск, пересобираем индекс:
docker exec -t mattermost-app mattermost search index rebuild

Отдельный совет, который экономит нервы: тестируйте восстановление заранее, на отдельном черновом сервере, а не в первый раз во время реальной аварии. Общие принципы разворачивания базы из дампа без привязки к конкретному приложению разобраны здесь: восстановление базы данных из бэкапа на практике — пригодится, если что-то пойдёт не по сценарию выше.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли бэкапить Mattermost «на горячую», не останавливая сервис?

Да, pg_dump и архивирование volume через отдельный служебный контейнер не блокируют работающий Mattermost. Единственный риск — снимок файлов и снимок базы делаются не строго в одну и ту же миллисекунду, поэтому теоретически возможен файл, который был загружен в момент между двумя шагами скрипта. На практике для большинства команд это не критично; если нужна строгая консистентность — на секунду переводите Mattermost в режим обслуживания.

Что делать, если версия образа при восстановлении отличается от версии, из которой снят дамп?

Мажорная версия должна совпадать или быть новее (Mattermost поддерживает миграцию схемы вперёд, но не назад). Проще всего восстанавливать на той же версии, что стояла на момент бэкапа, а потом обновляться штатным способом через docker compose pull && docker compose up -d.

Нужно ли бэкапить Elasticsearch, если он подключён вместо Bleve?

Нет, поисковый индекс — производная от данных в базе, его можно пересобрать командой переиндексации после восстановления. Бэкапить стоит только сами данные Elasticsearch, если пересборка индекса на вашем объёме данных занимает неприемлемо долго.

Сколько места нужно закладывать под бэкапы?

Ориентируйтесь на размер PostgreSQL-дампа плюс объём data-каталога с вложениями, умноженные на глубину хранения (например, 7 ежедневных копий). Точную цифру для вашей команды даст только пробный бэкап — объём переписки и вложений у всех разный.

Что если восстановление на другой сервер не проходит из-за разной версии PostgreSQL?

pg_restore из custom-формата обычно переносится между минорными версиями PostgreSQL без проблем, но для надёжности держите на новом сервере ту же мажорную версию (например, 16.x), что использовалась при бэкапе.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →