⏪ Откат (rollback)
Что делать, если деплой сломал прод. Приоритет - вернуть рабочее состояние быстро, разбор причины - потом. Инциденты фиксировать в
capital-support.
Уровни отката (по возрастанию радиуса)
| Уровень | Когда | Действие |
|---|---|---|
| 1. Код | новый билд падает/баг в UI | вернуть предыдущий коммит + пересобрать |
| 2. Данные | миграция/операция испортила данные | PITR / restore из бэкапа |
| 3. Целиком | сервер недоступен | DR на новый сервер (см. §DR) |
1. Откат кода
Быстрее всего - откатить рабочее дерево на прошлый коммит головного capital и
пересобрать:
# на capital-prod:
cd ~/capital && git log --oneline -5 # если репо есть на сервере; иначе rsync прошлой версии с dev
docker compose up -d --build # после возврата кода
Если деплой был через rsync (не git на сервере) - re-rsync предыдущего состояния
дерева с dev-машины (git checkout <prev> -- . локально → rsync → build → up).
⚠️ Если релиз включал миграцию - откат кода НЕ откатывает схему. Сначала оцени: новая схема обратно-совместима со старым кодом? Если да - можно откатить только код. Если нет - нужен откат данных (§2) или forward-fix миграцией.
Целевое состояние (GHCR): rollback = docker compose pull предыдущего тега образа
(храним 5 последних) - секунды.
2. Откат данных (PITR / restore)
- Интерим (сейчас): restore из age-бэкапа - см.
runbooks/backup-restore.md. Гранулярность - последний снимок (каждые 6 ч), т.е. можно потерять до ~6 ч. - Целевое (pgBackRest + WAL): PITR до точной секунды «до сбоя» - см.
deploy/pgbackrest/README.md, флаг--type=time --target='YYYY-MM-DD HH:MM:SS+00'. RPO ≤ 5 мин.
Перед рискованной миграцией/деплоем - внеочередной бэкап (~/bin/capital-backup.sh)
и запись LSN, чтобы можно было PITR ровно к моменту «до».
3. DR (полная потеря сервера)
Быстрый DR ≤ 2-4 ч (HA-кластера нет - сознательно). Ранбук:
1. Заказать новый сервер (Hetzner API), hardening с первого часа.
2. Restore БД из B2 (или age-бэкапа) - deploy/pgbackrest/README.md §Restore.
⚠️ Восстанавливать в точное имя volume, которое ждёт compose
(<project>_capital_db, на текущем проде capital_capital_db; authoritative -
/root/pgbackrest/RESTORE-NOTES.txt). Restore в неверное имя тихо игнорится, и
compose поднимет ПУСТУЮ БД.
3. Deploy образов (GHCR - целевое) / rsync + build.
4. Перевести Cloudflare tunnel на новый сервер.
5. Смоук: login-страницы обоих приложений рендерятся, select count(*) from companies.
Прецедент: переезд team-nextcloud → capital-prod 15.09.2026 был по сути первым DR-тестом (restore из age-бэкапа, 32 таблицы, ~1 мин простоя на переключении tunnel).
Мгновенный rollback после переезда
Старый стек на team-nextcloud остановлен, но не удалён (~/capital) - при остром
регрессе можно вернуть его как мгновенный rollback (удалить после недели стабильности
нового прода).
После отката
- Зафиксировать инцидент в
capital-support(что сломалось, как откатили, root cause). - Не оставлять расхождение репо ↔ сервер: привести обратно в консистентное состояние.