#!/bin/bash # NAS Backup Script — runs daily via cron # Crontab: 0 3 * * * /volume1/docker/nas-tools/backup.sh >> /volume1/backups/nas-tools/backup.log 2>&1 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" BACKUP_DIR="/volume1/backups/nas-tools" DATE=$(date +%Y%m%d_%H%M%S) RETENTION_DAYS=7 ERRORS=0 [ -f "$SCRIPT_DIR/.env" ] && source "$SCRIPT_DIR/.env" mkdir -p "$BACKUP_DIR" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"; } notify() { if [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ -d chat_id="$TELEGRAM_CHAT_ID" -d text="$1" -d parse_mode="Markdown" > /dev/null fi } run_backup() { local desc="$1"; shift log "Backing up $desc..." if "$@"; then log "$desc OK" else log "FAILED: $desc" ERRORS=$((ERRORS + 1)) fi } log "=== Backup started ===" # Database dumps run_backup "Gitea DB" docker exec gitea-db pg_dump -U gitea -f /tmp/gitea_dump.sql gitea docker cp gitea-db:/tmp/gitea_dump.sql "$BACKUP_DIR/gitea_db_$DATE.sql" 2>/dev/null run_backup "Immich DB" docker exec immich-db pg_dump -U postgres -f /tmp/immich_dump.sql immich docker cp immich-db:/tmp/immich_dump.sql "$BACKUP_DIR/immich_db_$DATE.sql" 2>/dev/null # Config backups CONFIGS=() for p in \ /volume1/docker/nas-dashboard/.env \ /volume1/docker/nas-dashboard/auth.json \ /volume1/docker/gitea/conf \ /volume1/docker/immich/.env \ /volume1/docker/navidrome/data/navidrome.db \ /volume1/docker/openclaw/data; do [ -e "$p" ] && CONFIGS+=("$p") done if [ ${#CONFIGS[@]} -gt 0 ]; then run_backup "Configs" tar -czf "$BACKUP_DIR/configs_$DATE.tar.gz" "${CONFIGS[@]}" fi # Cleanup old backups log "Cleaning backups older than $RETENTION_DAYS days..." find "$BACKUP_DIR" -type f \( -name "*.sql" -o -name "*.tar.gz" \) -mtime +$RETENTION_DAYS -delete # Summary log "=== Backup finished ($ERRORS errors) ===" if [ $ERRORS -gt 0 ]; then notify "🔴 *NAS Backup FAILED* ($DATE) $ERRORS error(s) — check logs" else notify "🟢 *NAS Backup OK* ($DATE)" fi