Hi.
I am new to desec, but already loves your DNS service!
I have a public dynamic IP, but it does not change that often, and I am not that fond of any of the DynDNS services out there, so discovering you have an API, just made my day.
I have made this script to keep my DNS settings updated, which only interacts with desec if the IP truly has changed. Use it freely.
Here is the somewhat readerfriendly shell script:
#!/bin/bash
currentIp=$(curl --silent https://ipinfo.io/ip)
FILE=/home/user/ip.txt
touch $FILE
LOG=/home/user/logs/publicip.log
touch $LOG
echo "Date: $(date +'%Y-%m-%d')" &>> $LOG
echo "Start time: $(date +'%T')" &>> $LOG
echo "" &>> $LOG
if [ ! -s "$FILE" ]
then
ipFile="0"
else
ipFile=$(cat "$FILE")
fi
echo "$currentIp : Current IP" >> $LOG
echo "$ipFile : Stored IP" >> $LOG
if [ $currentIp != $ipFile ]
then
echo "IP Changed in store. Checking DNS......" >> $LOG
echo "$currentIp" &> $FILE
domainIP=$(curl --silent https://desec.io/api/v1/domains/yourdomain.dom/rrsets/www/A/ -H "Authorization: Token {Your own token}" | jq -r '.records[0]')
echo "Public DNS resolved IP: $domainIP" >> $LOG
if [ $currentIp != $domainIP ]
then echo "Not matching. Trying to update....." >> $LOG
apiResult=$(curl --silent -X PUT https://desec.io/api/v1/domains/yourdomain.dom/rrsets/ -H "Authorization: Token {Your own token}" -H "Content-Type: application/json" -d '[{"subname": "www", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "cloud", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "meet", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "cloud-dev", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "join", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "", "type": "TXT", "ttl": 3600, "records": ["\"protonmail-verification={Your protonmail verification hash}\"","\"v=spf1 ip4:'$currentIp' include:_spf.protonmail.ch mx -all\""]},{"subname": "cloud", "type": "TXT", "ttl": 3600, "records": ["\"v=spf1 ip4:'$currentIp' mx -all\""]}]')
echo "Waiting for zone updating...." >> $LOG
for i in {0..8}; do echo -ne "Waiting for zone update. "$i"0s of total 80s"'\r'; sleep 10s; done; echo; echo "Done." >> $LOG; echo "Re-validating NSLookup" >> $LOG
if [ $currentIp != $(curl --silent https://desec.io/api/v1/domains/yourdomain.dom/rrsets/www/A/ -H "Authorization: Token {Your own token}" | jq -r '.records[0]') ]
then
echo "Something went wrong. Please check your DNS config manually!!" >> $LOG
else
echo "Matching. Zone has been successfully updated." >> $LOG
fi
else
echo
"Matching. No need to update zone." >> $LOG
fi
else
echo "IP not changed" >> $LOG
fi
echo "" &>> $LOG
echo "Finished: $(date +'%T')" >> $LOG
echo "" &>> $LOG
echo "########################################" &>> $LOG
And here I have it as implemented.
#!/bin/bash
currentIp=$(curl --silent https://ipinfo.io/ip); FILE=/home/user/ip.txt; touch $FILE; LOG=/home/user/logs/publicip.log; touch $LOG; echo "Date: $(date +'%Y-%m-%d')" &>> $LOG; echo "Start time: $(date +'%T')" &>> $LOG; echo "" &>> $LOG
if [ ! -s "$FILE" ]; then ipFile="0"; else ipFile=$(cat "$FILE"); fi
echo "$currentIp : Current IP" >> $LOG; echo "$ipFile : Stored IP" >> $LOG
if [ $currentIp != $ipFile ]
then
echo "IP Changed in store. Checking DNS......" >> $LOG; echo "$currentIp" &> $FILE; domainIP=$(curl --silent https://desec.io/api/v1/domains/yourdomain.dom/rrsets/www/A/ -H "Authorization: Token {Your own token}" | jq -r '.records[0]'); echo "Public DNS resolved IP: $domainIP" >> $LOG
if [ $currentIp != $domainIP ]; then echo "Not matching. Trying to update....." >> $LOG; apiResult=$(curl --silent -X PUT https://desec.io/api/v1/domains/yourdomain.dom/rrsets/ -H "Authorization: Token {Your own token}" -H "Content-Type: application/json" -d '[{"subname": "www", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "cloud", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "meet", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "cloud-dev", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "join", "type": "A", "ttl": 3600, "records": ["'$currentIp'"]},{"subname": "", "type": "TXT", "ttl": 3600, "records": ["\"protonmail-verification={Your protonmail verification hash}\"","\"v=spf1 ip4:'$currentIp' include:_spf.protonmail.ch mx -all\""]},{"subname": "cloud", "type": "TXT", "ttl": 3600, "records": ["\"v=spf1 ip4:'$currentIp' mx -all\""]}]'); echo "Waiting for zone updating...." >> $LOG
for i in {0..8}; do echo -ne "Waiting for zone update. "$i"0s of total 80s"'\r'; sleep 10s; done; echo; echo "Done." >> $LOG; echo "Re-validating NSLookup" >> $LOG
if [ $currentIp != $(curl --silent https://desec.io/api/v1/domains/yourdomain.dom/rrsets/www/A/ -H "Authorization: Token {Your own token}" | jq -r '.records[0]') ]; then echo "Something went wrong. Please check your DNS config manually!!" >> $LOG; else echo "Matching. Zone has been successfully updated." >> $LOG; fi; else echo "Matching. No need to update zone." >> $LOG; fi
else echo "IP not changed" >> $LOG; fi
echo "" &>> $LOG; echo "Finished: $(date +'%T')" >> $LOG; echo "" &>> $LOG; echo "########################################" &>> $LOG
You could probably get it much cleaner by using dig short - but not if you like me, has LAN side DNS because then it just returns the LAN IP of the dig command - instead of calling an external service to reveal your public IP.