Cloudflare DDNS Script

Categories: DNS Cloudflare

I had an issue with the public IP changing a few times a day. The firewall I’m using has some builtin DDNS services, but Cloudflare isn’t one of them. So I decided to create my own. The script uses Amazons checkip service to get the current public ip and if it doesn’t match with the dns record then the record will be updated.

I use cron to run the script every hour and log the output

0 * * * * sh /path/to/ >> /var/log/cloudflare-ddns-update.log

The script can be downloaded here: or you can see the content below


# Update a Cloudflare DNS A record with the Public IP of the source machine

# Prerequisites:
# - DNS Record has to be created manually at Cloudflare
# - Cloudflare API Token with edit dns zone permissions
# - curl, jq needs to be installed

# Proxy - uncomment and provide details if using a proxy
#export https_proxy=http://<proxyuser>:<proxypassword>@<proxyip>:<proxyport>

# Cloudflare zone is the zone which holds the record
# dnsrecord is the A record which will be updated

## Cloudflare authentication details
## keep these private

function update_ip() {
  # get the zone id for the requested zone
  zoneid=$(curl -s -X GET "$zone&status=active" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $cloudflare_api_token" | jq -r '{"result"}[] | .[0] | .id')

  echo "Zoneid for $zone is $zoneid"

  # get the dns record id
  dnsrecordid=$(curl -s -X GET "$zoneid/dns_records?type=A&name=$dnsrecord" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $cloudflare_api_token" | jq -r '{"result"}[] | .[0] | .id')

  echo "DNSrecordid for $dnsrecord is $dnsrecordid"

  # update the record
  curl -s -X PUT "$zoneid/dns_records/$dnsrecordid" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $cloudflare_api_token" \
    --data "{\"type\":\"A\",\"name\":\"$dnsrecord\",\"content\":\"$ip\",\"ttl\":1,\"proxied\":false}" | jq

function get_ip() {
  # Get the public IP address
  ip=$(curl -s -X GET
  dnsip=$(dig $dnsrecord +short @

  echo "Public IP is $ip"

  if [[ "$dnsip" == "$ip" ]]; then
    echo "$dnsrecord is currently set to $ip; no changes needed"


echo ""
echo "-- $(date '+%d/%m/%Y %H:%M:%S') --"
# Run function get_ip