gateway/ddns.sh

99 lines
3.8 KiB
Bash
Executable File

#!/bin/bash
# ============================================================================
# DYNAMIC DNS UPDATER FOR NAMECHEAP (MULTI-DOMAIN)
# ============================================================================
# Configuration - Edit these values
# ============================================================================
# Define your domains/hosts as an array of space-separated strings
# Format: "HOSTNAME:DOMAIN:PASSWORD"
# Use '@' for root domain, 'sub' for subdomain (e.g., 'home', 'video')
DOMAINS=(
"home:seanowiecki.com:d7b38fc4de474e81a79a309824aa8e2a"
"video:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"frigate:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"survey:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"memos:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"openwebui:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"immich:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"matrix:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"minecraft:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"chat:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"bentopdf:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"home:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"nextcloud:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"obico:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"obsidian:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"qr:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"cachet:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"grafana:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"valheim:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"satisfactory:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"vpn:atomic6.net:2a687057401f4401b4248d1d31b2ba81"
"salt:nase.dev:1fa7b1a67d404b339e38107db98c87f0"
"gitea:nase.dev:1fa7b1a67d404b339e38107db98c87f0"
)
# IP checking service (choose one that works reliably for you)
IP_SERVICE="https://api.ipify.org" # Alternatives: "https://ifconfig.io/ip", "https://icanhazip.com"
# ============================================================================
# Script Core - Do not edit below unless you know what you're doing
# ============================================================================
# Get current public IP
echo "[$(date)] Checking public IP..."
CURRENT_IP=$(curl -s "$IP_SERVICE")
if [ -z "$CURRENT_IP" ]; then
echo "[$(date)] ERROR: Could not fetch public IP. Check network or IP service."
exit 1
fi
echo "[$(date)] Current public IP: $CURRENT_IP"
# Process each domain entry
for ENTRY in "${DOMAINS[@]}"; do
# Split the entry into components
IFS=":" read -r HOSTNAME DOMAIN PASSWORD <<< "$ENTRY"
# Create a unique identifier for this host/domain combination
RECORD_ID="${HOSTNAME}.${DOMAIN}"
# File to store last IP for this specific record
IP_FILE="/tmp/last_ip_${RECORD_ID//[^a-zA-Z0-9]/_}.txt"
# Read last recorded IP if file exists
if [ -f "$IP_FILE" ]; then
LAST_IP=$(cat "$IP_FILE")
else
LAST_IP=""
fi
# Update only if IP has changed
if [ "$CURRENT_IP" != "$LAST_IP" ]; then
echo "[$(date)] IP changed for $RECORD_ID ($LAST_IP$CURRENT_IP). Updating..."
# Call Namecheap's API
RESPONSE=$(curl -s "https://dynamicdns.park-your-domain.com/update?host=$HOSTNAME&domain=$DOMAIN&password=$PASSWORD&ip=$CURRENT_IP")
# Check response for success
if echo "$RESPONSE" | grep -q "<ErrCount>0</ErrCount>"; then
echo "[$(date)] ✓ Successfully updated $RECORD_ID"
echo "$CURRENT_IP" > "$IP_FILE"
else
# Extract error message from response
ERROR=$(echo "$RESPONSE" | grep -o "<Err1>.*</Err1>" | sed 's/<Err1>\(.*\)<\/Err1>/\1/')
echo "[$(date)] ✗ Failed to update $RECORD_ID: $ERROR"
fi
# Optional: Log full response for debugging
# echo "API Response: $RESPONSE"
else
echo "[$(date)] IP unchanged for $RECORD_ID ($CURRENT_IP). Skipping."
fi
done
echo "[$(date)] DDNS update cycle completed."