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: cloudflare-update-record.sh. 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=”example.com”
record_name=”www.example.com”

# MAYBE CHANGE THESE
ip=$(curl -s http://ipv4.icanhazip.com)
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 “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

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/cur.sh

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/cur.sh

Change to the directory via:

cd /usr/local/bin/

And run the code via:

./cur.sh

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/cur.sh >/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.

Categories: Raspberry Pi

2 Comments

Gerald Brown · September 4, 2018 at 21:51

I keep getting “permission denied for the following files:” cloudflare.log and ip.txt. Where should these files be located?

I am also getting the following errors: command substitution: line 38: syntax error near unexpected token `(‘ , command substitution: line 38: `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 )' and line 47: changed: command not found.

    ryan · September 4, 2018 at 21:58

    Hi Gerald, thanks for writing. The cloudflare.log file, and three others, should be located in your home folder (/home/user/).

    You’ll want to make them executable via ‘sudo chmod +x filename’

    As for the api error, did you ONLY edit those top four lines?

Leave a Reply

Your email address will not be published. Required fields are marked *