We love and highly recommend Digital Ocean for your hosting needs – they have a ton of features and are very fast!
One of the features they provide is the doctl command line utility which allows you to set almost anything you need remotely. A common use case we’ve come across is updating a dynamic IP. In order to do that, we wrote a bash script that you can run manually or schedule with cron.
Digital Ocean API Access
Note that you will need to log in to your Digital Ocean account and create a read/write API key. When you log in, choose API from the left or use this link: https://cloud.digitalocean.com/account/api/
Adding the doctl command line
You’ll need to have the doctl command installed on your system, which you can do by following the installation steps at the project home page on GitHub.
Our script uses the default path of /snap/bin which would be the doctl path if you install from the Snap, but you can also set the path via the command line options.
Script Options
There are three required options you must use when calling the script:
- –domain=<domain_name>
- The name of the domain where the A record lives that will be updated.
- –hostname=<record_set>
- The name of the hostname set to update without the domain.
- –accesstoken=<docker_api_key>
- Provide your docker API key here.
There are also two optional settings:
- –email=<email_address>
- Optional: Enter an email where the log will be delivered. If no email is provided, the script will not attempt to send an email.
- –doctlpath=<path_to_doctl>
- Optional: Enter the path where the doctl command is on your system. It defaults to /snap/bin.
Example Usage
/opt/scripts/digitalocean-dynamic-ip.sh –domain=yourdomain.com –hostname=dynamichost –accesstoken=your_api_key_here –email=youremail@email.com
How to Use with Cron
If you’re on a Linux system, you can run this every 30 minutes (or whatever interval you like) with cron.
Open your crontab for editing with this command:
sudo crontab -e
Then add a line like this:
*/30 * * * * /opt/scripts/digitalocean-dynamic-ip.sh --domain=yourdomain.com --hostname=dynamichost --accesstoken=your_api_key_here --email=youremail@email.com
Get the Script!
You can always find the latest version of the script on our GitHub, but here it is in it’s entirety as well:
#!/bin/bash
# Version: 1.0
# Date: 2018/08/26
# Author: Steve Talley (Dusty Sun) <steve@dustysun.com>
usage=$(cat <<"EOF"
Usage:
./doctl-updatedns.sh [--help] --record=<record_set_name>
[--ttl=<ttl_seconds>] [--type=<record_type>]
--zone=<zone_id>
Update a Digital Ocean record with your external IP address. A log file is created in the same directory as this script.
OPTIONS
--help
Show this output
--domain=<domain_name>
The name of the domain where the A record lives that will be updated.
--hostname=<record_set>
The name of the hostname set to update without the domain.
--accesstoken=<docker_api_key>
Provide your docker API key here.
--email=<email_address>
Optional: Enter an email where the log will be delivered. If no email is provided, the script will not attempt to send an email.
--doctlpath=<path_to_doctl>
Optional: Enter the path where the doctl command is on your system. It defaults to /snap/bin.
EOF
)
SHOW_HELP=0
DOMAIN=""
HOSTNAME=""
ACCESSTOKEN=""
EMAIL=""
DOCTL_PATH="/snap/bin"
# Get current dir
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
LOGFILE="$DIR/digitalocean-dynamic-ip.log"
while [ $# -gt 0 ]; do
case "$1" in
--help)
SHOW_HELP=1
;;
--domain=*)
DOMAIN="${1#*=}"
;;
--hostname=*)
HOSTNAME="${1#*=}"
;;
--accesstoken=*)
ACCESSTOKEN="${1#*=}"
;;
--email=*)
EMAIL="${1#*=}"
;;
--doctlpath=*)
DOCTL_PATH="${1#*=}"
;;
*)
SHOW_HELP=1
esac
shift
done
if [ -z "$DOMAIN" -o -z "$HOSTNAME" -o -z "$ACCESSTOKEN" ]; then
SHOW_HELP=1
fi
if [ $SHOW_HELP -eq 1 ]; then
echo "$usage"
exit 0
fi
# Start logfile fresh
echo `date` > "$LOGFILE"
# get the current ip
${DOCTL_PATH}/doctl --access-token ${ACCESSTOKEN} compute domain records list ${DOMAIN} --output json > /tmp/digitalocean.json
echo "import json" > /tmp/digitalocean.py
echo "import sys" >> /tmp/digitalocean.py
echo "from pprint import pprint" >> /tmp/digitalocean.py
echo "jdata = sys.stdin.read()" >> /tmp/digitalocean.py
echo "jsonObject = json.loads(jdata)" >> /tmp/digitalocean.py
echo "for x in jsonObject:" >> /tmp/digitalocean.py
echo " if x[\"name\"]=='${HOSTNAME}':" >> /tmp/digitalocean.py
echo " print(\"{}|{}\").format(x[\"data\"],x[\"id\"])" >> /tmp/digitalocean.py
DIGITALOCEAN_INFO=`cat /tmp/digitalocean.json | python /tmp/digitalocean.py`
DIGITALOCEAN_IP=`echo $DIGITALOCEAN_INFO |cut -d '|' -f1`
DIGITALOCEAN_ID=`echo $DIGITALOCEAN_INFO |cut -d"|" -f2`
echo Digital Ocean Record ID: ${DIGITALOCEAN_ID} >> "$LOGFILE"
echo Digital Ocean Original IP: ${DIGITALOCEAN_IP} >> "$LOGFILE"
# Get the external IP address from OpenDNS (more reliable than other providers)
IP=`dig +short myip.opendns.com @resolver1.opendns.com`
function valid_ip()
{
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}
if ! valid_ip $DIGITALOCEAN_IP; then
echo "Unable to obtain valid IP address from Digital Ocean: $DIGITALOCEAN_IP" >> "$LOGFILE"
exit 1
fi
if ! valid_ip $IP; then
echo "Invalid IP address: $IP" >> "$LOGFILE"
exit 1
fi
#compare local IP to dns record
if [ "$IP" == "$DIGITALOCEAN_IP" ]; then
# code if found
echo "IP for ${HOSTNAME}.${DOMAIN} is still $IP. No change was made to the record." >> "$LOGFILE"
exit 0
else
echo "IP has changed to $IP. Updating Digital Ocean record." >> "$LOGFILE"
#update the IP record
${DOCTL_PATH}/doctl --access-token ${ACCESSTOKEN} compute domain records update ${DOMAIN} --record-name ${HOSTNAME} --record-data ${IP} --record-id ${DIGITALOCEAN_ID} --output json >> "$LOGFILE"
fi
if [ ! -z "$EMAIL" ]; then
cat $LOGFILE | /usr/bin/mail -s "DOCTL: IP Address Update" -a "From: ${EMAIL}" $EMAIL
fi
How Did This Work For You?
Do you have any questions on this? Did it work for you? We’d love to hear your feedback! Please leave a comment below or send us an email at support@dustysun.com.
- How To: Add Coupons with Zapier (and Klaviyo) - December 31, 2021
- How To: Use SendPulse to Create a Personalized Coupon in WooCommerce - March 1, 2019
- SendPulse Support! New for Urgency Coupons for Mailing Lists - March 1, 2019