MAATRIX / Блог / Бэкап и восстановление Matrix (Synapse)

Бэкап и восстановление Matrix (Synapse)

MAATRIX

Если вы держите собственный хаб Matrix на Synapse, то знаете: это не просто «ещё один докер-контейнер». Потерять базу — потерять всю переписку организации за годы. Потерять signing key — сломать доверие федерации к вашему серверу так, что другие домены перестанут вам верить, даже если вы поднимете сервер заново с тем же именем. Ниже — рабочая схема бэкапа и восстановления Synapse: что копировать, как автоматизировать и как проверить, что восстановление реально работает, а не просто «файлы где-то лежат».

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

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

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

Что именно нужно бэкапить в Synapse и почему это не то, что кажется

Synapse хранит состояние сервера в трёх принципиально разных местах, и упустить любое из них означает получить сервер, который поднимется, но будет вести себя неправильно.

  • База данных PostgreSQL — вся история сообщений, комнаты, учётные записи, устройства, access-токены, состояние федерации. Это самая большая по объёму и самая критичная часть.
  • Media store (media_store в конфиге) — загруженные файлы, аватары, превью ссылок, thumbnails. У активного сервера с десятками пользователей это легко десятки и сотни гигабайт.
  • Ключи и конфигhomeserver.yaml, <server_name>.signing.key, TLS-сертификаты (если не через reverse-proxy с автопродлением), файлы .log.config. Signing key — это криптографическая идентичность вашего сервера в федерации: другие серверы проверяют им подписи ваших событий.

Отдельно скажем сразу, чтобы не создавать ложных ожиданий: бэкап Synapse не восстанавливает end-to-end зашифрованные сообщения, если пользователь потерял ключи со всех своих устройств. E2EE-ключи для расшифровки живут у клиентов (или в encrypted key backup самого пользователя через Secure Backup в Element), сервер видит только зашифрованный блоб. Ваш бэкап защищает от потери *сервера* — упавшего диска, снесённого контейнера, сгоревшего дата-центра, — а не от того, что пользователь потерял пароль от Secure Backup. Это стоит явно проговорить с командой, чтобы не было иллюзии «раз есть бэкап сервера, значит переписка восстановится всегда».

Если Synapse развёрнут в Docker (типичная схема), структура обычно такая:

/opt/synapse/
├── docker-compose.yml
├── data/
│   ├── homeserver.yaml
│   ├── example.com.signing.key
│   ├── example.com.log.config
│   └── media_store/
└── postgres-data/   # если PostgreSQL тоже в контейнере

Дальше по каждому компоненту — отдельно.

Бэкап PostgreSQL: pg_dump vs pg_basebackup

Для базы Synapse есть два разумных подхода, и выбор зависит от размера базы и допустимого времени простоя при восстановлении (RTO).

pg_dump — логический бэкап, проще, но медленнее на больших базах. Подходит, если база до ~50–100 ГБ и вас устраивает восстановление в течение часа-другого.

docker exec -t synapse-postgres pg_dump \
  -U synapse_user -d synapse \
  --format=custom --compress=6 \
  -f /tmp/synapse_$(date +%Y%m%d).dump

docker cp synapse-postgres:/tmp/synapse_$(date +%Y%m%d).dump \
  /opt/synapse/backups/

Формат custom (-Fc) даёт сжатие и позволяет восстанавливать выборочно через pg_restore, в отличие от plain SQL.

pg_basebackup + WAL-архивирование — физический бэкап, быстрее восстанавливается, поддерживает PITR (point-in-time recovery). Оправдан, если база уже под сотню гигабайт и важно минимизировать время простоя.

# в postgresql.conf контейнера/хоста
wal_level = replica
archive_mode = on
archive_command = 'test ! -f /wal_archive/%f && cp %p /wal_archive/%f'

# сам базовый бэкап
pg_basebackup -U replicator -D /opt/synapse/backups/base_$(date +%Y%m%d) \
  -Fp -Xs -P

