#!/bin/sh # Work with DigitalOcean api to update "A" and "AAAA" records for a domain. # Store DigitalOcean API token in file : DIGITALOCEAN_TOKEN # Store domain to be updated in file : DIGITALOCEAN_DOMAIN ip_version="$1" if [ -z "${ip_version:-}" ] || ([ "$ip_version" != 4 ] && [ "$ip_version" != 6 ]); then echo "Error: no valid IP version provided" >&2 echo "Usage: dyndns.bash <4|6> [domain]" >&2 exit 1 fi SCRIPT="$0" SCRIPT_DIR=$(cd "${SCRIPT%/*}" && pwd ) SCRIPT_NAME=${SCRIPT##*/} CACHE_DIR=${CACHE_DIR:-~/.cache/dyndns} CONFIG_DIR=${CONFIG_DIR:-~/.config/dyndns} mkdir -p ${CACHE_DIR} mkdir -p ${CONFIG_DIR} IP="$($SCRIPT_DIR/get_ip_addr.sh $ip_version)" if [ -z "$IP" ]; then echo "Error: could not find IP address" >&2 exit 1 fi DIGITALOCEAN_TOKEN=`cat ${CONFIG_DIR}/DIGITALOCEAN_TOKEN` DOMAIN=${2:-`cat ${CONFIG_DIR}/DIGITALOCEAN_DOMAIN`} SUBDOMAIN=`echo $DOMAIN | sed "s/[^.]\+\.[^.]\+$//g"` if [ -z "$SUBDOMAIN" ]; then SUBDOMAIN="@" ROOT_DOMAIN=$DOMAIN else SUBDOMAIN=`echo $SUBDOMAIN | sed "s/\.$//g"` ROOT_DOMAIN=`echo $DOMAIN | sed "s/^${SUBDOMAIN}\.//g"` fi REPEAT_CHECK_DIR=${CACHE_DIR} REPEAT_CHECK_A=$REPEAT_CHECK_DIR/REPEAT_CHECK_${DOMAIN}_A REPEAT_CHECK_AAAA=$REPEAT_CHECK_DIR/REPEAT_CHECK_${DOMAIN}_AAAA REPEAT_CHECK="$([ $ip_version = 4 ] && echo $REPEAT_CHECK_A || echo $REPEAT_CHECK_AAAA)" get_a_record_ids() { curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ "https://api.digitalocean.com/v2/domains/$ROOT_DOMAIN/records" 2> /dev/null | jq '.domain_records | map(select(.type == "A" and .name == "$SUBDOMAIN")) | map(.id) | .[]' } get_aaaa_record_ids() { curl -X GET \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ "https://api.digitalocean.com/v2/domains/$ROOT_DOMAIN/records" 2> /dev/null | jq '.domain_records | map(select(.type == "AAAA" and .name == "$SUBDOMAIN")) | map(.id) | .[]' } add_a_record() { curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ -d "{\"type\":\"A\" \ ,\"name\":\"$SUBDOMAIN\" \ ,\"data\":\"$IP\" \ ,\"priority\":null \ ,\"port\":null \ ,\"ttl\":1800 \ ,\"weight\":null \ ,\"flags\":null \ ,\"tag\":null \ }" \ "https://api.digitalocean.com/v2/domains/$ROOT_DOMAIN/records" 2> /dev/null | jq '.domain_record.id' } add_aaaa_record() { curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ -d "{\"type\":\"AAAA\" \ ,\"name\":\"$SUBDOMAIN\" \ ,\"data\":\"$IP\" \ ,\"priority\":null \ ,\"port\":null \ ,\"ttl\":1800 \ ,\"weight\":null \ ,\"flags\":null \ ,\"tag\":null \ }" \ "https://api.digitalocean.com/v2/domains/$ROOT_DOMAIN/records" 2> /dev/null | jq '.domain_record.id' } delete_record_by_id() { echo deleting existing A/AAAA record for $DOMAIN curl -X DELETE \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ "https://api.digitalocean.com/v2/domains/$ROOT_DOMAIN/records/$1" > /dev/null 2>&1 } replace_a_records() { for id in `get_a_record_ids`; do delete_record_by_id $id done new_record_id=`add_a_record` if [ "$new_record_id" = "null" ] ; then echo unable to add new A record for $DOMAIN with value: $IP return 1 fi echo added new A record for $DOMAIN with value: $IP } replace_aaaa_records() { for id in `get_aaaa_record_ids`; do delete_record_by_id $id done new_record_id=`add_aaaa_record` if [ "$new_record_id" = "null" ] ; then echo unable to add new AAAA record for $DOMAIN with value: $IP return 1 fi echo added new AAAA record for $DOMAIN with value: $IP } replace_records() { [ $ip_version = 4 ] && replace_a_records || replace_aaaa_records } # exit if previous successful call was with same argument if [ -e $REPEAT_CHECK ]; then PREVIOUS_IP=`cat $REPEAT_CHECK` if [ "$IP" = "$PREVIOUS_IP" ]; then echo previous update was also with argument: \"$IP\" so exiting now to avoid duplicate work. exit fi fi # attempt to replace records and, if successful, save arguments to check against next time if replace_records $IP; then # if successful then save arguments. echo update worked so saving arguments \"$IP\" in $REPEAT_CHECK mkdir -p $REPEAT_CHECK_DIR echo "$IP" > $REPEAT_CHECK fi