Build Log · Infrastructure
A static site on Route 53, ACM, S3, and CloudFront — built by hand in the console as a hands-on run at AWS SAA-C03, and as the first real estate for this site itself.
Signed up a dedicated AWS account, separate from anything work-related. MFA on root first, then an IAM user (Kosichd) with AdministratorAccess for daily work — root only comes out for account-level actions from here on. A $5 monthly budget alarm went on before anything else got built, purely as a guardrail against a misconfiguration turning into a surprise bill.
Route 53 registers the domain and provisions the hosted zone in one step. First attempt failed on contact validation — Route 53 requires phone numbers in strict +1.XXXXXXXXXX format (E.164, period after the country code), not the usual dashed or parenthesized format most forms accept.
CloudFront only reads certificates issued in us-east-1, regardless of where anything else in the account lives. Requested a public certificate covering both automate-networks.com and www.automate-networks.com as Subject Alternative Names on a single cert — one certificate, both names, no need to issue twice. DNS validation, with Route 53 writing its own validation records via a one-click button.
Bucket named to match the domain, Block Public Access left fully on. The bucket is never meant to be reachable directly — only CloudFront, and only on behalf of this specific distribution, should ever read from it. index.html uploaded to the root as a placeholder to validate the pipeline end to end before writing real content.
S3 origin, Origin Access Control for the private-bucket handshake, both domain names attached as alternate domain names, the ACM cert selected, HTTP forced to HTTPS. The newer console wizard also offered to write the Route 53 alias records directly from the distribution's settings page — a nice shortcut over creating them by hand.
Alias A/AAAA records for both the apex and www, pointed at the CloudFront distribution — no IP addresses involved, Route 53 resolves straight to the edge and updates automatically if the distribution's endpoint ever changes.
First real request to the domain came back as a bare AccessDenied XML straight from S3 — no styling, no CloudFront framing, meaning the request reached the origin but got rejected there. Four hypotheses, checked in order:
index.html declared as the default, CloudFront forwards an empty key to S3. Since the bucket policy intentionally doesn't grant ListBucket, S3 answers a missing key with AccessDenied rather than a plain 404 — so a routing gap and a permissions failure produce an identical symptom. Setting the default root object resolved it immediately, no cache invalidation required.
The field is labeled "optional" in the console, which is true in general — plenty of architectures don't need it. For a static site meant to answer requests at the bare domain, it's effectively load-bearing.