Документация

К списку статей
27. Восстановление двух БД (портал + Сейф) после сбоя

Аудитория: суперадминистратор, инженер эксплуатации. Закрывает вопрос: «как восстановить данные после потери диска/порчи — с учётом того, что ПДн-связки лежат в ОТДЕЛЬНОМ инстансе Сейфа (F4-db)?». Связано: 08 — Эксплуатация и бэкап, 19-backup-restore (портал).


Что восстанавливаем — ДВА независимых инстанса

После выноса Сейфа (F4-db) контур держит две раздельные БД:

ИнстансТомЧто внутриБэкап-скрипт
db (портал)pgdataреестр ПО, лицензии, контракты, факты, аудит ФЗ-152 — обезличенные `user_id`deploy/backup.sh
vaultdb (Сейф)vaultdataсвязка user_id ↔ ФИО/табельный, журнал раскрытий — ПДнdeploy/backup-vault.sh
Бэкапы Сейфа хранятся отдельно от портальных (не в одном каталоге/хранилище) — иначе ПДн вернутся в один контур и расширят область аттестации (D15). Восстанавливать тоже раздельно.

Связка между ними — детерминированный хеш user_id = HMAC(ANON_SALT, …). Поэтому критично: восстанавливать обе БД на снимках одного периода и с той же `ANON_SALT`, что была на момент снятия. Иначе раскрытие в Сейфе и факты в портале не сойдутся.


Процедура восстановления (катастрофа/перенос)

0. Свежий бэкап текущего состояния, если БД ещё доступны (даже повреждённые) — на всякий случай.

1. Остановить контур:

cd /opt/licenziar
docker compose -f docker-compose.lic.yml --env-file .env.lic down   # тома НЕ трогаем пока

2. Восстановить ПОРТАЛ (db):

docker volume rm licenziar_pgdata 2>/dev/null || true     # только при полном восстановлении
docker compose -f docker-compose.lic.yml --env-file .env.lic up -d db
until docker compose -f docker-compose.lic.yml --env-file .env.lic exec -T db pg_isready -U postgres -d licenziar; do sleep 1; done
gunzip -c backups/licenziar-<ts>.sql.gz \
  | docker compose -f docker-compose.lic.yml --env-file .env.lic exec -T db psql -U postgres -d licenziar -v ON_ERROR_STOP=1

3. Восстановить СЕЙФ (vaultdb) — из ОТДЕЛЬНОГО бэкапа того же периода:

docker volume rm licenziar_vaultdata 2>/dev/null || true
docker compose -f docker-compose.lic.yml --env-file .env.lic up -d vaultdb
until docker compose -f docker-compose.lic.yml --env-file .env.lic exec -T vaultdb pg_isready -U postgres -d vaultdb; do sleep 1; done
gunzip -c backups-vault/vault-<ts>.sql.gz \
  | docker compose -f docker-compose.lic.yml --env-file .env.lic exec -T vaultdb psql -U postgres -d vaultdb -v ON_ERROR_STOP=1

4. Поднять остальное. dbinit/vault-init на непустых БД выйдут (already_seeded/аналог) и данные из дампов не тронут:

docker compose -f docker-compose.lic.yml --env-file .env.lic up -d

5. Убедиться, что `ANON_SALT` в `.env` — та же, что на момент бэкапа (дампы хранят уже обезличенные user_id; менять соль при восстановлении НЕЛЬЗЯ — см. 23).


Проверка после восстановления
  1. GET /api/health{"status":"ok","db":"ok"}.
  2. GET /api/<tenant>/dashboard-kpi → ненулевые агрегаты.
  3. Вход оператора (it_admin@<tenant>) проходит.
  4. Связка цела: DPO-раскрытие в Сейфе по user_id из портала возвращает ФИО (значит db и

vaultdb — согласованного периода и соли).

  1. Нет «осиротевших» фактов: каждый activity_facts.user_id имеет пару в masked_users.

Грабли
  • Несогласованные снимки. Портал и Сейф из разных периодов → раскрытие 404 / рассинхрон.

Снимайте бэкапы обеих БД близко по времени (в идеале — одним cron-окном).

  • `ANON_SALT` менять при восстановлении нельзя. Это не восстановление, а ротация (отдельная

процедура 23).

  • Бэкапы не смешивать. Дампы Сейфа (ПДн) — отдельное хранилище внутри контролируемого контура.
  • Том vs дамп. Быстрый откат — снимок тома; перенос между версиями Postgres — логический дамп.

Связанные: 08 — Эксплуатация и бэкап · 26 — Миграции и обновление · 17 — Топология Сейфа · 23 — Ротация соли.