Conversation
|
Hi @jgoux, really excited about this sandbox mode - the idea of running without Docker is a great direction. I've been working on dependency optimization for the CLI (see #4741) and tested how sandbox mode interacts with binary size. Some data points that might be useful:
¹ Stubs replace The sandbox adds ~22 MB from process-compose, gin, tcell/tview, etc. Since sandbox mode is about moving away from Docker, the If binary size matters for the sandbox use case (cloud IDEs, lightweight VMs), the dependency optimizations from our fork might be worth considering: https://github.com/Raudbjorn/supabase-cli/tree/develop Happy to help if useful! |
Sandbox Mode - Fully Native Local Development Stack
Summary
Adds
supabase start --sandboxto run a minimal Supabase stack using 100% native binaries - no Docker required. Enables local development in environments where containers aren't available (cloud IDEs, CI/CD, corporate restrictions).Motivation
The Docker-based stack requires a full container runtime, which isn't always available:
Sandbox mode runs PostgreSQL, GoTrue, PostgREST, and a Go proxy as native processes, orchestrated by process-compose.
Architecture
flowchart TB subgraph CLI["supabase start --sandbox"] START[Start Command] end subgraph SERVER["Background Server Process"] PC[process-compose<br/>embedded library] HTTP[HTTP Server<br/>port N] end subgraph NATIVE["Native Processes"] PG[(PostgreSQL<br/>native binary<br/>port random)] PROXY[API Proxy<br/>supabase _proxy<br/>port random] GOTRUE[GoTrue<br/>port random] POSTGREST[PostgREST<br/>port random] end START -->|spawns detached| SERVER PC --> PG PC --> PROXY PC --> GOTRUE PC --> POSTGREST PROXY -->|/auth/v1/*| GOTRUE PROXY -->|/rest/v1/*| POSTGREST GOTRUE --> PG POSTGREST --> PGStartup Sequence
sequenceDiagram participant User participant CLI as supabase start participant Server as _sandbox-server participant PC as process-compose participant Services as postgres/proxy/gotrue/postgrest User->>CLI: supabase start --sandbox CLI->>CLI: Allocate ports CLI->>CLI: Download/extract binaries (if needed) CLI->>CLI: Initialize PostgreSQL (if first run) CLI->>CLI: Generate configs CLI->>Server: Spawn detached process Server->>PC: Initialize runner Server->>PC: Start HTTP server PC->>Services: Start all services CLI->>Server: Poll /processes (HTTP) Server-->>CLI: Services status Note over CLI: Wait until healthy CLI-->>User: "All services running" Note over CLI: CLI exits Note over Server: Server keeps runningShutdown Sequence
sequenceDiagram participant User participant CLI as supabase stop participant Server as _sandbox-server participant PC as process-compose participant Services as postgres/proxy/gotrue/postgrest User->>CLI: supabase stop CLI->>CLI: Load state.json CLI->>Server: POST /project/stop (HTTP) Server->>PC: ShutDownProject() PC->>Services: SIGTERM (reverse order) Services-->>PC: Stopped Server-->>CLI: OK alt HTTP API unavailable CLI->>CLI: Kill server PID (fallback) end CLI->>CLI: Cleanup sandbox directory Note over CLI: pgdata persists for next start CLI-->>User: "Stopped"Until the GoTrue and PostgreSQL binaries are published to GitHub releases for macOS, you must manually place the following files at the root of the
supabase/clidirectory:auth-v2.186.0-darwin-arm64supabase-postgres-17.6-darwin-arm64.zipThe CLI will automatically detect these local files and use them instead of attempting to download from GitHub releases. See the Building Binaries Locally section for instructions on how to build these.
Usage
Files Changed
cmd/start.go--sandboxflagcmd/sandbox_server.go_sandbox-servercommand for background process-compose servercmd/proxy.go_proxycommand for API reverse proxyinternal/sandbox/sandbox.gointernal/sandbox/server.gointernal/sandbox/runner.gointernal/sandbox/proxy.gointernal/sandbox/binary.gointernal/sandbox/ports.gointernal/sandbox/context.gointernal/sandbox/status.gointernal/sandbox/stop.gointernal/sandbox/templates/process-compose.yaml.tmplinternal/status/status.gointernal/stop/stop.goHow It Works
Start (
supabase start --sandbox)config.toml, falls back to random if in usesupabase-postgres-<version>-<os>-<arch>.zipconfig.tomlauth settingssupabase _proxy) with auth transformation_sandbox-serverprocessstate.jsonStatus (
supabase status)state.jsonfile and PID checkpg_isreadyStop (
supabase stop)state.jsonShutDownProject()for graceful, dependency-ordered shutdownDirectory Structure
Binary Cache (versioned, shared across projects)
Project State
State File Format
{ "pid": 12345, "ports": { "api": 54321, "postgres": 54322, "gotrue": 54323, "postgrest": 54324, "postgrest_admin": 54325, "process_compose": 54326 } }API Proxy
The sandbox includes a pure Go reverse proxy (
supabase _proxy) that replaces nginx:/auth/v1/*→ GoTrue (with auth transformation for protected endpoints)/auth/v1/verify,/auth/v1/callback,/auth/v1/authorize→ GoTrue (no auth transformation)/rest/v1/*→ PostgREST (with auth transformation)/rest-admin/v1/*→ PostgREST admin server (no auth transformation)apikeyheader to JWT Authorization (anon key → anon JWT, service role key → service role JWT)Access-Control-Allow-Origin: *)/healthendpoint for process-compose readiness probesBuilding Binaries Locally
GoTrue (darwin/arm64)
PostgreSQL Bundle
Place the postgres archive next to the CLI binary:
The CLI will extract and install it to
~/.supabase/bin/postgres/17.6/.Breaking Changes
None. The
--sandboxflag is opt-in and doesn't affect the default Docker-based workflow.