This is a bash script to act as a Cloudflare DDNS client, useful replacement for ddclient.
This gist will no longer update, instead please go to https://github.com/lifehome/systemd-cfddns for more updated versions.
- Put the
cfupdater
files to/usr/local/bin
- If you are using IPv4 for A record, append
-v4
tocfupdater
in the following systemd service unit. - If you are using IPv6 for AAAA record, append
-v6
tocfupdater
in the following systemd service unit. - If you prefer a dual-stack record, append
-dualstack
tocfupdater
in the following systemd service unit.
chmod +x /usr/local/bin/cfupdater
- Create a systemd service unit at
/etc/systemd/system/
, thecfupdate.service
is shown as an example. - Create a systemd timer unit at the same location of the service unit, the
cfupdate.timer
is shown as an example. sudo systemctl enable cfupdate.timer
sudo systemctl start cfupdate.timer
The default cfupdate.timer
is set to execute the script every minute.
Please keep in mind not to spam the API or you will be rate limited.
The dual-stack script has NOT been tested, use with caution. The dual-stack script will always sync upon either IPv4 or IPv6 has changed.
A quote from Cloudflare FAQ:
All calls through the Cloudflare Client API are rate-limited to 1200 every 5 minutes.
-- https://support.cloudflare.com/hc/en-us/articles/200171456
Great work on this, thank you. I had to make a few minor edits to the cfupdater-dualstack file to make it work. I only tested it standalone (.sh), no systemd. Prior to the changes below, I was getting a bash error for line 33, and a "7001" error from Cloudflare, "Method PUT not available for that URI."
Line 12 should read
ip6=$(curl -s https://ipv6.icanhazip.com/)
instead ofip6=$(curl -s https://ipv46.icanhazip.com/)
Line 33 should read
if [[ $ip4 == $old_ip4 && $ip6 == $old_ip6 ]]; then
instead ofif [ $ip4 == $old_ip4 && $ip6 == $old_ip6 ]; then
Line 43 should read
update4=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record4_identifier" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"proxied\":false,\"name\":\"$record_name\",\"content\":\"$ip4\"}")
instead of
update4=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier4" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"proxied\":false,\"name\":\"$record_name\",\"content\":\"$ip4\"}")
Line 44 should read
update6=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record6_identifier" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"AAAA\",\"proxied\":false,\"name\":\"$record_name\",\"content\":\"$ip6\"}")
instead of
update6=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier6" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"AAAA\",\"proxied\":false,\"name\":\"$record_name\",\"content\":\"$ip6\"}")