apps/docs/content/guides/self-hosting/docker.mdx
Docker is the easiest way to get started with self-hosted Supabase. It should take you less than 30 minutes to get up and running.
This guide assumes you're comfortable with:
If you're new to these topics, consider starting with managed Supabase platform for free.
You need the following installed on your system:
Minimum requirements for running all Supabase components, suitable for development and small to medium production workloads:
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 4 GB | 8 GB+ |
| CPU | 2 cores | 4 cores+ |
| Disk | 50 GB SSD | 80 GB+ SSD |
If you don't need specific services, such as Logflare (Analytics), Realtime, Storage, imgproxy, or Edge Runtime (Functions), you can remove the corresponding sections and dependencies from docker-compose.yml to reduce resource requirements.
Follow these steps to start Supabase on your machine:
<Tabs scrollable size="small" type="underlined" defaultActiveId="general"
<TabPanel id="general" label="General">
# Get the code
git clone --depth 1 https://github.com/supabase/supabase
# Make your new supabase project directory
mkdir supabase-project
# Tree should look like this
# .
# ├── supabase
# └── supabase-project
# Copy the compose files over to your project
cp -rf supabase/docker/* supabase-project
# Copy the fake env vars
cp supabase/docker/.env.example supabase-project/.env
# Switch to your project directory
cd supabase-project
# Pull the latest images
docker compose pull
# Get the code using git sparse checkout
git clone --filter=blob:none --no-checkout https://github.com/supabase/supabase
cd supabase
git sparse-checkout set --cone docker && git checkout master
cd ..
# Make your new supabase project directory
mkdir supabase-project
# Tree should look like this
# .
# ├── supabase
# └── supabase-project
# Copy the compose files over to your project
cp -rf supabase/docker/* supabase-project
# Copy the fake env vars
cp supabase/docker/.env.example supabase-project/.env
# Switch to your project directory
cd supabase-project
# Pull the latest images
docker compose pull
If you are using rootless Docker, edit .env and set DOCKER_SOCKET_LOCATION to your docker socket location. For example: /run/user/1000/docker.sock. Otherwise, you will see an error like container supabase-vector exited (0).
While we provided example placeholder passwords and keys in the .env.example file, you should NEVER start your self-hosted Supabase using these defaults.
Review the configuration options below and ensure you set all secrets before starting the services.
</Admonition>To generate and apply all secrets at once you can run:
sh ./utils/generate-keys.sh
Review the output before proceeding and also check .env after it's updated by the script. Alternatively, configure all secrets manually as follows.
Change the placeholder password in the .env file before starting Supabase for the first time.
POSTGRES_PASSWORD: the password for the postgres and supabase_admin database rolesFollow the password guidelines for choosing a secure password. For easier configuration, use only letters and numbers to avoid URL encoding issues in connection strings.
Use the key generator below to obtain and configure the following secure keys in .env:
JWT_SECRET: Used by Auth, PostgREST, and other services to sign and verify JWTs.ANON_KEY: Client-side API key with limited permissions (anon role). Use this in your frontend applications.SERVICE_ROLE_KEY: Server-side API key with full database access (service_role role). Never expose this in client code.
<JwtGeneratorSimple />
JWT_SECRET in the .env file. Do not share this secret publicly or commit it to version control.ANON_KEY in the .env file.SERVICE_ROLE_KEY in the .env file.The generated keys expire in 5 years. You can verify them at jwt.io using the saved value of JWT_SECRET.
Edit the following settings in the .env file:
SECRET_KEY_BASE: encryption key for securing Realtime and Supavisor communications. (Must be at least 64 characters; generate with openssl rand -base64 48)VAULT_ENC_KEY: encryption key used by Supavisor for storing encrypted configuration. (Must be exactly 32 characters; generate with openssl rand -hex 16)PG_META_CRYPTO_KEY: encryption key for securing connection strings used by Studio against postgres-meta. (Must be at least 32 characters; generate with openssl rand -base64 24)LOGFLARE_PUBLIC_ACCESS_TOKEN: API token for log ingestion and querying. Used by Vector and Studio to send and query logs. (Must be at least 32 characters; generate with openssl rand -base64 24)LOGFLARE_PRIVATE_ACCESS_TOKEN: API token for Logflare management operations. Used by Studio for administrative tasks. Never expose client-side. (Must be at least 32 characters; generate with openssl rand -base64 24)S3_PROTOCOL_ACCESS_KEY_ID: Access key ID (username-like) for accessing the S3 protocol endpoint in Storage. (Generate with openssl rand -hex 16)S3_PROTOCOL_ACCESS_KEY_SECRET: Secret key (password-like) used with S3_PROTOCOL_ACCESS_KEY_ID. (Generate with openssl rand -hex 32)MINIO_ROOT_PASSWORD: Root administrator password for the MinIO server. (Must be 8+ characters; generate with openssl rand -hex 16)Review and change URL environment variables:
SUPABASE_PUBLIC_URL: base URL for accessing Supabase from the Internet (Dashboard, API, Storage, etc.), e.g, http://example.com:8000API_EXTERNAL_URL: base URL of the Auth service as seen externally, e.g., http://example.com:8000SITE_URL: default redirect URL for Auth, e.g., http://example.com:3000If you are only using self-hosted Supabase locally, you can use `localhost`.
Access to Studio dashboard and internal API is protected with HTTP basic authentication.
<Admonition type="danger">The default password MUST be changed before starting Supabase.
The password must include at least one letter: do not use numbers only and do not use any special characters.
Change the password in the .env file:
DASHBOARD_PASSWORD: password for Studio / dashboardOptionally change the user:
DASHBOARD_USERNAME: username for Studio / dashboardYou can start all services by using the following command in the same directory as your docker-compose.yml file:
# Start the services (in detached mode)
docker compose up -d
After all the services have started you can see them running in the background:
docker compose ps
After a minute or less, all services should have a status Up [...] (healthy). If you see a status such as created but not Up, try inspecting the Docker logs for a specific container, e.g.,
docker compose logs analytics
To stop Supabase, use:
docker compose down
After the Supabase services are configured and running, you can access the dashboard, connect to the database, and use edge functions.
You can access Supabase Studio through the API gateway on port 8000.
For example: http://example.com:8000, or http://<your-ip>:8000 (or localhost:8000 if you are running Docker Compose locally).
You will be prompted for a username and password. Use the credentials that you set up earlier in Studio authentication.
By default, the Supabase stack provides the Supavisor connection pooler for accessing Postgres and managing database connections.
You can connect to the Postgres database via Supavisor using the methods described below. Use your domain name, your server IP, or localhost depending on whether you are running self-hosted Supabase on a VPS, or locally.
The default POOLER_TENANT_ID is your-tenant-id (can be changed in .env), and the password is the one you set previously in Configure database password.
For session-based connections (equivalent to a direct Postgres connection):
psql 'postgres://postgres.[POOLER_TENANT_ID]:[POSTGRES_PASSWORD]@[your-domain]:5432/postgres'
For pooled transactional connections:
psql 'postgres://postgres.[POOLER_TENANT_ID]:[POSTGRES_PASSWORD]@[your-domain]:6543/postgres'
When using psql with command-line parameters instead of a connection string to connect to Supavisor, the -U parameter should also be postgres.[POOLER_TENANT_ID], and not just postgres.
If you need to configure Postgres to be directly accessible from the Internet, read Exposing your Postgres database.
To change the database password, read Changing database password.
Edge Functions are stored in volumes/functions. The default setup has a hello function that you can invoke on http://<your-domain>:8000/functions/v1/hello.
You can add new Functions as volumes/functions/<FUNCTION_NAME>/index.ts. Restart the functions service to pick up the changes: docker compose restart functions --no-deps
Each of the APIs is available through the same API gateway:
http://<your-domain>:8000/rest/v1/http://<your-domain>:8000/auth/v1/http://<your-domain>:8000/storage/v1/http://<your-domain>:8000/realtime/v1/We publish stable releases of the Docker Compose setup approximately once a month. To update, apply the latest changes from the repository and restart the services. If you want to run different versions of individual services, you can change the image tags in the Docker Compose file, but compatibility is not guaranteed. All Supabase images are available on Docker Hub.
To follow the changes and updates, refer to the self-hosted Supabase changelog.
You need to restart services to pick up the changes, which may result in downtime for your applications and users.
Example: You'd like to update or rollback the Studio image. Follow the steps below:
2025.11.26-sha-8f096b5image field in the docker-compose.yml file. It should look like this: image: supabase/studio:2025.11.26-sha-8f096b5docker compose pull, followed by docker compose down && docker compose up -d to restart Supabase.Be careful — the following destroys all data, including the database and storage volumes!
To uninstall, stop Supabase (while in the same directory as your docker-compose.yml file):
# Stop docker and remove volumes:
docker compose down -v
Optionally, ensure removal of all Postgres data:
rm -rf volumes/db/data
and all Storage data:
rm -rf volumes/storage
Everything beyond this point in the guide helps you understand how the system works and how you can modify it to suit your needs.
Supabase is a combination of open source tools specifically developed for enterprise-readiness.
If the tools and communities already exist, with an MIT, Apache 2, or equivalent open source license, we will use and support that tool. If the tool doesn't exist, we build and open source it ourselves.
<Image alt="Diagram showing the architecture of Supabase. The Kong API gateway sits in front of 7 services: GoTrue, PostgREST, Realtime, Storage, pg_meta, Functions, and pg_graphql. All the services talk to a single Postgres instance." src={{ dark: "/docs/img/supabase-architecture.svg", light: "/docs/img/supabase-architecture--light.svg", }}
width={1600} height={767} />
Multiple services require specific configuration within the Postgres database. Refer to the documentation describing the default roles to learn more.
You can find all the default extensions inside the schema migration scripts repo. These scripts are mounted at /docker-entrypoint-initdb.d to run automatically when starting the database container.
Each service has a number of configuration options you can find in the related documentation.
Configuration options are generally added to the .env file and referenced in docker-compose.yml service definitions, e.g.,
<$CodeTabs>
services:
rest:
image: postgrest/postgrest
environment:
PGRST_JWT_SECRET: ${JWT_SECRET}
## Never check your secrets into version control
JWT_SECRET=${JWT_SECRET}
</$CodeTabs>
You can configure each Supabase service separately through environment variables and configuration files. Below are the most common configuration options.
You will need to use a production-ready SMTP server for sending emails. You can configure the SMTP server by updating the following environment variables in the .env file:
SMTP_ADMIN_EMAIL=
SMTP_HOST=
SMTP_PORT=
SMTP_USER=
SMTP_PASS=
SMTP_SENDER_NAME=
We recommend using AWS SES. It's affordable and reliable. Restart all services to pick up the new configuration.
By default all files are stored locally on the server. You can connect Storage to an S3-compatible backend (AWS S3, MinIO, Cloudflare R2), enable the S3 protocol endpoint for tools like rclone, or both. These are independent features.
See the Configure S3 Storage guide for detailed setup instructions.
By default, Supabase is accessible over HTTP. For production deployments, especially when using OAuth providers, you need HTTPS with a valid TLS certificate. The recommended approach is to place a reverse proxy (such as Caddy or Nginx) in front of Kong.
See the Configure HTTPS guide for setup instructions.
See the Configure Social Login (OAuth) Providers guide for setup instructions.
See the Configure Phone Login & MFA guide for SMS provider setup, OTP settings, and multi-factor authentication configuration.
Configuring the Supabase AI Assistant is optional. By adding your own OPENAI_API_KEY to .env you can enable AI services, which help with writing SQL queries, statements, and policies.
By default, the database's log_min_messages configuration is set to fatal in docker-compose.yml to prevent redundant logs generated by Realtime. You can configure log_min_messages using any of the Postgres Severity Levels.
By default, Postgres connections go through the Supavisor connection pooler for efficient connection management. Two ports are available:
POSTGRES_PORT (default: 5432) - Session mode, behaves like a direct Postgres connectionPOOLER_PROXY_PORT_TRANSACTION (default: 6543) - Transaction mode, uses connection poolingFor more information on configuring and using Supavisor, see the Supavisor documentation.
By default, Postgres is only accessible through Supavisor. If you need direct access to the database (bypassing the connection pooler), you need to disable Supavisor and expose the Postgres port.
<Admonition type="danger">Exposing Postgres directly bypasses connection pooling and exposes your database to the network. Configure firewall rules or network policies to restrict access to trusted IPs only.
</Admonition>Edit docker-compose.yml:
supavisor service sectiondb service, it should look like the example below:db:
ports:
- ${POSTGRES_PORT}:${POSTGRES_PORT}
container_name: supabase-db
After restarting, you can connect to the database directly using a standard Postgres connection string:
postgres://postgres:[POSTGRES_PASSWORD]@[your-server-ip]:5432/[POSTGRES_DB]
To change the database password after initial setup, run:
sh ./utils/db-passwd.sh
The script generates a new password, updates all database roles, and modifies your .env file. After running it, restart the services with docker compose up -d --force-recreate.
By default, Storage backend is set to file, which is to use local files as the storage backend. If using Docker Desktop on a Mac, choose VirtioFS as the Docker container file sharing implementation (in Preferences > General).
Many components inside Supabase use secure secrets and passwords. These are kept in the .env file, but we strongly recommend using a secrets manager when deploying to production.
Some suggested systems include:
docker compose ps to see if all services are up and healthy.