Dynamic DNS Script


Hi folks - using MIAB to host my personal domains and absolutely love it! One thing I needed a little help with was some dynamic DNS capabilities…

Long story short - MIAB hosts one of my domains for email & web, but I wanted to have a subdomain I could use to access my VPN & NAS servers at home.

So, I wrote a shell script that runs on my pfSense gateway at home, which updates the subdomain records on the MIAB.

For Example:
box.mydomain.com (my MIAB) / IP address hosts:

But I want vpn.mydomain.com and nas.mydomain.com to point to (which is my home, dynamic IP).

So I run the attached shell script via cron on my pfSense gateway, and it will update the vpn.mydomain.com and nas.mydomain.com entries on the MIAB whenever my IP address changes.

Make sense?

Hope this is useful for someone – it is for me!



--------- CONTENTS OF dm-dyndns.sh below ---------
# dm-dyndns v1.0, dmurphy@dmurphy.com
# Shell script to provide dynamic DNS to a mail-in-the-box platform.
# Requirements:
# dig installed
# curl installed
# OpenDNS myip service availability (myip.opendns.com)
# Mailinabox host (see https://mailinabox.email)
# Mailinabox admin username/password in the CFGFILE below
# one line file of the format (curl cfg file):
# user = “username:password”
# Dynamic DNS name to be set
# DYNDNSNAMELIST file contains one hostname per line that needs to be set to this IP.


if [ ! -x $DIGCMD ]; then
  echo "$MYNAME: dig command $DIGCMD not found.  Check and fix please."
  exit 99

if [ ! -x $CURLCMD ]; then
  echo "$MYNAME: curl command $CURLCMD not found.  Check and fix please."
  exit 99

if [ ! -x $CATCMD ]; then
  echo "$MYNAME: cat command $CATCMD not found.  Check and fix please."
  exit 99

if [ ! -f $CFGFILE ]; then
  echo "$MYNAME: $CFGFILE not found.  Check and fix please."
  exit 99

if [ ! -f $DYNDNSNAMELIST ]; then
   echo "$MYNAME: $DYNDNSNAMELIST not found.  Check and fix please."
   exit 99

MYIP="`$DIGCMD +short myip.opendns.com @resolver1.opendns.com`"

  if [ -z "$MYIP" ]; then
    echo "$MYNAME: dig output was blank.  Check myip.opendns.com services."
    exit 99

  if [ -z "$PREVIP" ]; then
    echo "$MYNAME: dig output was blank.  Check $MIABHOST DNS server."
    exit 99

    if [ "x$PREVIP" = "x$MYIP" ]; then
      echo "$MYNAME: $DYNDNSNAME hasn't changed."
      echo "$MYNAME: $DYNDNSNAME changed (previously: $PREVIP, now: $MYIP)"
  STATUS="`$CURLCMD -X PUT -K $CFGFILE -s -d $MYIP https://$MIABHOST/admin/dns/custom/$DYNDNSNAME`"
  case $STATUS in
     "OK") echo "$MYNAME: mailinabox API returned OK, cmd succeded but no update.";;
     "updated DNS: $DOMAIN") echo "$MYNAME: mailinabox API updated $DYNDNSNAME OK.";;
     *) echo "$MYNAME: other status from mailinabox API. Please check.";;

    exit 0

----- Contents of dm-dyndns.cfg file below -----
user = "admin@mydomain.com:MYADMINPASSWORD"

------ Contents of dm-dyndns.dynlist below -----

Custom DNS API needs HTTP GET update for pfSense compatibility

Have you tried my Dynamic DNS script? https://github.com/mitchellurgero/mailinabox_dynamic_dns_script

Written in PHP it allows end users to create and delete DNS entries (A records only right now). With domain checking (allowing users to only delete the domains they add.) it’s alright for internal use. Probably not secure for use by external users.


Thanks Mitchell! Your PHP script is a little different use case, in that it allows end users to login and create their own A records, etc. Mine is a quick and dirty hack to allow my firewall to automatically update some entries if/when my home IP address changes. I wanted something no-touch so when my ISP changes my IP address, the DNS entries get automatically updated. Right now I have cron running my script every 10 minutes, so if my IP address changes, within 10 minutes, the A records will catch up. That’s good enough for my simple use!

Great job working on your PHP scripts; you’ve got a nice GUIfied interface to allow self-support for end users. Mine is a quick and dirty hack to solve my corner case!




Hoping this works out well. I have static IP at first ISP & dynamic on standby from dual wan Merlin router. Will attempt this evening.

Works fine :+1: I decided to keep the script on my server hosting the services.


Awesome! So glad it’s working for you… it’s saved my bacon when traveling more than once. Enjoy the weekend!


Here is another quick and dirty hack to access your home box, if you don’t necessarily need end users to access it, you just need the IP… I run basically the following in a cron job, output it to a sync’ed nextcloud directory… My address doesn’t change often (I just stick it with a name in .ssh/config for my purposes), but I can just look here on my other sync’ed systems to find it (I could theoretically write a cron job to keep a hosts file updated with the IP in this sync’ed directory if I wanted)

IP=$(/usr/bin/curl http://checkip.dyndns.org/ )
echo $IP| cut -d “>” -f 7 |cut -d “<” -f1 > /home/jay/ownCloud/home_ip.txt


Even better:

IP=$(/usr/bin/curl http://icanhazip.com) && echo $IP > /home/jay/ownCloud/ip.txt

One liners always better :wink:


Here’s something similar that I hacked together for the sake of sharing. I just run it in rc.local on all my VMs but cron might be better. There is no automated cleanup, so if you take a system out of production you need to cleanup manually. Make sure you set permissions on files in rc.local.d. I have mine set to root access only.

--------------------- rc.local


# get userid, password, and public name for server
# multiple names can map to the same server

for file in /etc/rc.local.d/*
  read -r machine server login username secret password <"$file"
  sitename=`basename $file`

  # set IPv4 and IPV6 names; comment out what you don't want to set
  curl -4 -X PUT --netrc-file $file https://$server/admin/dns/custom/$sitename/A
  curl -6 -X PUT --netrc-file $file https://$server/admin/dns/custom/$sitename/AAAA

For the files in rc.local.d, name them the FDQN of what you want to set. Example name the file “home.example.com”. Add as many files as you want to create aliases. You can even set on multiple separate MIAB “boxes” by changing the “machine” and login.

------file in rc.local.d named home.example.com

machine box.example.com login yourboxadminid@example.com password youradminpassword