Для большинства небольших и средних инстансов (сообщество, компания на 50–500 пользователей) логического pg_dump раз в сутки плюс WAL-архив для промежутков между дампами достаточно. PITR через полноценный pg_basebackup имеет смысл, если у вас регуляторные требования к RPO в минутах.

Важный нюанс именно для Synapse: база активно пишется даже без активности пользователей — фоновые задачи (background_updates), чистка кэшей, federation retry. pg_dump консистентен даже на «живой» базе благодаря MVCC PostgreSQL, отдельно останавливать Synapse для дампа не нужно.

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

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

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

Бэкап media store и файлов сервера

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

Restic хорошо подходит: снимки инкрементальны, дедупликация на уровне блоков, встроенное шифрование.

export RESTIC_REPOSITORY=/mnt/backup-disk/synapse-repo
export RESTIC_PASSWORD_FILE=/root/.restic-pass

restic backup /opt/synapse/data/media_store \
  --tag media --exclude-caches

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Если сервер разросся и media store занимает сотни гигабайт, стоит рассмотреть вынос медиа в S3-совместимое хранилище через модуль synapse-s3-storage-provider — тогда бэкап медиа становится задачей стороннего хранилища с его версионированием, а не вашего диска. Но для типичного self-hosted сервера на VPS локальный media store с restic-снимками — рабочее и простое решение.

Для самого хранилища бэкапов разумно смотреть VPS для бэкапов и архива — отдельный недорогой сервер именно под хранение снапшотов, физически не там же, где основной Synapse.

Ключи подписи сервера (signing key) — почему их потеря фатальна

<server_name>.signing.key — это Ed25519-ключ, которым Synapse подписывает исходящие федеративные события. Другие серверы в федерации кэшируют ваш публичный ключ и сверяют подписи. Если вы разворачиваете новый Synapse с тем же server_name, но другим signing key:

  • Уже установленные федеративные соединения могут временно принимать события неправильно или отклонять их до истечения кэша ключа на удалённых серверах (кэш живёт до нескольких дней согласно key_validity_period).
  • Историю событий, подписанную старым ключом, новый Synapse формально всё ещё может отдавать (она в базе), но новые исходящие события будут подписаны иначе — для федерации это выглядит как смена идентичности сервера.
  • В худших случаях (полная потеря и базы, и ключа одновременно) сервер с тем же именем домена, поднятый с нуля, будет восприниматься федерацией как новый узел, и историческая непрерывность сломается.

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

