Supabase Self-Hosted — User Guide
Guide to the Supabase Self-Hosted marketplace product: what it is, what it is for, how it differs from Supabase Cloud, and how to access and operate what gets installed.
1. What it is
Supabase is an open-source alternative to Firebase. In a single package, it delivers the complete backend of an application on top of a PostgreSQL database:
| Component | What it is for |
|---|---|
| PostgreSQL | Relational database, with direct access through a connection string |
| REST and GraphQL API | API generated automatically from your tables (PostgREST) |
| Auth | Sign-up, login (email/password, magic link, OAuth), sessions and JWT |
| Storage | File upload and delivery, with access rules |
| Realtime | Real-time events (database changes, broadcast, presence) |
| Edge Functions | Serverless functions in Deno/TypeScript |
| Studio | Web dashboard to manage all of the above |
This product installs the official self-hosted release (self-hosted/v0.8.2), following the Supabase documentation, on a Docker node in your environment, with HTTPS (Let's Encrypt certificate) through the Caddy proxy.
2. What it is for
- Getting an app's backend (web or mobile) — database, login, files and API — without writing a server from scratch.
- Keeping data on your own infrastructure, in your environment's region (useful for LGPD/GDPR and internal policies).
- Predictable cost, based on environment resources, with no Supabase charges per active user, request or storage.
- Development, staging or production environments that you fully control.
3. Self-hosted × Supabase Cloud: what changes
Only the differences that matter in day-to-day use:
| Topic | Supabase Cloud (hosted) | This product (self-hosted) |
|---|---|---|
| Projects | Multiple projects per organization | One project per environment (for another project, install another environment) |
| Updates | Handled by Supabase | Pinned version (v0.8.2); updating is manual |
| Auth settings (SMTP, OAuth providers, redirect URLs) | Through the dashboard | Through the .env file + restart (see section 8.2) |
| Auth emails | Built-in SMTP (with limits) | No real SMTP: configure your own before enabling email sign-up |
| Dashboard (Studio) | Full: organizations, billing, branching | Reduced: one project, no billing/branching |
| Edge Functions | Deployed with the CLI (supabase functions deploy) | Code in /home/supabase/volumes/functions on the server |
| Scaling and resources | Managed by Supabase | Node resources adjustable by you |
Summary: you gain control, data on your own server and a fixed cost; in exchange, backups, updates, email and monitoring become your job.
4. Installation
4.1 Options
| Option | Default | What it does |
|---|---|---|
| Habilitar MCP (Enable MCP) | Unchecked | Exposes the Supabase MCP server at https://<domain>/mcp, protected by a token (see sections 6.3 and 7). It can be enabled or disabled later through the MCP add-on. |
4.2 What gets created
A Docker Engine node with a public IP, ports 80/443, up to 32 cloudlets (8 reserved) and 30 GB of disk. Everything Supabase-related lives in /home/supabase (persistent volume).
During installation, automatically:
- The dashboard password, the PostgreSQL password, the JWT/API keys and, if checked, the MCP token are generated.
- The official Supabase files are downloaded and
.envis configured with the environment domain. - Docker images are pulled and services are started while the Let's Encrypt Free SSL add-on issues the certificate (in parallel, for a faster install).
- Caddy starts with the certificate and HTTPS is tested.
- The Senha do painel Supabase, Custom Domain and MCP add-ons are installed.
At the end, the success screen (also sent by email) lists all access details. Keep that email — it is the only place with all passwords and keys together.
5. Access
In the examples, <domain> is the environment domain (e.g. env-1234567.sp1.br.saveincloud.net.br) or your own domain, if configured.
5.1 Studio (dashboard)
| Access | Value |
|---|---|
| URL | https://<domain> |
| Username | supabase |
| Password | the one in the installation email (change it with the Senha do painel Supabase add-on) |
Studio is the admin dashboard: tables, SQL Editor, Auth users, Storage buckets, policies (RLS) and keys.
5.2 API (for your apps)
The project URL is https://<domain> — the same one used in the SDK:
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://<domain>', '<publishable key>')
| Key | Where to use it |
|---|---|
Publishable key (sb_publishable_…) | Frontend and mobile apps. It is public; access is limited by RLS policies. |
Secret key (sb_secret_…) | Backend only. It bypasses RLS: never put it in browser/app code. |
| Anon key (legacy) | Equivalent to the publishable key, for older libraries. |
| Service role key (legacy) | Equivalent to the secret key, for older libraries. Backend only. |
Available endpoints: /rest/v1, /graphql/v1, /auth/v1, /storage/v1, /realtime/v1 and /functions/v1.
5.3 PostgreSQL (direct connection)
The connection goes through the pooler (Supavisor). The username includes the environment name:
postgresql://postgres.<environment-name>:<postgres-password>@<domain>:5432/postgres
| Port | Mode | When to use it |
|---|---|---|
| 5432 | Session | Tools (DBeaver, pgAdmin, psql), migrations, apps with long-lived connections |
| 6543 | Transaction | Serverless and many short connections |
If external connections do not work, check whether the environment firewall allows ports 5432/6543. If you do not need external database access, keep them closed.
6. Add-ons
They are in the node's Add-Ons tab. All of them ask for confirmation before acting.
6.1 Senha do painel Supabase (Supabase dashboard password)
Redefinir senha (Reset password) button: generates a new Studio password (user supabase), applies it and sends it by email. The previous password stops working immediately. The dashboard is unavailable for a few seconds.
6.2 Custom Domain
Applies your own domain (e.g. api.yourcompany.com) to the Supabase settings. It does not issue a certificate. The order is:
- In DNS, point the domain to the environment: a CNAME to the environment domain or an A record to the node's public IP.
- In the Let's Encrypt Free SSL add-on → Configure, add the domain.
- In the Custom Domain add-on, enter the domain and click Configurar domínio (Configure domain).
The containers are restarted (up to ~1 minute offline). Supabase starts answering on the new domain and keeps answering on the environment domain. Afterwards, update the URL in your apps. To revert, enter the environment domain itself.
6.3 MCP
MCP (Model Context Protocol) lets AI assistants (Claude, Cursor, VS Code, etc.) query and manage the project: list tables, run SQL, read the documentation.
| Button | What it does |
|---|---|
| Habilitar / gerar novo token (Enable / generate new token) | Enables the endpoint (if not enabled yet) and generates a new token, sent by email. Any previous token stops working. |
| Desabilitar (Disable) | Blocks /mcp, removes the token and undoes the MCP configuration, returning to the installation default. |
In both cases the proxy and the api-gw are restarted (a few seconds offline).
⚠️ Whoever has the token has administrative access to the project. Treat it like the secret key: do not publish it, do not commit it to a repository, and generate a new one if it leaks.
7. Using MCP
7.1 Connection
| Field | Value |
|---|---|
| URL | https://<domain>/mcp |
| Header | Authorization: Bearer <token> |
Without the correct header, /mcp returns 401. With MCP disabled, the route is blocked (403).
7.2 Client configuration example
Most MCP clients accept a JSON like this:
{
"mcpServers": {
"supabase": {
"type": "http",
"url": "https://<domain>/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
8. Operation
Server access is through the node's Web SSH (user root). The commands below run in /home/supabase.
8.1 Commands
| Command | What it does |
|---|---|
sh run.sh start | Applies .env changes (recreates only what changed) |
sh run.sh status | Container status |
sh run.sh logs | Follows the logs (sh run.sh logs auth for one service; Ctrl+C to exit) |
sh run.sh restart | Restarts the services |
All configuration lives in /home/supabase/.env. After editing it, run sh run.sh start.
8.2 Auth and email settings
The .env comes without a real email server. Without SMTP, Auth emails (sign-up confirmation, magic link, password recovery) are not delivered — and since email confirmation is on, new users cannot confirm their sign-up.
Before enabling email sign-up, set in .env:
| Variable | Purpose |
|---|---|
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS | Your email provider |
SMTP_ADMIN_EMAIL, SMTP_SENDER_NAME | Email sender |
SITE_URL | Your app URL (default target of email links) |
ADDITIONAL_REDIRECT_URLS | Other allowed redirect URLs, comma-separated |
DISABLE_SIGNUP | true to block new sign-ups |
ENABLE_EMAIL_AUTOCONFIRM | true skips email confirmation (not recommended in production) |
OAuth providers (Google, GitHub, etc.) are also configured through environment variables of the auth service — see the Supabase documentation.
8.3 Where data lives
| Path | Contents |
|---|---|
/home/supabase/volumes/db/data | PostgreSQL data |
/home/supabase/volumes/storage | Storage files |
/home/supabase/volumes/functions | Edge Functions code (one folder per function) |
/home/supabase/.env | Configuration, passwords and keys |
8.4 Backups
There is no automatic backup. Recommended:
- Database: periodic
pg_dump, for example:and copy the file off the server.cd /home/supabase
docker exec supabase-db pg_dump -U postgres -Fc postgres > backup-$(date +%F).dump - Files: copy
/home/supabase/volumes/storage. - Configuration: keep a copy of
.envsomewhere safe (without it, the JWT keys change and issued tokens stop being valid).
8.5 Resources
If Studio gets slow or containers restart due to lack of memory, raise the node's cloudlet limit in the Environment Topology.
9. Security — checklist
- Keep the installation email somewhere safe, and change the dashboard password if it is shared.
- Use only the publishable key in the frontend; secret/service role only in the backend.
- Enable RLS on every table exposed through the API.
- Configure SMTP before opening email sign-up.
- Close ports 5432/6543 if there is no external database access.
- Enable MCP only if you will use it, generate a new token if it leaks, and disable it when no longer needed.
10. Common problems
| Symptom | Likely cause / what to do |
|---|---|
| Browser warns about an invalid certificate | Certificate not issued yet, or the domain is not in it: check the Let's Encrypt add-on |
| Custom domain does not load | DNS does not point to the environment, or the domain was not added to Let's Encrypt before Custom Domain |
| Confirmation email does not arrive | SMTP not configured (see section 8.2) |
/mcp returns 401 | Missing/wrong token in the Authorization: Bearer header |
/mcp returns 403 | MCP disabled: use Habilitar in the MCP add-on |
| Something does not start | sh run.sh status and sh run.sh logs <service> |