GoDaddy DDNS Updater

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.

GoDaddy.sh
GoDaddy.sh

First you will need is of course your paid domain name, then a GoDaddy “ProductionAPI 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 “ProductionAPI key/secret instead.

GoDaddy API
GoDaddy API

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:

Once the script is in place, schedule a Cron job every 5mins, crontab -e; , examples below on a single line:

a. No logging (recommended):

b. With logging for debugging purposes (you will need to do your own log housekeeping, try logrorate?):

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:

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

189 thoughts on “GoDaddy DDNS Updater”

  1. Will this work with several A records in the same domain? I have a few subdomains I use so I can have multiple websites for different reasons. Thanks! This tutorial is great!!!

    1. Hello Will,

      This script was made simple and can only update one record. However you can have multiple scripts running or link them together with the SuccessExec variable (If the first script updated successfully, it will then run the rest of the scripts defined in this variable). Just ensure you specify a unique CachedIP variable for each script if they’re running on the same system.

  2. Hey Nazar.. MANY Thanks for this!

    I was previously running the many variations of the pygodaddy scripts on my Synology NAS and the last day it actually worked was May 20, 2016. Every day since.. FAIL FAIL FAIL. heh

    Anyways, I got your script working with a few changes because I’m running ash instead of bash. One issue I see (on my system anyways)… This could bomb out (but not actually fail[ERROR]) IF… godaddy IP = 1.2.3.4, cached IP = 4.3.2.1, public IP = 4.3.2.1….

    1. Hello NtegrA,

      No problem glad it helps.

      As for the potential issue you brought up, this scenario usually happens when the GoDaddy IP has been changed manually or by other means. The script was made simple and will only check the IP at GoDaddy if there is a change between cached and public IP.

      If you’re worried about this, the key here is the cached IP file. I placed the cached IP in the tmpfs so when the NAS reboots (obviously tmpfs cleared) it will be forced to check with GoDaddy because of the missing cached IP. You can also schedule to remove this cached IP file say every 1hr to force the checks against GoDaddy at the next 5mins interval.

  3. @NtegrA

    What did you change to make it work in ash. I am using a Synology as well. But im haven’t really used ash over bash.

    Thanks

    1. I too have least knowledge of the ash, but I recalled quite sometime ago installing this script on one of my donor’s DSM6. Defaulted with ash but there’s bash installed on his Synology (can’t remember which model it was or if it was behind busybox but I remember installing python modules). So I just need to chmod the script then install it to the scheduler and it ran as expected. Try checking bash on your system if it’s available else I think it’s easier to install bash or let’s wait for NtegrA to reply.

  4. Hello,
    I have a fresh install of Debian Jessie and have run apt-get install curl, apt-get update, and apt-get upgrade but whenever I run the script I keep getting the “Unable to find curl CLI” error. I can see curl in /usr/bin/curl and when I run /usr/bin/which curl 2 it returns the correct /usr/bin/curl value. Any ideas?
    Thanks!

    1. Hi Nate,

      That is strange, I have no issues with any of Debian’s wheezy, jessie or sid. Could you try opening a new bash session then retry running the script?

      You should see /usr/bin/curl when you run this in a single line: Curl=$(/usr/bin/which curl); echo ${Curl}.

      1. Unfortunately still getting the same error running the scripts in a new window. When I run Curl=$(/usr/bin/which curl); echo ${Curl} I do get the output you indicated, /usr/bin/curl.

        The exact error output is below:
        root@*****:/usr/local/bin# /bin/bash udGDBeagle.sh;
        udGDBeagle.sh: line 2: $’\r’: command not found
        udGDBeagle.sh: line 16: $’\r’: command not found
        udGDBeagle.sh: line 22: $’\r’: command not found
        udGDBeagle.sh: line 25: $’\r’: command not found
        udGDBeagle.sh: line 29: $’\r’: command not found
        udGDBeagle.sh: line 32: $’\r’: command not found
        udGDBeagle.sh: line 36: $’\r’: command not found
        udGDBeagle.sh: line 39: $’\r’: command not found
        udGDBeagle.sh: line 43: $’\r’: command not found
        udGDBeagle.sh: line 49: $’\r’: command not found
        udGDBeagle.sh: line 56: $’\r’: command not found
        Error: Unable to find ‘curl CLI’.
        numeric argument requiredt: 1

        1. The issue seems to be with CRLF. Which text editor did you use? Try converting the file with dos2unix or create a new file using vi or nano from the console then paste the entire script then edit your variables and save.

          1. Thanks Nazar, copying it directly into nano fixed it. My first attempt I copied the script into Notepad to edit my variables and then copied it into nano. Works perfectly now!

  5. Thanks for sharing!

    i also run this script at boot to have faster response time in any WAN disconnect event.
    Maybe in can be incorporated?

    #!/bin/bash             
    
    connected=false         
    while true
    do
            if ping -q -c 1 -W 3 8.8.8.8 >/dev/null; then
                    if [ "$connected" = false ] ; then
                            connected=true
                            /bin/bash ./godns.sh
                    fi      
                    sleep 20
            else    
                    connected=false
                    sleep 5
            fi      
    done
    
    1. Hi Timson,

      No problem. My public IP seldom change on reconnects and my WAN seldom disconnects only in an event of a power trip. I also added this script to the cron @reboot and ifplugd service so the DDNS restore time if necessary is minimal.

      I prefer to have lesser stuffs running in background due to my underpowered NAS but yeah of course you can wrap your script around this script. Your script method is useful for those whose having frequent disconnects or IP changes. Thanks for sharing (-:

  6. Hi , thanks for the great script, But I have some problem while updating subdomain.
    I already add a CNAME record in DNS manager named z point to @
    and modify the script , domain=mc4.us , TYPE=CNAME,Name=z , but there`s some error messages like this

    Checking current 'Public IP' from 'http://api.ipify.org'...114.42.33.87!
    Checking 'mc4.us' IP records from 'GoDaddy'...changed!
    Updating 'mc4.us'...Fail! {"code":"INVALID_RECORDS","message":"One or more of the given records is invalid","errors":["CNAME z Invalid characters in hostname 114.42.33.87"],"name":"_Class"}
    

    please help , thanks

    1. I can’t remember if CNAME pointing to an IP used to work with GoDaddy. Actually by right it shouldn’t and it doesn’t work now, I’ll updated the guide. Can you setup Type=A, then Name=z both on GoDaddy and in the script?

  7. Hey!
    My ISP only provide me a IPv6 Address. What do I need to change in the script to make it work with IPv6? Thanks!

    1. Hi Rolf,

      I haven’t tried because I don’t have an IPv6 but this should work. The CheckURL variable should return an IPv6 in your case. If it doesn’t, change the URL to CheckURL=http://v6.ipv6-test.com/api/myip.php.

      Then change the followings in the script:

      1. Set Type=AAAA

      2. Replace the script in line 73 to:
        if [ $? -eq 0 ] && [ "${PublicIP}" != "" ];then

      Let me know how it goes.

      1. Thanks so much! It works!! 🙂 Um, maybe I can ask another question?
        My router from ISP only has Port Range Triggering (and no Port Forwarding). I entered port 22, but it is not open. I think SSH don’t trigger port 22 by itsown. Is there a way I can trigger this port on my raspberry pi so it will be open by the firewall? The only other way it would work is to disable the firewall 🙁

        1. No problem glad it helps (-:

          About your router, which make/model it is? Does it support UPnP? If yes you can install miniupnpc then setup a cronjob hourly (0 * * * * /usr/bin/upnpc …) and on startup (@reboot /usr/bin/upnpc…):-

          Forward to a specific IP:
          /usr/bin/upnpc -a ip port external_port protocol [duration]

          Forward directly to the Raspberry Pi:
          /usr/bin/upnpc -r port1 protocol1 [port2 protocol2] [...]

          Just type upnpc to see more options.

  8. Utterly Awesome. I’m a Dad with some low level bash and python and I think you’ve done a generous thing by sharing this. Works perfectly, I’m going to move from a static IP plan to a dynamic IP plan over our NBN and your script has made it possible for me to keep my servers running without a hassle. Thank you.

  9. The same applies here .. works excellent

    One additional remark
    My touch sometimes needs an different location and use
    perhaps it is nice to add flexibility in the environment ^_^
    TPATH=$(which touch)

  10. Lovely and useful work! Got it running on MacOS Sierra in 5 minutes, just needed to change a couple paths and a few permissions. MacOS has deprecated cron in favor of launchd, and I wasn’t up to crafting a launchd daemon script, but cron is still available. Thanks much, I’ve been grumbling about this problem for too long.

Leave a Reply

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

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax