Migrating adamcherrycomics.com to CloudFront + S3: Static Hosting with Apex Domain Aliasing

What Was Done

We migrated adamcherrycomics.com from a Namecheap URL redirect to a dedicated AWS CloudFront distribution backed by S3, enabling the apex domain to resolve with a 200 status code while serving content from s3://dc-sites/adamcherrycomics.dangerouscentaur.com/. This required provisioning an ACM certificate, building a CloudFront distribution with origin path routing, and updating DNS to alias the apex and www subdomain to the distribution.

Technical Details

Content Architecture

The adamcherrycomics static site lives in S3 at s3://dc-sites/adamcherrycomics.dangerouscentaur.com/. The site consists of:

  • index.html — Landing page with Stripe Checkout integration
  • checkout-return.html — Post-purchase confirmation page
  • Image assets (comics, product images) stored alongside HTML

The existing CloudFront distribution (dc-sites-router) uses a CloudFront function to route by Host header, allowing multiple sites from a single S3 bucket origin. For the apex domain alias requirement, we needed a dedicated distribution because CloudFront distributions cannot use the same certificate and aliases across multiple S3 origins with different OriginPath configurations.

Certificate Provisioning

We requested an ACM certificate for both adamcherrycomics.com and www.adamcherrycomics.com:

Certificate ARN: arn:aws:acm:us-east-1:782785212866:certificate/07a3c89d-3567-41e7-940c-86a4fc65e5c7
Status: Pending (awaiting DNS validation)

ACM uses DNS CNAME records for domain validation. We sent the validation CNAMEs to Adam via SMS for him to add to his Namecheap account. This two-phase approach (Phase 1: validation records, Phase 2: production DNS) ensures the certificate validates before we point production traffic.

CloudFront Distribution Configuration

The new distribution is configured with:

  • Origin: dc-sites.s3.amazonaws.com (regional S3 endpoint)
  • OriginPath: /adamcherrycomics.dangerouscentaur.com — CloudFront prepends this to all S3 requests, so /index.html becomes /adamcherrycomics.dangerouscentaur.com/index.html
  • Aliases (CNAMEs): adamcherrycomics.com, www.adamcherrycomics.com
  • SSL Certificate: Attached once ACM validation completes
  • Default Root Object: index.html
  • Viewer Protocol Policy: Redirect HTTP to HTTPS

This configuration allows users to type adamcherrycomics.com in their browser and receive a 200 status code with content served from the S3 origin at the specified OriginPath.

Why Apex Domain Aliasing Over URL Redirect

Initially, we considered a Namecheap URL Redirect (301 redirect from adamcherrycomics.comadamcherrycomics.dangerouscentaur.com). This approach is fast to deploy but:

  • Shows a redirect chain in browser history (poor UX)
  • Does not allow the apex domain to appear in the address bar
  • Requires the user to be on adamcherrycomics.dangerouscentaur.com for relative links to work correctly

The alias approach (CloudFront + ACM) allows adamcherrycomics.com to remain in the browser bar at all times, serving the same content without redirects. This is the correct pattern for branded domains.

Infrastructure & DNS

S3 Bucket Permissions

The S3 bucket dc-sites has a bucket policy allowing CloudFront to read objects:

Principal: CloudFront distribution OAI (Origin Access Identity)
Action: s3:GetObject
Resource: arn:aws:s3:::dc-sites/*

This ensures that public HTTP requests through CloudFront can fetch objects, while direct S3 bucket URLs remain restricted.

DNS Changes (Phase 2)

Once the ACM certificate reaches ISSUED status, Adam will update Namecheap DNS for adamcherrycomics.com:

  • Apex (@): Create or update CNAME/ALIAS record pointing to the CloudFront distribution domain name (e.g., d123abc.cloudfront.net)
  • www subdomain: Create or update CNAME pointing to the same CloudFront distribution
  • Remove old records: Delete any existing A records or URL redirects

Note: Traditional DNS does not allow CNAME records on the apex domain (@). However, many registrars (including Namecheap) support ALIAS or ANAME records that function like CNAMEs at the apex. The alternative is Route53 alias records if using AWS DNS.

Payment Processing & Lambda

During site inspection, we identified that the Stripe Checkout session is created by an AWS Lambda function behind API Gateway endpoint n0nh1zscq4. The Lambda code (/Users/cb/ac-lambda/checkout.py) contains:

  • CATALOG (lines 35–48): Hardcoded product amounts ($30 / $40 / $10)
  • Stripe session creation (lines 115–132): Initializes Stripe Checkout without application fees or Connect integration

The checkout flow on index.html calls this Lambda endpoint to generate a Stripe Checkout session. Upon successful payment, Stripe redirects to checkout-return.html.

Important note: The Lambda currently has no fee markup logic. If fee adjustments are needed (e.g., 1% → 3% pass-through), this must be implemented in the Lambda's session creation logic using Stripe's `application_fee_amount` field (for Connected accounts) or by adjusting the base prices in CATALOG.

Key Decisions

  • Dedicated CloudFront Distribution: Rather than reusing the existing dc-sites-router distribution with Host header routing, we provisioned a separate distribution. This simplifies the ACM certificate and alias configuration, and provides clearer billing/monitoring separation.
  • OriginPath for Multi-Tenant S3: By using OriginPath, multiple sites can coexist in the same S3 bucket without duplicating content. This is cost-effective and simplifies