84 lines
2.5 KiB
Bash
84 lines
2.5 KiB
Bash
#!/bin/bash
|
|
# =============================================================================
|
|
# DashCaddy Gitea — Off-host backup to Dropbox
|
|
# =============================================================================
|
|
# - Stops gitea container briefly to ensure SQLite DB consistency
|
|
# - Syncs /var/lib/docker/volumes/gitea-data to dropbox:/Apps/dashcaddy-gitea-backups/<date>/
|
|
# - Date-stamped snapshots (one per day), kept for 7 days locally
|
|
# - Restarts gitea even if sync fails
|
|
# - Logs to /var/log/gitea-backup.log
|
|
# =============================================================================
|
|
set -u # don't use -e: we want to always restart gitea
|
|
|
|
LOG=/var/log/gitea-backup.log
|
|
DATA_SRC=/var/lib/docker/volumes/gitea-data/_data
|
|
DEST="dropbox:/Apps/dashcaddy-gitea-backups"
|
|
TODAY=$(date -u +%Y-%m-%d)
|
|
BACKUP_PATH="${DEST}/${TODAY}"
|
|
RETENTION_DAYS=7
|
|
|
|
log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*" | tee -a "$LOG"; }
|
|
|
|
log "=== Backup start ==="
|
|
|
|
# 0. Sanity checks
|
|
if [ ! -d "$DATA_SRC" ]; then
|
|
log "ERROR: data dir $DATA_SRC missing"
|
|
exit 1
|
|
fi
|
|
|
|
# 1. Stop gitea to flush SQLite
|
|
log "Stopping gitea container..."
|
|
docker stop gitea >> "$LOG" 2>&1
|
|
STOP_RC=$?
|
|
if [ $STOP_RC -ne 0 ]; then
|
|
log "WARNING: docker stop returned $STOP_RC — container may not be running"
|
|
fi
|
|
|
|
# 2. Sync (use copy so source files are preserved as-is, no --delete)
|
|
log "Syncing $DATA_SRC -> $BACKUP_PATH"
|
|
rclone copy "$DATA_SRC" "$BACKUP_PATH" \
|
|
--transfers 4 \
|
|
--checkers 8 \
|
|
--retries 3 \
|
|
--low-level-retries 10 \
|
|
--stats 30s \
|
|
--log-file "$LOG" \
|
|
--log-level INFO
|
|
SYNC_RC=$?
|
|
|
|
# 3. Always restart gitea
|
|
log "Starting gitea container..."
|
|
docker start gitea >> "$LOG" 2>&1
|
|
START_RC=$?
|
|
|
|
# Wait for gitea to be ready
|
|
for i in {1..30}; do
|
|
if curl -sf http://localhost:3000/api/v1/version > /dev/null 2>&1; then
|
|
log "Gitea is up after ${i}s"
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
# 4. Cleanup old backups (older than RETENTION_DAYS)
|
|
log "Pruning local + remote snapshots older than ${RETENTION_DAYS} days..."
|
|
CUTOFF=$(date -u -d "${RETENTION_DAYS} days ago" +%Y-%m-%d)
|
|
rclone lsf "$DEST/" --dirs-only 2>/dev/null | while read -r d; do
|
|
# rclone returns names with trailing /
|
|
name="${d%/}"
|
|
if [[ "$name" < "$CUTOFF" ]]; then
|
|
log " removing old: $name"
|
|
rclone purge "${DEST}/${name}" >> "$LOG" 2>&1
|
|
fi
|
|
done
|
|
|
|
# 5. Report
|
|
if [ $SYNC_RC -eq 0 ] && [ $START_RC -eq 0 ]; then
|
|
log "=== Backup OK ==="
|
|
exit 0
|
|
else
|
|
log "=== Backup completed with errors (sync=$SYNC_RC, start=$START_RC) ==="
|
|
exit 1
|
|
fi
|