As I’m running this site itself on my 4TB WDMyCloud home NAS, refer to my post WebHosting on WDMyCloud V4 Firmwares, I will need my DNS to be always pointing to it when my public IP changes.
Although my public IP seldom changes, I’ve been using a Python based script with its ‘pygodaddy’ module for a while to auto update my GoDaddy DDNS pointing to my WDMyCloud NAS. The script is supposed to update my current public IP by parsing GoDaddys DNS update form. But on few occasions when there’s the need to update, the script failed to work because obviously GoDaddy had changed something in their front-end. I’ve also used a similar PHP based script but that too failed to work. And worst still, for as long that I know of, GoDaddy hasn’t provide any means of updating the records other than manually from their site itself.
Like many others with paid GoDaddy domain account, I’ve been looking for permanent solution not until recently and long awaited for, GoDaddy has finally implemented some APIs for developments which now provides the ability to update the DNS records via a REST call. You can see more details at their developer’s site, https://developer.godaddy.com.
Disclaimer: As I’m frequently updating the original guides and installers here on TeaNazaR.com, I will not be responsible for any brick issues if you were to follow my obsolete guides copied elsewhere. Thus subscribe to this post to get latest updates. Modifying any part of a device may void its warranty.
With this API, I’ve written another simple shell script to perform the DDNS update which can be scheduled with a 5mins repeating Cron job. It should work on any Linux based systems. Why shell script? It’s simple, low-resource and does the update faster than any similar Python, PHP, Perl, Java JIT compiler I’ve tested on the NAS. On each run, the script will check for public IP changes against the local cache and GoDaddy records itself using cURL and only attempt to update if necessary. Even though GoDaddy did not specify the minimum update interval, updating too frequently could affect DNS propagation which could cause delay of the DNS being updated across the internet.
First you will need is of course your paid domain name, then a GoDaddy “Production” API key/secret to use with this script. Go to this specific link, log in with your GoDaddy account then generate the API key/secret. Note that the very first time you do this, it will be created as “Test” environment (seen at the time of writing). Go back to the same page again or click on the “Keys” top menu then generate a new “Production” API key/secret instead.
You can place this script anywhere on your server. I’ll explain more for users who’s not familiar with Linux.
Launch the editor i.e. nano /root/scripts/GoDaddy.sh; . Copy & paste the script source from the bottom of this post into the terminal, update the API key/secret , Domain and other desired options, then CTRL+X to save. Test the script if it’s working:
1 | /bin/bash /root/scripts/GoDaddy.sh; |
Once the script is in place, schedule a Cron job every 5mins, crontab -e; , examples below on a single line:
a. No logging (recommended):
1 | */5 * * * * /bin/bash /root/scripts/GoDaddy.sh>/dev/null 2>&1 |
b. With logging for debugging purposes (you will need to do your own log housekeeping, try logrorate?):
1 | */5 * * * * /bin/bash /root/scripts/GoDaddy.sh>>/var/log/GoDaddy.sh.log |
To update a subdomain (second-level domain i.e. subdomain.domain.com) instead of primary domain (top-level domain i.e. domain.com), set
Type=A
Type=CNAME (Updated: CNAME by default can’t point to an IP) and
Name=subdomain where subdomain is your subdomain.domain.com as seen in the GoDaddy DNS setup page.
I’ve also added optional advanced variables to include any custom scripts, programs or commands to execute when the IP update occurs or failed. This is so that you can place this script on top of your other applications i.e. those which requires public IP update cached in /tmp/current_ip or those which triggers upon IP changes. Read the script’s comments for more details. For instance, you can use Postfix‘s sendmail to trigger an email notification upon IP update or failures by setting the SuccessExec or FailedExec values. Those who’s using my WebHosting on WDMyCloud V4 Firmwares mods, you can configure its ESMTP to get similar results. For an example to get notified upon successful IP update, set the SuccessExec value to:
1 | SuccessExec='echo -e "To:myself@mail.teanazar.com\nFrom:alert@mail.teanazar.com\nSubject:GoDaddy.sh IP Updated\n\nGoDaddy.sh IP Updated ${Domain} ${PublicIP} $(date)\n"|sendmail "myself@mail.teanazar.com"' |
This should be the permanent solution for now until GoDaddy decides to make other changes. Need a Windows based DDNS client updater? Not sure why would anyone leave their PC always awaked, unless it’s a Windows based NAS/server. Perhaps I can help to write a simple Windows executable. But you can always run Cygwin to deploy shell scripts also Ubuntu is already runnable in Windows 10 Insider Preview (at the time of writing). For now, only my NAS running 24/7 needs this. Any questions you can post it here, enjoy (-:
GoDaddy.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #!/bin/bash # GoDaddy.sh v1.3 by Nazar78 @ TeaNazaR.com ########################################### # Simple DDNS script to update GoDaddy's DNS. Just schedule every 5mins in crontab. # With options to run scripts/programs/commands on update failure/success. # # Requirements: # - curl CLI - On Debian, apt-get install curl # # History: # v1.0 - 20160513 - 1st release. # v1.1 - 20170130 - Improved compatibility. # v1.2 - 20180416 - GoDaddy API changes - thanks Timson from Russia for notifying. # v1.3 - 20180419 - GoDaddy API changes - thanks Rene from Mexico for notifying. # # PS: Feel free to distribute but kindly retain the credits (-: ########################################### # Begin settings # Get the Production API key/secret from https://developer.godaddy.com/keys/. # Ensure it's for "Production" as first time it's created for "Test". Key=fsvVddxVsfe_frhN1SAgfdgCdAfyVdWDdv Secret=FwkUfafh8dgrsdydrdfC1e # Domain to update. Domain=teanazar.com # Advanced settings - change only if you know what you're doing :-) # Record type, as seen in the DNS setup page, default A. Type=A # Record name, as seen in the DNS setup page, default @. Name=@ # Time To Live in seconds, minimum default 600 (10mins). # If your public IP seldom changes, set it to 3600 (1hr) or more for DNS servers cache performance. TTL=600 # Writable path to last known Public IP record cached. Best to place in tmpfs. CachedIP=/tmp/current_ip # External URL to check for current Public IP, must contain only a single plain text IP. # Default http://api.ipify.org. CheckURL=http://api.ipify.org # Optional scripts/programs/commands to execute on successful update. Leave blank to disable. # This variable will be evaluated at runtime but will not be parsed for errors nor execution guaranteed. # Take note of the single quotes. If it's a script, ensure it's executable i.e. chmod 755 ./script. # Example: SuccessExec='/bin/echo "$(date): My public IP changed to ${PublicIP}!">>/var/log/GoDaddy.sh.log' SuccessExec='' # Optional scripts/programs/commands to execute on update failure. Leave blank to disable. # This variable will be evaluated at runtime but will not be parsed for errors nor execution guaranteed. # Take note of the single quotes. If it's a script, ensure it's executable i.e. chmod 755 ./script. # Example: FailedExec='/some/path/something-went-wrong.sh ${Update} && /some/path/email-script.sh ${PublicIP}' FailedExec='' # End settings Curl=$(which curl 2>/dev/null) [ "${Curl}" = "" ] && echo "Error: Unable to find 'curl CLI'." && exit 1 [ -z "${Key}" ] || [ -z "${Secret}" ] && echo "Error: Requires API 'Key/Secret' value." && exit 1 [ -z "${Domain}" ] && echo "Error: Requires 'Domain' value." && exit 1 [ -z "${Type}" ] && Type=A [ -z "${Name}" ] && Name=@ [ -z "${TTL}" ] && TTL=600 [ "${TTL}" -lt 600 ] && TTL=600 echo -n>>${CachedIP} 2>/dev/null [ $? -ne 0 ] && echo "Error: Can't write to ${CachedIP}." && exit 1 [ -z "${CheckURL}" ] && CheckURL=http://api.ipify.org echo -n "Checking current 'Public IP' from '${CheckURL}'..." PublicIP=$(${Curl} -kLs ${CheckURL}) if [ $? -eq 0 ] && [[ "${PublicIP}" =~ [0-9]{1,3}\.[0-9]{1,3} ]];then echo "${PublicIP}!" else echo "Fail! ${PublicIP}" eval ${FailedExec} exit 1 fi if [ "$(cat ${CachedIP} 2>/dev/null)" != "${PublicIP}" ];then echo -n "Checking '${Domain}' IP records from 'GoDaddy'..." Check=$(${Curl} -kLsH"Authorization: sso-key ${Key}:${Secret}" \ -H"Content-type: application/json" \ https://api.godaddy.com/v1/domains/${Domain}/records/${Type}/${Name} \ 2>/dev/null|grep -Eo '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' 2>/dev/null) if [ $? -eq 0 ] && [ "${Check}" = "${PublicIP}" ];then echo -n ${Check}>${CachedIP} echo -e "unchanged!\nCurrent 'Public IP' matches 'GoDaddy' records. No update required!" else echo -en "changed!\nUpdating '${Domain}'..." Update=$(${Curl} -kLsXPUT -H"Authorization: sso-key ${Key}:${Secret}" \ -H"Content-type: application/json" -w"%{http_code}" -o/dev/null \ https://api.godaddy.com/v1/domains/${Domain}/records/${Type}/${Name} \ -d"[{\"data\":\"${PublicIP}\",\"ttl\":${TTL}}]" 2>/dev/null) if [ $? -eq 0 ] && [ "${Update}" -eq 200 ];then echo -n ${PublicIP}>${CachedIP} echo "Success!" eval ${SuccessExec} else echo "Fail! HTTP_ERROR:${Update}" eval ${FailedExec} exit 1 fi fi else echo "Current 'Public IP' matches 'Cached IP' recorded. No update required!" fi exit $? |
Can this be setup to update multiple domains at the same time, or do I just need multiple scripts each one fore each domain?
Each domain one script but you can chain them together to only execute the rest if the 1st script got updated.
This looks great.
Can you tell how can i use this script for ipv6 ?
Someone said it works after some changes. See this previous comment http://teanazar.com/2016/05/godaddy-ddns-updater/comment-page-3/#comment-991
This has been running fine on my QNAP for months, but after a firmware update I am getting an error – as attached.
Can you suggest what might be the issue ?
Thanks
It seems CURL is no longer installed on your system
But if you look at the attachment I did a cURL –version which showed:
CURL 7.43.0 and LIBCURL 7.43.0
So I am assuming they are installed.
Seems to be CRLF issue. Try creating a new script file using nano or vi then copy and paste the script content again. Or convert the existing script using dos2unix.
Repeating the “which” command from the script seems to get the right response – as attached – showing the directory as sbin/curl
But the $PATH setting appears to omit this sbin/curl folder – could this be the issue even though the CURL seems to be being found?
Your curl is in /sbin and /sbin is already in your path environment so everything is good except did you take a look at my previous reply minutes ago about CRLF?
Thank you.
I did create it originally with vi, but obviously got some extra line-ends in there somehow.
Fixed immediately with dos2unix.
I get error: 401
Nevermind, I’ve made a mistake with my keys. Works!
Thanks you! =)
or just try https://staticip.io
There’s lots of free DDNS provider but none will let you modify the domain settings unless you own it.
Hello,
I’ve been using your script for some time now and I really enjoy using it. I’ve made a few simple modifications to it and would like to share it with others.
Hi Donald,
Thanks for sharing. For me personally I would prefer not to flood the log every 5 minutes if there’s no IP changes. So in crontab I would just null the output and use sendmail if there’s changes to the
SuccessExec
andFailedExec
.Hello Nazar,
Where do you see that it says it logs every 5 minutes? I use a scheduled task on my server that runs this script every 1 hour and I personally have had no issues with the logs being flooded. I then use another scheduled task that runs every 30 days that executes this code:
Unless you are referring to the TTL setting, but I have mine set to 3600 seconds.
I check my logs once a week to see if there are any failed updates. If so, I re-run my script. Here in Alaska, my ISP does ip changes every few weeks. We are also limited on bandwidth allotment and they over charge by far. 200 GB of data is $300 a month at a download rate of 10mbps and 4 mbps upload.
If I’m missing the part in the script where it says it logs every 5 minutes, please point me to the area where it is.
Thanks,
-Donald
Hi Donald, There’s nothing wrong with your recommendation. Some might find it useful on several circumstances. The every 5 minutes is where I’m referring to the original post, TTL is 600 seconds and cron is every 5 minutes. There’s a reason to this.
Most ISP will change the IP almost every time when reconnecting hence it’s recommended to lower the TTL and cron frequency for such cases. Even for my case, where my IP stays for many months despite reconnecting, I still lower down the values because if an IP change should occur, it will take too long for DNS servers to propagate it thus extending my server unreachable down time further.
For me, I have an unlimited 1Gbps symmetrical connection. I also seldom check the logs as I rely mostly on email notifications so most of my logs are either disabled or limited to only warning level and above. So in an event if I do receive an email about my IP changes, I would expect all my apps incoming connection via DDNS to be up within 10 minutes or less. But if metered connection is also a concern, feel free to adjust the values accordingly.
For anyone else having an issue getting multiple subdomains to update but running the script only returns
“Public IP matches Cached IP recorded. No update required!”
change the CachedIP from
“/tmp/current_ip”
to
“/tmp/current_ip_subdomain”
and change subdomain as needed.
Hi, I’ve been using your script on openwrt routers for 4 years, I love your script, I recently migrated my GoDaddy domain to Cloudflare, but I don’t know how to write scripts, can you modify the script? I hope it works on Cloudflare too. Thank you
Think it’s easier with Cloudflare, https://developers.cloudflare.com/dns/manage-dns-records/how-to/managing-dynamic-ip-addresses/. When I first use GoDaddy I don’t remember any available clients hence I simply created one.
Thanks for your reply, I will learn
Thank you! It was an almost straightforward setup. I had some minor issues with security access. But that was on my end.
No problem glad it helps!