Skip to content

Instantly share code, notes, and snippets.

@m-wild
Last active June 5, 2026 13:43
Show Gist options
  • Select an option

  • Save m-wild/f1d2579f3c922e8bb4a0 to your computer and use it in GitHub Desktop.

Select an option

Save m-wild/f1d2579f3c922e8bb4a0 to your computer and use it in GitHub Desktop.
CloudFlare dynamic dns updater module for Synology
#!/bin/sh
# cloudflareddns.sh - dynamic dns updater module for Synology
#
# Author:
# Michael Wildman (http://mwild.me)
#
# Version:
# 0.2
#
# Description:
# copy to /sbin/cloudflaredns.sh
# make executable (chmod +x)
# add the following entry to /etc.defaults/ddns_provider.conf
#
# [CloudFlare]
# modulepath=/sbin/cloudflaredns.sh
# queryurl=https://www.cloudflare.com/api_json.html?a=rec_edit&tkn=__PASSWORD__&email=__USERNAME__&z=__HOSTNAME__&content=__MYIP__
#
# (note that URL is not actually used, DSM will pass us the variables)
# run a rec_load_all query to get the record id
# (see https://www.cloudflare.com/docs/client-api.html)
#
# Changelog:
# 0.2:
# - Simplified this thing to its most basic requirements (curl + logging)
# - Now either returns 'good' or the result (no checking for cases -- the log was always more useful anyway!)
#
# Based on Brian Schmidt Pedersen (http://blog.briped.net) gratisdns.sh
# TODO
# read addition parameters from cloudflare api calls
#
# these variables are passed by DSM
# username is your email
__USERNAME__="$(echo ${@} | cut -d' ' -f1)"
# password is your cloudflare API key
__PASSWORD__="$(echo ${@} | cut -d' ' -f2)"
__HOSTNAME__="$(echo ${@} | cut -d' ' -f3)"
__MYIP__="$(echo ${@} | cut -d' ' -f4)"
# log location
__LOGFILE__="/var/log/cloudflareddns.log"
# additional parameters needed for CloudFlare
__RECTYPE__="A"
__RECID__=""
__RECNAME__=""
__TTL__="1"
__SERVICEMODE__="0"
log() {
__LOGTIME__=$(date +"%b %e %T")
if [ "${#}" -lt 1 ]; then
false
else
__LOGMSG__="${1}"
fi
if [ "${#}" -lt 2 ]; then
__LOGPRIO__=7
else
__LOGPRIO__=${2}
fi
logger -p ${__LOGPRIO__} -t "$(basename ${0})" "${__LOGMSG__}"
echo "${__LOGTIME__} $(basename ${0}) (${__LOGPRIO__}): ${__LOGMSG__}" >> ${__LOGFILE__}
}
__URL__="https://www.cloudflare.com/api_json.html?a=rec_edit&tkn=${__PASSWORD__}&email=${__USERNAME__}&z=${__HOSTNAME__}&type=${__RECTYPE__}&id=${__RECID__}&name=${__RECNAME__}&content=${__MYIP__}&ttl=${__TTL__}&service_mode=${__SERVICEMODE__}"
# Update DNS record:
log "Updating with ${__MYIP__}..." 7
__RESPONSE__=$(curl --silent "${__URL__}")
# Strip the result element from response json
__RESULT__=$(echo ${__RESPONSE__} | grep -o -E .result.:.[A-z]+.)
case ${__RESULT__} in
'"result":"success"')
__STATUS__='good'
true
;;
*)
__STATUS__="${__RESULT__}"
log "__RESPONSE__=${__RESPONSE__}" 5
false
;;
esac
log "Status: ${__STATUS__}" 6
printf "%s" "${__STATUS__}"
@indigetal

Copy link
Copy Markdown

Can someone make a youtube video demonstrating how to install this on a synology diskstation? I've never done anything like this before (or maybe I have and don't know it)...

@htchaan

htchaan commented Nov 4, 2015

Copy link
Copy Markdown

@indigital see if my steps help

