Updating dynamic DNS on Amazon EC2

written by Scott on October 10th, 2007 @ 04:51 PM

basic idea

There are two steps to updating your dynamic DNS.

  1. Get your IP address
  2. Tell your dynamic DNS provider the IP address

On EC2, things are a little different from your standard hosting setup. Here’s how you get dynamic DNS working on EC2.

Getting your IP address

See this Amazon article about getting data about your instance for more information about instance data.

To make a long story short, to find out the public IP address of your EC2 instance, you make a http get request to

http://169.254.169.254/latest/meta-data/public-ipv4

Note that this has to be done from your EC2 instance.

Try it out from the command line. Log-in to your EC2 instance and type

curl http://169.254.169.254/latest/meta-data/public-ipv4

From Ruby, it’s just as simple. Cut and paste this into a script, or just run it in irb.

1
2
require 'open-uri'
ip = open('http://169.254.169.254/latest/meta-data/public-ipv4').read

Updating your DNS with your dynamic DNS provider

The following instructions assume that you want to use ez-ipupdate to update your DNS. If you don’t want to, or if ez-ipupdate doesn’t support your dynamic DNS provider, it should be relatively simple to get it working anyways.

For example, easy-dns (who I use) just requires logging in and then sending a get request formatted like this:

http://members.easydns.com/dyn/dyndns.php?hostname=example.com&myip=10.0.0.2

Installing ez-ipupdate

If you’re running Ubuntu, then install it using sudo aptitude install ez-ipupdate or sudo apt-get install ez-ipupdate. On a RedHat installation sudo yum install ez-ipupdate.

You can also install from source, of course.

When you install it using aptitude or apt-get, it will ask you for some configuration info. This won’t work on EC2, so ignore the configuration and use the script below instead.

Installing the Ruby script

Here’s the script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env ruby
require 'open-uri'
require 'yaml'

DYNAMIC_DNS_CONFIG_FILE = '/etc/ez-ipupdate/dynamic_dns.yml'
AMAZON_INSTANCE_DATA_ADDRESS = "http://169.254.169.254"
api = "latest"
ip = open(File.join(AMAZON_INSTANCE_DATA_ADDRESS, api, 'meta-data', 'public-ipv4')).read

dns_config = YAML::load(File.open(DYNAMIC_DNS_CONFIG_FILE))
hosts = dns_config['host'].split(',')
hosts.each do |host|
  puts "updating dynamic dns to ip = #{ip} for host #{host} using dynamic DNS service " +
       "#{dns_config['service']}"
  command = "ez-ipupdate --address #{ip} --service-type #{dns_config['service']} " +
            "--user #{dns_config['username']}:#{dns_config['password']} --host #{host}"
  puts command
  system(command)
end

If you’re running an ec2-on-rails instance, place the script in /usr/local/ec2-on-rails/startup-scripts/every-startup/update_dynamic_dns.rb

Otherwise, place it somewhere in your path and create a shell script to call it in /etc/init.d.

Make sure that both update_dynamic_dns.rb and the init script are executable.

The config file

Create a file called /etc/ez-ipupdate/dynamic_dns.yml. It should look something like this

1
2
3
4
5
6
7
8
9
# service should be one of the services supported by ez-ipupdate. 
# Possible values: null  ezip  pgpow  dhs  dyndns  dyndns-static 
#                         dyndns-custom ods tzo easydns easydns-partner 
#                         gnudip justlinux dyns hn zoneedit heipv6tb
# (The above list is from man ez-ipupdate)
service: service_type 
username: username_for_your_dynamic_dns_provider
password: password_for_your_dynamic_dns_provider
host: example1.com,example2.com

To update multiple hosts, put them all on the host entry, separated by commas.

Testing and debugging

Test out the script:
  • run it: ./update_dynamic_dns.rb.
  • Wait a couple of minutes.
  • ping your domain name from a local machine and make sure that it points at the right IP address.

Hopefully that works for you. Let me know if you have any problems, comments or suggestions.

Scott

Comments

  • Jim on 08 Nov 09:13

    Scott, We recently started working with EC2 and keeping a dynamic DNS in sync was a big question mark for us. This is exactly what we were looking for and it worked perfectly on our first try! Thanks! Jim
  • Scott on 08 Nov 10:03

    Jim, Thanks for the comment. It's good to hear that people are using the stuff I post here, especially if it goes well. Scott
  • Steven on 09 Nov 22:00

    Scott, I am running an ubuntu system and this worked for me on the first try. This will now allow me to completely get rid of my last windows system. Thanks, Steven
  • Scott on 12 Nov 09:00

    Glad to hear that it worked for you, Steven. Scott
  • Julien on 12 Dec 16:02

    Hey, I am using EC2 too, but my question is : if I stop my instance and decide to run another one a few hours later, do I have to upload the script again? and configure again? Is there any way to avoid this? Like, for example by saving this on my S3 bucket?
  • Scott on 13 Dec 10:11

    Julien: The easiest way to avoid having to configure and upload everything again is to create an AMI (Amazon Machine Image) file once you have everything set up how you like it (see "here":http://docs.amazonwebservices.com/AmazonEC2/dg/2006-06-26/creating-an-ami.html). This will save the state of your machine on S3. When you start up a new machine, use your new AMI and everything should be all set for you.
  • Julien on 13 Dec 12:56

    Hum... That's what I thought. You should really try to convince Paul Dowman to integrate your script in his image... I am sure that almost everyuser of ec2onrails will make use of your script sooner of later! Anyway, thanks for the good work!
  • Scott on 14 Dec 21:32

    I know, I really do need to do that. Before I do that, though I want to update the script to take advantage of instance data. I want to be able to start up a test instance without it clobbering the DNS of my real instance. -- Scott

Comments are closed