Skip to content

Резервное копирование и восстановление

Резервное копирование и восстановление

Стратегия

ТипЧастотаХранениеМесто
Ежедневный (daily)03:00 UTC+57 днейYandex Object Storage
Еженедельный (weekly)Воскресенье 03:004 неделиYandex Object Storage
ШифрованиеGPG AES-256152-ФЗ: ПД в дампах

Дамп создаётся через pg_dump → сжатие gzip → шифрование GPG → загрузка в S3.


Настройка бэкапа

1. Переменные окружения

Убедитесь, что в .env.prod заданы:

YC_BUCKET_NAME=terma-grand-backups
YC_ACCESS_KEY_ID=<ключ сервисного аккаунта>
YC_SECRET_ACCESS_KEY=<секрет>
YC_REGION=ru-central1
S3_ENDPOINT=https://storage.yandexcloud.net
BACKUP_GPG_PASSPHRASE=<сильный пароль шифрования>

2. Создать S3 bucket

Окно терминала
# Через YC CLI
yc storage bucket create \
--name terma-grand-backups \
--default-storage-class STANDARD
# Настроить private access
yc storage bucket update \
--name terma-grand-backups \
--public-read false \
--public-list false

3. Ручной запуск бэкапа

Окно терминала
# Загрузить переменные
source /opt/terma-grand/repo/.env.prod
# Запустить
bash /opt/terma-grand/repo/scripts/deploy/backup.sh

Логи:

[2026-04-22 03:00:01] [BACKUP] ========== BACKUP START: 20260422_030001 ==========
[2026-04-22 03:00:01] [BACKUP] Starting pg_dump → /tmp/terma-backups/terma_prod_20260422_030001.sql.gz
[2026-04-22 03:00:05] [BACKUP] Dump complete: 1.2M
[2026-04-22 03:00:05] [BACKUP] Encrypting dump with GPG...
[2026-04-22 03:00:05] [BACKUP] Upload complete: s3://terma-grand-backups/pg/daily/terma_prod_20260422_030001.sql.gz.gpg
[2026-04-22 03:00:06] [BACKUP] Rotation complete
[2026-04-22 03:00:06] [BACKUP] ========== BACKUP SUCCESS ==========

4. Cron-расписание

Окно терминала
crontab -e
# Ежедневно в 03:00 (UTC+5 = 22:00 UTC)
0 22 * * * source /opt/terma-grand/repo/.env.prod && \
bash /opt/terma-grand/repo/scripts/deploy/backup.sh \
>> /var/log/terma-grand-backup.log 2>&1

Структура в Object Storage

terma-grand-backups/
└── pg/
├── daily/
│ ├── terma_prod_20260421_220001.sql.gz.gpg
│ ├── terma_prod_20260422_220001.sql.gz.gpg
│ └── ... (7 файлов)
└── weekly/
├── terma_prod_20260419_220001.sql.gz.gpg
└── ... (4 файла)

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

⚠️ ВНИМАНИЕ: Восстановление перезаписывает текущую базу данных. Выполнять только при DR или плановой миграции.

1. Просмотр доступных бэкапов

Окно терминала
source /opt/terma-grand/repo/.env.prod
AWS_ACCESS_KEY_ID="${YC_ACCESS_KEY_ID}" \
AWS_SECRET_ACCESS_KEY="${YC_SECRET_ACCESS_KEY}" \
aws s3 ls s3://terma-grand-backups/pg/daily/ \
--endpoint-url https://storage.yandexcloud.net \
| sort

2. Восстановление из S3

Окно терминала
source /opt/terma-grand/repo/.env.prod
bash /opt/terma-grand/repo/scripts/deploy/restore.sh \
--from "s3://terma-grand-backups/pg/daily/terma_prod_20260421_220001.sql.gz.gpg"

Скрипт попросит подтверждение, затем:

  1. Скачает файл из S3
  2. Дешифрует GPG
  3. Остановит app и bot
  4. Восстановит базу через psql
  5. Запустит сервисы
  6. Выполнит healthcheck

3. Восстановление из локального файла

Окно терминала
bash /opt/terma-grand/repo/scripts/deploy/restore.sh \
--from /tmp/terma_prod_20260421.sql.gz.gpg

4. Dry-run (без изменений)

Окно терминала
bash /opt/terma-grand/repo/scripts/deploy/restore.sh \
--from "s3://..." \
--dry-run

Проверка бэкапа (тест восстановления)

Рекомендуется ежемесячная проверка работоспособности дампа:

Окно терминала
# 1. Скачать последний дамп
# 2. Дешифровать
gpg --batch --passphrase "${BACKUP_GPG_PASSPHRASE}" \
--decrypt dump.sql.gz.gpg | zcat | head -50
# 3. Восстановить на тестовую базу (не prod)
docker exec -i repo-postgres-1 \
psql -U terma -d postgres -c "CREATE DATABASE terma_test_restore;"
zcat dump.sql.gz | docker exec -i repo-postgres-1 \
psql -U terma -d terma_test_restore
# 4. Проверить количество записей
docker exec repo-postgres-1 \
psql -U terma -d terma_test_restore -c "SELECT COUNT(*) FROM users;"
# 5. Удалить тестовую базу
docker exec repo-postgres-1 \
psql -U terma -d postgres -c "DROP DATABASE terma_test_restore;"

Следующий шаг

07 — Откат на предыдущую версию