Бэкап и восстановление Matrix (Synapse)
Если вы держите собственный хаб 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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →