How to Configure Wildcard Subdomain (*.example.com) with Amazon Route53 and S3 Static Hosting


11 views

Here's my existing Route53 DNS configuration for a static website hosted on S3:

example.com.      A      ALIAS s3-website-us-east-1.amazonaws.com.
www.example.com. CNAME   www.example.com.s3-website-us-east-1.amazonaws.com.

Both example.com and www.example.com are configured as S3 buckets, with all HTML files residing in the root bucket (example.com). This setup works perfectly for the primary domain and www subdomain.

When attempting to add a wildcard subdomain record:

*.example.com. CNAME www.example.com.s3-website-us-east-1.amazonaws.com.

Accessing joker.example.com returns this error:

Code: NoSuchBucket
Message: The specified bucket does not exist
BucketName: joker.example.com

The issue occurs because S3 attempts to look for a bucket named exactly as the requested subdomain (joker.example.com), rather than routing to our main bucket. This is the default behavior of S3 website hosting.

We need to modify our approach in two ways:

  1. Create a proper wildcard DNS record that points to our primary S3 endpoint
  2. Configure S3 to handle the wildcard requests properly

1. DNS Configuration

Update your Route53 record to:

*.example.com. ALIAS example.com.s3-website-us-east-1.amazonaws.com.

2. S3 Bucket Policy

Add this bucket policy to your primary bucket (example.com):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example.com/*"
    }
  ]
}

For more complex requirements, consider using CloudFront:

1. Create a CloudFront distribution
2. Set the origin to your S3 bucket (example.com.s3.amazonaws.com)
3. Configure alternate domain names:
   - example.com
   - *.example.com
4. Update Route53 to point both root and wildcard to CloudFront

After implementing the solution:

dig +short test.example.com
curl -I http://test.example.com

Should return proper responses from your S3 bucket.


My existing Route53 DNS configuration for a static S3-hosted website works perfectly for the root domain and www subdomain:

example.com.        A     ALIAS s3-website-us-east-1.amazonaws.com.
www.example.com.    CNAME www.example.com.s3-website-us-east-1.amazonaws.com.

Both example.com and www.example.com properly resolve to my S3 bucket containing the static website files. However, attempts to access any other subdomain (e.g., test.example.com) fail with:

Code: NoSuchBucket
Message: The specified bucket does not exist
BucketName: test.example.com

The initial wildcard DNS configuration I tried:

*.example.com. CNAME www.example.com.s3-website-us-east-1.amazonaws.com.

This doesn't work because S3 expects the Host header to match exactly the bucket name. When visiting test.example.com:

  1. DNS resolves correctly via the wildcard record
  2. The request reaches S3 with Host: test.example.com
  3. S3 looks for a bucket named "test.example.com" (which doesn't exist)

We need two modifications:

1. Update Route53 Wildcard Record

Point the wildcard to the same endpoint as your www record:

*.example.com. CNAME example.com.s3-website-us-east-1.amazonaws.com.

2. Configure S3 Bucket Redirect

Create a new S3 bucket for each wildcard subdomain you want to support (or automate this via CloudFormation). For each subdomain bucket (e.g., test.example.com):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::test.example.com/*"
    }
  ]
}

Then enable static website hosting with redirect:

{
  "RedirectAllRequestsTo": {
    "HostName": "example.com",
    "Protocol": "https"
  }
}

For dynamic wildcard handling without creating multiple buckets:

exports.handler = async (event) => {
  const request = event.Records[0].cf.request;
  const host = request.headers.host[0].value;
  
  if (host.endsWith('example.com') && !['example.com','www.example.com'].includes(host)) {
    return {
      status: '301',
      statusDescription: 'Moved Permanently',
      headers: {
        'location': [{
          key: 'Location',
          value: 'https://example.com'
        }]
      }
    };
  }
  return request;
};

Attach this Lambda function to your CloudFront distribution's Viewer Request trigger.

  • Wildcard SSL certificates must cover *.example.com
  • CloudFront caching may need adjustment for dynamic subdomains
  • Consider DNS TTL values during configuration changes