DNS & Certificates¶
DNS for construo.build is on Cloudflare, not Route 53. Terraform creates
the ACM certificates; you add the validation and routing records in Cloudflare
by hand. Nothing here touches the existing planning.construo.build Worker.
What Terraform creates (F3)¶
Per environment (staging and prod — dev runs on localhost and keeps the default CloudFront certificate):
| Cert | Region | Used by | Covers |
|---|---|---|---|
acm_cloudfront |
us-east-1 (AWS requirement) | CloudFront | *.{base_domain}, {base_domain} |
acm_alb |
eu-west-2 | ALB HTTPS listener | *.{base_domain}, {base_domain} |
base_domain is staging.construo.build for staging and construo.build for
prod. Both certs use DNS validation. Terraform does not create a Route 53
zone, validation records, or an aws_acm_certificate_validation resource — it
cannot write Cloudflare records, so it must not block on validation.
All new Cloudflare records are DNS-only (grey cloud). Cloudflare does not proxy wildcards, and ACM validation records must be DNS-only regardless.
Apply order (the gate)¶
The CloudFront distribution and ALB HTTPS listener reference the cert ARNs and will not apply until the certs are ISSUED. So apply in two phases:
cd infra/terraform/environments/staging
# 1. Create the certs only.
terraform apply -target=module.acm_alb -target=module.acm_cloudfront
# 2. Read the validation CNAMEs.
terraform output acm_cloudfront_validation_records
terraform output acm_alb_validation_records
3. Add the validation CNAMEs in Cloudflare¶
For each record in the outputs (often the wildcard and bare name share one):
- Cloudflare →
construo.build→ DNS → Records → Add record. - Type: CNAME.
- Name: the host part without
.construo.build(Cloudflare appends the zone). E.g. enter_abc123.staging, not the full FQDN — the #1 cause of "validation stuck". - Target: the full
…acm-validations.awsvalue. - Proxy: DNS only.
The us-east-1 and eu-west-2 certs may present the same validation name for a given domain — one Cloudflare record then satisfies both. Add any that differ.
Validation completes a few minutes after the records resolve (aws acm
describe-certificate --certificate-arn <arn> → Status: ISSUED).
4. Apply the rest, then point the wildcard at CloudFront¶
terraform apply # CloudFront + ALB now get the issued certs
terraform output cloudfront_domain_name # e.g. d1234abcd.cloudfront.net
In Cloudflare add the tenant wildcard, DNS only:
- Type CNAME, Name
*.staging(→*.staging.construo.build), Target thecloudfront_domain_name.
If the API is reached on its own host, add api.staging → the same CloudFront
domain (the API is served through CloudFront's /api/* → ALB origin).
Prod¶
Same pattern in the prod account with base_domain = construo.build:
*.construo.build validation CNAMEs and a *.construo.build → prod CloudFront
record. A *.construo.build wildcard does not override the explicit
planning.construo.build record — DNS resolves the most specific name first.
Prerequisites / gotchas¶
- CAA: if a CAA record exists on
construo.build, ACM fails unless Amazon is allowed — add0 issue "amazon.com"(andamazonaws.com). - Cross-account state: staging/prod Terraform state lives in the dev-account
construo-terraform-statebucket. A staging/prod plan therefore needs those accounts' principals granted access to that bucket and its KMS key — see Terraform State & Accounts. Until that grant exists,terraform planfor staging/prod fails withAccessDeniedon the bucket.
Full click-level steps: platform/CLOUD-PREREQUISITES.md §6.