1 - Visit your Synology DiskStation's web
2 - Go to Control Panel / Advanced Mode / Terminal & SNMP / Enable Telnet service
3 - Connect to the DS with ssh -t admin@192.168.*.* 'telnet localhost'
4 - Enter root and admin's password to continue
5 - Paste:

wget https://gist.github.com/tehmantra/f1d2579f3c922e8bb4a0/raw/706f8db7d8506e62b17a5568951544e5c5ee0644/cloudflaredns.sh -O /sbin/cloudflaredns.sh
chmod +x /sbin/cloudflaredns.sh
cat >> /etc.defaults/ddns_provider.conf << 'EOF'
[CloudFlare]
        modulepath=/sbin/cloudflaredns.sh
        queryurl=https://www.cloudflare.com/api_json.html?a=rec_edit&tkn=__PASSWORD__&email=__USERNAME__&z=__HOSTNAME__&content=__MYIP__
EOF

6 - Visit CloudFlare account settings page and copy your API key
7 - Open up a local terminal and enter:

curl https://www.cloudflare.com/api_json.html \
  -d 'a=rec_load_all' \
  -d 'tkn=YOUR_API_KEY_HERE' \
  -d 'email=YOUR_ACCOUNT_HERE' \
  -d 'z=YOUR_ROOT_DOMAIN_HERE'

8 - In the reesult of above command, find out target entry (having the "name" field set to your desired sub-domain), and use the values from the record to update these two lines of /sbin/cloudflaredns.sh:

__RECID__="VALUE_OF_rec_id_FIELD"
__RECNAME__="VALUE_OF_display_name_FIELD"

9 - Visit DS web again and go to Control Panel / External Access / Add
10 - Set provider as "CloudFlare", enter your ROOT doamin as the hostname, then your account email as username and the API KEY as password
11 - Back to the telnet session and check out the log tail -f /var/log/cloudflareddns.log
12 - REMEMBER to disable the telent service after done.

@LittleLama

Copy link
Copy Markdown

Awesome tips thank you all very much ! :)

@wsokc

wsokc commented Mar 13, 2016

Copy link
Copy Markdown

Hi,

Thanks for the scripts, I have succeed to make work on one of my site on my Synology.
But how about if we have multiple site ?

What I did:
-- Create a copy of the script
--- Add modulepath modulepath=/sbin/cloudflare_otherdomain.sh
-- Put different RECID and RECNAME inside the scripts and and the log location
-- Add to synology external access, and it works as normal.

FYI, I have created virtualhost for each domain.
But when I try to open the site it still pointed out to the old ns (bluehost) while I already changed the name server to cloudflare.

Is this due to the scripts or something else ?

Cheers,
Raff

@Sizzl

Sizzl commented Mar 24, 2016

Copy link
Copy Markdown

There's a couple of improvements I'm going to play around with and suggest, after testing...

Starting by acknowledging the multi-host requirement from @wsokc , we can quite easily split the __HOSTNAME__ into an array by delimiter (e.g. semi-colon).

Next, do away with the need to manually specify record IDs... The code is there to fetch the ID, so why don't we just work out the root domain from each __HOSTNAME__ entry and pull the ID out from the returned result(s) and use it (or them)? This will help in dealing with the first requirement.

If I get anywhere with these ideas, I'll let you know (but anyone can feel free to try these out for themselves).

Updated fork with record ID fetching and zone validation:
https://gist.github.com/Sizzl/73018e45140cfdcc8ff7

@ledowong

Copy link
Copy Markdown

I use this script in DSM 5.2, it works, but system keep alert me malware detected every week, due to modified system files.

I just upgrade to DSM 6.0. After upgrade, the shell script is deleted by system.
Now I found a workaround on this.

Follow the above instruction (get RECID and RECNAME, API_KEY, etc), then put those variables into the URL. So now you have a full working URL ready.

https://www.cloudflare.com/api_json.html?a=rec_edit&tkn=__GLOBAL_API_KEY__&email=__EMAIL__&z=__ZONE__&type=A&id=__RECID__&name=__RECNAME__&content=__IPv4_ADDRESS__&ttl=1&service_mode=0

