amaingot lifts Mike onto AWS

A single, sweeping commit re-platforms the entire stack from Cloudflare and Supabase onto AWS-native services.

infrastructureintegration

In one go, amaingot swaps out almost every piece of infrastructure under Mike. Supabase auth gives way to Cognito (Amazon's identity service), the Cloudflare object store moves to S3, the Postgres layer is rewired through a modern query toolkit, and Claude access now flows through Bedrock - AWS's managed gateway to foundation models - instead of calling Anthropic directly. OpenAI and Gemini are left untouched.

Local development is built to mirror production: Docker Compose stands up local stand-ins for storage, auth, and email, so contributors can run the whole thing on a laptop. CI builds multi-architecture images and runs database migrations on every pull request. One product-level consequence worth noting: because Bedrock authenticates through AWS itself, the per-user 'bring your own Claude key' feature is removed and the underlying records are purged.

So what Anyone weighing whether to self-host Mike inside an AWS environment now has a working reference fork - and a clear signal that the BYO-Claude-key model is the first thing to disappear when you do.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

1 commit from amaingot/mike-aws, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
2dc27676 Re-platform from Cloudflare/Supabase to AWS Alex Maingot 2026-05-14 ↗ GitHub
commit body
Auth: Supabase Auth → AWS Cognito. Frontend uses amazon-cognito-identity-js
behind a supabase-shaped wrapper so existing call sites only changed import
paths. Backend uses aws-jwt-verify (CognitoJwtVerifier for real AWS,
JwtRsaVerifier with a custom HTTP fetcher for cognito-local). Signup page
now handles Cognito's email-confirmation step.

DB: Supabase PostgREST → RDS Postgres via Drizzle ORM. ~191 query sites
across 14 backend files (~8000 lines) rewritten. Drizzle schema mirrors
the original 17 tables minus the auth.uid()-based RLS helpers - access is
already enforced in lib/access.ts via service-role queries (defense in
depth note in the original schema.sql:1052). Initial migration committed
under backend/drizzle/. A new public.users table mirrors Cognito identities
(replaces the Postgres on-signup trigger).

Storage: R2 → S3 envs (S3_BUCKET_NAME, S3_ENDPOINT_URL, AWS_*). Endpoint
and forcePathStyle are conditional - set for MinIO locally, unset for real
AWS so the SDK uses the ECS task-role credential chain.

LLM: Anthropic SDK → @aws-sdk/client-bedrock-runtime for Claude only.
OpenAI and Gemini still call their providers directly. Per-user Claude
keys are dropped (Bedrock uses IAM); a migration purges existing rows and
narrows the user_api_keys.provider check constraint.

Account deletion: routes/user.ts now calls AdminDeleteUserCommand on the
Cognito User Pool plus a cascading delete on public.users.

Frontend runtime: Cloudflare Workers / OpenNext → Next.js standalone in
Docker (output: "standalone" + `node server.js`). Removes @opennextjs/
cloudflare, wrangler, @openrouter/sdk, @supabase/*.

Backend runtime: nixpacks → node:20-bookworm-slim with libreoffice +
fontconfig baked in for DOC/DOCX → PDF conversion.

Infra artifacts:
- frontend/Dockerfile, backend/Dockerfile (multi-stage, healthchecked)
- docker-compose.yml: postgres, cognito-local (ghcr.io/amaingot/cognito-local),
  MinIO + minio-init for bucket bootstrap, smtp4dev, backend, frontend
- scripts/bootstrap-local.sh: pre-seeds cognito-local's clients.json so the
  fork's auto-generated client id doesn't clash with the env-pinned id,
  then runs Drizzle migrations
- .github/workflows/ci.yml: PR build + lint + db:migrate against a postgres
  service
- .github/workflows/build-and-publish.yml: multi-arch (amd64/arm64) push to
  ghcr.io/<owner>/mike-{frontend,backend} on main and v* tags

End-to-end verified locally:
- docker compose up brings postgres/auth/minio/smtp to healthy
- bootstrap-local.sh provisions pool + client + bucket + schema
- Cognito signup → confirm → InitiateAuth → backend JWKS verify → users
  row auto-created (with deterministic UUID derivation for cognito-local's
  non-UUID subs)
- POST /projects, GET /projects, POST /single-documents all return 200
  with the expected DB rows and MinIO object

Operator notes captured in README.md: required AWS resources (Cognito
pool, RDS, S3, SES, Bedrock model access, ECS task role permissions),
ghcr.io → ECR re-tag flow, Bedrock model-ID verification step before
first deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-440.md from inside the repo you want the changes in.

⬇ Download capture-thread-440.md