Резервное копирование и восстановление¶
Всё долговременное состояние Umbryx лежит в двух местах: volume
PostgreSQL и каталог /data. Для рабочего восстановления нужны оба.
Что включать в резервную копию¶
| Объект | Содержимое | Зачем |
|---|---|---|
Volume PostgreSQL (сервис db) |
все сущности, пользователи, audit-события | база данных |
DATA_DIR (по умолчанию ./data) |
загрузки, loot-файлы (зашифрованные), JSONL-зеркало аудита, secret.key, файл с паролем админа |
файлы + сгенерированные ключи |
.env |
ENCRYPTION_KEY, JWT_SECRET, пароли БД/Redis |
без ENCRYPTION_KEY зашифрованные данные невосстановимы |
Процедура¶
# бэкап
docker compose exec db pg_dump -U umbryx umbryx | gzip > umbryx-$(date +%F).sql.gz
tar czf umbryx-data-$(date +%F).tar.gz data/ # включает secret.key
cp .env umbryx-env-$(date +%F).backup # хранить надёжно
# восстановление (свежий хост или после аварии)
docker compose up -d db
gunzip -c umbryx-<date>.sql.gz | docker compose exec -T db psql -U umbryx umbryx
tar xzf umbryx-data-<date>.tar.gz
cp umbryx-env-<date>.backup .env
docker compose up -d
Держите .env (с ключом шифрования) в secret-менеджере, а не рядом с
резервными копиями.
Ротация ключа при восстановлении¶
Если ENCRYPTION_KEY должен смениться — сначала восстановитесь со
старым ключом, затем выполните ротацию ключа с помощью backend/scripts/rekey.py:
OLD_KEY=<old> NEW_KEY=<new> python3 backend/scripts/rekey.py --dry-run
OLD_KEY=<old> NEW_KEY=<new> python3 backend/scripts/rekey.py # остановите API
Скрипт перешифровывает секреты учётных данных, зашифрованные notes/loot,
loot-файлы и токены C2-интеграций одной транзакцией. Per-project DEK
ротируются отдельно (POST /api/system/encryption/rotate-dek).
Верификация после восстановления¶
/api/healthвозвращаетok- Войдите; откройте проект с известными учётными данными и раскройте один секрет — расшифровка восстановленным ключом должна работать
- Скачайте loot-файл (проходит через файловое шифрование)
GET /api/admin/audit/verify— отчёт о целостности событий timeline (при заданномAUDIT_INTEGRITY_KEY)
Режимы отказа¶
| Симптом | Причина |
|---|---|
| Секреты отдают ошибки расшифровки | неверный/потерянный ENCRYPTION_KEY — намеренно невосстановимо |
| Вход не работает ни у кого | JWT_SECRET отличается от того, которым были подписаны сессии, — войдите заново; если файл пароля админа потерян — сброс через БД или путь first-run |
| Loot-файлы скачиваются мусором | data-volume не восстановлен или ключ не совпадает |