Skip to content

API Gateway Custom Domain

Brings up apigw.{env}.tradai-system.com for the HTTP API. All-code after a one-time hosted-zone bootstrap.

What Pulumi owns

  • ACM certificate (regional, eu-central-1) for apigw.{env}.tradai-system.com with SAN api.{env}.tradai-system.com.
  • Route 53 DNS validation records inside {env}.tradai-system.com.
  • aws.apigatewayv2.DomainName + ApiMapping (already wired in infra/edge/modules/api_gateway.py).
  • Public A-alias apigw.{env}.tradai-system.com → API Gateway regional endpoint.

What Pulumi does NOT own

  • The hosted zone {env}.tradai-system.com itself. Looked up via aws.route53.get_zone. Created once via the AWS CLI, NS records pasted into Squarespace once.

Prerequisites (per environment)

The hosted zone for {env}.tradai-system.com must exist in Route 53 and its 4 NS records must be live at the registrar (Squarespace) before pulumi up.

# 1. Create the zone (one-time, per env)
aws route53 create-hosted-zone \
  --name {env}.tradai-system.com \
  --caller-reference "$(date +%s)-{env}"

# 2. Grab the 4 NS values
aws route53 get-hosted-zone --id <ZONE_ID> --query 'DelegationSet.NameServers'

# 3. Paste into Squarespace
#    DNS Settings → Custom Records → add 4 rows:
#      Host: {env}   Type: NS   Data: <each NS value, one per row>

# 4. Verify propagation (expect the 4 AWS NS to appear)
dig +short NS {env}.tradai-system.com

Dev zone status: created 2026-06-22, ID Z00034421702TG3P6K259, NS propagation confirmed.

Deploy

just infra-up-edge {env}

Pulumi will:

  1. Request the ACM certificate (~30s).
  2. Write DNS validation records to the zone (~5s).
  3. Wait for ACM validation (~2-5min).
  4. Create the API Gateway custom DomainName + ApiMapping.
  5. Create the public A-alias.

Total: under 10 minutes from cold.

Verify

# DNS resolves
dig +short apigw.{env}.tradai-system.com

# Public TLS handshake + health
curl -fsS https://apigw.{env}.tradai-system.com/api/v1/health
# Protected paths need an M2M Bearer:
curl -fsS -H "Authorization: Bearer ${M2M_TOKEN}" \
  https://apigw.{env}.tradai-system.com/api/v1/jobs

Rollback

Flip the flag off and redeploy:

pulumi config set --stack {env} api_gateway:enable_custom_domain false --cwd infra/edge
just infra-up-edge {env}

Pulumi tears down (in order): A-alias, ApiMapping, DomainName, CertificateValidation, validation records, Certificate. The hosted zone and the frontend's existing api-{env}.tradai-system.com CNAME (on the apex zone → ALB) are untouched throughout — traffic falls back transparently.

Prod bootstrap checklist

When prod is ready:

  1. aws route53 create-hosted-zone --name prod.tradai-system.com --caller-reference "$(date +%s)-prod" (run with AWS_PROFILE=tradai).
  2. Capture the 4 NS values from the response.
  3. Squarespace → DNS Settings → Custom Records → 4 rows, host prod, type NS, one value per row.
  4. Wait for propagation: dig +short NS prod.tradai-system.com returns the 4 AWS NS.
  5. Edit infra/edge/Pulumi.prod.yaml: uncomment api_gateway:enable_custom_domain: "true".
  6. just infra-up-edge prod.
  7. Verify with the curl commands above (substituting prod).