Skip to content

Instantly share code, notes, and snippets.

@sixtyfive
Last active December 10, 2022 22:48
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 sixtyfive/ef1480538a4cf6928ff690ca8dc5dfad to your computer and use it in GitHub Desktop.
Save sixtyfive/ef1480538a4cf6928ff690ca8dc5dfad to your computer and use it in GitHub Desktop.
DIY dDNS service script using Hetzner's DNS API
#!/usr/bin/env ruby
# on OpenRC systems, place into e.g. /etc/periodic/15min
# (or create /etc/periodic/1min and add line to root's crontab)
# on systemd systems, install it as a timer
# must be registered at https://robot.hetzner.com/domain
ZONE="domain-of-your-choice.tld"
RECORD="subdomain-of-your-choice"
# create/find these in Hetzner's DNS admin interface at https://dns.hetzner.com/
API_TOKEN_NAME="..."
API_TOKEN="..."
ZONE_ID="..."
RECORD_ID="..."
require 'json'
require 'socket'
unless ZONE_ID
json = JSON.parse `curl -s "https://dns.hetzner.com/api/v1/zones" -H "Auth-API-Token: #{API_TOKEN}"`
ZONE_ID = json['zones'].select{|zone| zone['name']==ZONE}[0]['id']
end
json = JSON.parse `curl -s "https://dns.hetzner.com/api/v1/records?zone_id=#{ZONE_ID}" -H "Auth-API-Token: #{API_TOKEN}"`
record = json['records'].select{|record| record['name']==RECORD}[0]
RECORD_ID ||= record['id']
current_record_ip = record['value']
current_wan_ip = Socket.getifaddrs
.map{|iface| [iface.name, iface.addr.ip_address] if iface.addr.ipv4? if iface.addr}
.compact.select{|x| x[0]=='ppp0'}[0][1]
exit if current_record_ip == current_wan_ip
system %Q(
curl -X "PUT" "https://dns.hetzner.com/api/v1/records/#{RECORD_ID}" \\
-H "Content-Type: application/json" \\
-H "Auth-API-Token: #{API_TOKEN}" \\
-d $'{
"value": "#{current_wan_ip}",
"ttl": 60,
"type": "A",
"name": "#{RECORD}",
"zone_id": "#{ZONE_ID}"
}'
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment