backup-forgejo.sh забирал БД и голые репозитории — то есть СОДЕРЖИМОЕ
Forgejo, но не то, ЧЕМ оно поднимается.
Компоуз-файлы Forgejo и раннеров живут в /home/gendesign/forgejo/, ВНЕ
репозитория: `git rev-parse` там отвечает "not a git repository". Их не
трогает ни один деплой (включая #3071 — тот синхронизирует /opt/gendesign)
и не покрывал ни один бэкап.
Практический смысл: при потере хоста БД и репозитории восстановятся, а
конфигурация — нет. Пришлось бы вручную воссоздавать docker-compose.yml и
заново регистрировать три раннера. Для переезда это особенно неприятно:
Forgejo ОСТАЁТСЯ на Beget, то есть он и есть та машина, с которой всё
будет подниматься, если что-то пойдёт не так.
Косвенное подтверждение, что каталог правится руками и без истории:
рядом лежат runner-compose.yml.bak, .bak.1779049805, .bak.before-runner3 —
три самодельных снимка вместо version control.
Что НЕ включено намеренно: секрет-файл режима 600 и runner*/data/ с
регистрационными токенами. Они остаются ручным off-box пунктом владельца —
тем же, что рантайм-секреты в приёмке #2203. Раннеры при восстановлении
перерегистрируются из UI за пару минут; компоуз-файл руками не
восстановишь.
Проверки те же две, что у repo-бандла (не «объём», а «собрался и
читается»), плюс мягкая деградация: не собрался — WARN и продолжаем без
него, бэкап БД и репозиториев не теряем из-за 5 КБ конфига.
Проверено на настоящем каталоге прода (read-only, боевой бэкап не
тронут):
- tar код 0, ровно 2 файла: docker-compose.yml, runner-compose.yml
- 1070 байт, архив читается
- секрет-файла внутри нет, каталога data/ внутри нет
- раскрытие ${config_out:+...} в цикле выгрузки: пусто -> 2 файла,
задано -> 3
- bash -n чист
Refs #2203, #3057
Deliverable 1: ops/backup.sh and tradein-mvp/deploy/backup-tradein-db.sh now
write a sentinel file on every verified-good run. A new ops/check-backup-
staleness.sh (separate cron entry, hourly) alerts via the existing Telegram
channel (same TELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_ID idiom as ops/uptime-
healthcheck.sh, transition-tracked so it doesn't spam) if a sentinel goes
stale. Shared logic (notify/sentinel/state) factored into ops/lib-backup.sh
so it isn't triplicated; the two existing scripts' own hardening (integrity
checks, retention, etc.) is untouched.
Deliverable 2: ops/backup-forgejo.sh — Forgejo (git.gendsgn.ru) has no backup
today. Dumps the shared-postgres `forgejo` DB + tars the bare-repo tree, both
off-box to s3://gendsgn-backups/forgejo/ under a SEPARATE, narrower S3 key
(root-of-bucket writer key stays out of this). The key doesn't exist yet —
the script refuses to run and exits non-zero, loudly, until the four
FORGEJO_S3_* vars are filled in (see the example env file and PR description
for the exact bucket policy JSON to create it with).
Refs #2203, #2989