dd64420de1
Adds cloud sync extension to the daily backup script using rclone with client-side AES-256 encryption. Includes interactive setup script for configuring OneDrive, Google Drive, or any rclone provider. - scripts/setup-rclone.sh: interactive NAS rclone installer + config - scripts/cloud-backup.sh: sourced by backup.sh when CLOUD_ENABLED=true - backup.sh: cloud sync step runs after local backup Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
80 lines
2.6 KiB
Bash
Executable File
80 lines
2.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Off-site Backup — rclone cloud sync extension for backup.sh
|
|
#
|
|
# This script is sourced by backup.sh when CLOUD_ENABLED=true.
|
|
# It syncs local backups to a cloud provider via rclone with encryption.
|
|
#
|
|
# Prerequisites (handled by setup-rclone.sh):
|
|
# 1. rclone installed (Docker image: rclone/rclone)
|
|
# 2. Cloud remote configured (e.g., `onedrive`, `gdrive`)
|
|
# 3. Crypt remote configured (e.g., `nas-backup-crypt`)
|
|
#
|
|
# Env vars (set in .env or exported before running backup.sh):
|
|
# CLOUD_ENABLED=false # Set to true to enable cloud sync
|
|
# RCLONE_REMOTE=nas-backup # Base rclone remote name
|
|
# RCLONE_CRYPT_REMOTE="" # If set, uses encrypted remote (e.g., nas-backup-crypt:)
|
|
# CLOUD_RETENTION_DAYS=30 # Keep cloud copies for this many days
|
|
# RCLONE_EXTRA_FLAGS="" # Extra flags for rclone sync (e.g., "--bwlimit 2M")
|
|
|
|
CLOUD_ENABLED="${CLOUD_ENABLED:-false}"
|
|
RCLONE_REMOTE="${RCLONE_REMOTE:-nas-backup}"
|
|
RCLONE_CRYPT_REMOTE="${RCLONE_CRYPT_REMOTE:-}"
|
|
CLOUD_RETENTION_DAYS="${CLOUD_RETENTION_DAYS:-30}"
|
|
CLOUD_ERRORS=0
|
|
|
|
# Resolve the target remote (plain or crypt)
|
|
if [ -n "$RCLONE_CRYPT_REMOTE" ]; then
|
|
_cloud_target="${RCLONE_CRYPT_REMOTE}"
|
|
else
|
|
_cloud_target="${RCLONE_REMOTE}:nas-tools"
|
|
fi
|
|
|
|
_rclone() {
|
|
docker run --rm \
|
|
-v "$RCLONE_CONFIG_DIR:/config/rclone" \
|
|
-v "$BACKUP_DIR:/data:ro" \
|
|
rclone/rclone:latest \
|
|
"$@" --config /config/rclone/rclone.conf
|
|
}
|
|
|
|
cloud_backup() {
|
|
log "=== Cloud backup started ==="
|
|
|
|
# 1. Sync backup files to cloud
|
|
log "Syncing $BACKUP_DIR to $_cloud_target ..."
|
|
if _rclone sync /data/ "$_cloud_target" \
|
|
--verbose \
|
|
--progress \
|
|
--copy-links \
|
|
$RCLONE_EXTRA_FLAGS; then
|
|
log "Cloud sync OK"
|
|
else
|
|
log "FAILED: cloud sync"
|
|
CLOUD_ERRORS=$((CLOUD_ERRORS + 1))
|
|
fi
|
|
|
|
# 2. Cloud retention — delete files older than CLOUD_RETENTION_DAYS
|
|
log "Applying cloud retention: ${CLOUD_RETENTION_DAYS} days ..."
|
|
if _rclone delete "$_cloud_target" \
|
|
--min-age "${CLOUD_RETENTION_DAYS}d" \
|
|
--verbose; then
|
|
log "Cloud retention OK"
|
|
else
|
|
log "FAILED: cloud retention cleanup"
|
|
CLOUD_ERRORS=$((CLOUD_ERRORS + 1))
|
|
fi
|
|
|
|
# 3. Show cloud usage summary
|
|
log "Cloud storage summary:"
|
|
_rclone size "$_cloud_target" --json 2>/dev/null | python3 -c "
|
|
import json, sys
|
|
try:
|
|
d = json.load(sys.stdin)
|
|
print(f' {d.get(\"count\",0)} files, {d.get(\"bytes\",0)/1024/1024:.1f} MB')
|
|
except: pass
|
|
" || true
|
|
|
|
log "=== Cloud backup finished ($CLOUD_ERRORS errors) ==="
|
|
return $CLOUD_ERRORS
|
|
}
|