Route 53 Hosted Zones
Overview
This service contains code to deploy Route 53 Hosted Zones and AWS Cloud Map Namespaces on AWS.
Route 53 architecture
Features
- Manage DNS entries using AWS Route 53 or AWS Cloud Map
- Optionally order and automatically verify ACM wildcard certificates for public zones
- Automatic health checks to route traffic only to healthy endpoints
- Automatic integration with other AWS services, such as ELBs
Private hosted zone record management
This module now supports creating records (including A/AAAA and alias) inside Private Hosted Zones, mirroring the
existing capabilities for Public Hosted Zones. You can define both apex-level records and subdomain records in the
private_zones
input by specifying apex_records
and subdomains
.
Example:
module "route53" {
source = "git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/networking/route53?ref=<VERSION>"
private_zones = {
"corp.internal" = {
comment = "Private zone with records"
vpcs = [{ id = "vpc-0123456789abcdef0", region = null }]
tags = { Env = "dev" }
force_destroy = true
# Apex record (e.g., corp.internal)
apex_records = [
{
type = "A"
ttl = 60
records = ["10.0.0.5"]
}
]
# Subdomain records (e.g., app.corp.internal)
subdomains = {
app = {
type = "A"
ttl = 300
records = ["10.0.1.10"]
}
# Alias to an internal ALB/NLB
svc = {
type = "A"
alias = {
name = aws_lb.internal.dns_name
zone_id = aws_lb.internal.zone_id
evaluate_target_health = true
}
}
}
}
}
}
Notes:
- Alias targets must be resolvable within the associated VPC(s) (e.g., internal ALB/NLB).
- Query private records from within the VPC(s) that are associated to the Private Hosted Zone.
Learn
This repo is a part of the Gruntwork Service Catalog, a collection of reusable, battle-tested, production ready infrastructure code. If you’ve never used the Service Catalog before, make sure to read How to use the Gruntwork Service Catalog!
- Should you use AWS Route 53 or CloudMap for your DNS entries?
- AWS Cloud Map Documentation: Amazon’s docs for AWS Cloud Map that cover core concepts and configuration.
- Route 53 Documentation: Amazon’s docs for Route 53 that cover core concepts and configuration.
Deploy
Non-production deployment (quick start for learning)
If you just want to try this repo out for experimenting and learning, check out the following resources:
- examples/for-learning-and-testing folder: The
examples/for-learning-and-testing
folder contains standalone sample code optimized for learning, experimenting, and testing (but not direct production usage).
Production deployment
If you want to deploy this repo in production, check out the following resources:
- examples/for-production folder: The
examples/for-production
folder contains sample code optimized for direct usage in production. This is code from the Gruntwork Reference Architecture, and it shows you how we build an end-to-end, integrated tech stack on top of the Gruntwork Service Catalog.
Sample Usage
- Terraform
- Terragrunt
# ------------------------------------------------------------------------------------------------------
# DEPLOY GRUNTWORK'S ROUTE53 MODULE
# ------------------------------------------------------------------------------------------------------
module "route_53" {
source = "git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/networking/route53?ref=v0.127.8"
# ----------------------------------------------------------------------------------------------------
# OPTIONAL VARIABLES
# ----------------------------------------------------------------------------------------------------
# A map of private Route 53 Hosted Zones. In this map, the key should be the
# domain name. Supports optional record management similar to public zones.
# See examples below.
private_zones = {}
# A map of public Route 53 Hosted Zones. In this map, the key should be the
# domain name. See examples below.
public_zones = {}
# A map of domain names to configurations for setting up a new private
# namespace in AWS Cloud Map.
service_discovery_private_namespaces = {}
# A map of domain names to configurations for setting up a new public
# namespace in AWS Cloud Map. Note that the domain name must be registered
# with Route 53.
service_discovery_public_namespaces = {}
}
# ------------------------------------------------------------------------------------------------------
# DEPLOY GRUNTWORK'S ROUTE53 MODULE
# ------------------------------------------------------------------------------------------------------
terraform {
source = "git::git@github.com:gruntwork-io/terraform-aws-service-catalog.git//modules/networking/route53?ref=v0.127.8"
}
inputs = {
# ----------------------------------------------------------------------------------------------------
# OPTIONAL VARIABLES
# ----------------------------------------------------------------------------------------------------
# A map of private Route 53 Hosted Zones. In this map, the key should be the
# domain name. Supports optional record management similar to public zones.
# See examples below.
private_zones = {}
# A map of public Route 53 Hosted Zones. In this map, the key should be the
# domain name. See examples below.
public_zones = {}
# A map of domain names to configurations for setting up a new private
# namespace in AWS Cloud Map.
service_discovery_private_namespaces = {}
# A map of domain names to configurations for setting up a new public
# namespace in AWS Cloud Map. Note that the domain name must be registered
# with Route 53.
service_discovery_public_namespaces = {}
}
Reference
- Inputs
- Outputs
Optional
A map of private Route 53 Hosted Zones. In this map, the key should be the domain name. Supports optional record management similar to public zones. See examples below.
Any types represent complex values of variable type. For details, please consult `variables.tf` in the source repo.
{}
Details
Allow empty maps to be passed by default - since we sometimes define only public zones or only private zones in a given module call
Details
Example (basic private zone only):
private_zones = {
"backend.local" = {
comment = "Use for arbitrary comments"
vpcs = [{ id = "vpc-1234567890", region = null }]
tags = { CanDelete = true }
force_destroy = true
}
}
Example (with private A records):
private_zones = {
"corp.internal" = {
comment = "Private zone with records"
vpcs = [{ id = "vpc-1234567890", region = null }]
tags = { Env = "dev" }
force_destroy = true
subdomains = {
api = {
type = "A"
ttl = 300
records = ["10.0.1.10"]
}
Alternatively, alias to an internal NLB/ALB etc
app = {
type = "A"
alias = {
name = aws_lb.internal.dns_name
zone_id = aws_lb.internal.zone_id
evaluate_target_health = true
}
}
}
apex_records = [
{
type = "A"
ttl = 60
records = ["10.0.0.5"]
}
]
}
}
public_zones
anyA map of public Route 53 Hosted Zones. In this map, the key should be the domain name. See examples below.
Any types represent complex values of variable type. For details, please consult `variables.tf` in the source repo.
{}
Example
Example: Request a certificate protecting only the apex domain
public_zones = {
"example.com" = {
comment = "You can add arbitrary text here"
tags = {
Foo = "bar"
}
force_destroy = true
subject_alternative_names = []
created_outside_terraform = true
create_verification_record = true
verify_certificate = true
base_domain_name_tags = {
original = true
}
apex_records = [
{
type = "MX"
ttl = 3600
records = [
"1 mx.example.com.",
"5 mx1.example.com.",
"10 mx2.example.com.",
]
},
{
type = "SPF"
ttl = 3600
records = [
"v=spf1 include:_spf.example.com ~all"
]
},
{
type = "TXT"
ttl = 3600
records = [
"v=spf1 include:_spf.example.com ~all"
]
}
]
subdomains = {
txt-test = {
type = "TXT"
ttl = 3600
records = ["hello-world"]
}
txt-test-mx = {
fqdn = "txt-test.example.com"
type = "SPF"
ttl = 3600
records = ["hello-world"]
}
txt-test-docs = {
fqdn = "docs.example.com"
type = "A"
alias = {
name = aws_elb.main.dns_name
zone_id = aws_elb.main.zone_id
evaluate_target_health = true
}
}
}
}
}
Example: Request a wildcard certificate that does NOT protect the apex domain:
public_zones = {
"*.example.com = {
comment = ""
tags = {}
force_destroy = true
subject_alternative_names = []
base_domain_name_tags = {}
create_verification_record = true
verify_certificate = true
}
}
Example: Request a wildcard certificate that covers BOTH the apex and first-level subdomains
public_zones = {
"example.com" = {
comment = ""
tags = {}
force_destroy = false
subject_alternative_names = ["*.example.com"]
base_domain_name_tags = {}
create_verification_record = true
verify_certificate = true
}
}
Details
Allow empty maps to be passed by default - since we sometimes define only public zones or only private zones in a given module call
service_discovery_private_namespaces
map(object(…))A map of domain names to configurations for setting up a new private namespace in AWS Cloud Map.
map(object({
# The ID of the VPC where the private hosted zone is restricted to.
vpc_id = string
# A user friendly description for the namespace
description = string
}))
{}
Details
A user friendly description for the namespace
Details
Default to empty map so that private namespaces are only created when requested.
A map of domain names to configurations for setting up a new public namespace in AWS Cloud Map. Note that the domain name must be registered with Route 53.
Any types represent complex values of variable type. For details, please consult `variables.tf` in the source repo.
{}
Details
Whether or not to create a Route 53 DNS record for use in validating the issued certificate. You may want to set this to false if you are not using Route 53 as your DNS provider.
create_verification_record = bool
Whether or not to attempt to verify the issued certificate via DNS entries automatically created via Route 53 records. You may want to set this to false on your certificate inputs if you are not using Route 53 as your DNS provider.
verify_certificate = bool
Whether or not to create ACM TLS certificates for the domain. When true, Route53 certificates will automatically be
created for the root domain. Defaults to true.
provision_certificates = bool
Details
Default to empty map so that public namespaces are only created when requested.
A list of ARNs of the wildcard and service discovery certificates that were provisioned along with the Route 53 zone.
The names of the internal-only Route 53 Hosted Zones
The IDs of the internal-only Route 53 Hosted Zones
The name servers associated with the internal-only Route 53 Hosted Zones
The names of the public Route 53 Hosted Zones
A map of domains to their zone IDs. IDs are user inputs, when supplied, and otherwise resource IDs
The IDs of the public Route 53 Hosted Zones
The name servers associated with the public Route 53 Hosted Zones
A map of domains to resource arns and hosted zones of the created Service Discovery Private Namespaces.
A map of domains to resource arns and hosted zones of the created Service Discovery Public Namespaces.