All checks were successful
CI Trade-In / changes (pull_request) Successful in 24s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 29s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 3m15s
CI / backend-tests (pull_request) Successful in 7m37s
Тема форума для уведомлений бэкапов задаётся только env-файлом на хосте, а в образцах её не было вовсе. На проде она задана, но не та: 158 («алерты») в /opt/gendesign/secrets/backup-notify.env и forgejo-backup.env на Beget и в /etc/default/gendesign-backup на Poincare. По решению #3163 инфраструктура идёт в 245 «Metrics». Значение на хостах этот коммит не меняет. - ops/gendesign-backup*.default.example: строка #TELEGRAM_TOPIC_ID=245 с причиной и ловушкой: тема обязана лежать в одном файле с токеном и чатом, иначе notify() её не прочитает. - ops/crontab-beget.cron сверен с живым crontab Beget: сторожа и бэкап волта получают BACKUP_ENV_FILE=/opt/gendesign/secrets/backup-notify.env. Без него переустановка crontab из репозитория глушила бы алерты бэкапов на Beget. - ops/uptime-healthcheck.sh и его образец удалены: скрипт не запущен ни на одном хосте (crontab, cron.d, таймеры), доступность сторожат uptime-мониторы GlitchTip на Beget (gendsgn.ru, /health, meraocenka.ru — раз в 60 с). Тест исполняет настоящий check-backup-staleness.sh с образцом, заполненным по инструкции, и проверяет адрес в вызове curl: message_thread_id=245. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
91 lines
7.1 KiB
Text
91 lines
7.1 KiB
Text
# Environment file for ops/backup-forgejo.sh (Forgejo code + DB backup, #2203).
|
||
#
|
||
# Install on the prod VM as a ROOT-OWNED, chmod-600 file that is NOT in git:
|
||
# sudo cp /opt/gendesign/ops/gendesign-backup-forgejo.default.example /etc/default/gendesign-backup-forgejo
|
||
# sudo chmod 600 /etc/default/gendesign-backup-forgejo
|
||
# sudo $EDITOR /etc/default/gendesign-backup-forgejo # fill in real S3 credentials
|
||
#
|
||
# DELIBERATELY a separate file from /etc/default/gendesign-backup (used by
|
||
# ops/backup.sh and tradein-mvp/deploy/backup-tradein-db.sh) — this backup
|
||
# uses a SEPARATE, narrower-scoped S3 service user that can ONLY PutObject
|
||
# under s3://gendsgn-backups/forgejo/*, nothing else. The prod-host writer
|
||
# key used by the other two backups (`gendsgn-backup-writer`) has root-of-
|
||
# bucket access; that key must NOT be reused here, and this key must NOT be
|
||
# put in /etc/default/gendesign-backup.
|
||
#
|
||
# THE KEY DOES NOT EXIST YET (as of #2203). Until a human creates the
|
||
# `gendsgn-backup-forgejo-writer` service user + bucket policy in the
|
||
# Selectel panel (see the #2203 PR description for the exact policy JSON —
|
||
# PutObject-only on arn:aws:s3:::gendsgn-backups/forgejo/*, explicit Deny on
|
||
# GetObject/ListBucket/Delete*) and fills in the four FORGEJO_S3_* vars
|
||
# below, ops/backup-forgejo.sh refuses to run and exits non-zero loudly. That
|
||
# is expected, not a bug.
|
||
#
|
||
# --- S3 off-site upload (Selectel S3-compatible). All four required. ---
|
||
#FORGEJO_S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
|
||
#FORGEJO_S3_BUCKET=gendsgn-backups
|
||
#FORGEJO_S3_ACCESS_KEY=REPLACE_WITH_REAL_ACCESS_KEY_ONCE_CREATED
|
||
#FORGEJO_S3_SECRET_KEY=REPLACE_WITH_REAL_SECRET_KEY_ONCE_CREATED
|
||
|
||
# --- оповещения (Telegram) ---
|
||
# backup-forgejo.sh читает этот файл сам, поэтому канал задаётся здесь: без
|
||
# токена и чата notify() ищет их в /etc/default/gendesign-backup.
|
||
#TELEGRAM_BOT_TOKEN=123456789:AA-REPLACE_WITH_REAL_BOT_TOKEN
|
||
#TELEGRAM_CHAT_ID=123456789
|
||
# Тема форума (#3164). Бэкапы — инфраструктура, по решению #3163 они идут в
|
||
# «Metrics» (245); «алерты» (158) — только для клиентских инцидентов. Без
|
||
# переменной сообщение уходит в общую тему. Держать В ТОМ ЖЕ файле, что токен и
|
||
# чат: notify() читает env-файл, только если их нет в окружении.
|
||
#TELEGRAM_TOPIC_ID=245
|
||
|
||
# --- optional overrides (defaults are sensible; uncomment only to change) ---
|
||
#FORGEJO_S3_PREFIX=forgejo/ # key prefix inside the bucket; must match
|
||
# the policy's Resource path exactly
|
||
#KEEP=7 # how many recent local copies to retain
|
||
# (DB dumps and repo bundles are separate series)
|
||
#MIN_DB_DUMP_BYTES=2048 # sanity floor for the DB dump (small DB —
|
||
# config/issues/PRs/users, no git blobs)
|
||
#MIN_REPOS_BUNDLE_BYTES=10240 # sanity floor for the repo tar.gz
|
||
#LOCAL_BACKUP_DIR=/opt/gendesign/backups/forgejo
|
||
#FORGEJO_DIR=/home/gendesign/forgejo # Forgejo compose dir on the VM (NOT
|
||
# part of the gendesign git checkout)
|
||
#FORGEJO_REPOS_DIR=/home/gendesign/forgejo/data/forgejo/git/repositories
|
||
|
||
# --- контейнер с БД Forgejo (#3061) ---
|
||
# ЗАДАВАТЬ НЕ НУЖНО почти никогда: ops/backup-forgejo.sh находит контейнер сам.
|
||
# Он перебирает PG_CONTAINER_CANDIDATES, оставляет запущенные и берёт тот, в
|
||
# чьей базе `forgejo` реально ЕСТЬ ТАБЛИЦЫ.
|
||
#
|
||
# ПОЧЕМУ НЕ КОНСТАНТА. Раньше имя было зашито (gendesign-postgres-1 — общий
|
||
# кластер основного приложения). Переезд продукта на Selectel переносит базу
|
||
# forgejo оттуда в лёгкий инфраструктурный кластер (gendesign-infra-postgres,
|
||
# сервис infra-postgres в docker-compose.prod.yml), а старый контейнер после
|
||
# переноса какое-то время ещё жив и держит свою — с этого момента протухающую —
|
||
# копию базы. Зашитое имя означало бы, что бэкап продолжает исправно дампить
|
||
# именно её: дамп непустой, маркер завершения на месте, размер выше порога — и
|
||
# ни одной новой строки с момента cutover. Порогов на СВЕЖЕСТЬ здесь нет, так
|
||
# что выяснилось бы это только при восстановлении.
|
||
#
|
||
# КОГДА ЗАДАВАТЬ ЯВНО — ровно один случай: окно переезда, когда непустая база
|
||
# forgejo есть СРАЗУ В ДВУХ запущенных контейнерах. Автоопределение тогда не
|
||
# гадает, а останавливается с ошибкой (выбрать наугад = 50% шанс забэкапить
|
||
# труп) и ждёт прямого указания, какой контейнер боевой. Момент, с которого это
|
||
# нужно, наступает НЕ на cutover'е, а РАНЬШЕ — с первой же заливки дампа в новый
|
||
# кластер (шаг 3a в комментарии к сервису infra-postgres,
|
||
# docker-compose.prod.yml): с этой секунды кандидатов двое, и ночной бэкап
|
||
# git-хоста иначе просто не снимется. Поэтому значение здесь живёт двумя фазами:
|
||
# до cutover'а — боевой ещё старый кластер:
|
||
#PG_CONTAINER=gendesign-postgres-1
|
||
# после — новый:
|
||
#PG_CONTAINER=gendesign-infra-postgres
|
||
# Строку УБРАТЬ, как только старый контейнер погашен: дальше автоопределение
|
||
# снова однозначно и переживёт любое следующее переименование само.
|
||
#
|
||
# Явное значение берётся КАК ЕСТЬ, без проверок — это ручной override, и тот,
|
||
# кто его выставил, знает про свою инсталляцию больше. Пустое значение
|
||
# (PG_CONTAINER=) равносильно незаданному: включается автоопределение.
|
||
|
||
# Где искать, когда PG_CONTAINER пуст. Имена через пробел; КАВЫЧКИ ОБЯЗАТЕЛЬНЫ —
|
||
# файл читается через `source`, и без них второе имя bash попытается выполнить
|
||
# как команду. Трогать только если контейнеры называются иначе, чем здесь.
|
||
#PG_CONTAINER_CANDIDATES="gendesign-postgres-1 gendesign-infra-postgres"
|