Files

539 lines
21 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Self-Hosting with Docker"
description: "Learn how to configure and deploy Supabase with Docker."
subtitle: "Learn how to configure and deploy Supabase with Docker."
tocVideo: "FqiQKRKsfZE"
---
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.
## Contents
1. [Before you begin](#before-you-begin)
2. [System requirements](#system-requirements)
3. [Installing Supabase](#installing-supabase)
4. [Configuring and securing Supabase](#configuring-and-securing-supabase)
5. [Starting and stopping](#starting-and-stopping)
6. [Accessing Supabase services](#accessing-supabase-services)
7. [Updating](#updating)
8. [Uninstalling](#uninstalling)
9. [Advanced topics](#advanced-topics)
## Before you begin
This guide assumes you're comfortable with:
- Linux server administration basics
- Docker and Docker Compose
- Networking fundamentals (ports, DNS, firewalls)
If you're new to these topics, consider starting with [managed Supabase](/dashboard) for free, or try [local development with the CLI](/docs/guides/local-development).
You need the following installed on your system:
- [Git](https://git-scm.com/downloads)
- [Docker](https://docs.docker.com/manuals/):
- **Linux server/VPS**: Install [Docker Engine](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/)
- **Linux desktop**: Install [Docker Desktop](https://docs.docker.com/desktop/setup/install/linux/)
- **macOS**: Install [Docker Desktop](https://docs.docker.com/desktop/install/mac-install/)
- **Windows**: Install [Docker Desktop](https://docs.docker.com/desktop/install/windows-install/)
## System requirements
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.
## Installing Supabase
Follow these steps to start Supabase on your machine:
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="general"
> <TabPanel id="general" label="General">
```sh
# 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
```
</TabPanel>
<TabPanel id="advanced" label="Advanced">
```sh
# 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
```
</TabPanel>
</Tabs>
<Admonition type="tip">
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)`.
</Admonition>
## Configuring and securing Supabase
While we provided example placeholder passwords and keys in the `.env.example` file, you should NEVER start your self-hosted Supabase using these defaults.
<Admonition type="danger">
Review the configuration options below and ensure you set all secrets before starting the services.
</Admonition>
### Quick setup (experimental)
To generate and apply all secrets at once you can run:
```sh
sh ./utils/generate-keys.sh
```
The script is experimental, so review the output before proceeding and also check `.env` after it's updated by the script.
Alternatively, configure all secrets manually as follows.
### Configure database password
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 roles
Follow the [password guidelines](/docs/guides/database/postgres/roles#passwords) for choosing a secure password. For easier configuration, **use only letters and numbers** to avoid URL encoding issues in connection strings.
### Generate and configure API keys
Use the key generator below to obtain and configure the following secure keys in `.env`:
- `JWT_SECRET`: Used by PostgREST and GoTrue 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 />
1. Copy the generated value and update `JWT_SECRET` in the `.env` file. Do not share this secret publicly or commit it to version control.
2. Copy the generated value and update `ANON_KEY` in the `.env` file.
3. Copy the generated value and update `SERVICE_ROLE_KEY` in the `.env` file.
The generated keys expire in 5 years. You can verify them at [jwt.io](https://jwt.io) using the saved value of `JWT_SECRET`.
### Configure other keys, and important URLs
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`)
Review and change URL environment variables:
- `SUPABASE_PUBLIC_URL`: the base URL for accessing your Supabase via the Internet, e.g, `http://example.com:8000`
- `API_EXTERNAL_URL`: the base URL for API requests, e.g., `http://example.com:8000`
- `SITE_URL`: the base URL of your site, e.g., `http://example.com:3000`
<Admonition type="tip">
If you are only using self-hosted Supabase locally, you can use `localhost`.
</Admonition>
### Studio authentication
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.
</Admonition>
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 / dashboard
Optionally change the user:
- `DASHBOARD_USERNAME`: username for Studio / dashboard
## Starting and stopping
You can start all services by using the following command in the same directory as your `docker-compose.yml` file:
```sh
# Start the services (in detached mode)
docker compose up -d
```
After all the services have started you can see them running in the background:
```sh
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.,
```sh
docker compose logs analytics
```
To stop Supabase, use:
```sh
docker compose down
```
## Accessing Supabase services
After the Supabase services are configured and running, you can access the dashboard, connect to the database, and use edge functions.
### Accessing Supabase Studio
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](#studio-authentication).
### Accessing Postgres
By default, the Supabase stack provides the [Supavisor](https://supabase.github.io/supavisor/development/docs/) 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](#configure-database-password).
For session-based connections (equivalent to a direct Postgres connection):
```sh
psql 'postgres://postgres.[POOLER_TENANT_ID]:[POSTGRES_PASSWORD]@[your-domain]:5432/postgres'
```
For pooled transactional connections:
```sh
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](#exposing-your-postgres-database).
To change the database password, read [Changing database password](#changing-database-password).
### Accessing Edge Functions
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`
### Accessing the APIs
Each of the APIs is available through the same API gateway:
- REST: `http://<your-domain>:8000/rest/v1/`
- Auth: `http://<your-domain>:8000/auth/v1/`
- Storage: `http://<your-domain>:8000/storage/v1/`
- Realtime: `http://<your-domain>:8000/realtime/v1/`
## Updating
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](https://hub.docker.com/u/supabase).
To follow the changes and updates, refer to the self-hosted Supabase [changelog](https://github.com/supabase/supabase/blob/master/docker/CHANGELOG.md).
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:
1. Check the [supabase/studio](https://hub.docker.com/r/supabase/studio/tags) images on [Supabase Docker Hub](https://hub.docker.com/u/supabase)
2. Find the latest version (tag) number. It looks something like `2025.11.26-sha-8f096b5`
3. Update the `image` field in the `docker-compose.yml` file. It should look like this: `image: supabase/studio:2025.11.26-sha-8f096b5`
4. Run `docker compose pull`, followed by `docker compose down && docker compose up -d` to restart Supabase.
## Uninstalling
<Admonition type="danger">
Be careful — the following destroys all data, including the database and storage volumes!
</Admonition>
To uninstall, stop Supabase (while in the same directory as your `docker-compose.yml` file):
```sh
# Stop docker and remove volumes:
docker compose down -v
```
Optionally, ensure removal of all Postgres data:
```sh
rm -rf volumes/db/data
```
and all Storage data:
```sh
rm -rf volumes/storage
```
## Advanced topics
Everything beyond this point in the guide helps you understand how the system works and how you can modify it to suit your needs.
### Architecture
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",
}}
/>
- **[Studio](https://github.com/supabase/supabase/tree/master/apps/studio)** - A dashboard for managing your self-hosted Supabase project
- **[Kong](https://github.com/Kong/kong)** - Kong API gateway
- **[Auth](https://github.com/supabase/auth)** - JWT-based authentication API for user sign-ups, logins, and session management
- **[PostgREST](https://github.com/PostgREST/postgrest)** - Web server that turns your Postgres database directly into a RESTful API
- **[Realtime](https://github.com/supabase/realtime)** - Elixir server that listens to Postgres database changes and broadcasts them to subscribed clients
- **[Storage](https://github.com/supabase/storage)** - RESTful API for managing files in S3, with Postgres handling permissions
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
- **[imgproxy](https://github.com/imgproxy/imgproxy)** - Fast and secure image processing server
- **[postgres-meta](https://github.com/supabase/postgres-meta)** - RESTful API for managing Postgres (fetch tables, add roles, run queries)
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
- **[PostgreSQL](https://github.com/supabase/postgres)** - Object-relational database with over 30 years of active development
- **[Edge Runtime](https://github.com/supabase/edge-runtime)** - Web server based on Deno runtime for running JavaScript, TypeScript, and WASM services
- **[Logflare](https://github.com/Logflare/logflare)** - Log management and event analytics platform
- **[Vector](https://github.com/vectordotdev/vector)** - High-performance observability data pipeline for logs
- **[Supavisor](https://github.com/supabase/supavisor)** - Supabase's Postgres connection pooler
Multiple services require specific configuration within the Postgres database. Refer to the documentation describing the [default roles](/docs/guides/database/postgres/roles#supabase-roles) to learn more.
You can find all the default extensions inside the [schema migration scripts repo](https://github.com/supabase/postgres/tree/develop/migrations). These scripts are mounted at `/docker-entrypoint-initdb.d` to run automatically when starting the database container.
### Configuring services
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>
```yml name=docker-compose.yml
services:
rest:
image: postgrest/postgrest
environment:
PGRST_JWT_SECRET: ${JWT_SECRET}
```
```bash name=.env
## Never check your secrets into version control
JWT_SECRET=${JWT_SECRET}
```
</$CodeTabs>
### Common configuration tasks
You can configure each Supabase service separately through environment variables and configuration files. Below are the most common configuration options.
#### Configuring an email server
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:
```sh .env
SMTP_ADMIN_EMAIL=
SMTP_HOST=
SMTP_PORT=
SMTP_USER=
SMTP_PASS=
SMTP_SENDER_NAME=
```
We recommend using [AWS SES](https://aws.amazon.com/ses/). It's extremely cheap and reliable. Restart all services to pick up the new configuration.
#### Configuring S3 Storage
By default all files are stored locally on the server. You can configure the Storage service to use S3 by updating the following environment variables:
```yaml docker-compose.yml
storage:
environment: STORAGE_BACKEND=s3
GLOBAL_S3_BUCKET=name-of-your-s3-bucket
REGION=region-of-your-s3-bucket
```
You can find all the available options in the [storage repository](https://github.com/supabase/storage-api/blob/master/.env.sample). Restart the `storage` service to pick up the changes: `docker compose restart storage --no-deps`
#### Configuring Supabase AI Assistant
Configuring the Supabase AI Assistant is optional. By adding your own `OPENAI_API_KEY`, you can enable AI services, which help with writing SQL queries, statements, and policies.
<$CodeTabs>
```yaml name=docker-compose.yml
services:
studio:
image: supabase/studio
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
```
```bash name=.env
## Never check your secrets into version control
`${OPENAI_API_KEY}`
```
</$CodeTabs>
#### Setting database's `log_min_messages`
By default, `docker compose` sets the database's `log_min_messages` configuration to `fatal` to prevent redundant logs generated by Realtime. You can configure `log_min_messages` using any of the Postgres [Severity Levels](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-SEVERITY-LEVELS).
#### Accessing Postgres through Supavisor
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 connection
- `POOLER_PROXY_PORT_TRANSACTION` (default: 6543) – Transaction mode, uses connection pooling
For more information on configuring and using Supavisor, see the [Supavisor documentation](https://supabase.github.io/supavisor/).
#### Exposing your Postgres database
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`:
1. **Disable Supavisor** - Comment out or remove the entire `supavisor` service section
2. **Expose Postgres port** - Add the port mapping to the `db` service, it should look like the example below:
```yaml docker-compose.yml
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:
```sh
postgres://postgres:[POSTGRES_PASSWORD]@[your-server-ip]:5432/[POSTGRES_DB]
```
### Changing database password
To change the database password after initial setup, run:
```sh
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`.
#### File storage backend on macOS
By default, Storage backend is set to `file`, which is to use local files as the storage backend. For macOS compatibility, you need to choose `VirtioFS` as the Docker container file sharing implementation (in Docker Desktop -> Preferences -> General).
## Managing your secrets
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:
- [Doppler](https://www.doppler.com/)
- [Infisical](https://infisical.com/)
- [Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/general/overview) by Azure (Microsoft)
- [Secrets Manager](https://aws.amazon.com/secrets-manager/) by AWS
- [Secrets Manager](https://cloud.google.com/secret-manager) by GCP
- [Vault](https://www.hashicorp.com/products/vault) by HashiCorp
---
## Demo
<div className="video-container">
<iframe
src="https://www.youtube-nocookie.com/embed/FqiQKRKsfZE"
frameBorder="1"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</div>
1. The VPS instance is a DigitalOcean droplet. (For server requirements refer to [System requirements](#system-requirements))
2. To access Studio, use the IPv4 IP address of your Droplet.
3. If you're unable to use Studio, run `docker compose ps` to see if all services are up and healthy.