Your own Dynamic DNS (DDNS) with Raspberry Pi and Cloudflare

There are a lot of these types of tutorials out there, and most (well, some) of them work well. However, they end up leaving out just one or two things ('er, commands) to get things going. So, this may, or may not be for you. At the very least, I'll have it written down as a reminder to myself. (Credit for original post this is based on goes to David Flood.)

For this, we're using Cloudflare.

Cloudflare, in a nutshell,

"...provides content delivery network services, DDoS mitigation, Internet security and distributed domain name server services, sitting between the visitor and the Cloudflare user's hosting provider, acting as a reverse proxy for websites."

It's an excellent service, and even the free tier gives you a considerable amount of security for even the littlest sites out there.

I'm also using a Raspberry Pi running Ubuntu Server 18.04. Assuming you have an understanding of how to point Cloudflare to the machine you're trying to update with their service dynamically, we'll get right into it.

We're going to get a script from github shared by Ben Kulbertis that uses Clousflare's v4 API: Here's the current script as of this post:

#!/bin/bash # CHANGE THESE auth_email="[email protected]" auth_key="c2547eb745079dac9320b638f5e225cf483cc5cfdda41" # found in cloudflare account settings zone_name="" record_name="" # MAYBE CHANGE THESE ip=$(curl -s ip_file="ip.txt" id_file="cloudflare.ids" log_file="cloudflare.log" # LOGGER log() { if [ "$1" ]; then echo -e "[$(date)] - $1" >> $log_file fi } # SCRIPT START log "Check Initiated" if [ -f $ip_file ]; then old_ip=$(cat $ip_file) if [ $ip == $old_ip ]; then echo "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 "$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 "$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 "$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

We're going to take the above code and place it into a script. Copy the above and open terminal into the machine which will do the updating:

sudo nano /usr/local/bin/

The highlighted area above is the only part of the code that you need to change. The auth_email is the email you use with Cloudflare. The auth_key is the API key found on your Cloudflare profile page. Use the Global API key. The zone_name is your website address, and record_name is your website with the www at the front end. Let's save this and move on.

That's all you need to change. Once that's done we can run the script to see if it works. First, make the script executable:

sudo chmod +x /usr/local/bin/

Change to the directory via:

cd /usr/local/bin/

And run the code via:


Now, you may get an error code saying something about lack of permissions for cloudflare.ids, cloudflare.log, or ip.txt. If so, head to your home folder and see if these files exist. If so, you probably don't have permissions, let's fix this too. If they're the only thing in the folder then this is a one-step process:

sudo chmod +x *

This will make all the files here executable. To ensure what you did works you can do the above steps again, if no error, then we're in business.

Now, let's automate this to update Cloudflare in the event your IP changes. We'll do this via crontab. Open terminal again;

crontab -e

Once it's open place the following:

*/2 * * * * /usr/local/bin/ >/dev/null 2>&1

This will run our script every two minutes which should suffice for our little site's needs.

If you have any questions, please let me know.

Show Comments

Get the latest posts delivered right to your inbox.