-
-
Save benkulbertis/fff10759c2391b6618dd to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# CHANGE THESE | |
auth_email="user@example.com" | |
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 |
I updated API_TOKEN version like this :
#!/bin/bash
# Created by benkulbertis/cloudflare-update-record.sh
# CHANGE THESE
api_token="c2547eb745079dac9320b638f5e225cf483cc5cfdda41" # found in cloudflare account my profile - API Tokens - (Permission Zone.Zone, Zone.DNS)
zone_name="example.com"
record_name="www.example.com"
proxied="true"
# 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 ! [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
message="Fetched IP does not look valid! Quitting"
log "$message"
echo -e "$message"
exit 1
fi
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 "Authorization: Bearer $api_token" -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 "Authorization: Bearer $api_token" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*')
echo "$zone_identifier" > $id_file
echo "$record_identifier" >> $id_file
fi
echo "zone : $zone_identifier"
echo "record : $record_identifier"
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" -H "Authorization: Bearer $api_token" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"proxied\":\"$proxied\",\"name\":\"$record_name\",\"content\":\"$ip\"}")
case "$update" in
*"\"success\":false"*)
message="API UPDATE FAILED. DUMPING RESULTS:\n$update"
log "$message"
echo -e "$message"
exit 1;;
*)
message="IP changed to: $ip"
echo "$ip" > $ip_file
log "$message"
echo "$message";;
esac
I had to change the "update" line to remove the quotes around "$proxied". Cloudflare expects that json value to be a boolean:
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" -H "Authorization: Bearer $api_token" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"A\",\"proxied\":$proxied,\"name\":\"$record_name\",\"content\":\"$ip\"}")
I am getting the following result when I run the script:
{"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}
I am attempting to update and A record of a subdomain on an account with multiple domains. Is anyone else getting this error?
I have the same issue, also in an account with multiple domains. No solution on this thread worked so far.
Thank you for the script saved me lots of time. Tweaked to add DNS Record instead of updating. I did not add a check to see if the record already exist.
...
if [ -f
zone_identifier=$(head -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 )
echo "$zone_identifier" > $id_file
fi
addDns=$(curl -X POST "https://api.cloudflare.com/client/v4/zones/${zone_identifier}/dns_records" -H "X-Auth-Email: ${auth_email}" -H "X-Auth-Key: ${auth_key}" -H "Content-Type: application/json" --data '{"type":"A","name":"'${record_name}'","content":"'${ip}'","ttl":120,"priority":10,"proxied":true}')
if [[ $addDns == ""success":false" ]]; then
message="API UPDATE FAILED. DUMPING RESULTS:\n$addDns"
log "$message"
echo -e "$message"
exit 1
else
message="IP changed to: $ip"
echo "$ip" > $ip_file
log "$message"
echo "$message"
fi
just a heads up everyone, apparently Cloudflare made a few changes to their API and I found out the hards way today (bit of a downtime). All you need to do is to add a space character (
) in every regex when parsing a field.
specifically:
if [[ $record == *"\"count\":0"* ]]; then
needs to become
if [[ $record == *"\"count\": 0"* ]]; then
old_ip=$(echo "$record" | grep -Po '(?<="content":")[^"]*' | head -1)
to
old_ip=$(echo "$record" | grep -Po '(?<="content": ")[^"]*' | head -1)
*"\"success\":false"*)
has to become
*"\"success\": false"*)
Thanks @mrwhizzy
I also update my sed sample here.
HillLiu/cloudflare-bash-util@304d58e
just a heads up everyone, apparently Cloudflare made a few changes to their API and I found out the hards way today (bit of a downtime). All you need to do is to add a space character (
) in every regex when parsing a field.
specifically:
if [[ $record == *"\"count\":0"* ]]; then
needs to become
if [[ $record == *"\"count\": 0"* ]]; then
old_ip=$(echo "$record" | grep -Po '(?<="content":")[^"]*' | head -1)
to
old_ip=$(echo "$record" | grep -Po '(?<="content": ")[^"]*' | head -1)
*"\"success\":false"*)
has to become
*"\"success\": false"*)
just a heads up everyone, apparently Cloudflare made a few changes to their API and I found out the hards way today (bit of a downtime). All you need to do is to add a space character (
) in every regex when parsing a field.
specifically:
if [[ $record == *"\"count\":0"* ]]; then
needs to become
if [[ $record == *"\"count\": 0"* ]]; then
old_ip=$(echo "$record" | grep -Po '(?<="content":")[^"]*' | head -1)
to
old_ip=$(echo "$record" | grep -Po '(?<="content": ")[^"]*' | head -1)
*"\"success\":false"*)
has to become
*"\"success\": false"*)
Updated my scripts but still doesn't seem to work.
Anyone got it working again?
grep -Po '(?<="id":")[^"]*')
change to
grep -Po '(?<="id": ")[^"]*')
Why Cloudflare why do you do these things.
Thanks for the update
tx guys for the update, was wondering what was going on !
Did they change something again? Scripts no longer seem to work..
@niklasmato, yes they did, I've uploaded an up-to-date version of the script on GitHub which will work a bit more reliably no matter if they have spaces after semicolons or not, plus it will also update multiple records.
@niklasmato, yes they did, I've uploaded an up-to-date version of the script on GitHub which will work a bit more reliably no matter if they have spaces after semicolons or not, plus it will also update multiple records.
Thank you for this!
#!/bin/sh
#modify by: John Chen
# CHANGE THESE
zone_identifier="your_zone_id"
record_identifier="Your_record_iid"
auth_key="Your_auth_keys" # 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
else if [$ip == ""]; then
echo "Timeout! "
fi
fi
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" -H "Authorization: Bearer $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
change -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key"
to -H "Authorization: Bearer $auth_key"
and
change use sed to instead of grep to parse json data
like
sed -E "s/.+\{\"id\":\"([a-f0-9]+)\".+\"type\":\"A\".+/\1/g"
and
if [ -f $id_file ] && [ -n $(sed -n '1p' $id_file) ] && [ -n $(sed -n '2p' $id_file) ]; then
and
success=$( echo $update | sed -E "s/.+\"success\":[ ]*([a-z]+).+/\1/g")
if [[ $success == "false" ]]; then
message="API UPDATE FAILED. DUMPING RESULTS:\n$update"
log "$message"
echo -e "$message"
exit 1
else
check here
Hi all,
Previously I have posted a bash/systemd version fork of this script in another gist, I have moved and updated the script to an actual repository, please kindly visit it instead at: https://github.com/lifehome/systemd-cfddns
Regards,
Ivan
Thank you worked! perfectly. Make sure run under bash.