Compare commits

...

4 Commits
1.1 ... main

4 changed files with 193 additions and 69 deletions

View File

@ -1,66 +1,167 @@
#!/bin/bash #!/bin/bash
# Exit if any command fails set -euo pipefail
set -e
# Directory containing all .env config files # --- Configuration ---
ENV_DIR="./zones" : "${ENV_DIR:="./zones"}"
: "${LOG_DIR:="./logs"}"
DATE=$(date +%F)
LOG_FILE="$LOG_DIR/update_${DATE}.log"
# Fetch current IP from Mullvad # --- Ensure log directory exists ---
echo "[*] Fetching IP info from Mullvad..." mkdir -p "$LOG_DIR"
IP_INFO=$(curl -s https://ipv4.am.i.mullvad.net/json)
IP=$(echo "$IP_INFO" | jq -r '.ip')
if [[ -z "$IP" ]]; then # --- Logging function ---
echo "[!] Failed to extract IP address." log() {
local message="$1"
echo "$message" | tee -a "$LOG_FILE"
}
# --- Check required tools ---
for cmd in curl jq; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "[!] Required tool '$cmd' not found. Please install it." >&2
exit 1
fi
done
# --- Fetch current IP from Mullvad ---
log "[*] Fetching IP from Mullvad..."
IP_INFO=$(curl -sf https://ipv4.am.i.mullvad.net/json) || {
log "[!] Failed to fetch IP from Mullvad"
exit 1
}
if ! echo "$IP_INFO" | jq -e '.ip' >/dev/null; then
log "[!] Invalid Mullvad response or missing IP."
log "$IP_INFO"
exit 1 exit 1
fi fi
echo "[*] Current public IP is: $IP" CURRENT_IP=$(echo "$IP_INFO" | jq -r '.ip')
echo log "[*] Current public IP is: $CURRENT_IP"
log ""
# --- Get list of .env files ---
shopt -s nullglob
ENV_FILES=("$ENV_DIR"/*.env)
if [[ ${#ENV_FILES[@]} -eq 0 ]]; then
log "[!] No .env files found in $ENV_DIR"
exit 0
fi
# --- Process each env file ---
for ENV_FILE in "${ENV_FILES[@]}"; do
log "[*] Processing config: $ENV_FILE"
# Loop through all .env files in ENV_DIR
for ENV_FILE in "$ENV_DIR"/*.env; do
echo "[*] Processing config: $ENV_FILE"
# Load environment variables # Load environment variables
set -a set -a
source "$ENV_FILE" source "$ENV_FILE"
set +a set +a
# Check required variables # Validate required vars
if [[ -z "$ZONE_ID" || -z "$DNS_RECORD_ID" || -z "$CLOUDFLARE_EMAIL" || -z "$CLOUDFLARE_API_KEY" || -z "$DNS_NAME" ]]; then missing_vars=()
echo "[!] Missing required variables in $ENV_FILE" [[ -z "${ZONE_ID:-}" ]] && missing_vars+=("ZONE_ID")
[[ -z "${DNS_NAME:-}" ]] && missing_vars+=("DNS_NAME")
[[ -z "${CLOUDFLARE_API_KEY:-}" ]] && missing_vars+=("CLOUDFLARE_API_KEY")
if (( ${#missing_vars[@]} )); then
log "[!] Missing variables in $ENV_FILE: ${missing_vars[*]}"
log ""
continue continue
fi fi
# Make the API request # --- Check if DNS record exists ---
echo "[*] Updating Cloudflare record for $DNS_NAME..." log "[*] Checking DNS record for $DNS_NAME..."
UPDATE_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \ DNS_LOOKUP=$(curl -sf -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?type=A&name=$DNS_NAME" \
-H "Content-Type: application/json" \ -H "Authorization: Bearer $CLOUDFLARE_API_KEY" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ -H "Content-Type: application/json")
-H "X-Auth-Key: $CLOUDFLARE_API_KEY" \ CURL_EXIT_CODE=$?
-d '{
"name": "'$DNS_NAME'",
"ttl": 3600,
"type": "A",
"comment": "Domain verification record",
"content": "'$IP'",
"proxied": true
}')
if [[ $CURL_EXIT_CODE -ne 0 ]]; then
SUCCESS=$(echo "$UPDATE_RESPONSE" | jq -r '.success') log "[!] Failed to query DNS record for $DNS_NAME (curl exit code $CURL_EXIT_CODE)"
log "$DNS_LOOKUP"
if [[ "$SUCCESS" == "true" ]]; then log ""
echo "[+] $DNS_NAME updated successfully!" continue
else
echo "[!] Failed to update $DNS_NAME."
echo "Cloudflare response:"
echo "$UPDATE_RESPONSE"
fi fi
echo RECORD_ID=$(echo "$DNS_LOOKUP" | jq -r '.result[0].id // empty')
EXISTING_IP=$(echo "$DNS_LOOKUP" | jq -r '.result[0].content // empty')
if [[ -z "$RECORD_ID" ]]; then
log "[!] No existing record found. Creating new A record for $DNS_NAME..."
CREATE_RESPONSE=$(curl -sf -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $CLOUDFLARE_API_KEY" \
-d "{
\"name\": \"$DNS_NAME\",
\"ttl\": 3600,
\"type\": \"A\",
\"comment\": \"Domain verification record\",
\"content\": \"$CURRENT_IP\",
\"proxied\": true
}")
CURL_EXIT_CODE=$?
if [[ $CURL_EXIT_CODE -ne 0 ]]; then
log "[!] curl failed creating DNS record (exit code $CURL_EXIT_CODE)"
log "$CREATE_RESPONSE"
log ""
continue
fi
if [[ $(echo "$CREATE_RESPONSE" | jq -r '.success') == "true" ]]; then
log "[+] Successfully created DNS record for $DNS_NAME$CURRENT_IP"
else
log "[!] Failed to create DNS record for $DNS_NAME"
echo "$CREATE_RESPONSE" | tee -a "$LOG_FILE"
fi
log ""
continue
fi
# --- If record exists, check if update is needed ---
if [[ "$EXISTING_IP" == "$CURRENT_IP" ]]; then
log "[=] No update needed. $DNS_NAME already points to $CURRENT_IP"
log ""
continue
fi
# --- Patch the existing record ---
log "[*] IP has changed: $EXISTING_IP$CURRENT_IP"
log "[*] Updating existing DNS record via PATCH..."
UPDATE_RESPONSE=$(curl -sf -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $CLOUDFLARE_API_KEY" \
-d "{
\"name\": \"$DNS_NAME\",
\"ttl\": 3600,
\"type\": \"A\",
\"comment\": \"Domain verification record\",
\"content\": \"$CURRENT_IP\",
\"proxied\": true
}")
CURL_EXIT_CODE=$?
if [[ $CURL_EXIT_CODE -ne 0 ]]; then
log "[!] curl failed updating DNS record (exit code $CURL_EXIT_CODE)"
log "$UPDATE_RESPONSE"
log ""
continue
fi
if [[ $(echo "$UPDATE_RESPONSE" | jq -r '.success') == "true" ]]; then
log "[+] Successfully updated $DNS_NAME to $CURRENT_IP"
else
log "[!] Failed to update $DNS_NAME"
echo "$UPDATE_RESPONSE" | tee -a "$LOG_FILE"
fi
log ""
done done

View File

@ -1,5 +1,4 @@
ZONE_ID="abc123zoneid" ZONE_ID="abc123zoneid"
DNS_RECORD_ID="def456recordid"
CLOUDFLARE_EMAIL="you@example.com"
CLOUDFLARE_API_KEY="your_api_key_here"
DNS_NAME="subdomain.example.com" DNS_NAME="subdomain.example.com"
CLOUDFLARE_API_KEY="your_api_key_here"

View File

@ -1,2 +1,3 @@
# Cloudflare API Token (must have Zone:Read + DNS:Read permissions) # Cloudflare API Token (must have Zone:Read + DNS:Read permissions)
# Example env file (envs/site1.env)
CLOUDFLARE_API_TOKEN=your_api_token_here CLOUDFLARE_API_TOKEN=your_api_token_here

View File

@ -1,38 +1,61 @@
#!/bin/bash #!/bin/bash
set -euo pipefail set -euo pipefail
# Load config ENV_DIR="./envs"
source config.conf
EXPORT_FOLDER="export" EXPORT_FOLDER="export"
mkdir -p "$EXPORT_FOLDER" mkdir -p "$EXPORT_FOLDER"
# Step 1: Fetch all zones from Cloudflare # Find all .env files in the ENV_DIR
echo "Fetching zone list from Cloudflare..." env_files=("$ENV_DIR"/*.env)
zones_json=$(curl -s https://api.cloudflare.com/client/v4/zones \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json")
# Step 2: Parse zones (needs jq) if [ ${#env_files[@]} -eq 0 ]; then
zone_count=$(echo "$zones_json" | jq '.result | length') echo "❌ No .env files found in $ENV_DIR"
echo "Found $zone_count zones." exit 1
fi
# Step 3: Loop through zones for env_file in "${env_files[@]}"; do
for ((i=0; i<zone_count; i++)); do echo "🔄 Processing environment file: $env_file"
ZONE_ID=$(echo "$zones_json" | jq -r ".result[$i].id")
SITE_NAME=$(echo "$zones_json" | jq -r ".result[$i].name") # Load environment variables from .env file
set -o allexport
source "$env_file"
set +o allexport
TIMESTAMP=$(date +"%Y%m%d_%H%M%S") if [[ -z "${CLOUDFLARE_API_TOKEN:-}" ]]; then
OUTPUT_FILE="$EXPORT_FOLDER/${SITE_NAME}_$TIMESTAMP.txt" echo "⚠️ CLOUDFLARE_API_TOKEN not set in $env_file. Skipping."
continue
fi
echo "Exporting DNS records for $SITE_NAME..." # Step 1: Fetch all zones from Cloudflare
echo "Fetching zone list from Cloudflare..."
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/export" \ zones_json=$(curl -s https://api.cloudflare.com/client/v4/zones \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | tee "$OUTPUT_FILE" -H "Content-Type: application/json")
echo " -> Saved to $OUTPUT_FILE" # Step 2: Parse zones (needs jq)
zone_count=$(echo "$zones_json" | jq '.result | length')
echo "Found $zone_count zones."
# Step 3: Loop through zones
for ((i=0; i<zone_count; i++)); do
ZONE_ID=$(echo "$zones_json" | jq -r ".result[$i].id")
SITE_NAME=$(echo "$zones_json" | jq -r ".result[$i].name")
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
OUTPUT_FILE="$EXPORT_FOLDER/${SITE_NAME}_$TIMESTAMP.txt"
echo "Exporting DNS records for $SITE_NAME..."
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/export" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | tee "$OUTPUT_FILE"
echo " -> Saved to $OUTPUT_FILE"
done
echo "✅ Export complete for $env_file"
echo ""
done done
echo "✅ All exports complete. Files are in the '$EXPORT_FOLDER' folder." echo "🎉 All exports finished. Files are in the '$EXPORT_FOLDER' folder."