Files

63 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================
# GoToSocial backup: SQLite consistent + медиа → backups/
# + копия на Яндекс.Диск (ротация 7 дней локально / 30 на ЯД)
#
# Топология: /opt/gotosocial/data → /gotosocial/storage (контейнер)
# data/sqlite.db + media лежат прямо в data/ (storage-маунт)
# SQLite: Backup API через python3 (sqlite3 CLI не установлен)
# Тихий: stdout пуст при успехе (для no_agent cron), не-ноль при ошибке
# =============================================================
set -euo pipefail
BASE_DIR="/opt/gotosocial"
DATA_DIR="${BASE_DIR}/data"
BACKUP_DIR="${BASE_DIR}/backups"
YANDEX_MOUNT="/mnt/yandex-disk"
YANDEX_DIR="${YANDEX_MOUNT}/backup/gotosocial-backups"
STAGE="${BACKUP_DIR}/stage"
TS="$(date +%Y%m%d_%H%M%S)"
mkdir -p "${BACKUP_DIR}"
rm -rf "${STAGE}" && mkdir -p "${STAGE}"
# --- Компактный снапшот БД через SQLite Backup API (online, без конфликтов) ---
python3 - "${DATA_DIR}/sqlite.db" "${STAGE}/sqlite.db" <<'PYEOF'
import sqlite3, sys
src, dst = sys.argv[1], sys.argv[2]
s = sqlite3.connect(src)
d = sqlite3.connect(dst)
with d:
s.backup(d)
d.close()
s.close()
PYEOF
# --- Медиа копируем в stage (без WAL/SHM, с сохранением структуры) ---
# Исключаем служебные sqlite-файлы из data/, чтобы не дублировать БД
(cd "${DATA_DIR}" && tar -cf - --exclude='sqlite.db*' .) | tar -xf - -C "${STAGE}"
# --- Итоговый архив: consistent db + медиа ---
ARCHIVE="${BACKUP_DIR}/gotosocial_${TS}.tar.gz"
tar -C "${STAGE}" -czf "${ARCHIVE}" .
# --- Архив секретов (.env) отдельно ---
ENV_ARCHIVE="${BACKUP_DIR}/gotosocial_env_${TS}.tar.gz"
tar -C "${BASE_DIR}" -czf "${ENV_ARCHIVE}" .env
# --- Копия на Яндекс.Диск ---
if ! mountpoint -q "${YANDEX_MOUNT}"; then
echo "ERROR: Яндекс.Диск не примонтирован (${YANDEX_MOUNT})" >&2
exit 1
fi
mkdir -p "${YANDEX_DIR}"
cp -p "${ARCHIVE}" "${ENV_ARCHIVE}" "${YANDEX_DIR}/"
# --- Ротация: локально 7 дней, ЯД 30 дней ---
find "${BACKUP_DIR}" -maxdepth 1 -type f -name 'gotosocial_*' -mtime +7 -delete
find "${YANDEX_DIR}" -maxdepth 1 -type f -name 'gotosocial_*' -mtime +30 -delete
rm -rf "${STAGE}"
# Успех — тихо (для no_agent cron)
exit 0