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. GoDaddy API recently changes output so successful record change now outputs empty response body instead of “{}” so this script stopped working properly.
    You need to replace line 96 to:

    if [ $? -eq 0 ] && [ "${Update}" = "null" ];then
    

    As a workaround. But what you really wanna do is to rely on HTTP response codes instead of UB output. To do so you need to add options “-w “%{http_code}” -o /dev/null” to curl call and check against “200”.

  2. Yeah scratch that workaround, just replace line 93 to:

    -H"Content-type: application/json" -w "%{http_code}" -o /dev/null \
    

    And line 96 to:

    if [ $? -eq 0 ] && [ "${Update}" = "200" ];then
    
    1. Hi Timson,

      Thanks for alerting with the fix. My IP has not changed for a long time so I wasn't aware of the recent API updates.

      I've applied your HTTP respond code fix. Also noticed the check IP with GoDaddy results has changed, now the script will try to grep the available IP address on line 87.

  3. GoDaddy.sh Updated!
    v1.2 – 20180416 – GoDaddy API changes – thanks Timson from Russia for notifying.

  4. Hi, tks a lot for the update, your script i love it, i like you, my webpage stored at my house.

    best regards

  5. Hi, everyone, the script maybe has a problem, in this line

    -d "{\"data\":\"${PublicIP}\",\"ttl\":${TTL}}" 2>/dev/null)
    

    when debug the script says “Update=422”

    In the webpage: https://developer.godaddy.com/doc/endpoint/domains#/v1/recordReplace

    422 = domain is not a valid Domain name
    record does not fulfill the schema

    But my domain is correct.

    i think the schema is:

    -d "{\"data\":\" ${PublicIP}\",\"name\":\" @\",\"ttl\": ${TTL},\"type\": \"A\"}" 2>/dev/null)
    

    when i changed the resul is 411, so, i think i don’t have the solution.

    Best regards.

    1. Hi Rene,

      I just confirmed the script was working good 3 days back and now the API changed again. I’ve updated the script to v1.3.

  6. GoDaddy.sh Updated! v1.3 – 20180419 – GoDaddy API changes – thanks Rene from Mexico for notifying.

    1. I hope that’s not your real production keys included in this script 🙂
      Better to load them from external auth file so people won’t do similar mistake when sharing this script.

      1. No worries I always copy & paste except the settings part. Those are mock-up keys so that others may visualize what they really look like.

        I prefer the script to be all-in-one simple as it’s easier to manage since this is a straightforward record update process unless I’m dealing with other complex stuffs.

        Those sharing this script should share the link of this page instead but if you prefer, you can easily change to load the authentication from a file. Below is my quick example:

        An auth file mysecretkey.txt with content key:secret then replace line 23-24 with:

        Auth=`cat /path/to/mysecretkey.txt`
        Key=`echo $Auth|sed -r 's/^(.+):.+$/\1/'`
        Secret=`echo $Auth|sed -r 's/^.+:(.+)$/\1/'`
        
  7. I have used this successfully for a long time, and updated to 1.3 when things stopped working last month.
    It seems that it has stopped working again – for me at least – in the last week or so.

    1. I just tested the v1.3 and it’s working as expected. What errors are you getting?

  8. It may be related to firmware updates on the QNAP I’m using which may have happened around the same time. Running the command directly in PuTTY I see:

      Error: Unable to find 'curl CLI'.
      : numeric argument requiredline 62: exit: 1
    
      1. And that’s where you lose me as a simple cut’n’paster – bash is obviously there as the script ran with the /bin/bash in PuTTy session, but I don’t know anything about Linux and there is nothing recent showing up when googling QNAP & CURL. So, I am at a bit of a dead end.
        I’ll keep an eye on these comments in case a fellow QNAPer has any advice. Thanks

        1. Well, I tried repeating the “which curl” command from your script directly in PuTTy and got this:

          [~] # which curl

          /sbin/curl

          and confirmed with this:

          [/sbin] # cd /sbin

          [/sbin] # ls curl

          curl*

          Do that make things better or worse ?!

          1. I then commented out the lines doing the cURL check and ran the script again to get:

            [~] # /bin/bash /share/GoDaddy/GoDaddy.sh

            Error: Requires API ‘Key/Secret’ value.

            numeric argument requiredline 64: exit: 1

            there were “Command not found” for each blank lines in the file which I deleted here, and then it fails on, what is now, the first line of real code again – and the Google Key & Secret are definitely defined the same way the cURL is available and working.

            So it looks like it just fails each test when it shouldn’t, or isn’t able to execute successfully. Are there any permissions to check – the actual script got a chmod +x and is obviously executing – just not successfully.

            1. After deleting blocks of code, and seeing new errors pop-up each time, i just deleted the whole thing and re-created the GoDaddy.sh from scratch again based on the 1.3 script here. Ran the test and it just worked. No clue what was wrong with the original file, but clearly my error somewhere along the way. Thanks

  9. Nazar,
    I’ve built a small personal server for a friend and have enabled Postfix/Sendmail as the system MTA. In order to have the ability to send out email from her domain or receive email from the website contact form without it being flagged as spam, I’ve configured Postfix to use Gmail’s SMTP relay services. When I did this however their were unintended consequences. All of the emails to root generated by the GoDaddy DNS updater are getting forwarded to the Gmail account that I’m using as the relay. As you can imagine that’s an email every 5 min per my Cron schedule. Is there a way to disable the email function in the script or null it out or redirect to file? Thank you for everything!

    1. Hello TimR,

      By default cron will send out emails to localhost and since postfix is configured it will send out to the sendmail. To prevent cron from sending emails, append the stdout and stderr to null. E.g. */5 * * * * /home/user/scripts/GoDaddy.sh>/dev/null 2>&1. You can use the FailedExec variable to still send emails in case the update fails.

      1. I completely forgot about cron sending out email to localhost. Thank you for reminding me of that. I’ve nulled out that cronjob and added a script to email on FailedExec only. A pleasure as always.

  10. Checking current ‘Public IP’ from ‘http://icanhazip.com’…sh: =~: unknown operand

    i got error on this please revert A.S.A.P

    1. Looks like you are trying to run this script with “sh” interpreter instead of “bash”
      BTW, Nazar, clicking on “Reply” button in email notification on current Android Gmail client sent me to infinite full screen ad loop exiting only on “Span” wikipedia article.

      1. would it be hard to change the script to run with sh instead of bash ?
        Running busybox on Merlin Asus firmware and installing bash is not so obvious.
        Initially it was working with sh.
        Thanks for your help !

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