Terraform Hosted Zone Modules and Route53 Data Sources in AWS

Terraform hosted zone management spans creation modules that provision Route53 namespaces and data sources that reference pre-existing zones without import. The reference material covers a certificate-aware hosted zone module, the aws_route53_zone data source for lookup by name, ID, and tags, a delegation set capable module, the core Zones Module from the terraform-aws-route53 repository, and operational guidance on record types and nameserver outputs. Each of these artifacts reflects a different layer of DNS lifecycle control in AWS, from initial provisioning to cross-team reuse and delegation.

The practice of separating zone ownership from application record management is common. Hosted zones often predate Terraform adoption, are shared across multiple teams, and are managed separately from application-level infrastructure. Rather than importing these zones into every Terraform workspace that needs them, data sources let you look up hosted zones and use their attributes wherever you need them. This separation reduces coupling, avoids state collisions, and preserves the authority of a central platform team over the DNS namespace.

Terraform Module for Hosted Zone with Optional ACM Certificate

The rhythmictech hosted zone module creates a Route53 zone and optional wildcard certificate matching it. The module source is referenced as rhythmictech/hosted-zone/aws.

module "zone" { source = "rhythmictech/hosted-zone/aws" }

Version constraints documented for the module are:

  • terraform >= 0.12.19
  • aws >= 3.0

The module accepts the following inputs:

Name Description Type Default Required
domain Domain for hosted zone string n/a yes
create_certificate Create an ACM certificate associated with the domain bool true no
name Name tag to apply (will default to external_domain if not specified) string null no
tags Custom tags to add to resources map(string) {} no

The domain input is required and defines the DNS namespace that will be provisioned. The createcertificate flag defaults to true, meaning an ACM certificate is created alongside the zone unless explicitly disabled. The name tag provides a human readable identifier for the resources, falling back to externaldomain when omitted. Tags are passed through as a map of strings.

The module produces the following outputs:

Name Description
certificate_arn ACM SSL Certificate ARN
zone_id Zone ID
zone_name Zone name
zonenameservers Zone Name Servers

The certificatearn output allows downstream resources to reference the certificate created by the module for use with load balancers, CloudFront distributions, or API Gateway custom domains. The zoneid is the canonical identifier used by Route53 for record creation and data source lookups. The zonename reflects the configured domain and zonename_servers provides the four authoritative nameservers that must be registered with the domain registrar.

In practice, teams that adopt this module gain a single declaration point for both DNS namespace and TLS credential. The impact is reduced drift between certificate validity and zone existence, and a clear output set for export to other workspaces. Because the module creates the certificate by default, an operator who does not intend wildcard coverage can set create_certificate to false to avoid unnecessary ACM resources.

Data Source Lookup for Existing Route53 Hosted Zones

The aws_route53_zone data source supports looking up zones by name, zone ID, tags, or filters such as privatezone and vpcid. This capability is central to multi-team and multi-account architectures where the zone is owned centrally but referenced widely.

Lookup by Domain Name

data "aws_route53_zone" "main" { name = "example.com" private_zone = false }

The trailing dot is optional - Terraform handles both formats. "example.com" and "example.com." both work.

output "zone_info" { value = { zone_id = data.aws_route53_zone.main.zone_id name = data.aws_route53_zone.main.name name_servers = data.aws_route53_zone.main.name_servers } }

Using the domain name for lookup decouples Terraform configurations from hardcoded IDs. The real world consequence is portability across accounts and environments where the same logical domain may be recreated with different IDs. The private_zone argument filters to private hosted zones when set to true, enabling VPC-scoped DNS lookups.

Lookup by Zone ID

data "aws_route53_zone" "specific" { zone_id = "Z1234567890ABC" }

output "zone_name" { value = data.aws_route53_zone.specific.name }

Direct ID lookup is useful when the zone identifier is known from external systems, documentation, or previous outputs. It avoids name resolution ambiguity and is deterministic.

Lookup by Tags

data "aws_route53_zone" "tagged" { tags = { Environment = "production" ManagedBy = "platform-team" } }

Tag based lookup enables convention driven discovery. Teams can assign Environment and ManagedBy tags to zones and then find the correct zone without knowing the exact name. This pattern supports governance and automated compliance checks.

Public vs Private Hosted Zones

AWS Route53 supports both public and private hosted zones. Public zones are resolvable over the internet. Private zones are resolvable only within associated VPCs. The data source exposes privatezone and vpcid filters to narrow results.

Operational notes from the reference material include:

  • Zone names in Route53 always end with a trailing dot. The data source handles this for you, but be aware of it when debugging.
  • If you get a "no matching zone found" error, double-check the zone name spelling and ensure your AWS credentials have permission to list hosted zones.

