Last active
July 22, 2025 07:13
-
Star
(199)
You must be signed in to star a gist -
Fork
(91)
You must be signed in to fork a gist
-
-
Save Tras2/cba88201b17d765ec065ccbedfb16d9a to your computer and use it in GitHub Desktop.
A bash script to update a Cloudflare DNS A record with the external IP of the source machine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# A bash script to update a Cloudflare DNS A record with the external IP of the source machine | |
# Used to provide DDNS service for my home | |
# Needs the DNS record pre-creating on Cloudflare | |
# 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 | |
zone=example.com | |
# dnsrecord is the A record which will be updated | |
dnsrecord=www.example.com | |
## Cloudflare authentication details | |
## keep these private | |
[email protected] | |
cloudflare_auth_key=1234567890abcdef1234567890abcdef | |
# Get the current external IP address | |
ip=$(curl -s -X GET https://checkip.amazonaws.com) | |
echo "Current IP is $ip" | |
if host $dnsrecord 1.1.1.1 | grep "has address" | grep "$ip"; then | |
echo "$dnsrecord is currently set to $ip; no changes needed" | |
exit | |
fi | |
# if here, the dns record needs updating | |
# get the zone id for the requested zone | |
zoneid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone&status=active" \ | |
-H "X-Auth-Email: $cloudflare_auth_email" \ | |
-H "X-Auth-Key: $cloudflare_auth_key" \ | |
-H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id') | |
echo "Zoneid for $zone is $zoneid" | |
# get the dns record id | |
dnsrecordid=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?type=A&name=$dnsrecord" \ | |
-H "X-Auth-Email: $cloudflare_auth_email" \ | |
-H "X-Auth-Key: $cloudflare_auth_key" \ | |
-H "Content-Type: application/json" | jq -r '{"result"}[] | .[0] | .id') | |
echo "DNSrecordid for $dnsrecord is $dnsrecordid" | |
# update the record | |
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$dnsrecordid" \ | |
-H "X-Auth-Email: $cloudflare_auth_email" \ | |
-H "X-Auth-Key: $cloudflare_auth_key" \ | |
-H "Content-Type: application/json" \ | |
--data "{\"type\":\"A\",\"name\":\"$dnsrecord\",\"content\":\"$ip\",\"ttl\":1,\"proxied\":false}" | jq |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@pilang I chose your script above the others from this gist! :-)
My fork of pilang repo contains two major new enhancements:
When
logfile
is set to a non-empty value, some basic sanity checks are done; an attempt at creating the given directory path and then the final file path is done at the top of the script. Failure results in the script halting with an error message.ipv4_command
andipv6_command
can now optionally be an array. This is for the sake of redundancy -- in case one of the given URLs is offline or such. Additionally, upon the first error seen in the array looping, the script halts with an error message.Shortly after checking out your script, I was scratching my head, wondering why the script exited without any output, nor error. Even after I had the correct user, token and so forth, it was still exiting w/o output. It turns out that I had given curl an address that it could not find the right certificate for. This is why I began improving the script with the latter feature mention (command arrays). With my improvements, it should gracefully handle this and other error conditions.
Cheers,
Jeff