deploy/backup: образ на restic/restic:0.19.1 (+ sqlite, supercronic, tini), работает от uid 10001, как appuser. Скрипт fs-backup: - run: консистентная копия БД (VACUUM INTO + integrity_check), снимок в локальный репозиторий и на VPS (SFTP), теги players/matches, GFS-очистка (дни/недели/месяцы; именованные keep и pre-restore не удаляются), restic check; - list / status / verify / export (tar без сжатия; сжатие — только restic, репозиторий v2); - restore / import через промежуточную директорию: разворачивание в .restore-new внутри каждого тома, проверка (integrity_check, таблицы, число файлов, целостность tar), страховочный снимок pre-restore, двухфазная замена rename с файлом фазы и откатом; recover разбирает прерванное восстановление. Отказ при работающем app. Точка входа: без BACKUP_PASSWORD простой без рестарт-петли, первый снимок при пустом репозитории, расписание supercronic, healthcheck по возрасту последнего успеха. #64 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jBxs9nBCk5nBdTLzcGz91
39 lines
1.8 KiB
Bash
39 lines
1.8 KiB
Bash
#!/bin/sh
|
|
# Точка входа контейнера backup: первый снимок (если снимков ещё нет) и расписание.
|
|
# Расписание — supercronic по BACKUP_SCHEDULE (бэкап) и BACKUP_VERIFY_SCHEDULE (проверка).
|
|
set -eu
|
|
|
|
log() { printf '[backup %s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"; }
|
|
|
|
# Без пароля бэкапы невозможны. Не падаем (иначе restart-петля и спам в логах) — ждём,
|
|
# пока пароль появится в .env; healthcheck при этом показывает unhealthy.
|
|
if [ -z "${BACKUP_PASSWORD:-}" ]; then
|
|
log "BACKUP_PASSWORD не задан в .env — бэкапы ОТКЛЮЧЕНЫ."
|
|
log "Настройка по шагам: deploy/backup/README.md. После правки .env: docker compose up -d backup"
|
|
exec tail -f /dev/null
|
|
fi
|
|
|
|
mkdir -p /tmp/fs-backup
|
|
CRONTAB=/tmp/fs-backup/crontab
|
|
: > "$CRONTAB"
|
|
if [ -n "${BACKUP_SCHEDULE:-}" ]; then
|
|
echo "${BACKUP_SCHEDULE} fs-backup run --scheduled" >> "$CRONTAB"
|
|
fi
|
|
if [ -n "${BACKUP_VERIFY_SCHEDULE:-}" ]; then
|
|
echo "${BACKUP_VERIFY_SCHEDULE} fs-backup verify" >> "$CRONTAB"
|
|
fi
|
|
|
|
if [ ! -s "$CRONTAB" ]; then
|
|
log "Расписание отключено — только ручной запуск: docker compose exec backup fs-backup run"
|
|
exec tail -f /dev/null
|
|
fi
|
|
|
|
if ! fs-backup has-snapshots; then
|
|
log "Снимков в локальном репозитории ещё нет — делаю первый бэкап сразу."
|
|
fs-backup run --scheduled || log "Первый бэкап не удался — следующая попытка по расписанию."
|
|
fi
|
|
|
|
log "Расписание (TZ=${TZ:-UTC}):"
|
|
sed 's/^/[backup] /' "$CRONTAB"
|
|
exec supercronic -passthrough-logs "$CRONTAB"
|