#!/bin/bash # === Load environment === ENV_FILE="./AdGuardBackup.env" if [ ! -f "$ENV_FILE" ]; then echo "Environment file not found: $ENV_FILE" exit 1 fi source "$ENV_FILE" # === Sanity Check === sanity_check() { if [ -z "$HA_SSH_KEY" ]; then echo "Error: HA_SSH_KEY is not set."; exit 1 fi if [ -z "$HA_SSH_USER" ]; then echo "Error: HA_SSH_USER is not set."; exit 1 fi if [ -z "$BACKUP_DEST" ]; then echo "Error: BACKUP_DEST is not set."; exit 1 fi if [ -z "$SERVER_LIST" ]; then echo "Error: SERVER_LIST is not set."; exit 1 fi if [ "$NTFY_ENABLED" == "true" ]; then if [ -z "$NTFY_SERVER" ] || [ -z "$NTFY_TOPIC" ]; then echo "Error: NTFY settings are incomplete."; exit 1 fi fi if [ "$DISCORD_ENABLED" == "true" ]; then if [ -z "$DISCORD_WEBHOOK_URL" ]; then echo "Error: DISCORD_WEBHOOK_URL is not set."; exit 1 fi fi } # === Notification Functions === send_ntfy_notification() { local message="$1" if [ "$NTFY_ENABLED" = true ]; then curl -s -X POST -d "$message" "$NTFY_SERVER/$NTFY_TOPIC" >/dev/null fi } send_discord_notification() { local message="$1" if [ "$DISCORD_ENABLED" = true ]; then curl -s -X POST -H "Content-Type: application/json" \ -d "{\"content\": \"$message\"}" "$DISCORD_WEBHOOK_URL" >/dev/null fi } # === Run Sanity Check === sanity_check # === Setup Variables === TIMESTAMP=$(date '+%Y-%m-%d_%H-%M-%S') START_TIME=$(date +%s) LOG_FILE="$BACKUP_DEST/backup-$TIMESTAMP.log" REMOTE_FILE=${REMOTE_FILE:-"/opt/AdGuardHome/AdGuardHome.yaml"} mkdir -p "$BACKUP_DEST" touch "$LOG_FILE" # Parse server list IFS=' ' read -r -a SERVERS <<< "$SERVER_LIST" # === Start Logging and Notify === echo "[$(date)] Starting AdGuardHome backup..." | tee -a "$LOG_FILE" send_ntfy_notification "🛡️ AdGuardHome backup started at $TIMESTAMP" send_discord_notification "🛡️ AdGuardHome backup started at $TIMESTAMP" # === Main Backup Loop === for HOST in "${SERVERS[@]}"; do SERVER="$HA_SSH_USER@$HOST" echo "[$(date)] Connecting to $SERVER..." | tee -a "$LOG_FILE" REMOTE_HOSTNAME=$(ssh -i "$HA_SSH_KEY" -o StrictHostKeyChecking=no "$SERVER" 'hostname' 2>/dev/null) if [[ -z "$REMOTE_HOSTNAME" ]]; then echo "[$(date)] ❌ Failed to retrieve hostname from $HOST" | tee -a "$LOG_FILE" send_ntfy_notification "❌ Backup failed: could not retrieve hostname from $HOST" send_discord_notification "❌ Backup failed: could not retrieve hostname from $HOST" continue fi DEST_FILE="$BACKUP_DEST/AdGuardHome.yaml-$REMOTE_HOSTNAME-$TIMESTAMP" scp -i "$HA_SSH_KEY" -o StrictHostKeyChecking=no "$SERVER:$REMOTE_FILE" "$DEST_FILE" 2>>"$LOG_FILE" if [[ $? -eq 0 ]]; then echo "[$(date)] ✅ Backup successful: $DEST_FILE" | tee -a "$LOG_FILE" send_ntfy_notification "✅ Backup complete for $REMOTE_HOSTNAME" send_discord_notification "✅ Backup complete for $REMOTE_HOSTNAME" else echo "[$(date)] ❌ Failed to copy from $HOST" | tee -a "$LOG_FILE" send_ntfy_notification "❌ Backup failed for $REMOTE_HOSTNAME" send_discord_notification "❌ Backup failed for $REMOTE_HOSTNAME" fi done # === Finalize === END_TIME=$(date +%s) DURATION=$((END_TIME - START_TIME)) echo "[$(date)] Backup script completed in ${DURATION}s." | tee -a "$LOG_FILE" send_ntfy_notification "📦 Backup completed in ${DURATION}s" send_discord_notification "📦 Backup completed in ${DURATION}s"