Move a project from Supabase
One command copies a Supabase project (Cloud or self-hosted) into a new Sbarbase environment: tables, row level security, users with their passwords, and Storage files. Your application keeps using supabase-js; only the address and the key change.
1. Check first
From the Supabase dashboard, open Connect and copy the Session pooler or direct connection string with your database password. Then, on the Sbarbase server:
python3 lab/import_project.py <environment> --dry-run <<'JSON'
{"database_url": "postgresql://postgres.<ref>:<db password>@aws-0-<region>.pooler.supabase.com:5432/postgres"}
JSONIt reads the project without changing anything and lists what stops the import (for example Vault secrets, or an extension this server does not have), what behaves differently, and what you will set again by hand.
2. Import
Create a new, empty environment in the console, then run the same command without --dry-run, adding the project's API address and its service_role key (Project Settings, API) so the Storage files can be copied:
python3 lab/import_project.py <environment> --report import-report.json <<'JSON'
{"database_url": "postgresql://postgres.<ref>:<db password>@aws-0-<region>.pooler.supabase.com:5432/postgres",
"api_url": "https://<ref>.supabase.co", "service_role_key": "<service_role key>"}
JSONSettings are read from stdin, never from the command line, so passwords appear in no process list. The source is only read.
What moves, in order:
- The
publicschema: tables, views, functions, policies and your own triggers, with the grants the source gaveanon,authenticatedandservice_role, and no more. - Users and their sign-in identities with password hashes: people sign in with their old passwords.
- Every row in
public. - Buckets, then every file, with its owner, so Storage policies on
owner_idkeep working. - Your triggers on
auth.usersandstorage.objects(for example "create a profile at sign-up"), recreated after the rows so they do not run again for imported users. - A comparison of row counts, users, identities, buckets and files, source against target. The import only reports success when they all match.
3. Point your application at Sbarbase
- Create a publishable key on the environment's page.
- Replace the Supabase URL and anon key in your application with the environment's address and the new key.
- Set again what lives outside the database: sign-in settings and OAuth providers, email, Edge Functions (deploy the same
supabase/functionsfolder), Realtime.
People sign in again once: sessions do not move. Everything else, including their passwords, does.
CI runs an import on a clean machine with every change, from another environment standing in for a Supabase project: the user signs in with the old password, reads only their own row, downloads their own private file, a new sign-up runs the imported trigger, and a second import into the full environment is refused (evidence). It is not a run against Supabase Cloud.
Limits
- The target must be a new, empty environment. A failed import leaves it to be deleted and created again; it is never half-repaired.
- Only the
publicschema is copied among your own schemas; other schemas are listed in the check. - A project that holds Vault secrets is refused, because their root key is not in a dump. Empty the source's vault first, then add the secrets again in the new environment, which has its own Vault.
- Cron jobs and the project's JWT secret do not move; the check says when that matters.
- Files larger than the upload limit (
SBARBASE_UPLOAD_LIMIT_MB) are reported and not copied.