How to Configure Amazon Route53 for Naked Domain (Apex) with Subdomain CNAME Redirection


12 views

When setting up DNS records in Amazon Route53, many developers encounter the frustrating error: "RRSet of type CNAME with DNS name domain.com is not permitted at apex in zone domain.com". This occurs because DNS protocol restrictions prevent CNAME records at the zone apex (naked domain).

The fundamental issue stems from RFC 1912 and RFC 2181 specifications which state that a CNAME record cannot coexist with other records (MX, NS, SOA, etc.) at the zone apex. When you try to create a CNAME for your naked domain (like domain.com), Route53 enforces this standard.

Amazon now provides three viable approaches:

1. Using ALIAS Records (Recommended)

Route53's ALIAS records solve this elegantly by allowing apex domain resolution while adhering to DNS standards:

Name: @ (or leave blank)
Type: A - IPv4 address
Alias: Yes
Alias Target: s3-website-[region].amazonaws.com

2. S3 Website Endpoint Redirection

Configure your S3 bucket to redirect naked domain to www:

aws s3api put-bucket-website \
    --bucket example.com \
    --website-configuration '{
        "RedirectAllRequestsTo": {
            "HostName": "www.example.com",
            "Protocol": "https"
        }
    }'

3. CloudFront Distribution with Alternate Names

For advanced setups using CloudFront:

{
    "Aliases": {
        "Quantity": 2,
        "Items": ["example.com", "www.example.com"]
    },
    "ViewerCertificate": {
        "ACMCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/...",
        "SSLSupportMethod": "sni-only",
        "MinimumProtocolVersion": "TLSv1.2_2021"
    }
}

Here's a complete Terraform configuration:

resource "aws_route53_zone" "primary" {
  name = "example.com"
}

resource "aws_route53_record" "apex" {
  zone_id = aws_route53_zone.primary.zone_id
  name    = "example.com"
  type    = "A"

  alias {
    name                   = "s3-website-us-east-1.amazonaws.com"
    zone_id                = "Z3AQBSTGFYJSTF"
    evaluate_target_health = false
  }
}

resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.primary.zone_id
  name    = "www.example.com"
  type    = "CNAME"
  ttl     = 300
  records = ["example.com.s3-website-us-east-1.amazonaws.com"]
}
  • DNS propagation can take up to 48 hours (though typically faster)
  • Always verify with dig +trace example.com for accurate resolution
  • For HTTPS, ensure your SSL certificate covers both naked and www domains
  • Consider TTL values when making changes - lower them before modifications

When setting up domain routing in Amazon Route53, a common technical hurdle emerges when trying to configure the root domain (also called apex domain) - that is, yourdomain.com without the www subdomain. The error message you'll typically encounter is:

"RRSet of type CNAME with DNS name mydomain.com is not permitted at apex in zone mydomain.com"

This limitation exists because of DNS protocol specifications (RFC 1034). The root domain must have either:

  • An A record (IPv4 address)
  • An AAAA record (IPv6 address)
  • Or remain unresolved

CNAME records at the apex would interfere with other crucial DNS records like MX records for email.

Route53 provides a special solution through Alias records, which function similarly to CNAMEs but are compliant with DNS standards at the apex:

Record Type: A (IPv4)
Name: [leave blank for root domain]
Alias: Yes
Alias Target: [Select your S3 website endpoint or CloudFront distribution]

Here's exactly how to configure it in the Route53 console:

  1. Navigate to your hosted zone
  2. Create Record Set
  3. Leave the Name field empty (for root domain)
  4. Select Type "A - IPv4 address"
  5. Toggle "Alias" to "Yes"
  6. Choose your target from the dropdown (S3 website or CloudFront)
  7. Save the record

For an S3 static website, your configuration should look like:

{
    "Name": "",
    "Type": "A",
    "AliasTarget": {
        "HostedZoneId": "Z3AQBSTGFYJSTF",
        "DNSName": "s3-website-us-east-1.amazonaws.com.",
        "EvaluateTargetHealth": false
    }
}

When using CloudFront, the setup is similar but with different targets:

{
    "Name": "",
    "Type": "A",
    "AliasTarget": {
        "HostedZoneId": "Z2FDTNDATAQYW2",
        "DNSName": "d123.cloudfront.net.",
        "EvaluateTargetHealth": false
    }
}

After configuration, verify with:

dig mydomain.com +short
nslookup mydomain.com

Both should return the IP addresses of your S3 or CloudFront endpoint.

For HTTPS support at the root domain:

  • Use CloudFront rather than S3 directly
  • Request or upload an SSL certificate in ACM
  • Configure the certificate in your CloudFront distribution