DNS Management

Before I started working with Moltin, I ran a web development company (band-x.media) and built a custom CMS called Freedom. Projects that came with clients regularly ended up having some sort of DNS management requirements.

Over the course of ~10 years in business and working with hundreds of clients, I amassed DNS records for around 150 domains which were all hosted on a WHM server. WHM has a reasonable GUI for zone management and default zone templates when new clients are added but I no longer have the need for the full stack.

I wanted to gradully retire that server which is still in production as of 1st August 2018. A few clients still have some basic services on there (wordpress blogs, email etc) so migrating them to alternatives has been a recent priority. Instead of running a similar stack, which involves licensing costs and a hefty server requirement, I wanted to split those componenet services up individually rather than trying to get a one size fits all solution. Outsourcing these problems makes me sleep much easier.

So I went about first round of changes that could happen - DNS hosting. Leaving records on the existing server and migrating over before shutting down the DNS server allows this to happen gradually as there’s no rush (these things take propagation time anyways so they can’t be time sensitive.

To faciliate the transition, I decided to see if this was viable to do in terraform, using a free DNS provider. Fortunately, DigitalOcean offer exactly this directly in their terraform provider.

I wanted to have a single file with all of my domains in it, which is easy to view and edit. I learnt a lot about the limitations of variables in terraform in the process and as a result have had to workaround with a small Go program that outputs the data from a config file into a Terraform friendly version. It was painful but worthwhile.

Management

The end result is a simple configuration file that is applied to Digital Ocean. You just need an API key from them to allow terraform to edit your resources.

From there, creating your resources is simple. The current version of TF DNS DO supports A, CNAME, MX and TXT records which were required for a parity migration on my existing system.

A domain is simply defined in the config as:

domains:
  - name: example.com
    ip: 888.888.888.888
    a:
      - name: example.com.
        value: 888.888.888.888
      - name: www
        value: 888.888.888.888
    c:
      - name: mail
        value: ghs.googlehosted.com.
      - name: calendar
        value: ghs.googlehosted.com.
      - name: drive
        value: ghs.googlehosted.com.
    mx:
      - name: example.com.
        value: aspmx.l.google.com.
        priority: 1
      - name: example.com.
        value: alt1.aspmx.l.google.com.
        priority: 5
      - name: example.com.
        value: alt2.aspmx.l.google.com.
        priority: 5
      - name: example.com.
        value: alt3.aspmx.l.google.com.
        priority: 10
      - name: example.com.
        value: alt4.aspmx.l.google.com.
        priority: 10
    txt:
      - name: example.com.
        value: google-site-verification=81xFcTDuj3dQptTjmsd1pXbyC2cu5RjUYK7Ty5EUeUK

From here you simply run a make apply and confirm the change. With that done and the domains ready to be hosted on DigitalOcean, the process of changing the nameservers for each domain registrar can start. Helpfully, these are:

ns1.digitalocean.com
ns2.digitalocean.com
ns3.digitalocean.com

Issues

  • Bastardising config from toml to something TF understands is more complicated than it should be. TF have promised better handling of nested resources in the future but this touches all of their products so may take some time.
  • The TF provider has a couple of issues:
    • Updates do not get validated correctly therefore all domains are destroyed and then added again rather than doing an update when running make apply with existing resources.
    • A race condition occurs between the DO API accepting the domain creation request and it being available, so there’s a two stage plan with a sleep in it - create the zones, wait 10 secs then create the records.

Hashicorp Demo Stack

A playground for demostrating multiple parts of the Hashicorp stack including Terraform, Nomad and Consul.