[ Digital Ocean Dynamic DNS ]
🌐 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.
- Generate an API Token: DigitalOcean API Tokens
- Create an A Record: Do this manually in the DO networking dashboard first.
- 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:
700on the script is crucial because it contains yourTOKENin 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 againstLAST_IPV4much more reliable.