#!/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 }