Skip to content

feat(db): Supabase with TLS verified against its private CA - #11

Merged
devinder-dev merged 1 commit into
mainfrom
fix/supabase-tls
Sep 23, 2026
Merged

devinder-dev merged 1 commit into
mainfrom
fix/supabase-tls

Conversation

@devinder-dev

Copy link
Copy Markdown
Owner

Why

The database moves from Neon (paused, free compute quota) to Supabase. Supabase's certificates chain to a private root CA, and the app's pg pool and the Prisma CLI read TLS settings differently — a plain sslmode=require either fails (app) or connects without checking the certificate (migrations).

What

  • backend/certs/supabase-prod-ca-2021.crt — official root, SHA-256 80:70:25:AD…E6:CA:FA, matched against the root the pooler serves
  • lib/databaseTls.ts — DATABASE_URL stays as Supabase gives it; DATABASE_CA_CERT becomes ssl: { ca } for pg and sslaccept=strict&sslcert= for the CLI
  • Fail closed: production refuses to boot without database TLS; a CA plus ssl* URL parameters is refused everywhere
  • render.yaml sets DATABASE_CA_CERT; Dockerfile ships certs/
  • ADR 53, deployment guide rewritten

Verified in the production image (no password needed — non-existent tenant)

right CA wrong CA wrong host
runtime (pg) ✅ rejected rejected
migrations (Prisma CLI) ✅ rejected rejected

Plus: verify-full&sslrootcert in the Prisma CLI accepts a wrong CA — recorded in ADR 53, never emitted.

452 backend tests pass (14 new in tests/unit/database-tls.test.ts).

Deploy order

DATABASE_URL must be the Supabase session pooler string (port 5432) with no ?sslmode= — the old Neon URL has one and would be refused with this change.

Supabase certificates chain to "Supabase Root 2021 CA", which no system
trusts. The app pool and the Prisma CLI read TLS differently, so:

- backend/certs/supabase-prod-ca-2021.crt: official root, fingerprint
  matched against the one the pooler serves
- lib/databaseTls.ts: DATABASE_URL stays plain; DATABASE_CA_CERT becomes
  ssl: { ca } for pg and sslaccept=strict&sslcert= for migrations
- measured in the production image: CLI verify-full+sslrootcert accepts a
  wrong CA; only sslaccept=strict rejects wrong CA and wrong host
- fail closed: production needs TLS on the database; a CA plus ssl* URL
  parameters is refused (pg lets the URL override the CA)
- Dockerfile ships certs/ and the helper to the generate stage
- ADR 53, deployment guide rewritten for the session pooler
@vercel

vercel Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
fakturly-app Ready Ready Preview Sep 23, 2026 1:35pm UTC

@devinder-dev
devinder-dev merged commit 0f2b850 into main Sep 23, 2026
8 checks passed

This branch was successfully deployed

1 active deployment
Preview — c5fa154b Deployed Sep 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant