Self-hosted Docker stack: Supabase + MinIO with a JSONB sharing bug fixed along the way

osama-ata adds a full self-hosted deployment path - docker-compose, Supabase stack, MinIO, multi-stage Dockerfiles - and catches a real correctness bug in the process: shared-project lookups silently return zero rows on any fork that hasn't patched the JSONB query format.

infrastructuresecurity

The Docker work covers distroless Chainguard images for MinIO (no curl, so healthchecks use mc ready local instead), condition: service_healthy chains throughout, and a forcePathStyle: true fix to the S3 client so MinIO URLs resolve correctly inside Docker's internal DNS. Kong's CORS allowlist needed expanding with PostgREST-specific headers (Accept-Profile, Content-Profile, Prefer, Range) that are absent from most example configs - their absence causes CORS rejections on PostgREST operations.

The bug worth pulling independently: access.ts and routes/projects.ts were calling .contains("shared_with", [userEmail]) against a JSONB column. PostgREST serializes a raw JS array as a Postgres array literal, which the JSONB cs. operator rejects. The fix is wrapping it in JSON.stringify(). This is a silent correctness failure - the query runs without error but returns no results, so shared projects appear invisible to anyone who doesn't own them.

The Docker scaffolding as a whole (multiple Dockerfiles, Kong config, init SQL, a Claude Code agent file) is a substantial new surface to maintain. It's well-constructed but represents a full parallel deployment path, not a small addition.

So what Pull the JSONB fix now regardless of Docker interest - it's a real data bug, two lines to fix, and it affects the shared-projects feature on any standard Supabase deployment. The `forcePathStyle: true` S3 addition is also worth taking if your fork might ever point at MinIO or another non-R2 S3 endpoint. The full Docker stack is worth adopting only if self-host is a first-class target for you.

View this fork on GitHub →

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

Commits in this thread

3 commits from osama-ata/mikeoss, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
ac06a2f6 Fix Docker healthchecks for distroless images and clear auth schema Osama Ata 2026-05-04 ↗ GitHub
commit body
- Replace curl-based minio healthcheck with `mc ready local` (chainguard image has no curl)
- Replace wget-based supabase-auth healthcheck with `gotrue version` (distroless image)
- Replace wget-based supabase-rest healthcheck with `postgrest --help` (distroless image)
- Volume was wiped to resolve gotrue uuid=text migration error on fresh Postgres 17 schema

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
55aebbdd Enhance Docker setup and configuration Osama Ata 2026-05-04 ↗ GitHub
commit body
- Update .gitignore to include .env.docker
- Revise README.md for clearer Docker Compose instructions
- Add docker-setup-validator agent for Docker configuration validation
- Create backend and frontend Dockerfiles with multi-stage builds
- Implement health checks in Dockerfiles
- Establish docker-compose configuration for Supabase integration
- Introduce .dockerignore files for backend and frontend
- Add initialization scripts for Supabase roles and configurations
- Configure CORS in Kong for Supabase services

Co-authored-by: Copilot <copilot@github.com>
baa2a5bb Fix CORS headers, JSONB query format, and S3 path-style addressing Osama Ata 2026-05-04 ↗ GitHub
commit body
- kong.yml: add full set of PostgREST headers (Accept-Profile,
  Content-Profile, Prefer, Range, etc.) to CORS allowed list
- access.ts, projects.ts: fix shared_with containment query to use
  JSON.stringify([email]) instead of [email] - avoids Postgres array
  syntax {..} which is invalid for JSONB cs. operator
- storage.ts: add forcePathStyle: true to S3Client so MinIO URLs use
  path-style (http://minio:9000/bucket) instead of virtual-hosted style
  (http://bucket.minio:9000) which fails DNS resolution

Co-Authored-By: Claude Sonnet 4.6 <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-103.md from inside the repo you want the changes in.

⬇ Download capture-thread-103.md