A DNS server that serves up your ec2 instances by name.
aws-name-server --domain aws.bugsnag.com \
--aws-region us-east-1 \
--aws-access-key-id <access_key> \
--aws-secret-access-key <secret_key>
This will serve up DNS records for the following:
<name>.aws.bugsnag.com
all your EC2 instances tagged with Name=<name><n>.<name>.aws.bugsnag.com
the nth instances tagged with Name=<name><role>.role.aws.bugsnag.com
all your EC2 instances tagged with Role=<role><n>.<role>.role.aws.bugsnag.com
the nth instances tagged with Role=<role><instance-id>.aws.bugsnag.com
all your EC2 instances by instance id.<n>.<instance-id>.aws.bugsnag.com
all your EC2 instances by instance id.
It uses CNAMEs so that instances will resolve to internal IP addresses if you query from inside AWS, and external IP addresses if you query from the outside.
There's a long-winded Setup guide, but if you already know your way around EC2, you'll need to:
- Open up port 53 (UDP and TCP) on your security group.
- Boot an instance with an IAM Role with
ec2:DescribeInstances
permission. (or use an IAM user and configureaws-name-server
manually). - Install
aws-name-server
. - Setup your NS records correctly.
This is the domain you wish to serve. i.e. aws.example.com
. It is the
only required parameter.
The publically resolvable hostname of the current machine. This defaults sensibly, so you only need to set this if you see a warning in the logs.
An Amazon key pair with permission to run ec2:DescribeInstances
. This defaults to
the IAM role of the machine running aws-name-server
or to the values of the environment
variables $AWS_ACCESS_KEY_ID
and $AWS_SECRET_ACCESS_KEY
(or $AWS_ACCESS_KEY
and $AWS_SECRET_KEY
).
This defaults to the region in which aws-name-server
is running, or us-east-1
.
These instructions assume you're going to launch a new EC2 instance to run
aws-name-server
. If you want to run it on an existing server, adapt the
instructions to suit.
IAM Roles
let you give EC2 instances permission to access the AWS API. We will need our
dns machine to run ec2:DescribeInstances
.
-
Log into the AWS web console and navigate to IAM.
-
Create a new role called iam-role-aws-name-server
-
Select the Amazon EC2 role type.
-
Create a Custom Policy called describe-instances-only with the content:
{ "Version": "2012-10-17", "Statement": [{ "Action": ["ec2:DescribeInstances"], "Effect": "Allow", "Resource": "*" }] }
Security groups describe what traffic is allowed to get to your instance. DNS servers use UDP port 53 and TCP port 53.
-
Log into the AWS web console and navigate to EC2.
-
Create a new security group called aws-name-server
-
Configure it to have:
# Type # Protocol # Port # Source SSH TCP 22 My IP x.x.x.x/32 DNS UDP 53 Anywhere 0.0.0.0/0 Custom TCP 53 Anywhere 0.0.0.0/0
This will let you ssh in to the DNS server, and let anyone run DNS queries.
I recommend running 64bit HVM-based EBS-backed Ubuntu 14.04 on a t2.micro
(ami-acff23c4). You
can use whatever distro you like the most.
- Log into the AWS web console and navigate to EC2.
- Click "Launch Instance"
- Select your favourite AMI (e.g. ami-acff23c4).
- Select your favourite cheap instance type (e.g. t2.micro) (If you don't have VPCs yet, choose t1.micro instead)
- Set IAM role to iam-role-aws-name-server
- Skip through disks (the default is fine)
- Skip through tags (though if you set Name=dns1 and Role=dns you can test the server :)
- Select an existing security group
sg-aws-name-server
. - Launch!
-
Download the latest version.
wget http://gobuild.io/github.com/ConradIrwin/aws-name-server/master/linux/amd64 -O aws-name-server.zip unzip aws-name-server.zip
-
Move the binary into /usr/bin.
sudo cp aws-name-server /usr/bin sudo chmod +x /usr/bin/aws-name-server
-
(optional) Set the capabilities of aws-name-server so it doesn't need to run as root.
# the cap_net_bind_service capability allows this program to bind to ports below 1024 # when it us run as a non-root user. sudo setcap cap_net_bind_service=+ep /usr/bin/aws-name-server
If you use upstart (the default process manager under ubuntu) you can use the provided upstart script. You'll need to change the script to reflect your hostname:
- Open upstart/aws-name-server.conf and change --domain=internal to --domain <your-domain>
sudo cp upstart/aws-name-server.conf /etc/init/
sudo initctl start aws-name-server
To add your DNS server into the global DNS tree, you need to add an NS
record
from the parent domain to your new server.
Let's say you currently have DNS for example.com
, and you're running
aws-name-server
on the machine ec2-12-34-56-78.compute-1.amazonaws.com
. In
the admin page for example.com
s DNS add a new record of the form:
# name # ttl # value
aws.example.com 300 IN NS ec2-12-34-56-78.compute-1.amazonaws.com
The TTL can be whatever you want, I like 5 minutes because it's not too long to wait if I make a mistake.
The value should be a hostname for your server that is directly resolvable (i.e. not a CNAME). The public hostnames that Amazon gives instances are perfect for this.
There's a lot that can go wrong, so troubleshooting takes a while.
First try looking in the logs (/var/log/upstart/aws-name-server.log
if you're
using upstart). If there's nothing there, then try /var/log/syslog
.
Try running dig dns1.aws.example.com @localhost
while ssh'd into the machine.
It should return a CNAME
record. If not, look in the logs, the chances are
the DNS server is not running. This happens if your EC2 credentials are wrong.
Assuming you can make DNS lookups to localhost, try running
dig dns1.aws.example.com @ec2-12-34-56-78.compute-1.amazonaws.com
from your
laptop. If you don't get a reply, double check the security group config.
Assuming you can make DNS lookups correctly when pointing dig at the DNS
server, try running dig NS aws.example.com
. If this doesn't return anything,
you probably need to update your NS
records. If you've already done this, you
might need to wait a few minutes for caches to clear.
This happens when the --hostname
parameter has been set or auto-detected to
something different from what you've configured the NS
records to be. This
may cause hard-to-debug issues, so you should set --hostname
correctly.