Skip to content

Instantly share code, notes, and snippets.

@mougua
Created July 10, 2025 16:07
Show Gist options
  • Save mougua/469ecf59bedc88c5dcc2c1d7cf7a4e1e to your computer and use it in GitHub Desktop.
Save mougua/469ecf59bedc88c5dcc2c1d7cf7a4e1e to your computer and use it in GitHub Desktop.
Cloudflare DDNS Script
#!/bin/bash
# --- Configuration Variables (Please modify these) ---
auth_token="YOUR_API_TOKEN" # Your Cloudflare API Token
zone_identifier="YOUR_ZONE_ID" # Your Cloudflare Zone ID
record_name="your_record_name.example.com" # The full DNS record name you want to update (e.g., ddns.example.com)
# --- Script Core Logic ---
echo "Checking for IP update..."
# Get current public IPv4 address
current_ip=$(curl -s4 https://icanhazip.com/)
if [[ -z "$current_ip" ]]; then
echo "Error: Could not retrieve external IP address." >&2
exit 1
fi
echo "Current external IP: $current_ip"
# Set authorization header for API requests
auth_header=(-H "Authorization: Bearer $auth_token")
# Get existing DNS record
record_info=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?name=$record_name&type=A" \
"${auth_header[@]}" -H "Content-Type: application/json")
# Check if the record exists
if [[ -z "$record_info" ]] || [[ "$record_info" == *'"count":0'* ]]; then
echo "DNS record does not exist, creating a new record..."
# Create a new DNS record
create_response=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records" \
"${auth_header[@]}" -H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$current_ip\",\"ttl\":120,\"proxied\":false}") # Example: TTL 120s, not proxied
# You might want to add error checking for create_response here
if echo "$create_response" | jq -e '.success' > /dev/null; then
echo "Successfully created DNS record."
else
echo "Failed to create DNS record. Response: $create_response" >&2
exit 1
fi
else
# Extract old IP and record ID from existing record
old_ip=$(echo "$record_info" | jq -r '.result[0].content')
record_id=$(echo "$record_info" | jq -r '.result[0].id')
echo "Existing DNS record IP: $old_ip"
# Compare IPs
if [ "$current_ip" == "$old_ip" ]; then
echo "IP address has not changed, no update needed."
else
echo "IP address has changed, updating DNS record..."
# Update the DNS record
update_response=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_id" \
"${auth_header[@]}" -H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$current_ip\",\"ttl\":120,\"proxied\":false}") # Example: TTL 120s, not proxied
# You might want to add error checking for update_response here
if echo "$update_response" | jq -e '.success' > /dev/null; then
echo "Successfully updated DNS record."
else
echo "Failed to update DNS record. Response: $update_response" >&2
exit 1
fi
fi
fi
echo "DDNS update script finished."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment