It’s kind of cheating because Dynamic DNS isn’t something I learned about today. ¯\_(ツ)_/¯

I have a small Raspberry Pi server that I want to be able to SSH into from anywhere at anytime.

I have:

  • A domain

I don’t have:

  • A static IP address

SSHing into the Pi without knowing it’s IP address makes it tough. I bought my domain from Namecheap and they have a Dynamic DNS service available. They have a free software tool you can download that will broadcast the IP address back to Namecheap so that the domain can get updated with the new IP address.

But they also let you do that yourself if you want - so I thought I’d write a little script to do it and have the Pi update it’s own IP address periodically.

I wrote a Ruby script to do this for me and ran it on a cron scheduled at every hour.

0 * * * * HOST=blog DYNAMIC_DNS_DOMAIN_NAME=example.com DDNS_PASSWORD=some_password ruby path/to/dynamic_dns/app.rb >> path/to/dynamic_dns/logs/cron.log 2>&1

The gist of the script is this:

def update_dns!(previous_ip, new_ip)
  host          = ENV['HOST']
  domain_name   = ENV['DYNAMIC_DNS_DOMAIN_NAME']
  ddns_password = ENV['DDNS_PASSWORD']
  
  url = "https://dynamicdns.park-your-domain.com/update?host=#{host}&domain=#{domain_name}&password=#{ddns_password}&ip=#{new_ip}"
  require 'net/https'

  url  = URI.parse(url)
  http = Net::HTTP.new(url.host, url.port)
  req  = Net::HTTP::Get.new(url.path)

  http.use_ssl = url.port == 443
  http.start { |http| http.request(req) }
end

We need to hit the url with the host, domain, password, and new ip address.

The full script can be found here. It has some extras in there like logging and some basic validations.