napple-infra (2026-11-02, batch r7): deploy the game servers to pretend.napple.lat, DNS for napple.lat, local test stack¶
Branch claude/napple-infra-2026-11-02-r7 (Mac session, base 91c5b2e). Guide: deploy-servers.
What changed¶
infra/docker/: multi-stage Dockerfiles fornapple-onlineandnapple-room(build context allowlisted to the Rust workspace, non-root Debian slim runtime,/healthzhealth checks),compose.ymlwith Caddy terminating TLS forpretend.napple.lat(/room/*-> room, the rest -> online), the NEX UDP ports and the room port published directly;compose.aws.yml(EBS bind mounts, CloudWatch logs) andcompose.build.yml.infra/terraform/bootstrap/: the S3 state bucket (locking with S3 lock files, no DynamoDB), created once by the workflow, which then migrates the stack's own state into the bucket.infra/terraform/: own VPC, public subnet, security group (80/443, 443/udp, 60000-60010/udp, 31415 tcp+udp, no SSH), t4g.micro on AL2023 with Docker + Compose from user data (8 GB root, standard CPU credits), Elastic IP, a 1 GB encrypted data volume at/var/lib/napple, instance role (SSM, ECR pull, logs), two immutable-tag ECR repositories, the log group, and the Route 53 records in the existing zone:pretendA, apex A/AAAA to GitHub Pages,wwwand*CNAME to<owner>.github.io, an optional Pages verification TXT..github/workflows/deploy-servers.yml: a guard job (secrets present? crates present?mainfor apply) that skips cleanly, bootstrap, plan/apply, native arm64 image builds to ECR, the SSM roll and the smoke test. Scripts ininfra/scripts/; trust and deploy policies ininfra/aws/.infra/local/run.sh: native local stack on 127.0.0.1 (no Docker),--stub/--bin-dirfor testing without the crates.- Stand-in image
infra/docker/stub.Dockerfile: deployed in place of a server whose crate is not onmainyet, so the whole path can go live first. - Cost: ECR keeps 3 images, logs 3 days, about $11/month at list price with the instance under the free tier.
site/CNAME=www.napple.lat.- Names per the orchestrator's contract: secret
AWS_DEPLOY_ROLE_ARN(rolenapple-deploy) + access-key fallback, variablesAWS_REGION,NAPPLE_DOMAIN,NAPPLE_ZONE_ID, environmentnapple-servers, modesbootstrap/plan/apply/destroy(destroy keeps the zone and the Pages records).
Status¶
- tested: both stacks
tofu fmt -check,validateandtofu test(10 mocked plan runs, no AWS call); actionlint and shellcheck clean; the workflow's guard and image-source steps run for 8 + 3 cases; the stand-in's entrypoint and health check run natively;docker compose configof the three compose combinations;tools/check_docs.py. - verified (plumbing only):
infra/local/run.shwith the stand-in server: start,/healthz, UDP echo on the NEX ports, TCP on the room port, refusal of a second start, clean stop, failure cleanup. - untested: the
destroypath, the Docker image builds (the stand-in's too) (no Docker on this Mac), any real AWS apply, the SSM roll, Caddy's certificate, the real server binaries (the crates were not committed on their branches at hand-off).