Skip to content

Instantly share code, notes, and snippets.

@ripsnortntear
Created March 31, 2025 06:22
Show Gist options
  • Save ripsnortntear/bae00a0058e18ec09aaf99b175e11e6f to your computer and use it in GitHub Desktop.
Save ripsnortntear/bae00a0058e18ec09aaf99b175e11e6f to your computer and use it in GitHub Desktop.
This script retrieves the current public IP address and updates the corresponding A records in Cloudflare DNS if they differ, using the Cloudflare API and the jq tool for JSON processing.
#!/bin/bash
# Access the environment variables
api_token="CLOUDFLARE_API_TOKEN"
zone_name="FQDN"
# Function to get the current public IP address
get_public_ip() {
curl -s -X GET https://ifconfig.co
}
# Function to get the zone ID
get_zone_id() {
local response
response=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name" \
-H "Authorization: Bearer $api_token" \
-H "Content-Type: application/json")
if [[ $(echo "$response" | jq -r '.success') == "false" ]]; then
echo "Error retrieving zone ID: $(echo "$response" | jq -r '.errors')"
exit 1
fi
echo "$response" | jq -r '.result[0].id'
}
# Function to fetch all A records
get_a_records() {
local zone_id="$1"
local response
response=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records?type=A" \
-H "Authorization: Bearer $api_token" \
-H "Content-Type: application/json")
if [[ $(echo "$response" | jq -r '.success') == "false" ]]; then
echo "Error fetching A records: $(echo "$response" | jq -r '.errors')"
exit 1
fi
echo "$response" | jq -c '.result[]'
}
# Function to install jq
install_jq() {
if command -v apt &> /dev/null; then
echo "Installing jq using apt..."
sudo apt update && sudo apt install -y jq
elif command -v dnf &> /dev/null; then
echo "Installing jq using dnf..."
sudo dnf install -y jq
elif command -v yum &> /dev/null; then
echo "Installing jq using yum..."
sudo yum install -y jq
elif command -v apk &> /dev/null; then
echo "Installing jq using apk..."
sudo apk add jq
elif command -v pacman &> /dev/null; then
echo "Installing jq using pacman..."
sudo pacman -Sy --noconfirm jq
elif command -v brew &> /dev/null; then
echo "Installing jq using Homebrew..."
brew install jq
else
echo "Error: Could not detect package manager!"
return 1
fi
}
# Check for jq installation
if ! command -v jq &> /dev/null; then
echo "jq is not installed. Attempting to install..."
install_jq
# Verify installation
if ! command -v jq &> /dev/null; then
echo "Failed to install jq. Please install it manually."
exit 1
fi
echo "jq has been successfully installed."
else
echo "jq is already installed."
fi
# Main script logic
ipv4=$(get_public_ip)
if [ -z "$ipv4" ]; then
echo "Unable to retrieve public IP address."
exit 1
fi
echo "Current public IP: $ipv4"
zone_id=$(get_zone_id)
if [ -z "$zone_id" ]; then
echo "Zone ID is null. Please check the zone name and API token permissions."
exit 1
fi
# Fetch all A records
records=$(get_a_records "$zone_id")
# Loop through each record and update if necessary
while IFS= read -r record; do
name=$(echo "$record" | jq -r '.name')
record_id=$(echo "$record" | jq -r '.id')
current_ip=$(echo "$record" | jq -r '.content')
proxied=$(echo "$record" | jq -r '.proxied')
ttl=$(echo "$record" | jq -r '.ttl // 1')
if [ "$current_ip" != "$ipv4" ]; then
echo "Updating $name from $current_ip to $ipv4..."
update_response=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_i> -H "Authorization: Bearer $api_token" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$name\",\"content\":\"$ipv4\",\"ttl\":$ttl,\"proxied\":$proxied}")
if [[ $(echo "$update_response" | jq -r '.success') == "true" ]]; then
echo "✓ Successfully updated $name ($current_ip -> $ipv4)"
else
echo "✗ Failed to update $name: $(echo "$update_response" | jq -r '.errors')"
fi
else
echo "✓ $name is up to date ($current_ip)"
fi
done <<< "$records"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment