A self-contained Bash script that keeps all KingDezigns DreamHost A records synchronized with the current home WAN IP. It runs every 15 minutes via OMV Scheduled Tasks. It only calls the DreamHost API when the IP actually changes (or during a nightly sanity check), so there is zero risk of being banned for spamming.
/var/log/ddns/last_wan_ip.txtDreamHost has no "update" DNS command. To change an A record you must remove the old value then add the new one. The script always fetches the live DreamHost value immediately before each remove/add pair so it never tries to remove a value that isn't there.
| Record (DreamHost "record" field) | Zone / Domain | Type |
|---|---|---|
albranch.org | albranch.org | A (root / @) |
www.albranch.org | albranch.org | A |
indigorhayne.com | indigorhayne.com | A (root / @) |
www.indigorhayne.com | indigorhayne.com | A |
rufusking.com | rufusking.com | A (root / @) |
www.rufusking.com | rufusking.com | A |
kingdezigns.com | kingdezigns.com | A (root / @) |
www.kingdezigns.com | kingdezigns.com | A |
*.web.kingdezigns.com | kingdezigns.com | A (wildcard) |
cloud.kingdezigns.com | kingdezigns.com | A |
files08.kingdezigns.com | kingdezigns.com | A |
files16.kingdezigns.com | kingdezigns.com | A |
has.kingdezigns.com | kingdezigns.com | A |
nginx.kingdezigns.com | kingdezigns.com | A |
omv08.kingdezigns.com | kingdezigns.com | A |
omv16.kingdezigns.com | kingdezigns.com | A |
pihole.kingdezigns.com | kingdezigns.com | A |
plex.kingdezigns.com | kingdezigns.com | A |
vault.kingdezigns.com | kingdezigns.com | A |
webmin.kingdezigns.com | kingdezigns.com | A |
sudo apt-get update sudo apt-get install -y curl python3 mailutils
curl fetches WAN IP and calls the DreamHost API. python3 parses the JSON responses. mailutils provides the mail command for sending HTML notifications.
sudo cp ddns_update.sh /usr/local/sbin/ddns_update.sh
This puts it in a root-only system bin directory alongside other admin utilities.
sudo chown root:root /usr/local/sbin/ddns_update.sh sudo chmod 700 /usr/local/sbin/ddns_update.sh
The script reads/writes to /var/log/ddns/ and calls sendmail — it must run as root. Mode 700 prevents other users from reading the embedded API key.
sudo mkdir -p /var/log/ddns sudo chmod 700 /var/log/ddns
The script will create this automatically on first run, but creating it manually with 700 ensures no other user can read the cached IP or logs before then.
sudo /usr/local/sbin/ddns_update.sh
Run once by hand to verify API connectivity, confirm all 20 records are found, and check that the email arrives at rufus.king@kingdezigns.com. Watch the output — it prints everything it does.
On the very first run there is no cached IP, so it will treat every record as new and perform a full update cycle.
sudo cat /var/log/ddns/ddns_run.log
You should see the WAN IP detected, DreamHost responses for each record, and "DDNS run complete" at the bottom.
OMV → System → Scheduled Tasks → + (Add) Enabled: ✓ Minute: */15 Hour: * Day: * Month: * Weekday: * User: root Command: /usr/local/sbin/ddns_update.sh
This fires the script every 15 minutes around the clock. OMV uses standard cron under the hood — you can verify with sudo crontab -l after saving.
Script is now live and fully automated.
/usr/local/sbin/ddns_update.sh
/var/log/ddns/last_wan_ip.txt
/var/log/ddns/ddns_run.log
rufus.king@kingdezigns.com
sudo /usr/local/sbin/ddns_update.sh
sudo rm /var/log/ddns/last_wan_ip.txt && sudo /usr/local/sbin/ddns_update.sh
sudo tail -f /var/log/ddns/ddns_run.log
| Scenario | Email sent? | Subject line |
|---|---|---|
| IP unchanged, not daily window | No | Silent exit — no email |
| IP changed, all records updated successfully | Yes | [DDNS] ✅ All Records Updated — <new IP> |
| IP changed, some records failed after 2 attempts | Yes — action needed | [DDNS] ⚠️ PARTIAL FAILURE — Manual action needed — <new IP> |
| Daily sanity check (00:00–00:14), all records match | Yes | [DDNS] ✅ All Records Updated — <IP> |
| Daily sanity check, mismatch found & fixed | Yes | [DDNS] ✅ All Records Updated — <new IP> |
| WAN IP discovery fails (all 3 sources down) | No | Script aborts — will retry next 15-min run |
All emails are sent as HTML using the KingDezigns branded template — same typography and color system as this document. They include a record-by-record results table and, on failure, a direct link to the DreamHost DNS panel with the correct IP pre-noted for manual entry.
| Item | Detail |
|---|---|
| API key is embedded in the script | The script is chmod 700 / root only. Do not copy or share the file without scrubbing the key first. |
| DreamHost has no "update" API command | Every update is a remove + add pair. The script always reads the live DreamHost value first so it never removes the wrong IP. |
Wildcard record *.web.kingdezigns.com |
DreamHost supports wildcard A records via API. The script passes the literal string *.web.kingdezigns.com to dns-list_records and it will match correctly. |
| Mail must be configured on NAS16 | Run sudo apt-get install mailutils and ensure your MTA (Postfix or ssmtp) is configured to relay outbound email. Test with: echo "test" | mail -s "test" rufus.king@kingdezigns.com |
| First run behavior | On the very first run there is no cached IP. The script treats every record as needing an update and performs a full cycle. This is expected and correct. |
| Daily window fires once per day | The 00:00–00:14 window aligns with the every-15-min schedule — only one run per day falls in that window. No extra logic needed. |
| Log rotation | The run log auto-trims itself to 5000 lines on every execution. No logrotate config needed. |