🐞 fix: Update backup script for configurable backup retention

This commit is contained in:
Keith Solomon
2025-12-28 11:13:48 -06:00
parent 95dece016f
commit 5465665c26

View File

@@ -4,7 +4,11 @@ set -euo pipefail
# Paths — adjust if your layout changes # Paths — adjust if your layout changes
GITEA_DIR="/gitea/gitea" GITEA_DIR="/gitea/gitea"
BACKUP_DIR="/gitea/backups" BACKUP_DIR="/gitea/backups"
CONTAINER="gitea" CONTAINER="Gitea"
# Retention
KEEP_COUNT=7
B2_REMOTE="B2:SoloForge-backup"
mkdir -p "$BACKUP_DIR" mkdir -p "$BACKUP_DIR"
@@ -22,9 +26,68 @@ mv "$GITEA_DIR/$dump_file" "$BACKUP_DIR/$dump_file"
echo "[backup] Dump created at $BACKUP_DIR/$dump_file" echo "[backup] Dump created at $BACKUP_DIR/$dump_file"
# Optional: Upload to Backblaze B2 via rclone # Upload to Backblaze B2 via rclone
# Make sure you configured a remote named 'B2' rclone copy "$BACKUP_DIR/$dump_file" "$B2_REMOTE"
rclone copy "$BACKUP_DIR/$dump_file" B2:soloforge-backups
echo "[backup] Uploaded $dump_file to Backblaze B2" echo "[backup] Uploaded $dump_file to Backblaze B2"
# -----------------------
# Cleanup: keep latest N
# -----------------------
echo "[cleanup] Keeping newest $KEEP_COUNT local backups in $BACKUP_DIR"
mapfile -t localBackups < <(ls -1t "$BACKUP_DIR"/gitea-dump-*.zip 2>/dev/null || true)
if (( ${#localBackups[@]} > KEEP_COUNT )); then
for oldPath in "${localBackups[@]:KEEP_COUNT}"; do
oldFile="$(basename "$oldPath")"
# Extra safety: only delete files matching our exact dump pattern
if [[ "$oldFile" =~ ^gitea-dump-[0-9]{8}-[0-9]{6}\.zip$ ]]; then
echo "[cleanup] Deleting local: $oldPath"
rm -f -- "$oldPath"
else
echo "[cleanup] Skipping unexpected local filename (won't delete): $oldPath" >&2
fi
done
else
echo "[cleanup] Local backups <= $KEEP_COUNT, nothing to delete."
fi
echo "[cleanup] Keeping newest $KEEP_COUNT backups in B2 ($B2_REMOTE)"
# Safety guard: require remote to be in the form "REMOTE:bucket"
# (bucket root only, no trailing slash/path)
if ! [[ "$B2_REMOTE" =~ ^[^:]+:[^/]+$ ]]; then
echo "[cleanup] Refusing remote cleanup: B2_REMOTE must be bucket-root like 'B2:SoloForge-backup' (got: $B2_REMOTE)" >&2
exit 1
fi
# Remote prune: list only root-level filenames, newest-first (timestamped name makes this safe).
# rclone lsf on a bucket root returns immediate entries only (non-recursive by default).
mapfile -t remoteBackups < <(
rclone lsf "$B2_REMOTE" \
--files-only \
--max-depth 1 \
--include "gitea-dump-*.zip" 2>/dev/null \
| sed 's:/$::' \
| sort -r
)
if (( ${#remoteBackups[@]} > KEEP_COUNT )); then
for old in "${remoteBackups[@]:KEEP_COUNT}"; do
# Extra safety: ensure we only ever delete matching root-level dump zips
if [[ "$old" =~ ^gitea-dump-[0-9]{8}-[0-9]{6}\.zip$ ]]; then
echo "[cleanup] Deleting remote: $old"
rclone deletefile "$B2_REMOTE/$old"
else
echo "[cleanup] Skipping unexpected remote filename (won't delete): $old" >&2
fi
done
else
echo "[cleanup] Remote backups <= $KEEP_COUNT, nothing to delete."
fi
echo "[backup] All done." echo "[backup] All done."
Update backup sctip