gendesign/ops/gendesign-backup-couchdb.default.example
bot-backend 0111b32cb2
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
feat(ops): у волта Obsidian появился автоматический бэкап
Site Finder закрывает backup.sh, МЕРУ — backup-tradein-db.sh, Forgejo —
backup-forgejo.sh. CouchDB не закрывал никто: автоматического бэкапа волта не
существовало вообще, единственной копией был ручной месячный прогон на машине
владельца. При этом в волте вся накопленная база знаний проекта — решения,
разборы инцидентов, ограничения, — и восстановить её из кода нельзя.

Контейнер на время снимка останавливается. Файлы CouchDB пишутся append-only,
но копия работающего узла может застать запись между обновлением данных и
обновлением заголовка базы, а .shards/ и _dbs.couch — рассогласованными между
собой; документация прямо требует снимать file-level копию с остановленного
узла. Данных около 85 МБ, простой измерен и составляет примерно минуту, окно
ночное, а LiveSync к обрывам связи устойчив по своей природе.

Оставить волт лежать — отказ хуже отсутствия бэкапа, поэтому старт висит на
trap EXIT и отрабатывает при любом выходе, включая ошибку tar и нехватку
места. После подъёма проверяется, что /_up отвечает, иначе notify().

S3 обязателен, как в backup-forgejo.sh и в backup.sh после #3085: без ключей
скрипт падает ДО остановки контейнера. Ронять волт ради копии, которой некуда
уехать, незачем.

Отдельный ключ для волта не требуется. Если COUCHDB_S3_* не заданы, берутся
S3_* из конфига основного бэкапа — того же ключа, которым уже выгружается
Site Finder, но под своим префиксом couchdb/. Требовать узкий ключ как условие
запуска значило бы оставить волт без бэкапа до того дня, когда до ключа дойдут
руки; завести его никто не мешает, файл-образец для этого есть.

Фолбэк читается в ПОДОБОЛОЧКЕ, наружу выносятся ровно четыре значения. Прямой
source был бы тихой диверсией: конфиг основного бэкапа задаёт свои
LOCAL_BACKUP_DIR, KEEP и SENTINEL_FILE, они затёрли бы вычисленные для волта.
Архивы легли бы в чужой каталог, а write_sentinel обновил бы сентинел
ОСНОВНОГО бэкапа — его сторож свежести зеленел бы по чужому прогону, и
пропущенный дамп базы перестал бы замечаться.

Владелец архивов выравнивается внутри контейнера: читать том надо от root,
поэтому наружу файлы выходили root:root, в отличие от соседних серий. Ротацию
это не ломало, но ставило каталог в зависимость от отсутствия sticky-бита.

ops/*.cron добавлен в paths deploy-infra.yml: эта строка была только в
deploy.yml, и после разъезда хостов правка crontab-beget.cron доезжала бы
лишь до продового хоста — то есть не туда, где живёт волт.

Проверено на боевом Beget, дважды подряд:
- без S3-настроек — код возврата 1, контейнер не тронут (Up 12 hours);
- полный прогон — контейнер остановлен, снят снимок 53 219 001 байт (15
  файлов) и конфиг 788 байт (3 файла), контейнер поднят и healthy, оба архива
  выгружены, сентинел записан, весь прогон 103 с;
- изоляция подоболочки прогнана на подставном конфиге: S3-значения
  подхватываются, LOCAL_BACKUP_DIR / SENTINEL_FILE / KEEP не затираются;
- объекты в бакете подтверждены НЕЗАВИСИМЫМ читающим ключом:
  couchdb/couchdb-data_*.tar.gz 50.8 MiB и couchdb/couchdb-config_*.tar.gz.

Refs #3057, #3085
2026-08-25 08:37:02 +03:00

55 lines
3.4 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Образец /etc/default/gendesign-backup-couchdb
#
# Читается ops/backup-couchdb.sh. Файл содержит ключ S3 — держать 0600 и
# владельцем того пользователя, под которым стоит крон-задача.
#
# Установка:
# sudo install -m 0600 -o gendesign -g gendesign \
# ops/gendesign-backup-couchdb.default.example /etc/default/gendesign-backup-couchdb
# sudo -e /etc/default/gendesign-backup-couchdb # подставить реальные ключи
#
# ЭТОТ ФАЙЛ НЕОБЯЗАТЕЛЕН. Если COUCHDB_S3_ENDPOINT и COUCHDB_S3_ACCESS_KEY не
# заданы, скрипт берёт S3_* из /etc/default/gendesign-backup — того же ключа,
# которым уже выгружается основной бэкап, но под своим префиксом couchdb/.
# Заводить файл стоит, когда для волта появится ОТДЕЛЬНЫЙ узкий ключ (как у
# forgejo): своя область доступа лучше общей, просто не ценой отсутствия
# бэкапа вовсе.
#
# Если не настроено ни здесь, ни там — скрипт откажется работать и НЕ станет
# останавливать CouchDB: бэкап без выгрузки за пределы машины смысла не имеет.
# --- S3 (либо здесь, либо фолбэк на /etc/default/gendesign-backup) ----------
COUCHDB_S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
COUCHDB_S3_BUCKET=gendsgn-backups
COUCHDB_S3_PREFIX=couchdb/
COUCHDB_S3_ACCESS_KEY=
COUCHDB_S3_SECRET_KEY=
# --- что копируем (значения по умолчанию совпадают с боевыми) ---------------
# Имена берутся из docker-compose.obsidian.yml, проект gendesign-obsidian.
#COUCHDB_CONTAINER=gendesign-couchdb
#COUCHDB_DATA_VOLUME=gendesign-obsidian_couchdb_data
#COUCHDB_CONFIG_VOLUME=gendesign-obsidian_couchdb_config
# --- локальное хранение -----------------------------------------------------
#LOCAL_BACKUP_DIR=/opt/gendesign/backups/couchdb
#KEEP=7
# --- пороги целостности -----------------------------------------------------
# Про объём, а не про наличие файла: пустой архив весит около сотни байт и без
# порога неотличим от настоящего бэкапа. Поднимать, если волт заметно вырос.
#MIN_DATA_BYTES=1048576
#MIN_CONFIG_BYTES=256
# Сколько секунд ждать ответа /_up после подъёма контейнера.
#START_TIMEOUT=60
# --- оповещения -------------------------------------------------------------
# Дублировать сюда ничего не надо: notify() из ops/lib-backup.sh, не найдя
# TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID в окружении, сам читает
# /etc/default/gendesign-backup. То есть канал общий с остальными бэкапами.
# Переопределяй только если этому бэкапу нужен ОТДЕЛЬНЫЙ адресат:
#TELEGRAM_BOT_TOKEN=
#TELEGRAM_CHAT_ID=
# Либо укажи другой файл, откуда notify() возьмёт настройки канала:
#BACKUP_ENV_FILE=/etc/default/gendesign-backup