Updating DigitalOcean DNS Records With Dynamic IP

Preface

Full tutorial on how to update DigitalOcean’s DNS (Domain Name Servers) by utilizing Bash scripting. You can observe how I will use Bash to update all the domains and subdomains I own in automated way using Crontab. If you have dynamic IP and host a service at home, these will help you to point your hosting service’s DNS records at your home server(s).

Requirements

API Token

Login to Digital Ocean and generate your API key.

Domain Names

Take a note of all the domain names from your account that has to be updated with new public IP.

Collect All The Record IDs For Each Domain

For each domain, eg example1.com, you can have multiple subdomains. It can be the same for example2.com and so on. Grab every record ID for each domain and subdomain with this Bash script.

Create get_record_ids.sh Bash File

Execute this command to create a bash file.

$ nano get_record_ids.sh

Insert the code into the file.

# !/bin/bash
# SpawnTerror 2021
# Get domains record ids from DigitalOcean
# Usage:
# sudo ./get_record_ids.sh YOUR_DOMAIN_NAME
# Igonre all records with NS = nameservers
# Insert all other required record IDs to update_digital_ocean.sh
# Insert all required domain names to update_digital_ocean.sh
# Insert your TOKEN to communicate with DigitalOcean APIv2
# Execute updater:
# sudo ./update_digital_ocean.sh
# Add the update script to crontab -e
#
# Visit nodetwelve.com for more information

[[ -z "$1" ]] && { echo "Usage: sudo ./get_record_ids example.com"; exit 1; }
curl GET -H "Content-Type: application/json" \
     -H "Authorization: Bearer INSERT_YOUR_TOKEN_HERE" \
     https://api.digitalocean.com/v2/domains/$1/records | json_pp | grep -E "id|name|type"

Execute this command to make it executable and run it.

$ chmod u+x get_record_ids.sh

Collect Record IDs

Execute the file with a parameter for each domain the you have from previous step.

$ ./get_record_ids.sh example1.com
$ ./get_record_ids.sh example2.com
$ ./get_record_ids.sh example3.com

Note down all the required entries of type A record. Do not update the NS (nameserver) types. Here is a sample output:

# ./get_record_ids.sh example1.com
 
          "id" : 117631233, # we don't want SOA (Start Of Authority)
          "name" : "@",
          "type" : "SOA",

          "id" : 117499983, # we don't want NS (nameserver record)
          "name" : "@",
          "type" : "NS",

          "id" : 117636906, # we don't want NS (nameserver record)
          "name" : "@",
          "type" : "NS",

          "id" : 117634913, # we don't want NS (nameserver record)
          "name" : "@",
          "type" : "NS",

          "id" : 117634903, # A record for example1.com
          "name" : "@",
          "type" : "A",

          "id" : 117634912, # A record for www.example1.com
          "name" : "www",
          "type" : "A",

          "id" : 117634283, # A record for blog.example1.com
          "name" : "blog",
          "type" : "A",

          "id" : 117612323, # A record for store.example1.com
          "name" : "store",
          "type" : "A",

          "id" : 117634323,
          "name" : "www.blog", # A record for www.blog.example1.com
          "type" : "A",

Explanation

We only collect A records for every subdomain and domain. You never update nameserver records. You never update SOA (Start Of Authority) records either.

Create Update Script

With all the data we have:

  • 3 domain names (example1.com, example2.com, example3.com
  • API token from DigitalOcean
  • All the domain and subdomain records

It is time to create update script in bash.

Create update_digital_ocean.sh Bash File

Execute this command to create a bash file.

$ nano update_digital_ocean.sh

Insert the code into the file.

#!/bin/bash
# SpawnTerror 2021
# Update DigitalOcen DNS Records
# Usage:
# Run get_record_ids.sh script to get RECORD IDS of your  
# domains/subdomains
# Get API token from DigitalOcean website
# Update TOKEN
# Update DOMAIN… (add more or delete as required)
# Update RECORD… (add more or delete as required)
#
# Visit nodetwelve.com for more information

# Variables 
TOKEN="insert_your_TOKEN_here"
LOG_FILE="/home/YOUR_USERNAME/digital_ocean_update_logs.txt"

# Records
 DOMAIN1="example1.com"
 RECORD_A1="112176990" # example1.com
 RECORD_A2="112177021" # www.example1.com
 RECORD_A3="113300718" # blog.example1.com
 RECORD_A4="127939656" # www.blog.example1.com
 RECORD_A5="117087411" # store.example1.com

# add example2.com and so on, if required
# DOMAIN2="example2.com"
# RECORD_B1="107526235" # www.example2.com
# RECORD_B2="107939442" # example2.com

# Get current public IP and compare with last one in the log file
# If not the same, update all records at DigitalOcean.
 DETECTED="$(dig +short myip.opendns.com @resolver1.opendns.com)"
 PREVIOUS="$(tail -1 $LOG_FILE | awk -F, '{print $2}')"

 if [ "$DETECTED" = "$PREVIOUS" ]
 then

         echo "Previous IP -> ($PREVIOUS)."
         echo "Detected IP -> ($DETECTED)."
         echo "No change detected, exiting."

 else

         echo "Previous IP -> ($PREVIOUS)."
         echo "Detected IP -> ($DETECTED)."
         echo "New public IP detected, updating DigitalOcean records…" && echo
         echo "$(date),$DETECTED" >> "$LOG_FILE"

         # example1.com
         curl -X PUT -H "Content-Type: application/json" -H \     "Authorization: Bearer $TOKEN" -d '{"data":"'"$DETECTED"'"}' \     "https://api.digitalocean.com/v2/domains/$DOMAIN1/records/$RECORD_A1"
         # Copy and paste above line changing $RECORD_A1 with all records
         # Then change $DOMAIN1 with next one and all records
fi

Execute this command to make it executable and run it.

$ chmod u+x update_digital_ocean.sh

Script is saved and executable.

Initial Run Of Update Script

Run the script first time to create log file. It will throw an error, because the log file doesn’t exist yet.

$ ./update_digital_ocean.sh

Run it again and it will exit normally. That’s it.

Create Cronjob To Automate The Task

One of the options is to create a job in Crontab to automate the updating of DNS records on DigitalOcean backend.

To run the script every 15 minutes, use this command:

*/15 * * * * /path/to/script/update_digital_ocean.sh

Add this command at the bottom of the crontab and save.

crontab -e

Change The Frequency Of The Task

You can use online generator to change 15 minutes to any time you want. I wouldn’t use anything lower than 5 minutes, otherwise it may cause bother to DigitalOcean backend.