Use Digital Ocean’s API for Dynamic DNS

In cases where you want to host something behind a changing IP address, you need a Dynamic DNS service. This service changes the name IP address listed in the name resolution service to match your current address. There are many, some with adverts and some not free.

DigitalOcean provides DNS services to their customers. If you use their DNS services you already have API access to update your DNS records, remotely.

This script will allow you to address the server at home by updating a DNS record periodically with the current address.

0 . Latest updates and prerequisites.

2023.09.23 – First draft, Ubuntu 22.04 Server.

Check back for updates, if you run into trouble. Leave a comment if the post is missing some detail.

You need any server at home that can run a simple shell script, such as Ubuntu, Debian, Red Hat, even a Synology NAS can do this. You also need an account at DigitalOcean and to have hosted there, a domain.

1 . Create a DNS record at DigitalOcean.

The record that will be change in the DigitalOcean hosting services is homeoffice.aardvark.systems as I would like to have my development environment hosted on a Raspberry Pi in my home office.

The DNS host for the domain aardvark.systems is hosted within DigitalOcean, so it is a simple case of creating an A record, with any random IP address for this name, for example, 10.10.10.10.

Make sure to set the record to have a low TTL, in this case, 600 seconds (ten minutes), as the record will be tested every 20 minutes. This should not be a problem, if the number of visitors expected, is low.

DigitalOcean will provide an API key through the control panel. Make sure to copy the token as it is never revealed, again. The token needs write access. If you are planning on making many tokens, a useful and descriptive name is recommended.

Copy the token to a text file, it is needed later. The token should look like this:

dop_v1_fc79ae6a0db599df3...

2 . Get the DNS record ID.

The record ID is a unique number associated with the DNS entry. This ID is needed by the updater. From a command line, anywhere, run this curl statement, substituting values (please note, it is all one line):

sudo curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_API_TOKEN" "https://api.digitalocean.com/v2/domains/YOUR_DOMAIN/records"

Check the output for the record, in curly braces, that matches the record created earlier. In this case, the record above looks like this:

...{"id":1702703150,"type":"A","name":"homeoffice","data":"1.2.3.4","priority":null,"port":null,"ttl":600,"weight":null,"flags":null,"tag":null}],"links":{},"meta":{"total":14}
...

The ID needed for the updater is, in this case:

1702703150

Save this somewhere, it is needed later.

3 . Create a shell script.

A script that runs once every 20 minutes will need to learn the current IP address, then make a curl statement to DigitalOcean with the record ID and the API key.

Create a folder to keep the script:

sudo mkdir -p /opt/ddns

Use nano or some other editor to create the script:

sudo nano /opt/ddns/ddnsupdater.sh

Create a script like this, substituting the variables for your own. Notice the IP address is sought via the URL, checkip.amazonaws.com, or any service that returns a raw IP address:

#!/bin/sh
#variables
ACCESS_TOKEN=YOUR_API_TOKEN
DOMAIN=YOUR_DOMAIN
RECORD_ID=YOUR_RECORD_ID

#the script
IP=$(curl -s http://checkip.amazonaws.com/)
curl -fs -o /dev/null -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" -d "{\"data\":\"$IP\"}" "https://api.digitalocean.com/v2/domains/$DOMAIN/records/$RECORD_ID"

Don’t forget to make the file executable:

chmod +x /opt/ddns/ddnsupdater.sh

Using crontab, schedule the script to run every 20 minutes:

crontab -e

My crontab line looks like this:

*/20 * * * * /opt/ddns/ddnsupdater.sh

Notice the asterisk is divided by 20, this means, every 20 minutes, but some implementations of cron may not support this syntax and you’ll have to use an static time, such as every hour. Beware if you make too many API calls, such as every second, DigitalOcean may throttle your requests.

4 . Test the Updater Script.

Now you can wait 20 minutes to see if the script updates the IP address created earlier or you can run it manually to check what output comes:

/opt/ddns/ddnsupdater.sh

The output from cron statements is stored in syslog, check it with:

cat /var/log/syslog | grep cron

To test the script at anytime, just change the DNS record to a random IP and run the script manually. The record should change immediately after the script runs, again.

5 . Monitoring

Completely optional, but if you have setup Discord for your server notifications, then consider this script, which is built on the work in this post, to check if the DNS record has changed, first, then send a notification if so:

#!/bin/sh
#variables
ACCESS_TOKEN=dop_v1_30b510f06cb9d6069cbc18eae76e605sdagfasgagarg
PUB_DNS=8.8.8.8
SRV=$(hostname)
IP=$(curl -s http://checkip.amazonaws.com/)

#homeoffice.aardvark.systems
HOST=homeoffice
DOMAIN=homeoffice.aardvark.systems
RECORD_ID=1688425637
#the script
DNSIP=$(nslookup $HOST.$DOMAIN $PUB_DNS | awk '/^Address: / { print $2 }')
if [ $DNSIP = $IP ]; then
    echo "$PUB_DNS and checkip.amazonaws.com agree on $IP for $HOST.$DOMAIN."
else
    echo "$PUB_DNS and checkip.amazonaws.com cannot agree on $IP or $DNSIP for $HOST.$DOMAIN."
    /opt/discord/discord.sh "$SRV" "IP must be changed from $DNSIP to $IP for $HOST.$DOMAIN"
    curl \
    -fs -o /dev/null \
    -X PUT \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -d "{\"data\":\"$IP\"}" \
    "https://api.digitalocean.com/v2/domains/$DOMAIN/records/$RECORD_ID"
fi

You can now receive a notification when the IP needs to be changed.

6 . Supporting this blog.

This type of content takes a lot of effort to write. Each post is drafted, researched, then tested multiple times, even a simple step or detail might take more than a few hours to go from the idea to a published blog post.

If you feel I have saved you some time, you can support me by;

  • buying me a beer through PayPal – PayPal.

© HorseFreeGlue, 2025. Unauthorized use and/or duplication of this material without express and written permission from this site’s author and/or owner is strictly prohibited