проектdocs/operations/backup-restore-runbook.md
Runbook резервного копирования и восстановления
Обновлён 1 апр. 2026 г., 12:41 · 0 комментариев
Runbook резервного копирования и восстановления
Паспорт документа
- Статус документа: working reference
- Актуально на: 31 марта 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении runtime topology, storage-модели, путей данных или стратегии backup
- Область применения: текущий production-контур Qadam на host-based runtime, автоматизированном backup baseline и off-host retention
- Связанные документы:
Цель документа
Этот документ фиксирует канонический backup/restore-контур Qadam для текущего production-сервера. На сегодня базовый backup уже автоматизирован через qadam-backup.service и qadam-backup.timer, но restore по-прежнему остаётся осознанной операционной процедурой, которую нужно выполнять аккуратно и вручную.
1. Текущий production backup-контур
- Автоматический backup запускается через
qadam-backup.service. - Планировщик работает через
qadam-backup.timerежедневно в03:30 UTCс небольшимRandomizedDelaySec. - Канонический исполняемый runtime находится в
/data/qadam-core/scripts/backup-runtime.mjs. - Локальные snapshot-каталоги хранятся в
/var/backups/qadam/<STAMP>. - Последний результат backup фиксируется в
/var/lib/qadam-backup/state.json. - Off-host archive выгружается в S3-compatible storage по префиксу
backups/runtime/<STAMP>.tar.gz. - Текущая retention policy:
- локальные snapshot-каталоги:
7дней; - off-host archive в object storage:
30дней.
- локальные snapshot-каталоги:
- Telegram alerting работает без лишнего шума: backup шлёт сообщение при первом переходе в
FAILи отдельноеRECOVERYпосле следующего успешного прогона; обычные success-run'ы молчат, если специально не включёнQADAM_BACKUP_NOTIFY_ON_SUCCESS=true.
2. Что обязательно защищать
Данные PostgreSQL
- Канонический источник:
DATABASE_URLиз/etc/qadam/qadam.env - Текущий production runtime использует локальный PostgreSQL на хосте
- Критичность: максимальная
API uploads
- Каталог:
/var/lib/qadam-core/uploads/images - Содержимое: изображения, загруженные через
POST /api/v1/upload/image - Критичность: высокая
Данные roadmap-сервиса
- Загруженные markdown-файлы:
/var/lib/qadam-roadmap/uploads - Комментарии:
/var/lib/qadam-roadmap/comments.json - Feedback overlay frontend-команды:
/var/lib/qadam-roadmap/frontend-package-feedback.json - Критичность: средняя
Конфигурация runtime
/etc/qadam/qadam.env/etc/qadam/qadam-roadmap.env/etc/qadam/qadam-monitor.env/etc/qadam/qadam-backup.env/etc/systemd/system/qadam-api.service/etc/systemd/system/qadam-web.service/etc/systemd/system/qadam-roadmap.service/etc/systemd/system/qadam-monitor.service/etc/systemd/system/qadam-monitor.timer/etc/systemd/system/qadam-backup.service/etc/systemd/system/qadam-backup.timer/etc/nginx/sites-available/qadam.2fab.app.conf/etc/nginx/sites-available/qadam-roadmap.2fab.app.conf- Критичность: высокая
3. Когда backup обязателен
- Перед любой Prisma migration на production, даже если ночной backup уже работает по timer.
- Перед релизом, который меняет auth, registration, billing, upload/storage или другую критичную бизнес-логику.
- Перед ручным ремонтом PostgreSQL, Redis,
systemdилиnginx. - Перед изменением storage paths, env-файлов или TLS-контура.
- Перед rollback, если текущее состояние уже могло изменить данные.
- После существенного изменения backup policy, env-модели или storage account boundaries.
4. Состав backup-пакета
Каждый backup-пакет должен содержать:
postgres.dump— custom-format dump production БД.api-uploads.tar.gz— архив API uploads.roadmap-uploads.tar.gz— архив roadmap uploads.comments.json— comments storage roadmap-сервиса.frontend-package-feedback.json— operational overlay со статусами frontend adoption.metadata.json— служебное описание snapshot, host и off-host object key.- Копии актуальных
env,systemdиnginxфайлов вconfig/. SHA256SUMS— контрольные суммы файлов backup-пакета.
5. Как запускать backup
Канонический способ
systemctl start qadam-backup.service
systemctl status qadam-backup.service --no-pager
cat /var/lib/qadam-backup/state.json
Ручной запуск тем же runtime без systemd
set -a
source /etc/qadam/qadam.env
source /etc/qadam/qadam-backup.env
set +a
cd /data/qadam-core
pnpm backup:run
Что делает скрипт автоматически
- снимает
pg_dumpproduction PostgreSQL; - архивирует API uploads и roadmap uploads;
- копирует roadmap comments и frontend feedback overlay;
- копирует актуальные
env,systemdиnginxфайлы; - пишет
metadata.jsonиSHA256SUMS; - локально верифицирует dump через
pg_restore --list; - локально проверяет контрольные суммы;
- собирает off-host archive и выгружает его в S3-compatible storage;
- подрезает локальные и off-host backup'ы по retention policy;
- пишет последний status/result в
/var/lib/qadam-backup/state.json.
6. Минимальная верификация backup
systemctl status qadam-backup.timer qadam-backup.service --no-pager
cat /var/lib/qadam-backup/state.json
find /var/backups/qadam -maxdepth 1 -mindepth 1 | sort
Минимум, который должен подтвердиться:
qadam-backup.timerнаходится вactive (waiting);- последний
qadam-backup.serviceзавершилсяstatus=0/SUCCESS; состояниеinactive (dead)после этого нормально, потому что сервисType=oneshot; - в
state.jsonестьstatus: "ok",backupDirиoffsiteObjectKey; - каталог snapshot существует локально в
/var/backups/qadam/<STAMP>; - off-host object существует в S3-compatible storage.
7. Процедура восстановления
До восстановления
- Зафиксировать причину restore и момент времени.
- Остановить запись в систему.
- Снять аварийный backup текущего состояния, если это ещё возможно.
Остановить приложения
systemctl stop qadam-web qadam-roadmap qadam-api
Если восстанавливаемся из off-host archive
- Скачать
backups/runtime/<STAMP>.tar.gzиз object storage любым S3-compatible client или через provider console. - Развернуть архив в локальный backup root:
mkdir -p /var/backups/qadam
tar -xzf "/path/to/20260331T100420Z.tar.gz" -C /var/backups/qadam
После этого используется тот же локальный путь /var/backups/qadam/<STAMP>, как и для локального snapshot.
Восстановить PostgreSQL
set -a
source /etc/qadam/qadam.env
set +a
pg_restore \
--clean \
--if-exists \
--no-owner \
--no-privileges \
--dbname="${DATABASE_URL}" \
"/var/backups/qadam/<STAMP>/postgres.dump"
Восстановить файловые артефакты
rm -rf /var/lib/qadam-core/uploads/*
tar -xzf "/var/backups/qadam/<STAMP>/api-uploads.tar.gz" \
-C /var/lib/qadam-core/uploads
rm -rf /var/lib/qadam-roadmap/uploads/*
tar -xzf "/var/backups/qadam/<STAMP>/roadmap-uploads.tar.gz" \
-C /var/lib/qadam-roadmap/uploads
cp "/var/backups/qadam/<STAMP>/comments.json" /var/lib/qadam-roadmap/comments.json
cp "/var/backups/qadam/<STAMP>/frontend-package-feedback.json" \
/var/lib/qadam-roadmap/frontend-package-feedback.json
Восстановить конфигурацию при необходимости
Если проблема затрагивала env, systemd или nginx, вернуть файлы из backup-пакета и затем выполнить:
systemctl daemon-reload
systemctl start qadam-api qadam-web qadam-roadmap
systemctl reload nginx
8. Проверка после восстановления
systemctl status qadam-api qadam-web qadam-roadmap nginx
curl -I https://qadam.2fab.app
curl https://qadam.2fab.app/api/v1/health
curl -I https://qadam.2fab.app/api/docs
curl -I -u <login>:<password> https://qadam-roadmap.2fab.app
curl -u <login>:<password> https://qadam-roadmap.2fab.app/api/health
Минимум, который должен подтвердиться:
qadam-api,qadam-web,qadam-roadmap,nginxнаходятся вactive;https://qadam.2fab.app/api/v1/healthотвечает200;https://qadam-roadmap.2fab.app/api/healthотвечает200после basic auth;- критичные пользовательские данные, uploads и roadmap feedback state на месте.
9. Ограничения текущей модели
- Product data и roadmap storage по-прежнему сначала живут на том же хосте, что и runtime; backup лишь снижает риск потери, а не устраняет shared-failure domain.
- Off-host backup использует те же object storage account boundaries, что и текущий S3-compatible storage для product media; отдельный backup-only bucket или отдельные credentials пока не выделены.
- Restore регулярно не прогоняется на staging/backup-контуре, поэтому recovery-time по-настоящему подтверждён только частично.
10. Что ещё нужно улучшить
- Вынести backup в отдельный bucket и отдельные credentials, если requirements по разделению доступов станут жёстче.
- Добавить archive-level encryption, если backup-контур начнёт жить вне доверенного object storage perimeter.
- Добавить регулярную проверку restore-процедуры на staging/backup-контуре.