It should update your IP address if you run this in browser.

Now do the same thing that the script do, run this using curl command.

First change IPv4_ADDRESS to curl --silent ipecho.net/plain ; echo, which get your external IPv4 address.
In Synology DSM Control Panel > Task Scheduler, create a new task, and put the command in it. Set it run every 5 mins. Thats it.

curl --silent "https://www.cloudflare.com/api_json.html?a=rec_edit&tkn=__GLOBAL_API_KEY__&email=__EMAIL__&z=__ZONE__&content=`curl --silent ipecho.net/plain ; echo`&type=A&id=__REC_ID__&name=__REC_NAME__&ttl=1&service_mode=0"

@SimonNick

Copy link
Copy Markdown

Awesome script thanks! Since Cloudflare is migrating their API v1 to v4 the script needs to be updated (https://www.cloudflare.com/migrating-to-v4/). Will you do this some time?

Best, Nick

@huseyinozyilmaz

Copy link
Copy Markdown

One line curl command to update a DNS record in CloudFlare using v4 API:

curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/dns_records/{RECORD_ID}" -H "X-Auth-Email: {EMAIL}" -H "X-Auth-Key: {API_KEY}" -H "Content-Type: application/json" --data "{\"id\":\"{ZONE_ID}\",\"type\":\"A\",\"name\":\"{RECORD_NAME}\",\"content\":\"curl ifconfig.co\"}"

If you need further details and other API calls to retrieve ZONE_ID and RECORD_ID then check Using CloudFlare as a DDNS Service Provider in Synology post.

@SimonNick

Copy link
Copy Markdown

@huseyinozyilmaz Thanks. And do you know how i can use your command in the script?

@m-wild

m-wild commented Jan 6, 2017

Copy link
Copy Markdown
Author

Sorry for the late reply. I no longer have a synology nas, so I will not be maintaining this script.
Check the forks for fixes (or maybe turn this into a full github repo so it can get pull requests etc?)

Cheers, Michael

@joshuaavalon

Copy link
Copy Markdown

I have created a modified version script using Cloudflare API v4 here. You may want to check it out.

@lioujheyu

Copy link
Copy Markdown

@joshuaavalon. Thanks for the hint of Cloudflare API v4. I went a little bit deep into Cloudflare's github repository and find that Cloudflare has provided many Cloudflare API v4 wrappers in different languages such as php and python. One of API wrapper examples in python does demonstrate how to update DDNS. I took it and modified it a little bit so that it can work with Synology NAS interface. It features automatically zone and recid retrival. You can check it out in my repository.

@fire1ce

fire1ce commented Sep 5, 2018

Copy link
Copy Markdown

getting this error:
RESPONSE={"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}
Sep 5 13:17:42 cloudflaredns.sh (7): Status: false,

@dvershinin

Copy link
Copy Markdown

A better Cloudflare module for Synology is here.

Available to install via pip and most importantly, supports root domain to be set as your DDNS, e.g. example.com, as well as properly handles geographic domains (example.co.uk).

@mrikirill

Copy link
Copy Markdown

I've made a Cloudflare DDNS updater script which supports mulidomains and subdomains, feel free to use it https://github.com/mrikirill/SynologyDDNSCloudflareMultidomain

@dvershinin

Copy link
Copy Markdown

@mrikirill same to many scripts out there, yours will choke on example.co.uk domain (e.g. complex TLDs).
Don't assume that TLD has no dots inside :)

@mrikirill

Copy link
Copy Markdown

@dvershinin yep mate, you're right, didn't think about this case. I'm going to fix it. Feel free to send an issue in my project)

@dvershinin

Copy link
Copy Markdown

@mrikirill just above your comment, I mention cloudflareddns which addresses all these edge case from the start.

@scyto

scyto commented Feb 23, 2022

Copy link
Copy Markdown

nice script
personally i went this route as it's less invasive https://hub.docker.com/r/oznu/cloudflare-ddns/#!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment