Supabase Local Development: Self-Hosted Setup Guide

Local Supabase development enables running complete Supabase stack on your machine using Docker providing offline development, faster iteration without API rate limits, safe experimentation without affecting production, cost-free testing, and complete control over backend infrastructure. Unlike cloud-only development requiring internet connectivity and consuming project resources, local setup offers instant feedback loops, unlimited database resets, ability to modify core services, and confidence deploying schema changes after local testing. This comprehensive guide covers installing Docker and Supabase CLI, initializing local Supabase projects, starting and stopping local services, accessing local dashboard and APIs, managing local database with migrations, seeding test data, running Edge Functions locally, syncing local and production schemas, troubleshooting common issues, and deploying local changes to cloud. Local development becomes essential when building offline-first features, testing database migrations before production, developing without internet access, iterating rapidly without API costs, or learning Supabase fundamentals in safe environment. Before proceeding, understand initial setup, migrations, and Edge Functions.
Prerequisites and Installation
# Install Docker Desktop
# Download from https://www.docker.com/products/docker-desktop
# Ensure Docker is running
# Verify Docker installation
docker --version
# Output: Docker version 24.0.0 or later
# Install Supabase CLI
# macOS/Linux
brew install supabase/tap/supabase
# Windows (with Scoop)
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase
# Or with npm (all platforms)
npm install -g supabase
# Verify Supabase CLI installation
supabase --version
# Output: 1.x.x or later
# Login to Supabase (optional, for linking)
supabase loginInitialize Local Project
# Create new project directory
mkdir my-supabase-project
cd my-supabase-project
# Initialize Supabase
supabase init
# This creates:
# supabase/
# .gitignore
# config.toml # Supabase configuration
# seed.sql # Seed data
# migrations/ # Database migrations
# functions/ # Edge Functions
# Start Supabase locally
supabase start
# Output shows:
# Started supabase local development setup.
#
# API URL: http://localhost:54321
# DB URL: postgresql://postgres:postgres@localhost:54322/postgres
# Studio URL: http://localhost:54323
# Inbucket URL: http://localhost:54324
# anon key: eyJhbGci...
# service_role key: eyJhbGci...
# Services started:
# - PostgreSQL (Database)
# - PostgREST (Data API)
# - Realtime Server
# - Storage API
# - Auth Server
# - Supabase Studio (GUI)
# - Inbucket (Email testing)Configure Local Environment
# .env.local file for your application
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-local-anon-key
# Get the anon key from
supabase status
# supabase/config.toml - Customize local setup
[api]
enabled = true
port = 54321
schemas = ["public", "storage", "graphql_public"]
max_rows = 1000
[db]
port = 54322
major_version = 15
[studio]
enabled = true
port = 54323
[auth]
enabled = true
site_url = "http://localhost:3000"
additional_redirect_urls = ["http://localhost:3000"]
enable_signup = true
[auth.email]
enable_signup = true
double_confirm_changes = true
enable_confirmations = false # For local dev
# Customize other services as neededManaging Local Services
# Start all services
supabase start
# Check status
supabase status
# Shows all running services and their URLs
# Stop all services
supabase stop
# Stop and remove all data (reset)
supabase stop --no-backup
# View logs
supabase logs
# View specific service logs
supabase logs db
supabase logs api
supabase logs auth
# Restart services after config changes
supabase stop
supabase start
# Access local Supabase Studio
# Open http://localhost:54323 in browser
# Use the Studio GUI to:
# - View and edit database tables
# - Test queries
# - Manage auth users
# - Configure storage buckets
# - View API logsDatabase Migrations Locally
# Create new migration
supabase migration new create_posts_table
# Edit the migration file in supabase/migrations/
# Example: supabase/migrations/20260125120000_create_posts_table.sql
create table posts (
id uuid default gen_random_uuid() primary key,
title text not null,
content text,
user_id uuid references auth.users(id) on delete cascade,
created_at timestamp with time zone default now()
);
alter table posts enable row level security;
create policy "Users can view all posts"
on posts for select
using (true);
create policy "Authenticated users can create posts"
on posts for insert
with check (auth.uid() = user_id);
# Apply migrations to local database
supabase db reset
# This:
# 1. Drops local database
# 2. Recreates from scratch
# 3. Applies all migrations in order
# 4. Runs seed.sql
# View migration status
supabase migration list
# Generate migration from schema diff
supabase db diff -f new_migration_name
# This compares local schema with last migration
# and creates SQL for changesSeeding Test Data
-- supabase/seed.sql
-- Runs after migrations on 'supabase db reset'
-- Create test users
insert into auth.users (
id,
instance_id,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
raw_app_meta_data,
raw_user_meta_data,
aud,
role
)
values (
'550e8400-e29b-41d4-a716-446655440000',
'00000000-0000-0000-0000-000000000000',
'[email protected]',
crypt('password123', gen_salt('bf')),
now(),
now(),
now(),
'{"provider":"email","providers":["email"]}',
'{"name":"Test User"}',
'authenticated',
'authenticated'
);
-- Create sample posts
insert into posts (title, content, user_id)
values
(
'Getting Started with Supabase',
'This is a sample post about Supabase local development.',
'550e8400-e29b-41d4-a716-446655440000'
),
(
'Building with Next.js',
'Learn how to integrate Supabase with Next.js 15.',
'550e8400-e29b-41d4-a716-446655440000'
),
(
'Real-time Features',
'Explore real-time subscriptions in Supabase.',
'550e8400-e29b-41d4-a716-446655440000'
);
-- Create test data for development
insert into categories (name, slug)
values
('Technology', 'technology'),
('Tutorial', 'tutorial'),
('News', 'news');
-- Reset and seed
-- Run: supabase db resetLocal Edge Functions
# Create new Edge Function
supabase functions new hello
# Edit supabase/functions/hello/index.ts
import { serve } from 'https://deno.land/[email protected]/http/server.ts'
serve(async (req) => {
const { name } = await req.json()
const data = {
message: `Hello ${name || 'World'}!`,
timestamp: new Date().toISOString()
}
return new Response(
JSON.stringify(data),
{ headers: { 'Content-Type': 'application/json' } },
)
})
# Serve Edge Functions locally
supabase functions serve
# Or serve specific function
supabase functions serve hello
# Test function locally
curl -i --location --request POST 'http://localhost:54321/functions/v1/hello' \
--header 'Authorization: Bearer YOUR_ANON_KEY' \
--header 'Content-Type: application/json' \
--data '{"name":"Supabase"}'
# Deploy function to cloud (when ready)
supabase functions deploy hello
# View function logs
supabase functions logs helloLinking Local and Cloud
# Link local project to cloud project
supabase link --project-ref your-project-ref
# Find your project ref in Supabase dashboard URL:
# https://app.supabase.com/project/YOUR-PROJECT-REF
# Pull remote schema to local
supabase db pull
# This creates a migration file from your cloud schema
# Push local migrations to cloud
supabase db push
# Deploy Edge Functions
supabase functions deploy
# Pull storage buckets config
supabase storage pull
# View remote database
supabase db remote ls
# Execute SQL on remote database
supabase db execute --remote < migration.sql
# Generate types from remote schema
supabase gen types typescript --linked > types/database.types.tsLocal Development Best Practices
- Use Git for Migrations: Commit migration files to version control for team collaboration
- Separate Environments: Use .env.local for local and .env.production for cloud credentials
- Test Migrations Locally First: Run supabase db reset before pushing to production
- Seed Realistic Data: Create comprehensive seed data matching production scenarios
- Use Studio for Debugging: Access local Studio at localhost:54323 for visual debugging
- Monitor Docker Resources: Local Supabase uses significant RAM and CPU
- Keep CLI Updated: Regularly update Supabase CLI for latest features and fixes
Common Issues
- Services Won't Start: Ensure Docker Desktop is running and has sufficient resources allocated
- Port Conflicts: Change ports in config.toml if default ports (543xx) are in use
- Migration Errors: Check migration SQL syntax and dependencies between migrations
- Auth Not Working: Verify site_url and redirect URLs match your local app URL in config.toml
Next Steps
- Build Applications: Integrate with React or Next.js locally
- Learn Migrations: Master database migrations workflow
- Test Edge Functions: Develop serverless functions locally
- Optimize Performance: Apply performance best practices
Conclusion
Local Supabase development using Docker provides complete backend stack on your machine enabling offline development, faster iteration without API rate limits, safe experimentation, and confidence deploying changes after local testing. By installing Docker and Supabase CLI, initializing projects with supabase init, managing services with start/stop commands, creating migrations for schema changes, seeding test data for realistic scenarios, developing Edge Functions locally, and linking local to cloud for synchronized deployments, you build production applications with robust development workflows. Local development eliminates internet dependency, provides instant feedback loops with supabase db reset, allows unlimited database resets without costs, and offers complete control over backend infrastructure for experimentation. Always test migrations locally before production deployment, commit migration files to version control for team collaboration, use separate environment variables for local and cloud, seed comprehensive test data matching production, monitor Docker resource usage, and keep Supabase CLI updated for latest features. Local setup becomes essential for building offline-first features, testing database changes safely, rapid iteration without API costs, and learning Supabase fundamentals in controlled environment. Continue building with migration workflows, Edge Functions, and production deployments.
$ share --platform
$ cat /comments/ (0)
$ cat /comments/
// No comments found. Be the first!


