Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Cloudflare as Dynamic DNS
#!/bin/bash
# Cloudflare as Dynamic DNS
# From: https://letswp.io/cloudflare-as-dynamic-dns-raspberry-pi/
# Based on: https://gist.github.com/benkulbertis/fff10759c2391b6618dd/
# Original non-RPi article: https://phillymesh.net/2016/02/23/setting-up-dynamic-dns-for-your-registered-domain-through-cloudflare/
# Update these with real values
auth_email="email@example.com"
auth_key="global_api_key_goes_here"
zone_name="example.com"
record_name="home.example.com"
# Don't touch these
ip=$(curl -s http://ipv4.icanhazip.com)
ip_file="ip.txt"
id_file="cloudflare.ids"
log_file="cloudflare.log"
# Keep files in the same folder when run from cron
current="$(pwd)"
cd "$(dirname "$(readlink -f "$0")")"
log() {
if [ "$1" ]; then
echo -e "[$(date)] - $1" >> $log_file
fi
}
log "Check Initiated"
if [ -f $ip_file ]; then
old_ip=$(cat $ip_file)
if [ $ip == $old_ip ]; then
log "IP has not changed."
exit 0
fi
fi
if [ -f $id_file ] && [ $(wc -l $id_file | cut -d " " -f 1) == 2 ]; then
zone_identifier=$(head -1 $id_file)
record_identifier=$(tail -1 $id_file)
else
zone_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 )
record_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?name=$record_name" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*')
echo "$zone_identifier" > $id_file
echo "$record_identifier" >> $id_file
fi
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\"}")
if [[ $update == *"\"success\":false"* ]]; then
message="API UPDATE FAILED. DUMPING RESULTS:\n$update"
log "$message"
echo -e "$message"
exit 1
else
message="IP changed to: $ip"
echo "$ip" > $ip_file
log "$message"
echo "$message"
fi
@kanetzach

This comment has been minimized.

Copy link

@kanetzach kanetzach commented Jun 25, 2019

This happens
lwp-cloudflare-dyndns.sh: 33: [: ipaddress: unexpected operator
lwp-cloudflare-dyndns.sh: 39: [: 2: unexpected operator
lwp-cloudflare-dyndns.sh: 51: lwp-cloudflare-dyndns.sh: [[: not found
IP changed to: ipaddress

I changed my real ip for ipaddress

@TheFirsh

This comment has been minimized.

Copy link
Owner Author

@TheFirsh TheFirsh commented Jul 11, 2019

We even started using this script on Ubuntu in an AWS EC2 instance and works fine. What have you tried and how were you using it to have run into that error?

@kanetzach

This comment has been minimized.

Copy link

@kanetzach kanetzach commented Jul 12, 2019

Raspbian 10 (Buster), probably it's because of that. A similar thing happened with another cloudflare ddns script but I fixed that through shellcheck.

@MohaBeacon

This comment has been minimized.

Copy link

@MohaBeacon MohaBeacon commented Jul 24, 2019

working good but can't enable proxy via ddns

@chitypo

This comment has been minimized.

Copy link

@chitypo chitypo commented Aug 25, 2019

enable proxy

update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\",\"proxied\":true}")

@tarasis

This comment has been minimized.

Copy link

@tarasis tarasis commented Sep 23, 2019

No working for me from a Raspberry Pi.

First attempts kept getting a URI error.

~/cf $ sudo ./lwp-cloudflare-dyndns.sh
API UPDATE FAILED. DUMPING RESULTS:
{"success":false,"errors":[{"code":7003,"message":"Could not route to \/zones\/dns_records, perhaps your object identifier is invalid?"},{"code":7000,"message":"No route for that URI"}],"messages":[],"result":null}

After self populating zone_identifier and record_identifier I get this error:

API UPDATE FAILED. DUMPING RESULTS:
{"success":false,"errors":[{"code":7001,"message":"Method PUT not available for that URI."}],"messages":[],"result":null}

Same result when I used a custom API token just for this script:

./lwp-cloudflare-dyndns.sh API UPDATE FAILED. DUMPING RESULTS: {"success":false,"errors":[{"code":7001,"message":"Method PUT not available for that URI."}],"messages":[],"result":null}

@TheFirsh

This comment has been minimized.

Copy link
Owner Author

@TheFirsh TheFirsh commented Oct 1, 2019

Hi, it still works fine for me. From the docs: https://api.cloudflare.com/#accounts-update-account It tells us to use PUT, and these permissions are required: #organization:edit not sure where those are set though.

@ILAsoft

This comment has been minimized.

Copy link

@ILAsoft ILAsoft commented Nov 30, 2019

This happens
lwp-cloudflare-dyndns.sh: 33: [: ipaddress: unexpected operator
lwp-cloudflare-dyndns.sh: 39: [: 2: unexpected operator
lwp-cloudflare-dyndns.sh: 51: lwp-cloudflare-dyndns.sh: [[: not found
IP changed to: ipaddress

I changed my real ip for ipaddress

This is most likely due to running as an SH vs BASH command. Try running like so: "bash lwp-cloudflare-dyndns.sh".

@strontiumss

This comment has been minimized.

Copy link

@strontiumss strontiumss commented Dec 20, 2019

Works great on RPi with buster. Thanks!

@natelandau

This comment has been minimized.

Copy link

@natelandau natelandau commented Jan 10, 2020

FWIW, getting the same error

{"success":false,"errors":[{"code":7001,"message":"Method PUT not available for that URI."}],"messages":[],"result":null}

No idea how to fix it yet. Would appreciate it if someone could point out how to do so...

@pedrof1gueiredo

This comment has been minimized.

Copy link

@pedrof1gueiredo pedrof1gueiredo commented Feb 29, 2020

Getting:
API UPDATE FAILED. DUMPING RESULTS:
{"success":false,"errors":[{"code":7003,"message":"Could not route to /zones/dns_records, perhaps your object identifier is invalid?"},{"code":7000,"message":"No route for that URI"}],"messages":[],"result":null}

Any idea? It is an account with multiple domains.

@heygambo

This comment has been minimized.

Copy link

@heygambo heygambo commented Mar 17, 2020

Managed to get it to work:
https://gist.github.com/heygambo/6a6180d62469002297b2ec63406b7d37

  • Updated it to work with Cloudflare API tokens that can be limited.
  • Fixed id parsing for the identifiers
@giovanniferretti

This comment has been minimized.

Copy link

@giovanniferretti giovanniferretti commented Aug 24, 2020

For whoever's interested in using API Tokens instead of API Keys (which makes it possible to fine-tune the access rights of a given API Token) the headers of the GET and PUT requests sent using curl can be changed as follows:

delete X-Auth-Email: and X-Auth-Key:
add Authorization: Bearer <your API Token>

Only permission necessary for the API Token is Zone.DNS in my experience

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.