supabase-selfhosted-cli
v0.2.1
Published
CLI for self-hosted Supabase — deploy edge functions, push migrations, and sync types (VPS, Docker, local)
Maintainers
Readme
Supabase Selfhosted CLI
CLI for self-hosted Supabase — on a VPS, in Docker on a remote server, or running locally on your machine. Wraps the repetitive work you do by hand: deploy edge functions, restart the runtime, push migrations, and regenerate TypeScript types.
Inspired by the official Supabase CLI, but built for self-hosted layouts on your own VPS (Docker, Docker Compose, or bare metal) instead of Supabase Cloud.
Install
npm install -g supabase-selfhosted-cliyarn global add supabase-selfhosted-cliOr run from source:
git clone https://github.com/spykesocial/supabase-selfhosted-cli.git
cd supabase-selfhosted-cli
npm install
npm linkYou still need the Supabase CLI installed for db push and gen types (this package shells out to it). Supabase CLI also uses docker to create its own copy of the remote instance so you'll need docker installed when generating types.
Quick start
From your project root (where supabase/migrations lives):
supabase-selfhosted-cli setupThe wizard asks where your instance runs:
- Local machine — Docker / Docker Compose on this computer (copies files directly to your volume mount, runs restart locally)
- Remote server — VPS or cloud VM over SSH (SFTP upload + remote restart)
Remote server (VPS) example
| Setting | Example |
| --- | --- |
| SSH user | root |
| Server IP | 203.0.113.10 |
| Functions destination | /etc/supabase/volumes/functions |
| SSH password | stored once in ~/.supabase-selfhosted-cli/ |
| Postgres tenant id | your-tenant-id (from postgres.your-tenant-id) |
| DB password | your pooler password |
| Migration port | 5453 |
| Types port | 6438 |
| Restart command | e.g. docker restart <edge-container> |
Local Docker example
| Setting | Example |
| --- | --- |
| Functions destination | /path/to/supabase/docker/volumes/functions (absolute path to your edge-runtime volume mount) |
| Database host | 127.0.0.1 |
| Migration port | 5432 (or your exposed Postgres port) |
| Types port | 5432 |
| Restart command | docker compose restart edge-runtime or auto-detect edge container |
Setup creates .supabase-selfhosted-cli.json in your project so commands know which profile to use.
Commands
Deploy edge functions
Remote (SSH) — replaces:
scp -r supabase/functions/. [email protected]:/etc/supabase/volumes/functions
ssh [email protected] 'docker restart ...'Local (Docker) — replaces manually copying into your Docker volume and restarting containers.
supabase-selfhosted-cli functions deployFlags:
--restart— always restart after deploy--no-restart— never restart--prune— remove destination files/folders not present locally (use after deleting a function)- default — prompts based on your setup preference
End-to-end verification against a configured project:
npm run build
./scripts/e2e-deploy-test.sh /path/to/your-projectPush migrations
Replaces:
npx supabase db push --db-url postgresql://postgres.your-tenant-id:...@host:5453/postgres --yessupabase-selfhosted-cli db push
supabase-selfhosted-cli db push --debugGenerate TypeScript types
Replaces:
npx supabase gen types typescript --db-url postgresql://...@host:6438/postgres --schema public > database.types.tssupabase-selfhosted-cli gen types
supabase-selfhosted-cli gen types -o database.types.tsManage credentials
supabase-selfhosted-cli settings- Show masked configuration
- Re-run setup wizard
- Delete stored credentials
Configuration storage
- Profiles:
~/.supabase-selfhosted-cli/profiles/<name>.json(mode600) - Project link:
.supabase-selfhosted-cli.jsonin your repo
Passwords are stored locally on your machine. Delete them anytime via supabase-selfhosted-cli settings.
Multiple projects / instances
Each repo gets its own profile linked via .supabase-selfhosted-cli.json. Credentials live in ~/.supabase-selfhosted-cli/profiles/ and can point at different servers.
From a project directory:
# See all linked projects and which server each profile uses
supabase-selfhosted-cli projects --list
# First time in a new repo — creates profile "supabase-keepalive" from the folder name
supabase-selfhosted-cli setup
# Link this repo to an existing profile (same or different server)
supabase-selfhosted-cli projects --link
# Point this repo at a different profile
supabase-selfhosted-cli projects --switch
# Edit SSH/DB credentials for a profile
supabase-selfhosted-cli projects --edit
# Remove stored credentials for a profile
supabase-selfhosted-cli projects --deleteNamed profiles still work with -p:
supabase-selfhosted-cli setup --profile production
supabase-selfhosted-cli functions deploy --profile productionRestart command tips
Self-hosted setups differ. During setup, provide any shell command that works for your target:
# Docker (auto-detect edge container name)
docker ps --format '{{.Names}}' | grep -i edge | head -n 1 | xargs -I{} docker restart {}
# Docker Compose (local or remote)
docker compose restart edge-runtime
# Docker Compose from stack directory on the server
cd /etc/supabase/compose && docker compose restart edge-runtime
# systemd
systemctl restart supabase-edge-runtimeRoadmap
- OS keychain integration for secrets
- Remote profile sync for teams
- Migration status, function diff, and health checks
License
MIT
