What this runs
Before you start
You need:
Use security-group references, not public database endpoints:
- EC2 inbound: SSH only from the operator’s current IP. Do not expose port 3000.
- RDS inbound: PostgreSQL
5432only from the EC2 security group. - Redis inbound: TLS Redis
6379only from the EC2 security group. - EC2 outbound: HTTPS plus the approved RDS and Redis destinations.
Install
1
Connect to the EC2 instance
Connect through Session Manager when available. Otherwise use the temporary,
IP-restricted SSH rule:
2
Install Docker, Git, and PostgreSQL tools
Review the Docker installation script before running it if customer policy
requires source inspection.Install the AWS RDS CA bundle for administrative
psql commands:3
Create the two databases with the RDS administrator
Run this once with a temporary administrative connection. The application
and Better Auth roles must be separate and must not retain administrative
membership. Replace all angle-bracket values before running it.RDS requires its administrative role to install
pgvector, even when the
narrow sanity profile keeps vector search disabled. The normal migration
and runtime commands must use the restricted overlay_app role afterward.
If roles or databases already exist, inspect them instead of blindly
rerunning the creation statements.4
Clone the approved release
Use the customer-controlled repository when one exists.Record the exact commit:
5
Create the runtime files
The real environment file is ignored by Git.Edit Do not reuse a generated value. Do not paste secret values into chat,
tickets, logs, screenshots, Git, or the coding agent’s final report.Database passwords containing reserved URL characters must be URL-encoded
in
deploy/ec2/.env and replace every replace_me or replace-me
value. Generate every Overlay-owned secret independently:OVERLAY_DATABASE_URL and BETTER_AUTH_DATABASE_URL.6
Configure Google Workspace login
In a customer-controlled Google Cloud project, configure Google Auth Platform
with an Internal audience and create a Web application OAuth client.
Register these exact values:In
deploy/ec2/.env, replace example.edu with the Workspace domain and
set BETTER_AUTH_CONNECTION_CLIENT_ID and
BETTER_AUTH_CONNECTION_CLIENT_SECRET. Keep the connection ID as
workspace so it matches the callback path.Follow Google Workspace
for the complete console flow. If Auth0 is the approved broker instead,
follow Auth0 and use connection ID
auth0. Cognito, Okta, and Keycloak use Generic OIDC.7
Validate and pull the release image
Define a short helper for the remaining commands:Continue with
OVERLAY_WEB_IMAGE must name the approved versioned release, such as
ghcr.io/layernorm/overlay-web:0.1.0-rc.1. Do not use latest for a
customer qualification run. The web, worker, scheduler, and migration roles
all use the same immutable image.To build inspected or customized source instead, use the build override:compose_source instead of compose for the remaining steps
when using a source build. The override builds the tested enterprise runtime,
including the web server, worker, scheduler, and migration tooling.8
Run migrations once
Migrations must complete before any long-running service starts:The command must exit with status
0 and report that both app-data and
Better Auth migrations are current. Do not run migrations from every web,
worker, or scheduler container.9
Start web, worker, and scheduler
web to become healthy. Worker and scheduler logs should show a
successful schema check and regular runtime activity without restart loops.10
Open the SSH tunnel
From the operator’s computer, open a second terminal:Keep that terminal open and visit
http://localhost:3000. The browser and IdP see a
localhost origin while the application runs inside the customer VPC.
Verify the sanity check
Run these commands on EC2:- A signed-out user sees one
Continue with Googleoption on a single line. - Sign-in returns to
/app/chat. /api/auth/sessionreportsauthenticated: trueandemailVerified: true.- Create a conversation and send one model request.
- Rename the conversation and refresh the page.
- Restart only the web container with
compose restart web. - Refresh again and confirm the conversation and title persist.
- Sign out and confirm the session is cleared.
- Confirm the browser network and container logs contain no Convex URL.
provider: "postgres" and
requiresConvexClient: false. Features disabled by the sanity profile should
not appear as usable navigation or routes.
Troubleshooting
Stop and remove the sanity host
Paste into a coding agent
Paste the following only after authenticating the agent through the customer’s approved AWS mechanism:Next: Deploy On AWS
Replace the single EC2 host with the qualified ECS, RDS, Redis, S3, Secrets
Manager, and CloudWatch architecture.