[ Digital Ocean Dynamic DNS ]

SOFTWARE STABLE

🌐 DigitalOcean Dynamic DNS (DDNS) Script

I found a guide for this ages ago on Medium and haven’t been able to find it since. Because I use this so rarely, I’ve had to piece it back together more than once. I’m documenting it here for posterity and for anyone else who needs a lightweight, self-hosted DDNS solution.

Prerequisites

Having a static IP makes a massive difference in a homelab setup. This script fetches your current public IPv4 address, compares it against a local log, and updates your DigitalOcean A-Record only if a change is detected.

  1. Generate an API Token: DigitalOcean API Tokens
  2. Create an A Record: Do this manually in the DO networking dashboard first.
  3. Find your Record ID: Use the following command to find the unique ID for your specific A record:
curl -X GET \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer YOUR_TOKEN" \
 "https://api.digitalocean.com/v2/domains/YOUR_DOMAIN/records"

Installation & Permissions

Create the log file and the script, then set the permissions. We use 700 and 600 to ensure your API tokens remain private.

touch iplog.txt
nano dyndns.sh
chmod 700 dyndns.sh
chmod 600 iplog.txt

Automation (Cron)

Since the script only pings the API when the IP actually changes, you can run it frequently without hitting rate limits. Every 15 minutes is a good balance.

crontab -e
# Add the following line at the bottom:
*/15 * * * * /bin/bash /path/to/dyndns.sh

📄 The Script (dyndns.sh)

#!/bin/bash

# ==========================================================
# SERVICE: DigitalOcean Dynamic DNS Update
# PURPOSE: Monitors and updates A-Record via API
# ==========================================================

#################### CONFIGURATION ####################
TOKEN="YOUR_TOKEN"
DOMAIN="YOUR_DOMAIN"
RECORD_ID="YOUR_RECORD_ID" 
LOG_FILE="/path/to/iplog.txt"
#######################################################

# Fetch current public IP using OpenDNS
CURRENT_IPV4="$(dig +short myip.opendns.com @resolver1.opendns.com)"

# Fetch last recorded IP from the log
if [ -f "$LOG_FILE" ]; then
    LAST_IPV4="$(tail -1 $LOG_FILE | awk -F, '{print $2}')"
else
    LAST_IPV4=""
fi

if [ "$CURRENT_IPV4" = "$LAST_IPV4" ]; then
    echo "$(date): IP has not changed ($CURRENT_IPV4)"
else
    echo "$(date): IP has changed to $CURRENT_IPV4. Updating DigitalOcean..."
    
    # Update the A record via DigitalOcean API
    RESPONSE=$(curl -X PUT \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $TOKEN" \
        -d "{\"data\":\"$CURRENT_IPV4\"}" \
        "https://api.digitalocean.com/v2/domains/$DOMAIN/records/$RECORD_ID")
    
    # Log the update
    echo "$(date),$CURRENT_IPV4" >> "$LOG_FILE"
    echo "Update complete."
fi

Technical Notes:

  • Permissions: 700 on the script is crucial because it contains your TOKEN in plain text. This ensures only the file owner can read or execute it.
  • Logic: By using dig +short, we get a clean IP string without header noise, making the comparison against LAST_IPV4 much more reliable.