Set Up Supabase Locally
Guide for running a local Supabase instance for development on auth, sync, or cloud features.
Goal
Start a local Supabase stack (Postgres, Auth, Storage, Studio) so you can develop and test cloud-dependent features without connecting to the staging or production Supabase project.
Prerequisites
-
Docker Desktop installed and running (
docker infoshould succeed) -
Supabase CLI installed:
Terminal window brew install supabase/tap/supabaseVerify with
supabase --version. -
The project cloned and dependencies installed (
pnpm install)
Steps
1. Start the local Supabase stack
From the project root:
supabase startThis reads supabase/config.toml and starts Docker containers for Postgres, Auth (GoTrue), Storage, Studio, and other
services. The first run downloads container images and may take several minutes.
On success, the CLI prints a status table with connection details:
API URL: http://127.0.0.1:54321 GraphQL URL: http://127.0.0.1:54321/graphql/v1 S3 Storage URL: http://127.0.0.1:54321/storage/v1/s3 DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres Studio URL: http://127.0.0.1:54323 anon key: eyJ...service_role key: eyJ...Note the API URL and anon key values — you will need them in the next step.
2. Configure environment variables
Copy the example file if you have not already:
cp .env.example .envThe .env file is gitignored. Set the two Supabase variables to point at your local instance:
SUPABASE_URL=http://127.0.0.1:54321SUPABASE_PUBLISHABLE_KEY=<anon key from supabase start output>The Rust backend loads .env via dotenvy at startup (apps/desktop/src-tauri/src/main.rs). The SupabaseConfig
struct resolves SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY from runtime environment variables first, falling back to
compile-time values only for release builds. See crates/infrastructure/supabase/src/config.rs for the resolution
logic.
You can retrieve these values again at any time:
supabase status3. Verify the setup
Open the Supabase Studio dashboard in your browser:
http://127.0.0.1:54323Studio provides a web UI for browsing tables, running SQL, inspecting auth users, and managing storage buckets. Confirm
that you can see the tables defined in the baseline migration (e.g., users, devices, workspaces).
4. Apply and reset migrations
All Supabase (Postgres) migrations live in supabase/migrations/. The local stack applies them automatically on
supabase start. The current migration files are:
00000000000000_baseline.sql— flattened baseline covering all cloud sync tables, RLS policies, and functions20260303000000_create_templates_bucket.sql— templates storage bucket and RLS policy
To reset the local database to a clean state (drops all data, re-applies migrations and seed data):
supabase db resetThis also runs supabase/seed.sql, which creates a test auth user:
| Field | Value |
|---|---|
test@example.com | |
| Password | password123 |
| Name | Test User |
5. Run the desktop app against local Supabase
With the .env configured and supabase start running:
pnpm desktop:devIn dev mode, the app uses an in-memory auth repository instead of the OS keychain to avoid repeated keychain authorization prompts from unsigned binaries. Auth tokens are still managed identically, but they do not survive app restarts.
6. Stop Supabase
When you are done developing:
supabase stopThis stops all Docker containers but preserves the database volume. Data persists across stop/start cycles. To also
remove the database volume and start completely fresh next time:
supabase stop --no-backupCommon Issues
Docker is not running
Error: Cannot connect to the Docker daemonStart Docker Desktop before running supabase start.
Port conflicts
The local Supabase stack uses these ports (configured in supabase/config.toml):
| Service | Port |
|---|---|
| API | 54321 |
| Postgres | 54322 |
| Studio | 54323 |
If another process occupies these ports, supabase start will fail. Stop the conflicting process or edit
supabase/config.toml to use different ports (note: changing API port requires updating SUPABASE_URL in .env).
Migration errors after pulling new changes
If someone added a new migration upstream, run:
supabase db resetThis drops and recreates the local database with all migrations applied in order.
App fails to start with “Missing required environment variable”
The SupabaseConfig::from_env() call requires both SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY. Verify your .env
file exists in the project root and contains non-empty values for both. Run supabase status to confirm the local stack
is running and retrieve the correct values.
Configuration Reference
The local Supabase configuration is defined in supabase/config.toml:
- API (port 54321): REST and GraphQL endpoints
- DB (port 54322): Direct Postgres access (
postgres:postgrescredentials) - Studio (port 54323): Web dashboard
- Auth: Email signup enabled, email confirmations disabled for local dev, custom email templates in
supabase/templates/ - MFA: TOTP and WebAuthn enrollment enabled
- Storage buckets:
workspace-attachments(10 MB limit, private) andtemplates(1 MB limit, JSON only)
See Also
- Writing a Migration — adding workspace SQLite migrations (separate from Supabase Postgres migrations)
- Auth Flow — how authentication flows through the system
- Sync Flow — how sync uses Supabase for cloud storage
supabase/config.toml— local Supabase configurationsupabase/seed.sql— seed data for local developmentcrates/infrastructure/supabase/src/config.rs— environment variable resolution logic
Was this page helpful?
Thanks for your feedback!