API_TOKEN="${API_TOKEN:-ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcd}" ZONE="${ZONE:-example.com}" DOMAIN="${DOMAIN:-example.com}" EVENT() { printf "\x1b[95m>>> \x1b[0m\x1b[98m$1\n" } LOG() { printf "\x1b[98m$1\n" } ERROR() { >&2 printf "\x1b[91mError: \x1b[0m\x1b[98m$1\n" } CURL() { RESPONSE=$(curl --silent --request $1 \ --url "https://api.cloudflare.com/client/v4$2" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $API_TOKEN" \ --data "$3") SUCCESS=$(echo $RESPONSE | jq -r ".success") if [ "$SUCCESS" != "true" ]; then ERROR "$(echo $RESPONSE | jq -r ".errors[0].message")" kill $$ fi echo $RESPONSE | jq ".result" } PATCH() { CURL "PATCH" "$1" "$2" } POST() { CURL "POST" "$1" "$2" } GET() { CURL "GET" "$1" "" } EVENT "Getting Zones" ZONES=$(GET "/zones") ZONE_ID="null" i=0 while true; do ZONE_JSON=$(echo $ZONES | jq ".[$i]") if [ "$ZONE_JSON" == "null" ]; then break fi NAME=$(echo $ZONE_JSON | jq -r ".name") ID=$(echo $ZONE_JSON | jq -r ".id") LOG "Found Zone $NAME ($ID)" if [ "$NAME" == "$ZONE" ]; then ZONE_ID=$ID break fi ((i=i+1)) done if [ "$ZONE_ID" == "null" ]; then ERROR "Could not find zone $DOMAIN" exit 1 fi EVENT "Getting Records" RECORDS=$(GET "/zones/$ZONE_ID/dns_records") IPv4Current="null" IPv6Current="null" IPv4Id="null" IPv6Id="null" i=0 while true; do RECORD=$(echo $RECORDS | jq ".[$i]") if [ "$RECORD" == "null" ]; then break fi NAME=$(echo $RECORD | jq -r '.name') TYPE=$(echo $RECORD | jq -r '.type') CONTENT=$(echo $RECORD | jq -r '.content') ID=$(echo $RECORD | jq -r '.id') LOG "Found record $NAME $TYPE \"$CONTENT\" ($ID)" if [ "$NAME" == "$DOMAIN" ] && [ "$TYPE" == "A" ]; then IPv4Current="$CONTENT" IPv4Id="$ID" fi if [ "$NAME" == "$DOMAIN" ] && [ "$TYPE" == "AAAA" ]; then IPv6Current="$CONTENT" IPv6Id="$ID" fi ((i=i+1)) done EVENT "Getting current IPs" IPv4New=$(curl ip.me -4sL --silent) LOG "Using IPv4 $IPv4New" IPv6New=$(curl ip.me -6sL --silent) LOG "Using IPv6 $IPv6New" UPDATE() { PATCH "/zones/$ZONE_ID/dns_records/$1" "$2" > /dev/null } CREATE() { POST "/zones/$ZONE_ID/dns_records" "$1" > /dev/null } IPv4JSON="{ \"content\": \"$IPv4New\", \"name\": \"$DOMAIN\", \"proxied\": false, \"type\": \"A\" }" IPv6JSON="{ \"content\": \"$IPv6New\", \"name\": \"$DOMAIN\", \"proxied\": false, \"type\": \"AAAA\" }" EVENT "Updating Records" if [ "$IPv4Id" == "null" ]; then LOG "No IPv4 record found... creating new one" CREATE "$IPv4JSON" elif [ "$IPv4Current" != "$IPv4New" ]; then LOG "IPv4 record found... updating" UPDATE "$IPv4Id" "$IPv4JSON" else LOG "IPv4 is up to date... skipping" fi if [ "$IPv6Id" == "null" ]; then LOG "No IPv6 record found... creating new one" CREATE "$IPv6JSON" elif [ "$IPv6Current" != "$IPv6New" ]; then LOG "IPv6 record found... updating" UPDATE "$IPv6Id" "$IPv6JSON" else LOG "IPv6 is up to date... skipping" fi EVENT "Successfully updated records"