The trailing dot detail is a common source of confusion when comparing Terraform state with AWS console output. Awareness prevents false mismatches during troubleshooting. Permission errors for listing hosted zones manifest as lookup failures even when the zone exists, highlighting the importance of least privilege IAM scoping.

The guide covers how to query public and private hosted zones, use their attributes in record creation, and handle common patterns like multi-account DNS architectures. By looking up zones dynamically instead of hardcoding zone IDs, configurations become more portable, easier to read, and less likely to break when zone IDs change.

Delegation Sets and Root and Delegated Zone Creation

The cytopia terraform-aws-route53-zone module is able to create an arbitrary number of delegation sets, public and private hosted zones for root and delegated domains.

Public hosted zones can be created with or without a delegation set. Private hosted zones will always have the default VPC from the current region attached, but can optionally also attach more VPCs from any region.

When adding delegated secondary zones, the NS records are added automatically to their corresponding root zone. The only thing you need to choose, is the TTL (in seconds), of those NS records, per item.

Example usage:

module "public_zone" { source = "github.com/cytopia/terraform-aws-route53-zone?ref=v1.0.0" delegation_sets = [ "root-zone", "sub-zone", ] public_root_zones = [ { name = "example.com", delegation_set = "root-zone", }, { name = "example.org", delegation_set = null, }, ] }

The delegation_sets list defines named delegation sets to be created. Public root zones reference a delegation set by name or null to use AWS defaults. The module supports creation of delegated secondary zones with automatic NS record insertion into parent zones.

The impact for organizations with hierarchical DNS is automated delegation without manual NS record maintenance. The TTL choice per item gives control over propagation timing for subdomains. Private zones defaulting to the current region VPC simplifies secure DNS for internal services while still allowing additional VPC attachments across regions.

Terraform AWS Modules Zones Core Component

The Zones Module is a core component of the terraform-aws-route53 repository that provides a simple, reusable interface for creating and managing AWS Route53 hosted zones. This module specifically handles the provisioning of DNS namespaces in AWS, which serve as containers for DNS records. For information about managing DNS records within these zones, see Records Module.

The module creates AWS Route53 zones using a simple, map-based input structure. It supports both public and private hosted zones, with VPC associations for private zones.

The module creates a single resource type:

Resource Description
awsroute53zone Creates a Route53 zone (public or private)

Inputs accepted by the module are:

Input Name Description Type Default Required
create Whether to create Route53 zone bool true no
tags Tags added to all zones (precedence over zone-specific tags) map(any) {} no
zones Map of Route53 zone parameters any {} no

The primary input is the zones variable, which is a map of zone configurations. The create flag allows conditional provisioning, useful for feature flags or environment specific enablement. Tags are applied to all zones with precedence over zone-specific tags, supporting consistent cost allocation and ownership metadata.

The map-based zones input enables bulk creation of multiple zones from a single module call, reducing repetition and enabling data driven deployments.

DNS Record Types and Hosted Zone Outputs

Route53 supports a variety of record types for different resolution needs.

Type Purpose Example
A IPv4 address 1.2.3.4
AAAA IPv6 address 2001:db8::1
CNAME Canonical name app.example.com → lb.aws.com
MX Mail exchange 10 mail.example.com
TXT Text (SPF, DKIM) v=spf1 include:...
NS Name servers Delegated zone
Alias AWS-native (free) ALB, CloudFront, S3

Use alias records (free, no TTL) for AWS services instead of CNAME. Add health checks with failover routing for high availability. Use weighted routing for blue-green deployments. Always output nameservers after creating a hosted zone so you can update the registrar.

The recommendation to output nameservers after creating a hosted zone reflects the operational step of registering the zone with an external registrar via NS record updates. Alias records avoid additional DNS lookups and TTL limitations compared to CNAME. Health checks and weighted routing provide resilience and deployment strategies within the same zone.

The combination of zone creation modules, data source lookups, delegation automation, and record type awareness forms a complete workflow for DNS as code. Zones are provisioned once, referenced widely via data sources, and records are managed in separate workspaces. Delegation sets enable sub-team ownership while maintaining root authority. Outputs for certificate ARNs and nameservers connect Terraform state to external systems such as registrars and TLS termination.

Sources

  1. rhythmictech/terraform-aws-hosted-zone
  2. oneuptime.com blog post on Terraform data sources Route53 hosted zones
  3. cytopia/terraform-aws-route53-zone
  4. deepwiki terraform-aws-route53 zones module
  5. terraformpilot AWS Route53 DNS with Terraform

Related Posts