Supabase self-hosted with Docker: secure setup, every default replaced (Linux, Windows, Mac)
Before you start
- 20 min read
Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#
Supabase self-hosted is the open-source Supabase backend (Postgres database, login, auto-generated REST API, file storage, realtime and edge functions) running as Docker containers on a machine you control, so your app's data never has to sit on someone else's cloud.
Logo: the official Supabase brand assets (supabase.com/brand-assets). Supabase and the Supabase logo are trademarks of Supabase Inc.
It suits a side project, a team tool, or an app with data-residency rules. It is not the cloud product: one project, community support, and you do the backups, updates and hardening. The rule that matters most: never start with the example passwords and keys.
| What | Value (official docs, read October 2026) |
|---|---|
| Release used | self-hosted/v0.8.3, 16 October 2026 (latest tag; images are tested together and published about monthly) |
| Licence | Apache License 2.0 (LICENSE at the release tag) |
| Time needed | "Less than 15 minutes" per the docs; allow 30 minutes with this guide's extra steps (our estimate) |
| Machine | Minimum 4 GB RAM, 2 CPU cores, 40 GB SSD. Recommended 8 GB+, 4 cores+, 80 GB+ SSD |
| Ports | 8000 (gateway: dashboard and APIs), 5432 and 6543 (database pooler), 80 and 443 (only with the HTTPS proxy) |
| Containers | 11 by default (counted from the compose file at the tag) |
| Official docs | supabase.com/docs/guides/self-hosting/docker |
At a glance:
- What runs: gateway (Envoy), Studio dashboard, Auth, REST (PostgREST), Realtime, Storage, image proxy, Edge Functions, Postgres 17 and a connection pooler.
- The big risk: the example
.envhas working passwords and demo keys that everyone knows. Replace all of them before the first start. - Second risk: by default the gateway and the pooler publish ports on every network interface. This guide binds them to the local machine.
- Platforms: Linux is the main route. Mac runs it through Docker Desktop. Windows runs it best inside WSL 2. We did not run Windows or Mac ourselves.
- Privacy: the docs say it "does not phone home or collect any telemetry". "Security and testing" lists what still leaves your machine.
How it fits together#
Apps and the dashboard reach one gateway; the gateway routes by path to the services; every service talks to one Postgres database whose files live in your project folder.
Drawn for this guide from the official compose file and docs. The dashed HTTPS proxy is optional.
What self-hosted lacks compared with the cloud#
Read this before you commit. The official self-hosting overview says it plainly.
| Topic | Supabase cloud | Self-hosted (official docs) |
|---|---|---|
| Projects | Many organisations and projects | One project; Studio has no multi-project support |
| Branching, Management API, ETL | Yes | Not available |
| Backups and point-in-time recovery | Managed | You build them (see "Updates and backups") |
| Metrics and analytics | Dashboards | Logs only; analytics are off until you add the logs override |
| Vector buckets | Yes | Not available |
| API keys | Several sb_ keys per project | One publishable key and one secret key |
| Settings | Dashboard | Mostly .env variables |
| Built in | You must supply a real mail server | |
| Support | Plans | "Community-supported" (Discussions, Issues, Discord) |
You also own server upkeep, hardening, Postgres maintenance, high availability, backups, disaster recovery and monitoring. If that worries you, the managed platform is the honest answer.
Before you start#
| System | What you need |
|---|---|
| Linux | Docker Engine with Compose (v2.24.4 or newer for the override files), Git, openssl, and Node.js 16+ or Docker (the key script falls back to Docker) |
| Windows | Windows 10 or 11 with Docker Desktop (WSL 2 backend) and an Ubuntu distribution in WSL 2. Run the commands inside Ubuntu |
| Mac | Docker Desktop, Git (Xcode command line tools), Terminal. Intel and Apple silicon both work according to Docker |
Check the tools. Linux or inside WSL Ubuntu:
docker --version docker compose version git --version openssl version
Windows PowerShell (installs Ubuntu once, then restart; skip if you have it):
wsl --install -d Ubuntu wsl -l -v docker --version
In Docker Desktop settings, switch on WSL integration for Ubuntu, then run wsl -d Ubuntu to get the Ubuntu prompt.
Mac Terminal:
docker --version docker compose version git --version
Checklist:
- [ ] 4 GB RAM free for Docker (8 GB is better) and 40 GB of disk
- [ ] Ports 8000, 5432 and 6543 free on the machine (
docker psshows nothing using them) - [ ] A password manager open: you will generate about a dozen secrets
- [ ] For the HTTPS section only: a domain, DNS pointing to the server, ports 80 and 443 free
Tested by DIY Lab Hub: not yet. Commands come from the official docs and files at the release tag, read on 2026-10-30. We did not run them. The Docker images for the main services list both amd64 and arm64 on Docker Hub.
Step 1: Get the official files at a pinned release#
The Docker setup is a folder in the Supabase repository. You copy it into ~/docker_volumes/supabase, so your config and data live in one place.
Linux#
mkdir -p ~/docker_volumes cd ~/docker_volumes git clone --depth 1 --branch self-hosted/v0.8.3 https://github.com/supabase/supabase supabase-source mkdir -p supabase cp -rf supabase-source/docker/. supabase cd supabase cp .env.example .env chmod 600 .env printf 'ref=self-hosted/v0.8.3\n' > .supabase-version docker compose pull
The .supabase-version file lets the update script find your starting point later. You may delete ~/docker_volumes/supabase-source now.
Windows (PowerShell)#
Use the Linux commands inside Ubuntu on WSL 2. Keep the project in the Linux home folder, not on C:, so file permissions work:
wsl -d Ubuntu
Then run the Linux block above at the Ubuntu prompt. The docs give no PowerShell-only route, and every script is sh. We did not test Windows.
Mac (Terminal)#
Same commands as Linux:
mkdir -p ~/docker_volumes cd ~/docker_volumes git clone --depth 1 --branch self-hosted/v0.8.3 https://github.com/supabase/supabase supabase-source mkdir -p supabase cp -rf supabase-source/docker/. supabase cd supabase cp .env.example .env chmod 600 .env printf 'ref=self-hosted/v0.8.3\n' > .supabase-version docker compose pull
Check it worked. ls ~/docker_volumes/supabase lists docker-compose.yml, .env, run.sh, utils and volumes, and docker compose pull ends without an error.
Tip: The docs also offer a Linux quick start (
curl -fsSL https://supabase.link/setup.sh | sh) for Debian, Ubuntu and RHEL-family servers. It installs Docker and generates every secret, but takes the newest release, not a pinned one. Download and read it before running it.
Step 2: Replace every default secret#
The example .env ships working passwords and demo API keys. The docs say you should "never" start with them, and the file itself shouts that you must change all of them before the first start. Two official scripts do it.
Linux#
cd ~/docker_volumes/supabase sh utils/generate-keys.sh --update-env sh utils/add-new-auth-keys.sh --update-env rm -f .env.old docker-compose.yml.old chmod 600 .env
The first script writes new values for the database password, JWT_SECRET, the legacy ANON_KEY and SERVICE_ROLE_KEY, the dashboard password and the encryption keys. The second creates the newer sb_publishable_ and sb_secret_ keys plus an ES256 key pair, and switches on the matching lines in docker-compose.yml. It needs Node.js 16+ or Docker (it pulls node:22-alpine once).
Both scripts leave .env.old copies behind. The second copy holds your freshly generated secrets, so the rm above matters.
Windows (PowerShell)#
Run the Linux commands at the Ubuntu prompt. Afterwards, from PowerShell, confirm that Ubuntu sees the project files:
wsl -d Ubuntu -- ls -a /home/<your-user>/docker_volumes/supabase
Mac (Terminal)#
Same commands as Linux. macOS has sh and an openssl command; we did not run the scripts on a Mac:
cd ~/docker_volumes/supabase sh utils/generate-keys.sh --update-env sh utils/add-new-auth-keys.sh --update-env rm -f .env.old docker-compose.yml.old chmod 600 .env
Now choose your own dashboard user name and look at what you have. Edit .env (nano .env) and change DASHBOARD_USERNAME from supabase if you like. The dashboard password must contain at least one letter and no special characters; the generated one does. POSTGRES_PASSWORD must be set before the first start; letters and numbers only avoid URL-encoding trouble.
Check it worked. This must print nothing. It looks for the example values and the signatures of the two demo keys:
grep -nE "your-super-secret|this_password_is_insecure|your-32-character|your-encryption-key|supabaserealtime|UpNVntn3|secret1234|dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE|DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" .env grep -c "^SUPABASE_SECRET_KEY=sb_secret_" .env
The second line should print 1. One value stays as in the example: POOLER_TENANT_ID=your-tenant-id. It is a label, not a secret; you may rename it.
Tip: Never paste
.envinto a chat, an issue or an AI assistant. Share variable names, not values.sh run.sh secretsprints key values to the screen, so run it only on your own terminal.
Step 3: Set the URLs and keep the ports private#
Three variables tell Auth where your instance lives. Then a small override file keeps the gateway and pooler off the network until you add HTTPS.
Linux#
Edit .env (nano .env). For a local trial keep the defaults. For a server with a domain, use your public address:
SUPABASE_PUBLIC_URL=http://<your-domain>:8000 API_EXTERNAL_URL=http://<your-domain>:8000/auth/v1 SITE_URL=http://<your-app-domain>
SITE_URL is where your own app lives, not Supabase. Use https:// URLs once the HTTPS section is done.
The official compose file publishes ports 8000, 5432 and 6543 on every interface. This override, our own and built from the docs' !override syntax, restricts them to the local machine:
cd ~/docker_volumes/supabase
cat > docker-compose.local.yml << 'EOF'
services:
api-gw:
ports: !override
- "127.0.0.1:${API_GW_HTTP_PORT:-8000}:8000/tcp"
supavisor:
ports: !override
- "127.0.0.1:${POSTGRES_PORT}:5432"
- "127.0.0.1:${POOLER_PROXY_PORT_TRANSACTION}:6543"
EOF
sh run.sh config add local
Windows (PowerShell)#
Do the same inside Ubuntu. Docker Desktop forwards localhost ports from WSL to Windows, so http://localhost:8000 opens in your Windows browser.
Mac (Terminal)#
Same commands as Linux. Docker Desktop for Mac publishes the loopback ports to your Mac.
Check it worked. sh run.sh config prints COMPOSE_FILE=docker-compose.yml:docker-compose.local.yml and lists both files.
Tip: Do not rely on
ufwto protect Docker ports. Docker's own documentation says published ports are diverted before ufw's rules apply. Binding to127.0.0.1is the reliable fix. We did not run this override; ifdocker compose configcomplains, check that Compose is 2.24.4 or newer.
Step 4: Start Supabase and check every container#
Linux#
cd ~/docker_volumes/supabase sh run.sh start docker compose ps
sh run.sh start is docker compose up -d --wait: it starts everything and waits until the containers report healthy.
Windows (PowerShell)#
Run the Linux commands at the Ubuntu prompt, then confirm from PowerShell:
curl.exe -I http://localhost:8000/
Mac (Terminal)#
Same commands as Linux.
Check it worked. Per the docs, after a minute or less all services show Up ... (healthy). If one shows created but not Up, run:
sh tests/test-container-logs.sh sh run.sh logs storage
Use the name of the failing service. The docs publish no sample docker compose ps output, so we show none.
Step 5: Open the dashboard and test the keys#
Studio is behind HTTP basic authentication, with the user and password from .env.
Linux#
Open http://localhost:8000 on the same machine and log in. Test the API with the new keys (values from sh run.sh secrets):
curl http://localhost:8000/rest/v1/ -H "apikey: <SUPABASE_SECRET_KEY>" curl -i http://localhost:8000/rest/v1/ -H "apikey: <SUPABASE_PUBLISHABLE_KEY>"
On a remote server, tunnel instead of exposing the port: ssh -N -L 8000:127.0.0.1:8000 <your-user>@<your-server-address>.
Windows (PowerShell)#
Open http://localhost:8000 in your Windows browser. Test with curl.exe:
curl.exe http://localhost:8000/rest/v1/ -H "apikey: <SUPABASE_SECRET_KEY>"
For a remote server run the same SSH tunnel from PowerShell.
Mac (Terminal)#
Same commands as Linux, with localhost:8000 in Safari or another browser.
Check it worked. You can log in, and the secret-key request returns "a valid response from PostgREST" (docs wording). The publishable key must return 403 on this endpoint; the docs say /rest/v1/ needs an admin-level key. Your app uses SUPABASE_PUBLIC_URL as supabaseUrl with the publishable key; the secret key stays on a trusted server.
Put it behind HTTPS (with or without Traefik)#
The docs call HTTPS "required for production": the dashboard password would otherwise cross the network in the clear, and OAuth providers need it. On localhost only, skip this section. Both routes need a domain whose DNS points to the server.
Official proxy rules: forward to the gateway on port 8000, allow WebSockets (Realtime), add X-Forwarded headers, drop the gateway's host port, and set the three URLs to https://.
With Traefik#
On a server that already runs Traefik v3 with the Docker provider, add a small override and join the proxy network. This assumes an entrypoint named https; use yours. Traefik handles WebSockets and forwarded headers by default (not tested here).
docker network create proxy
cd ~/docker_volumes/supabase
cat > docker-compose.traefik.yml << 'EOF'
services:
api-gw:
ports: !reset []
networks:
default: {}
proxy: {}
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.supabase.rule=Host(`supabase.<your-domain>`)"
- "traefik.http.routers.supabase.entrypoints=https"
- "traefik.http.routers.supabase.tls=true"
- "traefik.http.services.supabase.loadbalancer.server.port=8000"
networks:
proxy:
external: true
EOF
sh run.sh config add traefik
Set SUPABASE_PUBLIC_URL=https://supabase.<your-domain>, API_EXTERNAL_URL=https://supabase.<your-domain>/auth/v1 and SITE_URL=https://<your-app-domain> in .env, then sh run.sh recreate. If docker network create says the network exists, that is fine.
Check it worked. The docs' check works here too: curl -I https://supabase.<your-domain>/auth/v1/ returns 401, which proves you reached Auth over HTTPS.
Without Traefik: Caddy#
Supabase ships its own Caddy override. It gets and renews Let's Encrypt certificates for a public domain. Order matters: add caddy after local, because Caddy's override clears the gateway's host port.
Set PROXY_DOMAIN=<your-domain> and the three https:// URLs in .env, then run (Linux, WSL Ubuntu and Mac alike):
cd ~/docker_volumes/supabase sh run.sh config add caddy sh run.sh start
The Caddyfile lives at volumes/proxy/caddy/Caddyfile. Its core is {$PROXY_DOMAIN} with reverse_proxy api-gw:8000 for the API paths and the dashboard behind basic auth. The container is supabase-caddy; ports 80, 443 and 443/udp must reach the server.
Home only, no public domain. Caddy's own local certificate authority works: add tls internal as the first line inside the {$PROXY_DOMAIN} { block of that Caddyfile and set PROXY_DOMAIN to a name your devices resolve (for example supabase.home.arpa in your router's DNS or a hosts entry). We did not run this edit; it follows Caddy's documented tls internal. Then copy Caddy's root certificate out and trust it on each device:
docker exec supabase-caddy find /data -name root.crt docker cp supabase-caddy:<path-from-find> ./caddy-root.crt
Install caddy-root.crt as a trusted root. These OS steps are not from the Supabase or Caddy docs: Windows, "Trusted Root Certification Authorities"; macOS, Keychain Access, "Always Trust"; Linux, your distribution's CA store. Windows and Mac are only clients here.
Check it worked.
curl -I https://<your-domain>/auth/v1/ docker logs supabase-caddy --tail 50
You should see 401. A padlock for a tls internal name appears only after the root is trusted on that device.
Tip: Let's Encrypt has rate limits. If the certificate fails twice, fix DNS and ports first (the docs list both) and wait before retrying.
Security and testing#
| Control | How |
|---|---|
| Secrets | Replace every default (Step 2). .env mode 600, never in Git or a chat |
| Ports | Gateway and pooler on 127.0.0.1 (Step 3). Only 80 and 443 face the internet |
| Dashboard | Studio can run SQL on your database. Strong password, HTTPS, ideally an SSH tunnel or a VPN |
| Postgres direct access | Not exposed by default. The docs warn that exposing it "opens your database to the network" |
| Secret key | SUPABASE_SECRET_KEY and SERVICE_ROLE_KEY bypass row-level security. Server side only |
| Sign-ups | DISABLE_SIGNUP=false by default. Set true if only you should create accounts |
| Rotation | sh utils/rotate-new-api-keys.sh --update-env, then sh run.sh recreate |
| Production secrets | The docs suggest a secrets manager instead of .env |
Tests after every change:
cd ~/docker_volumes/supabase docker compose ps docker compose logs --tail=100 auth curl -I http://localhost:8000/auth/v1/
The docs use this /auth/v1/ request over HTTPS as their connection test: a 401 means Auth answered.
What leaves the machine. Per the docs, no telemetry. Still: image downloads, the Let's Encrypt request for your domain, mail through the SMTP server you configure, OAuth providers you enable, and prompts to OpenAI if you add your own OPENAI_API_KEY for the Studio AI Assistant. The separate Supabase CLI does collect telemetry.
Common mistakes#
These come from the official docs' warnings and from open or closed issues on the Supabase repository, read in October 2026.
| Mistake | Why it happens | Do this instead |
|---|---|---|
Starting with .env.example as it is | It looks like a ready config. The docs say you should "never" use these values | Run both key scripts (Step 2) and run the check that prints nothing |
| A dashboard password with only digits or special characters | The docs: the password "must include at least one letter" and no special characters | Letters plus numbers; let the script generate it |
Changing POSTGRES_PASSWORD after the first start | The database was created with the old one | Set it before the first start. Later use sh utils/db-passwd.sh, then sh run.sh recreate |
| Leaving ports 5432 and 6543 on every interface | The compose file publishes the pooler without an address, and ufw does not filter Docker ports | Bind to 127.0.0.1 (Step 3). Open Postgres to others only with a firewall |
| Rootless Docker without telling Supabase | The log collector cannot find the socket (container supabase-vector exited (0)). Issue #36726: Storage uploads fail with 500 when volumes/storage is owned by root | Set DOCKER_SOCKET_LOCATION in .env; make the Storage folder writable for your user |
| Expecting big downloads or slow SQL through the gateway | Issue #51618 (open): Envoy cuts most routes after 30 seconds; big files arrive truncated with status 200, long Studio queries return 504 | Keep requests short; read the issue before relying on big files |
Sending a redirect_to header to Auth | Issue #51791 (open): Envoy rejects headers with underscores | Pass redirect_to as a query parameter |
Changing POSTGRES_DB | Issue #50486 (open): jwt.sql hard-codes postgres, so the JWT settings land in the wrong database | Keep the default database name |
| Installing on a 2 GB machine | Issue #44376 (open): Studio's health check has no start period, so slow machines fail in a cascade. The docs ask for 4 GB | Use 4 GB or more; if it fails once, run sh run.sh start again |
| Waiting for sign-up emails that never arrive | .env points to a placeholder mail host (supabase-mail) | Configure a real SMTP server in .env, then restart |
| AI assistants: describing the old layout | Many answers still show Kong as the gateway, Postgres 15 and only ANON_KEY / SERVICE_ROLE_KEY. The docs now use Envoy (since v0.8.0), Postgres 17 and the sb_ keys | Follow the pinned release's own files and docs, not remembered configs |
AI assistants: telling you to run supabase start to self-host | The CLI starts a local test stack | The docs say that stack "is not a self-hosted deployment" and "must not be exposed to external traffic". Use the Docker files here |
| AI assistants: putting the secret key in browser code | Examples often use one key for everything | Publishable key in the app, secret key on the server only |
Tip: On Windows keep the project inside the Linux file system of WSL 2. The docs warn that Windows line endings (CRLF) can break the gateway start-up with an entrypoint error.
Tip: Before any update, copy your
.envand read the changelog entry. The docs sayupdate.shbacks up configuration only, never your data.
Tip: After each step, run
docker compose psand read the first error line insh run.sh logs <service>. Most failures print the cause there.
Troubleshooting#
| Problem | Solution |
|---|---|
A service shows created, not Up | sh tests/test-container-logs.sh, then sh run.sh logs <service> |
container supabase-vector exited (0) | Rootless Docker: set DOCKER_SOCKET_LOCATION in .env (for example /run/user/1000/docker.sock) |
| Gateway fails with an entrypoint error | Files have CRLF line endings. Re-clone inside WSL or Linux, or convert docker/ files to LF |
| Studio unhealthy, rest of the stack never starts | Slow start (issue #44376). Give Docker more RAM, then sh run.sh start again |
403 on /rest/v1/ | Expected with the publishable key. Use the secret key (docs) |
504 upstream request timeout or truncated downloads | The 30 second gateway timeout (issue #51618). Shorten the request |
| Certificate not issued | Ports 80 and 443 open? DNS A record correct? docker logs supabase-caddy (docs) |
| OAuth "callback URL mismatch" | API_EXTERNAL_URL must be your HTTPS URL plus /auth/v1; then sh run.sh recreate (docs) |
| Realtime socket fails behind your proxy | The proxy must pass WebSocket upgrades (Caddy does; Nginx needs explicit headers) |
Changed .env but nothing changed | sh run.sh recreate (environment changes apply only when containers are recreated) |
Known bugs (open when read, October 2026)#
- Realtime in v0.8.3: Postgres Changes events can be missed for a few seconds every 10 minutes. The changelog's workaround is
REGION: us-east-1underrealtimeenvironment:indocker-compose.yml. It is not fixed in this release. - Issue #43643:
pg_walfiles can grow without limit when the analytics replication slot falls behind. Only relevant if you enabled the logs override; watch disk space. - Issue #52346: the gateway's CORS rules for
/functions/v1allow every origin and override your function's own CORS.
Diagnostics: docker compose ps, sh run.sh logs <service>, sh run.sh printenv <service>, docker inspect supabase-db.
Updates and backups#
Update. Supabase publishes tested snapshots about once a month. Releases can contain one-way database migrations: v0.8.3 changes Storage so that rolling back to the previous Storage version makes uploads fail. Back up first (below), then:
cd ~/docker_volumes/supabase sh update.sh --dry-run sh update.sh sh run.sh pull sh run.sh recreate
update.sh needs git and jq (on Mac, brew install jq), keeps your .env and data, merges new files over yours and stops at breaking changes. Pin a release with sh update.sh --to self-hosted/<tag>.
Our override files are not part of Supabase's release, so after an update check that sh run.sh config still lists them. Note any docker-compose.yml edit (such as the Realtime workaround): it may conflict.
Back up. The official docs give no database backup command; they say you own backups. This is a plain cold copy, our method: stop, archive the database files, uploads, config and the pgsodium key volume, start.
cd ~/docker_volumes/supabase cat > backup.sh << 'EOF' #!/bin/sh cd "$(dirname "$0")" || exit 1 mkdir -p backups sh run.sh stop tar -czf "backups/supabase-$(date +%F).tar.gz" .env docker-compose.yml volumes/db/data volumes/storage volumes/functions docker run --rm -v supabase_db-config:/src -v "$PWD/backups":/dst alpine tar -czf "/dst/db-config-$(date +%F).tar.gz" -C /src . chmod 600 backups/*.tar.gz sh run.sh start EOF sudo sh backup.sh
sudo is needed on Linux because the database files belong to the database user; on a Mac, drop it. Copy the archives to another machine; they contain every secret.
Schedule. Linux and Mac: sudo crontab -e, then add 0 3 * * * sh /home/<your-user>/docker_volumes/supabase/backup.sh (on Mac use your own home path). Windows: a Task Scheduler task that runs wsl -d Ubuntu -u root -- sh /home/<your-user>/docker_volumes/supabase/backup.sh daily at 03:00. We did not test the schedules.
Restore test. Unpack into a new empty folder, never over the live one:
mkdir -p /tmp/supabase-restore && tar -xzf backups/supabase-<date>.tar.gz -C /tmp/supabase-restore ls /tmp/supabase-restore/volumes/db/data | head
Uninstall. sh reset.sh deletes the containers, named volumes, database and storage folders; irreversible.
Performance and resources#
The official minimum is 4 GB RAM, 2 cores and 40 GB SSD; recommended 8 GB+, 4 cores+ and 80 GB+. We did not measure memory or CPU, so this page gives no figures of its own.
- Watch it:
docker statsshows live CPU and memory for each container. - Slim it down: the docs say you may remove services you do not need (Realtime, Storage, imgproxy, Edge Runtime) from
docker-compose.yml. - Logs: analytics are off by default because they add load.
sh run.sh config add logsturns them on. - Connections: pooler defaults are 20 database and 100 client connections (
POOLER_DEFAULT_POOL_SIZE,POOLER_MAX_CLIENT_CONN). - Mac: Docker Desktop bind mounts can break the Storage file backend. The docs say to switch that mount to a named Docker volume.
FAQ#
Is it free? The code is Apache License 2.0. You pay for the server and your own time.
Can I run more than one project? Not in one stack: Studio supports a single project.
Can I run it on a Raspberry Pi? The main images list arm64, but the docs ask for 4 GB RAM and an SSD, and issue #44376 shows small machines struggling.
Does it send data to Supabase? The docs say it does not phone home or collect telemetry. See "What leaves the machine" for the traffic you cause yourself.
Where do I get help? GitHub Discussions and Issues with the self-hosted label, Discord and Reddit, per the docs.
Sources#
- Self-Hosting with Docker, Self-Hosting overview, New API keys and asymmetric authentication, Configure reverse proxy and HTTPS, Update your self-hosted deployment and Accessing Postgres - read 2026-10-30
- Release self-hosted/v0.8.3, its docker folder (
docker-compose.yml,.env.example,run.sh,utils/), CHANGELOG and LICENSE - read 2026-10-30 - Supabase brand assets (logo) - 2026-10-30
- Docker: Compose merge (
!override,!reset), packet filtering and ufw, port publishing, Docker Desktop on Windows and on Mac - 2026-10-30 - Install WSL and Caddy automatic HTTPS - 2026-10-30
- GitHub issues #36726, #43643, #44376, #50486, #51618, #51791 and #52346 - read 2026-10-30
Checked against the official docs on 2026-10-30.