Skip to content

Instantly share code, notes, and snippets.

@onnimonni
Last active January 8, 2018 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save onnimonni/c4e0a9393564bdda2a3e to your computer and use it in GitHub Desktop.
Save onnimonni/c4e0a9393564bdda2a3e to your computer and use it in GitHub Desktop.
Digital Ocean dynamic dns DIY. Script which updates your DO domain records when public IP changes. Useful for services running in home office.
#!/usr/bin/env ruby
require 'json'
####MODIFY THESE#####
DOMAIN="example.com"
RECORDNAME="subdomain"
API_KEY="thahh4aevi4poophuM1eish5rashi4xoo9hoo5fish8Pie6jaekoquahy3phagoh" #This is not real api key :P
####MODIFY THESE#####
#####SCRIPT STARTS#######
##
# Super safe way to get external ip in unix system with curl installed
##
#Get external IP from untrusted source, but there's so many of them that so one should work
ip_echo_domains = ["http://wtfismyip.com/text","http://api.ipify.org/","http://ipecho.net/plain","http://icanhazip.com"]
ip_array = []
ip_echo_domains.each do |domain|
result = `curl #{domain}`
next unless result.length.between?(7,15) and result.count('.') == 3 # result is something between '8.8.8.8' and '123.123.123.132'
ip_array << result
end
#Hash frequencys and take the result with highest freq
freq = ip_array.inject(Hash.new(0)) { |h,v| h[v] += 1; h }
ip = ip_array.max_by { |v| freq[v] }
#Get list of my domain records
json_response = `curl -H "Authorization: Bearer #{API_KEY}" -H "Content-Type: application/json" \
-X GET "https://api.digitalocean.com/v2/domains/#{DOMAIN}/records"`
my_records = JSON.parse(json_response)['domain_record']
record_id = ''
my_records.each do |record|
if record['type'] == 'A' && record['name'] == RECORDNAME
exit 0 if record['data'] == ip #Exit if it hasn't changed
record_id = record['id']
break
end
end
#Update Domain Record
json_response =`curl -X PUT "https://api.digitalocean.com/v2/domains/#{DOMAIN}/records/#{record_id}" \
-d\'{"data":\"#{ip}\"}\' \
-H "Authorization: Bearer #{API_KEY}" \
-H "Content-Type: application/json"`
record = JSON.parse(json_response)['domain_record']
if record['data'] != ip
puts "Updating #{RECORDNAME}.#{DOMAIN} failed"
exit 100
else
puts "Updated #{RECORDNAME}.#{DOMAIN} succesfully"
end
@benyanke
Copy link

Here's an alternative I wrote, which I think is much more secure.

https://github.com/benyanke/configScripts/tree/master/dns-update-server

In this case, the DO api key only exists on a single central API server with this script, and every other host can connect to this api server to inform it of it's IP. This means your DO keys (which provide complete access to your DO account) are not spread around on multiple hosts.

@jjshoe
Copy link

jjshoe commented Jan 8, 2018

my_records = JSON.parse(json_response)['domain_record'] -> my_records = JSON.parse(json_response)['domain_records']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment