Files
go-synapse-backupper/README.ru.md
T

232 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Synapse Backupper
Инструмент для резервного копирования PostgreSQL [Synapse](https://github.com/element-hq/synapse) с композитным шифрованием на основе двух механизмов обмена ключами (dual-KEM).
## Обзор
`synapse-backupper` создает зашифрованные дампы PostgreSQL с использованием **композитной** схемы шифрования, которая объединяет постквантовый KEM (ML-KEM-768) и классический KEM (X25519). Для расшифровки резервной копии требуются оба ключа (модель AND). Инструмент поддерживает два режима работы: разовое резервное копирование (`backup`) и планировщик (`run`), который выполняет копирование по расписанию cron.
Копии хранятся локально на диске; устаревшие копии автоматически удаляются по возрасту.
## Установка
Сборка Docker-образа:
```bash
make docker-build
```
В результате собирается образ `synapse-backupper:latest`. Внутри образа находится скомпилированный бинарник, клиентские утилиты PostgreSQL, а сам контейнер запускается от непривилегированного пользователя.
## Быстрый старт
### 1. Генерация ключей шифрования
Сгенерируйте обе пары ключей (постквантовую и классическую) с помощью подкоманды `keygen`:
```bash
mkdir -p ./keys
docker run --rm -u root -v "$(pwd)/keys:/keys" synapse-backupper:latest \
keygen --type both --out-prefix /keys/synapse
chown -R "$(id -u):$(id -g)" ./keys
```
> **Примечание:** Образ контейнера по умолчанию запускается от непривилегированного пользователя `app`. Подкоманда `keygen` должна писать в смонтированный с хоста каталог, поэтому здесь она запускается от `root`, а затем владение файлами возвращается текущему пользователю. Если вы не работаете от `root`, скорректируйте команду `chown` (например, через `sudo`).
В каталоге `./keys/` появятся четыре файла:
| Файл | Назначение |
|------|------------|
| `synapse.pq.pub.pem` | Постквантовый публичный ключ (для резервного копирования) |
| `synapse.pq.priv.pem` | Постквантовый приватный ключ (для восстановления, хранить офлайн) |
| `synapse.classical.pub.pem` | Классический публичный ключ (для резервного копирования) |
| `synapse.classical.priv.pem` | Классический приватный ключ (для восстановления, хранить офлайн) |
**Важно:** приватные ключи никогда не следует монтировать в контейнер, который делает резервные копии. Храните их офлайн или на отдельном хосте, предназначенном только для восстановления.
### 2. Режимы работы
#### Режим планировщика (`run`)
Команда по умолчанию запускает планировщик по расписанию cron и HTTP-эндпоинт для проверки здоровья:
```bash
docker run -d -u root \
--name synapse-backupper \
-v "$(pwd)/keys:/keys:ro" \
-v "$(pwd)/backups:/backups" \
-e APP_PG_HOST=db \
-e APP_PG_DATABASE=postgres \
-e APP_PG_USER=synapse \
-e APP_PG_PASSWORD=changeme \
-e APP_PQ_PUBLIC_KEY_PATH=/keys/synapse.pq.pub.pem \
-e APP_CLASSICAL_PUBLIC_KEY_PATH=/keys/synapse.classical.pub.pem \
-e APP_BACKUP_DIR=/backups \
synapse-backupper:latest
```
По умолчанию резервное копирование выполняется ежедневно в `03:00`. Расписание задается параметром `backup.cron` в конфигурационном файле или переменной окружения `APP_BACKUP_CRON`.
#### Разовое резервное копирование (`backup`)
Выполнить одну резервную копию немедленно:
```bash
docker run --rm -u root \
-v "$(pwd)/keys:/keys:ro" \
-v "$(pwd)/backups:/backups" \
-e APP_PG_HOST=5432 \
-e APP_PG_DATABASE=postgres \
-e APP_PG_USER=synapse \
-e APP_PG_PASSWORD=changeme \
-e APP_PQ_PUBLIC_KEY_PATH=/keys/synapse.pq.pub.pem \
-e APP_CLASSICAL_PUBLIC_KEY_PATH=/keys/synapse.classical.pub.pem \
-e APP_BACKUP_DIR=/backups \
synapse-backupper:latest backup
```
Результирующий файл получает имя `synapse-<timestamp>.dump.pqenc` и сохраняется в каталог резервных копий. Дамп создается в формате PostgreSQL custom (`--format=custom`), который ожидает `pg_restore`.
### 3. Восстановление на отдельном хосте
Процедура восстановления специально выполняется на хосте, который **не** имеет доступа к базе данных. Достаточно только приватных ключей.
```bash
docker run --rm \
-v "$(pwd)/keys:/keys:ro" \
-v "$(pwd)/backups:/backups:ro" \
-v "$(pwd)/restored:/out" \
synapse-backupper:latest restore \
--in /backups/synapse-20260102-150405.dump.pqenc \
--privkey-pq /keys/synapse.pq.priv.pem \
--privkey-classical /keys/synapse.classical.priv.pem \
--out /out/restored.dump
```
После этого восстановите расшифрованный дамп стандартными средствами PostgreSQL:
```bash
pg_restore --clean --if-exists --dbname=synapse restored.dump
```
## Конфигурация
Приоритет источников настроек: флаги командной строки → переменные окружения `APP_*` → файл конфигурации → значения по умолчанию.
Примеры в разделе «Быстрый старт» используют переменные окружения. Префикс — `APP_`, вложенные ключи разделяются подчеркиванием, например:
- `APP_PG_HOST`
- `APP_PG_DATABASE`
- `APP_BACKUP_DIR`
- `APP_PQ_PUBLIC_KEY_PATH`
- `APP_CLASSICAL_PUBLIC_KEY_PATH`
Чтобы использовать файл конфигурации, сгенерируйте пример и смонтируйте его в контейнер:
```bash
docker run --rm synapse-backupper:latest generate-config --lang ru > config.yaml
```
Отредактируйте `config.yaml`, затем смонтируйте его в `/config.yaml` при запуске контейнера:
```bash
docker run -d \
--name synapse-backupper \
-v "$(pwd)/config.yaml:/config.yaml" \
-v "$(pwd)/keys:/keys:ro" \
-v "$(pwd)/backups:/backups" \
synapse-backupper:latest
```
Переменные окружения переопределяют значения из файла конфигурации.
## Docker Compose
Планировщик можно запустить через Docker Compose. Пример `docker-compose.yml`:
```yaml
version: '3.8'
services:
synapse-backupper:
image: synapse-backupper:latest
volumes:
- ./backups:/backups
- ./keys:/keys:ro
environment:
- APP_PG_HOST=synapse-pg
- APP_PG_DATABASE=synapse
- APP_PG_USER=synapse
- APP_PG_PASSWORD=secret
- APP_PQ_PUBLIC_KEY_PATH=/keys/synapse.pq.pub.pem
- APP_CLASSICAL_PUBLIC_KEY_PATH=/keys/synapse.classical.pub.pem
- APP_BACKUP_DIR=/backups
- APP_BACKUP_CRON=0 0 3 * * *
healthcheck:
test: ["CMD", "synapse-backupper", "healthcheck"]
interval: 30s
timeout: 3s
start_period: 10s
restart: unless-stopped
```
> **Важно:** В каталоге `./keys` должны находиться только публичные ключи (`*.pub.pem`). Перед запуском контейнера переместите приватные ключи (`*.priv.pem`) на офлайн-хост или хост, предназначенный только для восстановления.
>
> Перед промышленным развёртыванием замените `APP_PG_PASSWORD=secret` на надёжный пароль; указанное значение только пример.
Запуск планировщика:
```bash
docker compose up -d
```
## Модель безопасности
### Многоуровневая защита
Резервные копии шифруются по **композитной** схеме: общий секрет вычисляется независимо от постквантового и классического KEM, а полезная нагрузка шифруется симметричным ключом, полученным из обоих секретов. Злоумышленник должен взломать **оба** механизма, чтобы получить данные.
### Модель AND
Для расшифровки требуются **оба** приватных ключа. Команда `restore` завершится с ошибкой, если хотя бы один ключ отсутствует или неверен. Это исключает компрометацию копий при компрометации одного ключа.
### Plug-and-play KEM
Реализации KEM регистрируются в runtime-реестре по идентификатору схемы. Новые постквантовые или классические алгоритмы можно добавлять без изменения логики резервного копирования и восстановления.
### Изоляция приватных ключей
Приватные ключи **не нужны** при создании резервной копии. Контейнер, выполняющий бэкап, монтирует только публичные ключи (`:ro`). Приватные ключи должны находиться на отдельном хосте восстановления или в офлайн-хранилище, что сужает зону поражения при компрометации сервера резервного копирования.
## Ограничения
Это MVP-релиз. Следующие возможности **не реализованы**:
- **S3 / объектное хранилище** — копии пишутся только в локальный каталог.
- **Развертывание в Kubernetes** — Helm-чарт и оператор не предоставляются.
- **Потоковое / инкрементальное резервное копирование** — каждый запуск создает полный `pg_dump`.
- **Поддержка нескольких баз данных** — предполагается одна база данных на инстанс.
## Разработка
Запуск unit-тестов:
```bash
make test
```
Запуск сквозного интеграционного теста (требуется Docker):
```bash
make integration-test
```
Кросс-компиляция:
```bash
make cross-build
```
## Лицензия
MIT