# минимальный, но критичный бэкап
tar czf signing-key-$(date +%Y%m%d).tar.gz \
  /opt/synapse/data/*.signing.key \
  /opt/synapse/data/homeserver.yaml

gpg --symmetric --cipher-algo AES256 \
  signing-key-$(date +%Y%m%d).tar.gz

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

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

Собираем всё в один скрипт, который снимает дамп БД, снапшот media через restic и раз в сутки проверяет наличие критичных файлов.

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

BACKUP_DIR=/opt/synapse/backups
DATE=$(date +%Y%m%d_%H%M)
mkdir -p "$BACKUP_DIR"

# 1. Дамп PostgreSQL
docker exec -t synapse-postgres pg_dump \
  -U synapse_user -d synapse --format=custom --compress=6 \
  -f /tmp/synapse_$DATE.dump
docker cp synapse-postgres:/tmp/synapse_$DATE.dump "$BACKUP_DIR/"

# 2. Media store через restic
export RESTIC_REPOSITORY=/mnt/backup-disk/synapse-repo
export RESTIC_PASSWORD_FILE=/root/.restic-pass
restic backup /opt/synapse/data/media_store --tag media

# 3. Конфиг и ключи — отдельно, зашифрованно
tar czf - /opt/synapse/data/*.signing.key /opt/synapse/data/homeserver.yaml \
  | gpg --symmetric --cipher-algo AES256 --batch --passphrase-file /root/.gpg-pass \
  -o "$BACKUP_DIR/keys_$DATE.tar.gz.gpg"

# 4. Ротация локальных дампов БД (7 дней)
find "$BACKUP_DIR" -name "synapse_*.dump" -mtime +7 -delete

# 5. Отправка на удалённое хранилище
rclone copy "$BACKUP_DIR" remote:synapse-backups/ --max-age 25h
# /etc/cron.d/synapse-backup
0 3 * * * root /opt/synapse/backup.sh >> /var/log/synapse-backup.log 2>&1

Дамп базы раз в сутки в 3 ночи — разумная частота для большинства сообществ. Если у вас активная организация с сотнями сообщений в минуту и низкая терпимость к потере данных, добавьте archive_command для WAL, как описано выше, чтобы иметь возможность докатить изменения между дампами.

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

Восстановление: пошаговая процедура на новом сервере

Проверенная последовательность для полного восстановления Synapse с нуля — например, на новом VPS после потери старого сервера.

1. Поднимите PostgreSQL и восстановите базу.

docker compose up -d postgres
docker exec -i synapse-postgres createdb -U synapse_user synapse
docker cp synapse_20260830_0300.dump synapse-postgres:/tmp/restore.dump
docker exec -t synapse-postgres pg_restore \
  -U synapse_user -d synapse --no-owner --role=synapse_user /tmp/restore.dump

2. Восстановите ключи и конфиг ДО первого запуска Synapse.

gpg --decrypt --batch --passphrase-file gpg-pass keys_20260830_0300.tar.gz.gpg \
  | tar xz -C /opt/synapse/data/

Это критичный шаг именно в такой последовательности: если Synapse запустится без старого signing key, он молча сгенерирует новый — и вы получите проблему из раздела выше, даже не заметив момента, когда это произошло.

3. Восстановите media store.

restic restore latest --target /opt/synapse/data/media_store --tag media

4. Запустите Synapse и проверьте состояние.

docker compose up -d synapse
docker logs -f synapse-app
curl https://matrix.example.com/_matrix/client/versions

5. Проверьте федерацию. Через federation tester убедитесь, что сервер отдаёт корректный server_name и signing key совпадает с тем, что уже знают другие домены федерации.

6. Обязательно протестируйте эту процедуру заранее, не дожидаясь реального инцидента — разверните восстановление на отдельном тестовом сервере хотя бы раз в квартал. Это выявляет ровно те проблемы (забытый чмод на файле ключа, несовпадение версии PostgreSQL, потерянный пароль от GPG), которые иначе всплывают в самый неподходящий момент. Общая логика тестового восстановления разобрана в восстановлении базы данных из бэкапа на практике.

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

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

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

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

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

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

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

Зависит от media store — обычно закладывайте объём, равный текущему размеру media_store плюс 20–30% на рост, плюс несколько сотен мегабайт — гигабайт на дампы БД (в сжатом виде дамп обычно в 3–5 раз меньше объёма реальных данных в PostgreSQL за счёт --compress).

Можно ли бэкапить Synapse без остановки сервиса?

Да. pg_dump консистентен на живой базе благодаря MVCC, а restic снимает файлы media store инкрементально без блокировки — специально гасить Synapse на время бэкапа не нужно.

Что будет, если восстановить только БД, но не signing key?

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

Нужно ли бэкапить сами E2EE-ключи пользователей?

Нет, сервер их не хранит в расшифрованном виде и не может восстановить содержимое зашифрованных сообщений за пользователя. Это ответственность клиента — пользователям стоит включить Secure Backup в Element и запомнить security key или passphrase.

Как часто снимать бэкап для активного сервера компании?

Для большинства случаев достаточно ежесуточного дампа БД и ежесуточного снапшота media. Если недопустима потеря даже часа переписки, добавьте WAL-архивирование PostgreSQL для point-in-time recovery.

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

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

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