Skip to content

Setting up DNS Subdomain Delegation with Terraform

How do you set the default DNS NS servers for a hosted zone in Route53 using Terraform?

Sometimes you want to delegate DNS resolution for a subdomain. This happened recently for one of our clients because a third party provider offered a whitelabel service delivering email.

It’s relatively easy to set up within Route53 manually, but I struggled a bit to find the correct syntax for Terraform, which we use to manage DNS. When you are setting up delegation, there are two main pieces. You need to add an NS record in the main domain for the subdomain, pointing to the custom name servers. And you need to create a zone for that domain and make sure the default name servers for the zone are the custom name servers.
The first task was easy, you just create another record. The second turned out to be a little more challenging.

The first thing I did was consult the documentation, which is terse but good. But it wasn’t clear to me how to set the NS records of the new hosted zone. We had already set things up manually, and I then imported the zone and the records. Importing is less helpful than I thought because you basically have to create the enttiy in your .tf file and then import it via “terraform import …”. Then running “terraform plan” tells you how .tf file differs from the import. So it’s still a bit of hunting to make sure configuration lines up. Would be nice if the .tf file was just updated with the remote state.

Finally, after hunting around a bit, I realized that you can specify the default name servers for a zone by adding a record with the same name as the zone.
Here’s the new .tf entries which set up a delegated subdomain:

resource "aws_route53_zone" "sub_example_com" {
name          = ""
comment       = "Managed by Terraform, NS delegate for third party provider"
force_destroy = false
tags {
ManagedBy = "Terraform"

resource "aws_route53_record" "sub_example_com_zone_ns_record" {
zone_id = "${aws_route53_zone.example_com.zone_id}"
name    = "sub"
type    = "NS"
records = ["thirdparty.dns.server", "thirdparty2.dns.server"] ttl     = "86400" } resource "aws_route53_record" "sub_example_com_zone_default_ns_record" { zone_id = "${aws_route53_zone.sub_example_com.zone_id}" type    = "NS" name    = "" records = ["thirdparty.dns.server", "thirdparty2.dns.server"] ttl     = "86400" } 

Hope this helps someone!


Join the Culture Foundry Community

Even if you’re not ready to make the leap yet, you’ll find our community to be a helpful source of key insights and advice to help you learn more about how to thrive in digital. All are welcome.

Join the Community