Simplify Domain Management with Terraform

Managing DNS can be hard, but it doesn’t have to be. I would say aside from the physical connectivity itself, it is the backbone of the internet. Luckily, DigitalOcean makes managing DNS easy, which is why I have been using them for years. Instead of having to run my own BIND server or PowerDNS, etc, I can point my domains from Namecheap to DigitalOcean’s nameservers to quickly being serving traffic.

Now, there are a lot of record types we would normally need to deal with when setting up a new domain. This includes MX records for mail, TXT for domain validation with 3rd party services like Google as well as using TXT records for SPF and domain verification, and most commonly, A/AAAA/CNAME for pointing your domain to IP addresses to serve resources.

This is where the module comes in handy. I used to login to DigitalOcean and click on the Networking page, select my domain and manage my records. With terraform, I am now able to manage my resources locally in a text file, so a simple list can now easily be managed and controlled using my CI/CD pipeline. I prefer this approach because it not only allows me to recover and lost changes that I might have ran into, but if I change one service, server or IP, all of my services are updated as well.

I felt it quickly became repetitive and time consuming

Although you can easily manage DNS with the built-in terraform resources and provider, I felt it quickly became repetitive and time consuming. To help me stay on task, worry less about making mistakes or missing a step, and increasing consistency across my domains, I created a terraform module.

Leading by Example

Among my normal resource definitions, I include a call to my custom domain module. This module exists within a local modules/ directory, although at some point, I might break it out into its own repo for better version control. Within this module, there are a few variables we can pass. They include:

  • fqdn — which is the domain we are looking to manage.
  • use_gmail — which will automatically configure for use with Google Workspaces
  • google_verification — which will automatically configure the Google Workspace verification TXT record.

There are a few other options in my module that I use, but to help keep the article focused and on point, I have omitted them.module "domain" {
 source = "./modules/domain"
 fqdn   = "mikemackintosh.com"

 use_gmail           = true
 google_verification = "google-site-verification=xxxxx"
}

Defining The Module

Let’s take a look at how our module is configured. Each one of these files below can be added to directory, modules/domain.

Let’s start by defining the variables we accept and validate within our module.

modules/domain/variables.tf

We apply validation on specific variables like google_validation to make sure we are passing the right string to the right record. Failure to provide a valid Google Verification record here would throw an error during the plan/apply.

modules/domain/main.tf

Using a hack for variable presence, we are able to run, or skip, the execution of certain blocks. For example, if google_verification is not set in the call for the module, then its count is 0 and it is skipped.

modules/domain/outputs.tf

The outputs resource allows us to pass the domain from the module back to the calling script. This allows for per-domain configuration to still be configured within the calling terraform code.

Conclusion

I’ve gone from having to login and manually configure my domains to using terraform to boilerplate every new idea and service. On average, this probably saves me around 30 minutes for every new domain I purchase, configure and deploy.

How do you manage your domains?

Note: I may earn a referral bonus if you sign up using my link to DigitalOcean.

Share this post