chore: STATUS.md обновлён (деплой завершён), backup.sh на SQLite Backup API

This commit is contained in:
estorozhenko
2026-09-06 19:43:05 +00:00
parent d9951b6048
commit 9f693c8f7b
2 changed files with 76 additions and 38 deletions
+33 -15
View File
@@ -2,35 +2,52 @@
# =============================================================
# 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_DIR="/mnt/yandex-disk/backup/gotosocial-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)"
# --- SQLite consistent: VACUUM INTO (не горячая копия файла) ---
SQLITE_TMP="${BACKUP_DIR}/sqlite-consistent-${TS}.db"
mkdir -p "${BACKUP_DIR}"
sqlite3 "${DATA_DIR}/sqlite.db" "VACUUM INTO '${SQLITE_TMP}';"
rm -rf "${STAGE}" && mkdir -p "${STAGE}"
# --- Сбор архива: consistent db + медиа ---
# --- Компактный снапшот БД через 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 "${DATA_DIR}" -czf "${ARCHIVE}" \
--transform="s|sqlite-consistent-${TS}.db|sqlite.db|" \
"${SQLITE_TMP#${DATA_DIR}/}" storage 2>/dev/null \
|| tar -C "${BACKUP_DIR}" -czf "${ARCHIVE}" "sqlite-consistent-${TS}.db" -C "${DATA_DIR}" storage
rm -f "${SQLITE_TMP}"
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_DIR%/backup/*}"; then
echo "ERROR: Яндекс.Диск не примонтирован (${YANDEX_DIR%/backup/*})" >&2
if ! mountpoint -q "${YANDEX_MOUNT}"; then
echo "ERROR: Яндекс.Диск не примонтирован (${YANDEX_MOUNT})" >&2
exit 1
fi
mkdir -p "${YANDEX_DIR}"
@@ -40,6 +57,7 @@ cp -p "${ARCHIVE}" "${ENV_ARCHIVE}" "${YANDEX_DIR}/"
find "${BACKUP_DIR}" -maxdepth 1 -type f -name 'gotosocial_*' -mtime +7 -delete
find "${YANDEX_DIR}" -maxdepth 1 -type f -name 'gotosocial_*' -mtime +30 -delete
echo "OK: ${ARCHIVE}"
echo "OK: ${ENV_ARCHIVE}"
ls -lh "${ARCHIVE}" "${ENV_ARCHIVE}"
rm -rf "${STAGE}"
# Успех — тихо (для no_agent cron)
exit 0