mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore(self-hosted): update how-to guides to match current configs (#45011)
This commit is contained in:
1 parent
2555e81dde
commit
5181be6005
16 files changed
+343
-270
No files matched your search
@@ -7,7 +7,7 @@ hideToc: true
|
||||
|
||||
## Get started
|
||||
|
||||
The fastest and recommended way to self-host Supabase is using Docker.
|
||||
The fastest and recommended way to self-host Supabase is to use Docker.
|
||||
|
||||
<div className="grid md:grid-cols-12 gap-4 not-prose">
|
||||
<div className="md:col-span-6 xl:col-span-4 relative" key="/guides/self-hosting/docker">
|
||||
@@ -55,7 +55,7 @@ There are several other options to deploy Supabase. If you're interested in help
|
||||
|
||||
## About self-hosting
|
||||
|
||||
Self-hosting is a good fit if you need full control over your data, have compliance requirements that prevent using managed services, or want to run Supabase in an isolated environment.
|
||||
Self-hosting is a good fit if you need full control over your data, have compliance requirements that prevent you from using managed services, or want to run Supabase in an isolated environment.
|
||||
|
||||
### How self-hosted Supabase differs
|
||||
|
||||
@@ -64,11 +64,7 @@ Self-hosted Supabase is different from:
|
||||
- **Supabase CLI** (local development), which is intended for development and testing only.
|
||||
- **Managed Supabase** platform, which is fully hosted and operated by Supabase.
|
||||
|
||||
### Telemetry
|
||||
|
||||
Self-hosted Supabase (Docker) does not phone home or collect any telemetry.
|
||||
|
||||
The **Supabase CLI** is a [separate tool](/docs/guides/local-development/cli/getting-started) from self-hosted Supabase and collects usage telemetry to help improve the developer experience. You can opt out by running `supabase telemetry disable` or setting `SUPABASE_TELEMETRY_DISABLED=1`. See [CLI telemetry](/docs/guides/local-development/cli/getting-started#telemetry) for other opt-out methods.
|
||||
Self-hosted Supabase mimics a single project. Studio doesn't support multiple organizations or projects. Platform-only [features](/features) such as branching, advanced metrics beyond logs, managed backups and PITR, analytics and vector buckets, ETL, and the platform management API are **unavailable** in self-hosted configuration. Most settings are configured through [environment variables](https://github.com/supabase/supabase/blob/master/docker/.env.example).
|
||||
|
||||
### Your responsibilities when self-hosting
|
||||
|
||||
@@ -76,10 +72,18 @@ When you self-host, **you are responsible for**:
|
||||
|
||||
- Server provisioning and maintenance
|
||||
- Security hardening and keeping OS and services updated
|
||||
- Maintaining the Postgres database
|
||||
- Service configuration and management
|
||||
- Postgres database maintenance
|
||||
- High availability and scalability
|
||||
- Backups and disaster recovery
|
||||
- Monitoring and uptime
|
||||
|
||||
### Telemetry
|
||||
|
||||
Self-hosted Supabase (run via Docker Compose) **does not phone home or collect any telemetry**.
|
||||
|
||||
The **Supabase CLI** is a [separate tool](/docs/guides/local-development/cli/getting-started) and collects usage telemetry to help improve the developer experience. See [CLI telemetry](/docs/guides/local-development/cli/getting-started#telemetry) for opt-out methods.
|
||||
|
||||
## Support and community
|
||||
|
||||
Self-hosted Supabase is community-supported.
|
||||
|
||||
@@ -39,7 +39,7 @@ For better performance with large files, use the direct storage hostname: `https
|
||||
|
||||
## Step 2: Create buckets on self-hosted
|
||||
|
||||
Buckets must exist on the destination before you can copy objects into them. You can create them through dashboard UI, or with **SQL Editor**.
|
||||
Buckets must exist on the destination before you can copy objects into them. You can create them through the dashboard UI, or with the **SQL Editor**.
|
||||
|
||||
<Admonition type="tip">
|
||||
|
||||
@@ -93,7 +93,7 @@ Replace the credentials with your actual values. For self-hosted, use the `REGIO
|
||||
|
||||
Verify both remotes connect:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
rclone lsd platform:
|
||||
rclone lsd self-hosted:
|
||||
```
|
||||
@@ -104,13 +104,13 @@ Both commands should list your buckets.
|
||||
|
||||
Copy a single bucket:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
rclone copy platform:your-storage-bucket self-hosted:your-storage-bucket --progress
|
||||
```
|
||||
|
||||
To copy all buckets:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
for bucket in $(rclone lsf platform: | tr -d '/'); do
|
||||
echo "Copying bucket: $bucket"
|
||||
rclone copy "platform:$bucket" "self-hosted:$bucket" --progress
|
||||
@@ -127,7 +127,7 @@ For large migrations, consider adding `--transfers 4` to increase parallelism, o
|
||||
|
||||
Compare object counts between source and destination:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
rclone size platform:your-storage-bucket && \
|
||||
rclone size self-hosted:your-storage-bucket
|
||||
```
|
||||
@@ -154,7 +154,7 @@ If rclone reports that a bucket doesn't exist on the self-hosted side, create it
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
For very large files, increase rclone's timeout:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
rclone copy platform:your-storage-bucket self-hosted:your-storage-bucket --timeout 30m
|
||||
```
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ volumes/
|
||||
|
||||
Update the `auth` service to depend on `templates-server`, and pass the email template environment variables. Then add a `templates-server` service to serve the templates from `./volumes/templates`.
|
||||
|
||||
```yml
|
||||
```yml name=docker-compose.yml
|
||||
services:
|
||||
auth:
|
||||
depends_on:
|
||||
@@ -90,7 +90,7 @@ services:
|
||||
|
||||
#### What this configuration does
|
||||
|
||||
- Adds a `templates-server`service that runs alongside the Supabase services in the same docker network.
|
||||
- Adds a `templates-server` service that runs alongside the Supabase services in the same docker network.
|
||||
- Serves your custom email template files from the `./volumes/templates` directory.
|
||||
- Keeps the templates-server private to the Docker network (no published ports), so it is not accessible from outside.
|
||||
- Allows the `auth` service to fetch templates via `http://templates-server/<template>.html`.
|
||||
@@ -148,7 +148,7 @@ volumes/
|
||||
|
||||
Update the `auth` service in `docker-compose.yml` to enable password changed notification
|
||||
|
||||
```yml
|
||||
```yml name=docker-compose.yml
|
||||
services:
|
||||
auth:
|
||||
depends_on:
|
||||
|
||||
@@ -14,7 +14,7 @@ Docker is the easiest way to get started with self-hosted Supabase. It should ta
|
||||
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)
|
||||
6. [Accessing Supabase services](#accessing-supabase-studio-dashboard)
|
||||
7. [Updating](#updating)
|
||||
8. [Uninstalling](#uninstalling)
|
||||
9. [Advanced topics](#advanced-topics)
|
||||
@@ -27,7 +27,7 @@ This guide assumes you're comfortable with:
|
||||
- Docker and Docker Compose
|
||||
- Networking fundamentals (ports, DNS, firewalls)
|
||||
|
||||
If you're new to these topics, consider starting with managed [Supabase platform](/dashboard) for free.
|
||||
If you're new to these topics, consider starting with the managed [Supabase platform](/dashboard) for free.
|
||||
|
||||
You need the following installed on your system:
|
||||
|
||||
@@ -37,6 +37,9 @@ You need the following installed on your system:
|
||||
- **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/)
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
- OpenSSL and Node.js 16+ (when switching to the [new API keys](/docs/guides/self-hosting/self-hosted-auth-keys) and new auth)
|
||||
|
||||
|
||||
## System requirements
|
||||
|
||||
@@ -133,105 +136,89 @@ While we provided example placeholder passwords and keys in the `.env.example` f
|
||||
|
||||
<Admonition type="danger">
|
||||
|
||||
Review the configuration options below and ensure you set all secrets before starting the services.
|
||||
Review the configuration steps below and ensure you set all secrets properly before starting the services.
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Quick setup (experimental)
|
||||
### Quick setup
|
||||
|
||||
To generate and apply all secrets at once you can run:
|
||||
To generate secure passwords and secrets, run:
|
||||
|
||||
```sh
|
||||
sh ./utils/generate-keys.sh
|
||||
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.
|
||||
As the **next step**, use the following script to add the new API keys and asymmetric key pair:
|
||||
|
||||
### Configure database password
|
||||
```sh
|
||||
sh utils/add-new-auth-keys.sh
|
||||
```
|
||||
|
||||
Change the placeholder password in the `.env` file **before** starting Supabase for the first time.
|
||||
Review the output of both scripts and check the `.env` file **before proceeding** to configure [Supabase URLs](#configure-supabase-urls).
|
||||
|
||||
- `POSTGRES_PASSWORD`: the password for the `postgres` and `supabase_admin` database roles
|
||||
For a description of all secrets refer to the [related section](#configuring-secrets) in the "Advanced topics" below. If you'd like to learn more about how the new API keys and asymmetric JWT signing work in a self-hosted Supabase setup, make sure to read the detailed [how-to guide](/docs/guides/self-hosting/self-hosted-auth-keys).
|
||||
|
||||
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.
|
||||
### Configure Supabase URLs
|
||||
|
||||
### Generate and configure API keys
|
||||
Review and change URL configuration variables:
|
||||
|
||||
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 />
|
||||
|
||||
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`)
|
||||
- `S3_PROTOCOL_ACCESS_KEY_ID`: Access key ID (username-like) for [accessing](/docs/guides/self-hosting/self-hosted-s3) 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`)
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
- `MINIO_ROOT_PASSWORD`: Root administrator password for the [MinIO server](/docs/guides/self-hosting/self-hosted-s3#using-minio). (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:8000`
|
||||
- `API_EXTERNAL_URL`: base URL of the Auth service as seen externally, e.g., `http://example.com:8000`
|
||||
- `SUPABASE_PUBLIC_URL`: base URL for accessing Supabase from the Internet (Dashboard, API, Storage, etc.), e.g., `http://example.com:8000`
|
||||
- `API_EXTERNAL_URL`: used by the Auth service to configure callback URLs, e.g., `http://example.com:8000`
|
||||
- `SITE_URL`: default [redirect URL](/docs/guides/auth/redirect-urls) for Auth, e.g., `http://example.com:3000`
|
||||
|
||||
<Admonition type="tip">
|
||||
<Admonition type="note" label="What your-domain means in the docs">
|
||||
|
||||
If you are only using self-hosted Supabase locally, you can use `localhost`.
|
||||
Throughout the self-hosting guides, `<your-domain>` stands for the host where your Supabase instance is reachable: your domain name, your server's IP, or `localhost`, depending on your setup.
|
||||
|
||||
- **Default setup:** Kong listens on port `8000`, so the full URL is `http://<your-domain>:8000`.
|
||||
- **Behind a [reverse proxy](/docs/guides/self-hosting/self-hosted-proxy-https):** the proxy terminates TLS on port `443`, so the URL becomes `https://<your-domain>`.
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Where to find your credentials
|
||||
|
||||
The generated secrets and password are written to the `.env` file. The ones you are most likely to need when connecting your application to self-hosted Supabase are:
|
||||
|
||||
- `POSTGRES_PASSWORD`: database password used in Postgres connection strings and by `psql`
|
||||
- `SUPABASE_PUBLISHABLE_KEY`: publishable API key for client-side use (e.g., in your frontend)
|
||||
- `SUPABASE_SECRET_KEY`: secret API key for server-side use. Never expose this in client code
|
||||
- `SUPABASE_PUBLIC_URL`: base URL you pass as `supabaseUrl` to the client libraries
|
||||
|
||||
If you are still using the [legacy API keys](#configuring-legacy-api-keys), look for `ANON_KEY` and `SERVICE_ROLE_KEY` instead of the new publishable and secret API keys above.
|
||||
|
||||
### Studio authentication
|
||||
|
||||
Access to Studio dashboard and internal API is protected with **HTTP basic authentication**.
|
||||
Access to Studio (Dashboard) is protected with **HTTP basic authentication**.
|
||||
|
||||
<Admonition type="danger">
|
||||
|
||||
The default password MUST be changed before starting Supabase.
|
||||
A secure password MUST be set before starting Supabase. The password must include at least one letter - do not use numbers only or any special characters.
|
||||
|
||||
</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
|
||||
In the `.env` file, edit `DASHBOARD_PASSWORD` to change the password, and optionally `DASHBOARD_USERNAME` to change the username.
|
||||
|
||||
## Starting and stopping
|
||||
|
||||
You can start all services by using the following command in the same directory as your `docker-compose.yml` file:
|
||||
You can start Supabase 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:
|
||||
Check the status of the services:
|
||||
|
||||
```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.,
|
||||
After a minute or less, all services should have a status `Up [...] (healthy)`. If you see a status such as `created` but not `Up`, run the test script to determine what the problem might be:
|
||||
|
||||
```sh
|
||||
sh tests/test-container-logs.sh
|
||||
```
|
||||
|
||||
Then try inspecting the Docker logs for a specific container, e.g.,
|
||||
|
||||
```sh
|
||||
docker compose logs analytics
|
||||
@@ -243,21 +230,17 @@ To stop Supabase, use:
|
||||
docker compose down
|
||||
```
|
||||
|
||||
## Accessing Supabase services
|
||||
## Accessing Supabase Studio (Dashboard)
|
||||
|
||||
After the Supabase services are configured and running, you can access the dashboard, connect to the database, and use edge functions.
|
||||
By default, you can access the dashboard through the API gateway on port `8000`.
|
||||
|
||||
### Accessing Supabase Studio
|
||||
For example: `http://<your-domain>:8000`, or `http://<your-ip>:8000` (or `localhost:8000` if you are running Docker Compose locally).
|
||||
|
||||
You can access Supabase Studio through the API gateway on port `8000`.
|
||||
You will be prompted for a username and password. See the [Studio authentication](#studio-authentication) section for details.
|
||||
|
||||
For example: `http://example.com:8000`, or `http://<your-ip>:8000` (or `localhost:8000` if you are running Docker Compose locally).
|
||||
## Accessing Postgres
|
||||
|
||||
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.
|
||||
The self-hosted 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.
|
||||
|
||||
@@ -281,13 +264,23 @@ If you need to configure Postgres to be directly accessible from the Internet, r
|
||||
|
||||
To change the database password, read [Changing database password](#changing-database-password).
|
||||
|
||||
### Accessing Edge Functions
|
||||
## 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`.
|
||||
Edge Functions live in `volumes/functions`. The default setup includes a `hello` function you can invoke with `curl`:
|
||||
|
||||
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`
|
||||
```sh
|
||||
curl http://<your-domain>:8000/functions/v1/hello
|
||||
```
|
||||
|
||||
### Accessing the APIs
|
||||
Add new functions at `volumes/functions/<FUNCTION_NAME>/index.ts`, then restart the service to pick them up:
|
||||
|
||||
```sh
|
||||
docker compose restart functions --no-deps
|
||||
```
|
||||
|
||||
See the [self-hosted Edge Functions guide](/docs/guides/self-hosting/self-hosted-functions) for more details.
|
||||
|
||||
## Accessing APIs
|
||||
|
||||
Each of the APIs is available through the same API gateway:
|
||||
|
||||
@@ -296,9 +289,15 @@ Each of the APIs is available through the same API gateway:
|
||||
- Storage: `http://<your-domain>:8000/storage/v1/`
|
||||
- Realtime: `http://<your-domain>:8000/realtime/v1/`
|
||||
|
||||
## Configuring HTTPS
|
||||
|
||||
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](/docs/guides/self-hosting/self-hosted-proxy-https) guide for detailed setup instructions.
|
||||
|
||||
## 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).
|
||||
We publish stable releases of the Docker Compose setup approximately once a month. The versions in each release are tested together, so they may lag behind the latest images on Docker Hub. 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).
|
||||
|
||||
@@ -320,10 +319,11 @@ You'd like to update or rollback the Studio image. Follow the steps below:
|
||||
|
||||
</Admonition>
|
||||
|
||||
To uninstall, stop Supabase (while in the same directory as your `docker-compose.yml` file):
|
||||
To uninstall, stop Supabase (while in the same directory as your `docker-compose.yml` file).
|
||||
|
||||
Stop the containers and remove volumes:
|
||||
|
||||
```sh
|
||||
# Stop docker and remove volumes:
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
@@ -345,9 +345,10 @@ Everything beyond this point in the guide helps you understand how the system wo
|
||||
|
||||
### Architecture
|
||||
|
||||
Supabase is a combination of open source tools specifically developed for enterprise-readiness.
|
||||
Supabase is built from open source tools, each chosen or developed for production use.
|
||||
|
||||
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.
|
||||
{/* supa-mdx-lint-disable-next-line Rule004ExcludeWords */}
|
||||
If the tools and communities already exist, with an MIT, Apache 2, PostgreSQL, 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."
|
||||
@@ -369,7 +370,6 @@ If the tools and communities already exist, with an MIT, Apache 2, or equivalent
|
||||
{/* 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 */}
|
||||
- **[Postgres](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
|
||||
@@ -378,9 +378,55 @@ If the tools and communities already exist, with an MIT, Apache 2, or equivalent
|
||||
|
||||
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.
|
||||
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 Postgres container.
|
||||
|
||||
### Configuring services
|
||||
### Setting database password
|
||||
|
||||
The `generate-keys.sh` script creates a secure random database password. If you want to use your own, you can change `POSTGRES_PASSWORD` in the `.env` file **before** starting Supabase for the first time.
|
||||
|
||||
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.
|
||||
|
||||
### Changing database password
|
||||
|
||||
To change the database password after the 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`.
|
||||
|
||||
### Configuring legacy API keys
|
||||
|
||||
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 />
|
||||
|
||||
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`.
|
||||
|
||||
### Configuring secrets
|
||||
|
||||
The `generate-keys.sh` script sets the following secrets automatically. You can also configure them manually in the `.env` file if needed:
|
||||
|
||||
- `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](/docs/guides/self-hosting/self-hosted-s3) 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`)
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
- `MINIO_ROOT_PASSWORD`: Root administrator password for the [MinIO server](/docs/guides/self-hosting/self-hosted-s3#using-minio). (Must be 8+ characters; generate with `openssl rand -hex 16`)
|
||||
|
||||
### Configuring Supabase services
|
||||
|
||||
Each service has a number of configuration options you can find in the related documentation.
|
||||
|
||||
@@ -396,22 +442,26 @@ services:
|
||||
PGRST_JWT_SECRET: ${JWT_SECRET}
|
||||
```
|
||||
|
||||
```bash name=.env
|
||||
```sh name=.env
|
||||
## Never check your secrets into version control
|
||||
JWT_SECRET=${JWT_SECRET}
|
||||
```
|
||||
|
||||
</$CodeTabs>
|
||||
|
||||
### Common configuration tasks
|
||||
### Configuring social login (OAuth) providers
|
||||
|
||||
You can configure each Supabase service separately through environment variables and configuration files. Below are the most common configuration options.
|
||||
See the [Configure Social Login (OAuth) Providers](/docs/guides/self-hosting/self-hosted-oauth) guide for setup instructions.
|
||||
|
||||
#### Configuring an email server
|
||||
### Configuring phone login, SMS, and MFA
|
||||
|
||||
See the [Configure Phone Login & MFA](/docs/guides/self-hosting/self-hosted-phone-mfa) guide for SMS provider setup, OTP settings, and multi-factor authentication configuration.
|
||||
|
||||
### 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 in the `.env` file:
|
||||
|
||||
```sh .env
|
||||
```sh name=.env
|
||||
SMTP_ADMIN_EMAIL=
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
@@ -422,35 +472,17 @@ SMTP_SENDER_NAME=
|
||||
|
||||
We recommend using [AWS SES](https://aws.amazon.com/ses/). It's affordable and reliable. Restart all services to pick up the new configuration.
|
||||
|
||||
#### Configuring S3 Storage
|
||||
### Configuring S3 Storage
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
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.
|
||||
By default, all files are stored locally on the server. You can connect Storage to an S3-compatible backend (AWS S3, RustFS, MinIO, Cloudflare R2), enable the S3 protocol endpoint for tools like `rclone`, or both. These are independent features.
|
||||
|
||||
See the [Configure S3 Storage](/docs/guides/self-hosting/self-hosted-s3) guide for detailed setup instructions.
|
||||
|
||||
#### Configuring HTTPS
|
||||
|
||||
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](/docs/guides/self-hosting/self-hosted-proxy-https) guide for setup instructions.
|
||||
|
||||
#### Configuring social login (OAuth) providers
|
||||
|
||||
See the [Configure Social Login (OAuth) Providers](/docs/guides/self-hosting/self-hosted-oauth) guide for setup instructions.
|
||||
|
||||
#### Configuring phone login, SMS, and MFA
|
||||
|
||||
See the [Configure Phone Login & MFA](/docs/guides/self-hosting/self-hosted-phone-mfa) guide for SMS provider setup, OTP settings, and multi-factor authentication configuration.
|
||||
|
||||
#### Configuring Supabase AI Assistant
|
||||
### Configuring Supabase AI Assistant
|
||||
|
||||
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.
|
||||
|
||||
#### Setting log_min_messages in Postgres
|
||||
|
||||
By default, the database's `log_min_messages` configuration is set to `fatal` in [docker-compose.yml](https://github.com/supabase/supabase/blob/df8729a82b1847e2989c14ede27965612761d503/docker/docker-compose.yml#L466) 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
|
||||
### Accessing Postgres through Supavisor
|
||||
|
||||
By default, Postgres connections go through the Supavisor connection pooler for efficient connection management. Two ports are available:
|
||||
|
||||
@@ -459,7 +491,7 @@ By default, Postgres connections go through the Supavisor connection pooler for
|
||||
|
||||
For more information on configuring and using Supavisor, see the [Supavisor documentation](https://supabase.github.io/supavisor/).
|
||||
|
||||
#### Exposing your Postgres database
|
||||
### 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.
|
||||
|
||||
@@ -474,7 +506,7 @@ 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
|
||||
```yaml name=docker-compose.yml
|
||||
db:
|
||||
ports:
|
||||
- ${POSTGRES_PORT}:${POSTGRES_PORT}
|
||||
@@ -487,23 +519,18 @@ After restarting, you can connect to the database directly using a standard Post
|
||||
postgres://postgres:[POSTGRES_PASSWORD]@[your-server-ip]:5432/[POSTGRES_DB]
|
||||
```
|
||||
|
||||
### Changing database password
|
||||
### Setting log_min_messages in Postgres
|
||||
|
||||
To change the database password after initial setup, run:
|
||||
By default, the database's `log_min_messages` configuration is set to `fatal` in [docker-compose.yml](https://github.com/supabase/supabase/blob/df8729a82b1847e2989c14ede27965612761d503/docker/docker-compose.yml#L466) 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).
|
||||
|
||||
```sh
|
||||
sh ./utils/db-passwd.sh
|
||||
```
|
||||
### Using file backend in Storage on macOS
|
||||
|
||||
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. If using Docker Desktop on a Mac, choose `VirtioFS` as the Docker container file sharing implementation (in **Preferences** > **General**).
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
By default, the Storage backend uses local files via a bind mount. On macOS, Docker Desktop bind mounts have known limitations (missing xattr support, permission issues) that can prevent Storage from working correctly. Change the [bind mount](https://github.com/supabase/supabase/blob/a5f4a59e0e262394b345600e8d8a2241d6ac3b64/docker/docker-compose.yml#L391) to a named Docker volume instead.
|
||||
|
||||
## 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.
|
||||
Many components inside Supabase rely on secrets and passwords being kept securely. By default, all secrets are in the `.env` file, but we strongly recommend using a secrets manager when deploying to production.
|
||||
|
||||
Some suggested systems include:
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ When connecting via an SSH tunnel to the Studio Docker container, the source IP
|
||||
|
||||
Determine the Docker bridge gateway IP on the host running your Supabase containers:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker inspect supabase-kong \
|
||||
--format '{{range .NetworkSettings.Networks}}{{println .Gateway}}{{end}}'
|
||||
```
|
||||
@@ -43,7 +43,7 @@ Add the IP address you discovered to the Kong configuration by editing the follo
|
||||
3. Add your local IP to the 'allow' list.
|
||||
4. Your edited configuration should look like the example below.
|
||||
|
||||
```yaml
|
||||
```yaml name=volumes/api/kong.yml
|
||||
## MCP endpoint - local access
|
||||
- name: mcp
|
||||
_comment: 'MCP: /mcp -> http://studio:3000/api/mcp (local access)'
|
||||
@@ -79,7 +79,7 @@ Add the IP address you discovered to the Kong configuration by editing the follo
|
||||
|
||||
After you've added the local IP address as above, restart the Kong container:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker compose restart kong
|
||||
```
|
||||
|
||||
@@ -87,7 +87,7 @@ docker compose restart kong
|
||||
|
||||
From your local machine, create an SSH tunnel to your Supabase host:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
ssh -L localhost:8080:localhost:8000 you@your-supabase-host
|
||||
```
|
||||
|
||||
@@ -111,7 +111,7 @@ Edit the settings for your MCP client and add the following to `"mcpServers": {}
|
||||
|
||||
From your local machine, check that the MCP server is reachable:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
curl http://localhost:8080/mcp \
|
||||
-X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
|
||||
@@ -12,7 +12,7 @@ Self-hosted Supabase ships with Postgres 15 by default. This guide covers two sc
|
||||
## Before you begin
|
||||
|
||||
- Complete the [Self-Hosting with Docker](/docs/guides/self-hosting/docker) setup
|
||||
- Your current database image should be `supabase/postgres:15.x` (check with `docker inspect supabase-db --format '{{.Config.Image}}'`)
|
||||
- Your current database image should be `supabase/postgres:15.x`
|
||||
|
||||
## New deployment with Postgres 17
|
||||
|
||||
@@ -24,7 +24,7 @@ docker compose -f docker-compose.yml -f docker-compose.pg17.yml up -d
|
||||
|
||||
This uses the `docker-compose.pg17.yml` override file which swaps the database image:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.pg17.yml
|
||||
services:
|
||||
db:
|
||||
image: supabase/postgres:17.6.1.084
|
||||
@@ -32,11 +32,11 @@ services:
|
||||
|
||||
<Admonition type="tip">
|
||||
|
||||
Always include both compose files when running commands. If you omit the override, Docker Compose falls back to the Postgres 15 image defined in `docker-compose.yml`.
|
||||
If you use the override file, remember to include both compose files when running commands. Alternatively, you can update the image tag directly in `docker-compose.yml` instead of using an override.
|
||||
|
||||
</Admonition>
|
||||
|
||||
The rest of the setup is the same as the standard Docker guide. All init scripts (`roles.sql`, `jwt.sql`, `webhooks.sql`, etc.) are compatible with Postgres 17.
|
||||
The rest of the setup is the same as for Postgres 15 (see the Docker install [guide](/docs/guides/self-hosting/docker)).
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
If the new Postgres 17 container fails to start, make sure to check for an old `db-config` Docker volume. See [Postgres 17 fails to start with a leftover db-config volume](#postgres-17-fails-to-start-with-a-leftover-db-config-volume) for details.
|
||||
@@ -136,7 +136,9 @@ docker compose -f docker-compose.yml -f docker-compose.pg17.yml exec db psql -U
|
||||
The original Postgres 15 data is preserved at `./volumes/db/data.bak.pg15`. The pgsodium root key is saved as `./volumes/db/pgsodium_root.key.bak.pg15`. The upgrade binaries tarball is cached at `./volumes/db/pg17_upgrade_bin_*.tar.gz`. Once you have verified that everything works, you can reclaim disk space:
|
||||
|
||||
```sh
|
||||
rm -rf ./volumes/db/data.bak.pg15 ./volumes/db/pgsodium_root.key.bak.pg15 ./volumes/db/pg17_upgrade_bin_*.tar.gz
|
||||
rm -rf ./volumes/db/data.bak.pg15 \
|
||||
./volumes/db/pgsodium_root.key.bak.pg15 \
|
||||
./volumes/db/pg17_upgrade_bin_*.tar.gz
|
||||
```
|
||||
|
||||
<Admonition type="caution">
|
||||
@@ -274,7 +276,7 @@ If you run out of space mid-upgrade, the safest path is to roll back and free up
|
||||
|
||||
### Postgres 17 fails to start with a leftover db-config volume
|
||||
|
||||
If you are starting a **fresh** Postgres 17 deployment (not upgrading from Postgres 15) and the container fails to start, the most likely cause is a leftover `db-config` volume from a previous Postgres 15 installation. Try to start the containers without the `-d` option and/or check the logs for errors about `postgresql.conf` or other configuration mismatch.
|
||||
If you are starting a **fresh** Postgres 17 deployment (not using the upgrade script) and the container fails to start, the most likely cause is a leftover `db-config` volume from a previous Postgres 15 installation. Start the containers without the `-d` option or check the logs for errors about `postgresql.conf` or other configuration mismatch.
|
||||
|
||||
To fix, remove the old volume and let Postgres 17 initialize a clean configuration:
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ description: 'Restore your database from the Supabase platform to a self-hosted
|
||||
subtitle: 'Restore your database from the Supabase platform to a self-hosted instance.'
|
||||
---
|
||||
|
||||
This guide walks you through restoring your database from a Supabase platform project to a [self-hosted Docker instance](/docs/guides/self-hosting/docker). Storage objects transfer or redeploying edge functions is not covered here.
|
||||
This guide walks you through restoring your database from a Supabase platform project to a [self-hosted Docker instance](/docs/guides/self-hosting/docker). Transferring storage objects or redeploying edge functions is not covered here.
|
||||
|
||||
## Before you begin
|
||||
|
||||
@@ -24,15 +24,15 @@ On your managed Supabase project dashboard, click [**Connect**](/dashboard/proje
|
||||
|
||||
Export roles, schema, and data as three separate SQL files:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
supabase db dump --db-url "[CONNECTION_STRING]" -f roles.sql --role-only
|
||||
```
|
||||
|
||||
```bash
|
||||
```sh
|
||||
supabase db dump --db-url "[CONNECTION_STRING]" -f schema.sql
|
||||
```
|
||||
|
||||
```bash
|
||||
```sh
|
||||
supabase db dump --db-url "[CONNECTION_STRING]" -f data.sql --use-copy --data-only
|
||||
```
|
||||
|
||||
@@ -64,7 +64,7 @@ Use your domain name, your server IP, or localhost for `[your-domain]` depending
|
||||
|
||||
Run `psql` to restore:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
psql \
|
||||
--single-transaction \
|
||||
--variable ON_ERROR_STOP=1 \
|
||||
@@ -81,7 +81,7 @@ Setting `session_replication_role` to `replica` disables triggers during the dat
|
||||
|
||||
Connect to your self-hosted database and run a few checks:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
psql "postgres://postgres.your-tenant-id:[POSTGRES_PASSWORD]@[your-domain]:5432/postgres"
|
||||
```
|
||||
|
||||
@@ -119,7 +119,13 @@ Your `auth.users` table and related data are included in the database dump, so u
|
||||
|
||||
## Postgres version compatibility
|
||||
|
||||
Managed Supabase may run a newer Postgres version (Postgres 17) than the self-hosted Docker image (currently Postgres 15). The `supabase db dump` command produces plain SQL files that work across major Postgres versions.
|
||||
Managed Supabase may run a newer Postgres version (Postgres 17) than the self-hosted Docker image (currently it's Postgres 15 by default). The `supabase db dump` command produces plain SQL files that work across major Postgres versions.
|
||||
|
||||
<Admonition type="tip">
|
||||
|
||||
If your managed project runs Postgres 17, consider starting your self-hosted deployment with Postgres 17 as well. See the [Postgres 17 guide](/docs/guides/self-hosting/postgres-upgrade-17) for setup instructions.
|
||||
|
||||
</Admonition>
|
||||
|
||||
Keep in mind:
|
||||
|
||||
@@ -141,7 +147,7 @@ The platform may run a newer Postgres version (17 vs 15) and newer Auth service
|
||||
|
||||
**Workaround:** Edit `data.sql` before restoring:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
# Comment out PG17-only transaction_timeout
|
||||
sed -i 's/^SET transaction_timeout/-- &/' data.sql
|
||||
```
|
||||
|
||||
@@ -8,8 +8,10 @@ You can configure self-hosted Supabase to use the [new API keys](/docs/guides/ap
|
||||
|
||||
## Before you begin
|
||||
|
||||
- Complete the [Docker setup guide](/docs/guides/self-hosting/docker), including running `generate-keys.sh` so that `JWT_SECRET`, `ANON_KEY`, and `SERVICE_ROLE_KEY` are set in your `.env` file.
|
||||
- Ensure `openssl` and `node` version 16 or newer are available on the machine where you will generate new keys.
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
|
||||
- Ensure OpenSSL and Node.js 16+ are available on the machine where you will generate new keys
|
||||
- Complete the [Docker setup guide](/docs/guides/self-hosting/docker), including running `generate-keys.sh` so that `JWT_SECRET`, `ANON_KEY`, and `SERVICE_ROLE_KEY` are set in your `.env` file
|
||||
- If you are upgrading an existing self-hosted Supabase environment, make sure to check the [changelog](https://github.com/supabase/supabase/blob/master/docker/CHANGELOG.md) and add/update the following files:
|
||||
- `.env.example` (merge new sections into your `.env` file)
|
||||
- `docker-compose.yml`
|
||||
@@ -36,7 +38,7 @@ The script reads `JWT_SECRET` from `.env` and includes it as a symmetric key ins
|
||||
|
||||
After updating `.env`, enable new authentication by uncommenting these lines in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# JSON array of signing JWKs (EC private + legacy symmetric)
|
||||
@@ -55,7 +57,13 @@ storage:
|
||||
|
||||
PostgREST does not need uncommenting - it already uses `PGRST_JWT_SECRET: ${JWT_JWKS:-${JWT_SECRET}}` which automatically picks up `JWT_JWKS` when set.
|
||||
|
||||
Then restart all services:
|
||||
<Admonition type="caution">
|
||||
|
||||
Podman does not support nested variable interpolation (`${A:-${B}}`). If you are using Podman, replace each nested expression with the required variable directly - see the inline comments in `docker-compose.yml` for the exact substitutions.
|
||||
|
||||
</Admonition>
|
||||
|
||||
Restart all services:
|
||||
|
||||
```sh
|
||||
docker compose down && docker compose up -d
|
||||
@@ -74,14 +82,14 @@ sb_secret_<22-char-random>_<8-char-checksum>
|
||||
|
||||
Test with the new publishable key:
|
||||
|
||||
```
|
||||
```sh
|
||||
curl http://<your-domain>/rest/v1/ \
|
||||
-H "apikey: your-supabase-publishable-key"
|
||||
```
|
||||
|
||||
You should receive a valid response from PostgREST. Then verify that the legacy key still works:
|
||||
|
||||
```
|
||||
```sh
|
||||
curl http://<your-domain>/rest/v1/ \
|
||||
-H "apikey: your-anon-key"
|
||||
```
|
||||
@@ -90,7 +98,7 @@ Both should work and return the same result.
|
||||
|
||||
You can also verify the public JWKS endpoint:
|
||||
|
||||
```
|
||||
```sh
|
||||
curl http://<your-domain>/auth/v1/.well-known/jwks.json
|
||||
```
|
||||
|
||||
@@ -119,10 +127,8 @@ New variables default to empty values in `.env.example`. When empty, the API gat
|
||||
|
||||
The new authentication configuration is fully backward compatible:
|
||||
|
||||
- **All new variables are optional.** If left with empty values, the API gateway (Kong) and all services behave exactly as before.
|
||||
- **Kong accepts both key types simultaneously.** You can migrate clients incrementally - some using legacy API keys, others using the new ones.
|
||||
- **JWKS includes the symmetric key.** `JWT_JWKS` contains both the EC public key (for verifying new ES256 tokens) and the legacy `JWT_SECRET` as a symmetric JWK (for verifying old HS256 tokens). Services that receive `JWT_JWKS` can verify both token types.
|
||||
- **Services fall back gracefully.** PostgREST uses `${JWT_JWKS:-${JWT_SECRET}}` - if `JWT_JWKS` is empty, it uses `JWT_SECRET` directly.
|
||||
- **No database changes required.** The asymmetric key system operates entirely at the API gateway and service configuration layer.
|
||||
|
||||
<Admonition type="caution">
|
||||
@@ -190,7 +196,7 @@ For **Realtime WebSocket** connections, the API key is sent as a `?apikey=` quer
|
||||
|
||||
Kong is configured with two consumers that each accept both the legacy and new API keys:
|
||||
|
||||
```yaml
|
||||
```yaml name=volumes/api/kong.yml
|
||||
consumers:
|
||||
- username: anon
|
||||
keyauth_credentials:
|
||||
|
||||
@@ -16,8 +16,8 @@ On managed Supabase platform, Edge Functions are deployed across multiple region
|
||||
|
||||
The default `hello` function is located at `volumes/functions/hello/index.ts`. You can invoke it immediately after starting your stack:
|
||||
|
||||
```bash
|
||||
curl http://<your-domain>:8000/functions/v1/hello
|
||||
```sh
|
||||
curl http://<your-domain>/functions/v1/hello
|
||||
```
|
||||
|
||||
This returns `"Hello from Edge Functions!"`.
|
||||
@@ -26,12 +26,12 @@ This returns `"Hello from Edge Functions!"`.
|
||||
|
||||
### Step 1: Add a new function directory and the function code
|
||||
|
||||
```
|
||||
```sh
|
||||
mkdir -p volumes/functions/my-function &&
|
||||
touch volumes/functions/my-function/index.ts
|
||||
```
|
||||
|
||||
add the following code to `index.ts`:
|
||||
Add the following code to `index.ts`:
|
||||
|
||||
```typescript
|
||||
Deno.serve(async (req: Request) => {
|
||||
@@ -46,22 +46,22 @@ Deno.serve(async (req: Request) => {
|
||||
|
||||
### Step 2: Restart the functions service to pick up the new function
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker compose restart functions --no-deps
|
||||
```
|
||||
|
||||
### Step 3: Invoke your function
|
||||
|
||||
```bash
|
||||
curl -X POST http://<your-domain>:8000/functions/v1/my-function \
|
||||
```sh
|
||||
curl -X POST http://<your-domain>/functions/v1/my-function \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"name": "World"}'
|
||||
```
|
||||
|
||||
You should be able to see the response from `my-function`:
|
||||
|
||||
```
|
||||
{"message":"Hello, World!"}
|
||||
```json
|
||||
{ "message": "Hello, World!" }
|
||||
```
|
||||
|
||||
## Custom environment variables
|
||||
@@ -70,13 +70,13 @@ You should be able to see the response from `my-function`:
|
||||
|
||||
For multiple variables or secrets, create a separate env file, e.g., `.env.functions` in your `docker/` directory:
|
||||
|
||||
```bash
|
||||
```
|
||||
MY_CUSTOM_VAR=some-value
|
||||
```
|
||||
|
||||
Add `env_file` to the `functions` service in `docker-compose.yml` (variables in `env_file` load first, then `environment` values take precedence):
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
functions:
|
||||
env_file:
|
||||
- .env.functions
|
||||
@@ -93,7 +93,7 @@ Don't commit `.env.functions` to version control if it contains secrets. Add it
|
||||
|
||||
Restart the functions service:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker compose up -d --force-recreate --no-deps functions
|
||||
```
|
||||
|
||||
@@ -101,7 +101,7 @@ docker compose up -d --force-recreate --no-deps functions
|
||||
|
||||
For one or two variables, you can add them directly under `environment` in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
functions:
|
||||
environment:
|
||||
# Custom variables
|
||||
@@ -115,7 +115,7 @@ Then define `MY_CUSTOM_VAR` in your main `.env` file, or specify the value direc
|
||||
|
||||
### Accessing variables in functions
|
||||
|
||||
All container environment variables are forwarded to function workers by `main/index.ts`. Access them with:
|
||||
All container environment variables are forwarded to the function workers by `main/index.ts`. Access them with:
|
||||
|
||||
```typescript
|
||||
const customVar = Deno.env.get('MY_CUSTOM_VAR')
|
||||
@@ -125,14 +125,16 @@ const customVar = Deno.env.get('MY_CUSTOM_VAR')
|
||||
|
||||
The functions service is pre-configured with the following environment variables:
|
||||
|
||||
| Variable | Value | Purpose |
|
||||
| --------------------------- | --------------------------- | ------------------------------------------------------------------- |
|
||||
| `SUPABASE_URL` | `http://kong:8000` | Internal API gateway URL |
|
||||
| `SUPABASE_PUBLIC_URL` | `http://<your-domain>:8000` | Base URL for accessing Supabase from the Internet |
|
||||
| `JWT_SECRET` | Your secret key | Legacy symmetric encryption key used to sign and verify JWTs |
|
||||
| `SUPABASE_ANON_KEY` | Your anon key | Client-side API key with limited permissions (`anon` role). |
|
||||
| `SUPABASE_SERVICE_ROLE_KEY` | Your service role key | Server-side API key with full database access (`service_role` role) |
|
||||
| `SUPABASE_DB_URL` | Postgres connection string | Can be used for direct database access |
|
||||
| Variable | Value | Purpose |
|
||||
| --------------------------- | --------------------------------- | ------------------------------------------------- |
|
||||
| `SUPABASE_URL` | `http://kong:8000` | Internal API gateway URL |
|
||||
| `SUPABASE_PUBLIC_URL` | `http(s)://<your-domain>` | Base URL for accessing Supabase from the Internet |
|
||||
| `JWT_SECRET` | `your-jwt-secret` | Legacy symmetric encryption key for JWTs |
|
||||
| `SUPABASE_ANON_KEY` | `your-anon-key` | Client-side API key (`anon` role). |
|
||||
| `SUPABASE_SERVICE_ROLE_KEY` | `your-service-role-key` | Server-side API key (`service_role` role) |
|
||||
| `SUPABASE_DB_URL` | `postgresql://...` | Postgres connection string |
|
||||
| `SUPABASE_PUBLISHABLE_KEYS` | `{"default":"sb_publishable_...}` | New publishable API key |
|
||||
| `SUPABASE_SECRET_KEYS` | `{"default":"sb_secret_...}` | New secret API key |
|
||||
|
||||
Here's an example function that queries a table using `@supabase/supabase-js`:
|
||||
|
||||
@@ -159,7 +161,7 @@ This is a key distinction that affects how you build URLs in your functions:
|
||||
|
||||
- **`SUPABASE_URL`** contains an internal Docker network hostname. Use it for server-side calls from your functions to other Supabase services (Auth, Storage, database via PostgREST). This is what the Supabase JS client should use inside functions.
|
||||
|
||||
- **`SUPABASE_PUBLIC_URL`** is the externally-reachable URL of your Supabase instance (e.g., `<your-domain>:8000`). Use it if your function needs to build URLs that HTTP clients can reach from the outside.
|
||||
- **`SUPABASE_PUBLIC_URL`** is the externally-reachable URL of your Supabase instance. Use it if your function needs to build URLs that HTTP clients can reach from the outside.
|
||||
|
||||
## Managing functions via dashboard
|
||||
|
||||
@@ -169,13 +171,13 @@ Self-hosted Studio [mounts](https://github.com/supabase/supabase/blob/df8729a82b
|
||||
|
||||
To deploy a function to a remote server running self-hosted Supabase, copy the function directory with `scp`:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
scp -r ./my-function user@<your-domain>:/path/to/self-hosted/volumes/functions/
|
||||
```
|
||||
|
||||
Then restart the functions service on the remote host:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
ssh user@<your-domain> 'cd /path/to/self-hosted && docker compose restart functions --no-deps'
|
||||
```
|
||||
|
||||
@@ -203,7 +205,7 @@ The request URL must include the function name after `/functions/v1/`. For examp
|
||||
|
||||
Check the functions service logs:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker compose logs functions
|
||||
```
|
||||
|
||||
@@ -218,7 +220,7 @@ Common causes: syntax errors in your function code, invalid imports, or missing
|
||||
|
||||
Restart the functions service:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker compose restart functions --no-deps
|
||||
```
|
||||
|
||||
@@ -230,7 +232,7 @@ docker compose restart functions --no-deps
|
||||
|
||||
Use the following command to recreate the container, not just `restart`:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker compose up -d --force-recreate --no-deps functions
|
||||
```
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@ You need:
|
||||
|
||||
<Admonition type="danger">
|
||||
|
||||
HTTPS is strongly recommended in production. Most OAuth providers reject `http://` callback URLs (except `localhost`).
|
||||
HTTPS is required by most OAuth providers - `http://` callback URLs are rejected (except `localhost`). See the HTTPS [how-to guide](/docs/guides/self-hosting/self-hosted-proxy-https) for setup instructions.
|
||||
|
||||
</Admonition>
|
||||
|
||||
Your **OAuth callback URL** is built from `API_EXTERNAL_URL`. For example, if `API_EXTERNAL_URL` is `https://<your-domain>`, the callback URL will become:
|
||||
Your **OAuth callback URL** should look like the following:
|
||||
|
||||
```
|
||||
https://<your-domain>/auth/v1/callback
|
||||
@@ -60,7 +60,7 @@ The default `.env.example` and `docker-compose.yml` include commented-out placeh
|
||||
|
||||
Uncomment the lines for your provider in `.env` and add your client ID and secret, e.g., for Google:
|
||||
|
||||
```
|
||||
```sh
|
||||
GOOGLE_ENABLED=true
|
||||
GOOGLE_CLIENT_ID=your-client-id
|
||||
GOOGLE_SECRET=your-client-secret
|
||||
@@ -72,7 +72,7 @@ GOOGLE_SECRET=your-client-secret
|
||||
|
||||
Uncomment the corresponding `GOTRUE_EXTERNAL_` lines in the `auth` service's `environment`:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -104,7 +104,7 @@ curl -H 'apikey: your-anon-key' https://<your-domain>/auth/v1/settings
|
||||
|
||||
The response should include your provider under `external`:
|
||||
|
||||
```
|
||||
```json
|
||||
{
|
||||
"external": {
|
||||
"google": true
|
||||
@@ -136,17 +136,13 @@ The response should include your provider under `external`:
|
||||
9. Under **Authorized redirect URIs**, add: `https://<your-domain>/auth/v1/callback`
|
||||
10. Click **Create** and copy the client ID and client secret
|
||||
|
||||
**`.env`:**
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
GOOGLE_ENABLED=true
|
||||
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
|
||||
GOOGLE_SECRET=your-google-client-secret
|
||||
```
|
||||
|
||||
**`docker-compose.yml`:**
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -169,17 +165,13 @@ auth:
|
||||
5. Click **Register application**
|
||||
6. Copy the client ID, generate and copy a client secret
|
||||
|
||||
**`.env`:**
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
GITHUB_ENABLED=true
|
||||
GITHUB_CLIENT_ID=your-github-client-id
|
||||
GITHUB_SECRET=your-github-client-secret
|
||||
```
|
||||
|
||||
**`docker-compose.yml`:**
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -206,9 +198,7 @@ auth:
|
||||
9. Click on **New client secret** and add a client secret
|
||||
10. Copy the secret value (not "secret ID")
|
||||
|
||||
**`.env`:**
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
AZURE_ENABLED=true
|
||||
AZURE_CLIENT_ID=your-azure-application-client-id
|
||||
AZURE_SECRET=your-azure-client-secret
|
||||
@@ -216,9 +206,7 @@ AZURE_SECRET=your-azure-client-secret
|
||||
# AZURE_URL=https://login.microsoftonline.com/your-tenant-id
|
||||
```
|
||||
|
||||
**`docker-compose.yml`:**
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -240,17 +228,13 @@ auth:
|
||||
2. Create a private key for sign in with Apple
|
||||
3. Generate a client secret JWT from your private key. See [Apple Developer documentation](https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret) for details.
|
||||
|
||||
**`.env`:**
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
APPLE_ENABLED=true
|
||||
APPLE_CLIENT_ID=com.example.your-services-id
|
||||
APPLE_SECRET=your-generated-jwt-client-secret
|
||||
```
|
||||
|
||||
**`docker-compose.yml`:**
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -281,9 +265,7 @@ Apple uses `response_mode=form_post` for its OAuth flow. The Auth service handle
|
||||
7. Under **Valid redirect URIs**, add: `https://<your-domain>/auth/v1/callback`
|
||||
8. Save, then go to the **Credentials** tab and copy the **Client secret**
|
||||
|
||||
**`.env` variables:**
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
KEYCLOAK_ENABLED=true
|
||||
KEYCLOAK_CLIENT_ID=supabase
|
||||
KEYCLOAK_SECRET=your-keycloak-client-secret
|
||||
@@ -291,9 +273,7 @@ KEYCLOAK_SECRET=your-keycloak-client-secret
|
||||
KEYCLOAK_URL=https://keycloak.example.com/realms/myrealm
|
||||
```
|
||||
|
||||
**`docker-compose.yml` passthrough:**
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -411,8 +391,11 @@ For detailed client-side integration, see [Social Login](/docs/guides/auth/socia
|
||||
|
||||
Configuration variables from `.env` are **not** automatically available inside the container unless there's a matching passthrough definition in `docker-compose.yml`. Check, e.g., for:
|
||||
|
||||
```
|
||||
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
|
||||
```
|
||||
|
||||
Run `docker compose exec auth env | grep GOTRUE_EXTERNAL` to verify the variables are reaching the container.
|
||||
@@ -442,8 +425,11 @@ When using Google Sign In on mobile with ID tokens, nonce verification may fail
|
||||
|
||||
To enable it, uncomment the following line in `docker-compose.yml`:
|
||||
|
||||
```
|
||||
GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: true
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: 'true'
|
||||
```
|
||||
|
||||
### Auth service fails to start
|
||||
|
||||
@@ -25,7 +25,9 @@ To enable SMS delivery:
|
||||
|
||||
### Step 1: Uncomment and configure the environment variables
|
||||
|
||||
```
|
||||
Edit the `.env` file as follows:
|
||||
|
||||
```sh name=.env
|
||||
SMS_PROVIDER=twilio
|
||||
SMS_OTP_EXP=60
|
||||
SMS_OTP_LENGTH=6
|
||||
@@ -44,7 +46,7 @@ SMS_TWILIO_MESSAGE_SERVICE_SID=your-message-service-sid
|
||||
|
||||
Uncomment the `GOTRUE_SMS_*` lines in the `auth` service's `environment` block:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -90,7 +92,7 @@ The default OTP expiration is **60 seconds**. This is often too short for produc
|
||||
|
||||
Set `SMS_OTP_EXP` in `.env` (value is in seconds):
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
# Set expiration to 5 minutes
|
||||
SMS_OTP_EXP=300
|
||||
```
|
||||
@@ -101,7 +103,7 @@ And ensure `GOTRUE_SMS_OTP_EXP: ${SMS_OTP_EXP}` is uncommented in `docker-compos
|
||||
|
||||
The default OTP length is 6 digits. You can set it to any value between 6 and 10:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
SMS_OTP_LENGTH=8
|
||||
```
|
||||
|
||||
@@ -109,7 +111,7 @@ SMS_OTP_LENGTH=8
|
||||
|
||||
`SMS_MAX_FREQUENCY` controls the minimum interval between SMS sends to the same phone number. The default is 60 seconds:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
## Allow one SMS every 30 seconds
|
||||
SMS_MAX_FREQUENCY=30s
|
||||
```
|
||||
@@ -118,11 +120,11 @@ SMS_MAX_FREQUENCY=30s
|
||||
|
||||
To avoid sending real SMS during development, use `SMS_TEST_OTP` to map phone numbers to fixed OTP codes:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
SMS_TEST_OTP=16505551234:123456,16505555678:654321
|
||||
```
|
||||
|
||||
And uncomment `GOTRUE_SMS_TEST_OTP: ${SMS_TEST_OTP}` in `docker-compose.yml`.
|
||||
Make sure to also uncomment `GOTRUE_SMS_TEST_OTP: ${SMS_TEST_OTP}` in `docker-compose.yml`.
|
||||
|
||||
When a test phone number requests an OTP, the Auth service skips SMS delivery and accepts only the mapped code. Other phone numbers continue to use the real SMS provider.
|
||||
|
||||
@@ -142,7 +144,7 @@ TOTP is **enabled by default** - users can enroll with apps like Google Authenti
|
||||
|
||||
To disable TOTP:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
MFA_TOTP_ENROLL_ENABLED=false
|
||||
MFA_TOTP_VERIFY_ENABLED=false
|
||||
```
|
||||
@@ -153,7 +155,7 @@ Phone MFA is **disabled by default** (opt-in). It uses the same SMS provider con
|
||||
|
||||
To enable:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
MFA_PHONE_ENROLL_ENABLED=true
|
||||
MFA_PHONE_VERIFY_ENABLED=true
|
||||
```
|
||||
@@ -162,7 +164,7 @@ MFA_PHONE_VERIFY_ENABLED=true
|
||||
|
||||
By default, a user can enroll up to 10 MFA factors. To change this:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
MFA_MAX_ENROLLED_FACTORS=5
|
||||
```
|
||||
|
||||
@@ -172,7 +174,7 @@ MFA_MAX_ENROLLED_FACTORS=5
|
||||
|
||||
The default `SMS_OTP_EXP` is 60 seconds. Increase it in `.env`:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
SMS_OTP_EXP=300
|
||||
```
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ HTTPS is required for production self-hosted Supabase deployments. This guide co
|
||||
|
||||
You need:
|
||||
|
||||
- A working self-hosted Supabase installation. See [Self-Hosting with Docker](/docs/guides/self-hosting/docker).
|
||||
- A domain name with DNS pointing to your server's public IP address (to obtain Let's Encrypt certificate).
|
||||
- Ports 80 and 443 open.
|
||||
- A working self-hosted Supabase installation. See [Self-Hosting with Docker](/docs/guides/self-hosting/docker)
|
||||
- A domain name with DNS pointing to your server's public IP address (to obtain Let's Encrypt certificate)
|
||||
- Ports 80 and 443 open
|
||||
|
||||
## Set up HTTPS
|
||||
|
||||
@@ -24,10 +24,10 @@ If you already run [HAProxy](https://www.haproxy.com/), [Traefik](https://traefi
|
||||
|
||||
- Proxy to Kong on port `8000` (or `<your-ip>:8000` if the proxy runs outside the Docker network)
|
||||
- Enable WebSocket support (required for Realtime)
|
||||
- Proxy traffic to Storage directly to the container, bypassing Kong
|
||||
- Add `X-Forwarded` headers to all requests
|
||||
- Comment out Kong's host port bindings in `docker-compose.yml` if the proxy runs in the same Docker network
|
||||
- Update `SUPABASE_PUBLIC_URL`, `API_EXTERNAL_URL`, and `SITE_URL` in `.env` to your HTTPS URL
|
||||
- See `volumes/proxy` for example proxy configuration files
|
||||
|
||||
</Admonition>
|
||||
|
||||
@@ -35,15 +35,15 @@ If you already run [HAProxy](https://www.haproxy.com/), [Traefik](https://traefi
|
||||
|
||||
Update the URL configuration in your `.env` file to use your HTTPS domain:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
SUPABASE_PUBLIC_URL=https://<your-domain>
|
||||
API_EXTERNAL_URL=https://<your-domain>
|
||||
SITE_URL=https://<your-domain>
|
||||
```
|
||||
|
||||
Change the following to your domain name and a **valid** email address:
|
||||
For Nginx, change the following to your domain name and a **valid** email address:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
PROXY_DOMAIN=your-domain.example.com
|
||||
CERTBOT_EMAIL=admin@your-domain.example.com
|
||||
```
|
||||
@@ -73,7 +73,7 @@ Caddy configuration is in `volumes/proxy/caddy/Caddyfile`.
|
||||
</TabPanel>
|
||||
<TabPanel id="nginx" label="Nginx + Let's Encrypt">
|
||||
|
||||
This option uses a 3rd party Nginx Docker image ([`jonasal/nginx-certbot`](https://github.com/JonasAlfredsson/docker-nginx-certbot)), which includes Certbot for automatic Let's Encrypt certificate issuance and renewal in a single container.
|
||||
This option uses a third-party Nginx Docker image ([`jonasal/nginx-certbot`](https://github.com/JonasAlfredsson/docker-nginx-certbot)), which includes Certbot for automatic Let's Encrypt certificate issuance and renewal in a single container.
|
||||
|
||||
Start Nginx by using the pre-configured `docker-compose.nginx.yml` overlay:
|
||||
|
||||
@@ -90,11 +90,17 @@ HTTP-to-HTTPS redirects are handled automatically by the `jonasal/nginx-certbot`
|
||||
|
||||
### Step 3: Verify HTTPS connection
|
||||
|
||||
Test the HTTPS connection - you should get a `401` response confirming you could connect to Auth:
|
||||
|
||||
```sh
|
||||
curl -I https://<your-domain>/auth/v1/
|
||||
```
|
||||
|
||||
You should receive a `401` response confirming you could connect to Auth.
|
||||
Check container logs if needed (use `supabase-nginx` for Nginx):
|
||||
|
||||
```sh
|
||||
docker logs supabase-caddy
|
||||
```
|
||||
|
||||
## Self-signed certificates (development only)
|
||||
|
||||
@@ -125,7 +131,7 @@ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
|
||||
Comment out Kong's **HTTP** port mapping in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
kong:
|
||||
# ...
|
||||
ports:
|
||||
@@ -134,7 +140,7 @@ kong:
|
||||
|
||||
Uncomment the certificate volume mounts and SSL environment variables in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
kong:
|
||||
# ... existing configuration ...
|
||||
volumes:
|
||||
@@ -151,7 +157,7 @@ kong:
|
||||
|
||||
Edit your `.env` file to use HTTPS with the Kong HTTPS port:
|
||||
|
||||
```
|
||||
```sh name=.env
|
||||
SUPABASE_PUBLIC_URL=https://<your-domain>:8443
|
||||
API_EXTERNAL_URL=https://<your-domain>:8443
|
||||
SITE_URL=https://<your-domain>:8443
|
||||
|
||||
@@ -17,9 +17,9 @@ You can configure either feature independently. For example, you can enable the
|
||||
|
||||
The S3 protocol endpoint at `/storage/v1/s3` allows standard S3 clients to interact with your self-hosted Storage instance. It works with any storage backend, including the default file-based storage - you do not need to configure an S3 backend first. The Supabase REST API and SDK do not use the S3 protocol.
|
||||
|
||||
Make sure to check that `REGION`, `S3_PROTOCOL_ACCESS_KEY_ID` and `S3_PROTOCOL_ACCESS_KEY_SECRET` are properly configured in you `.env` file. Read more about the secrets and passwords in [Configuring and securing Supabase](/docs/guides/self-hosting/docker#configuring-and-securing-supabase).
|
||||
Make sure to check that `REGION`, `S3_PROTOCOL_ACCESS_KEY_ID` and `S3_PROTOCOL_ACCESS_KEY_SECRET` are properly configured in your `.env` file. Read more about the secrets and passwords in [Configuring and securing Supabase](/docs/guides/self-hosting/docker#configuring-and-securing-supabase).
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
storage:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -30,7 +30,7 @@ storage:
|
||||
|
||||
### Test with the AWS CLI
|
||||
|
||||
```bash
|
||||
```sh
|
||||
( set -a && \
|
||||
source .env > /dev/null 2>&1 && \
|
||||
echo "" && \
|
||||
@@ -46,7 +46,7 @@ s3://your-storage-bucket )
|
||||
|
||||
### Test with rclone
|
||||
|
||||
```bash
|
||||
```sh
|
||||
( set -a && \
|
||||
source .env > /dev/null 2>&1 && \
|
||||
echo "" && \
|
||||
@@ -65,7 +65,7 @@ Use `aws login` and `rclone config` for persistent configuration.
|
||||
|
||||
In general, the following configuration variables define S3 backend configuration for Storage in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
storage:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -80,17 +80,38 @@ storage:
|
||||
```
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
Depending on your setup, you may need to adjust these values - for example, to use a local S3-compatible service like MinIO or a cloud provider like AWS.
|
||||
Depending on your setup, you may need to adjust these values - for example, to use a local S3-compatible service like RustFS, MinIO or a cloud provider like AWS.
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
|
||||
### Using RustFS
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
An overlay `docker-compose.rustfs.yml` configuration can be added to enable RustFS container and provide an S3-compatible API for Storage backend:
|
||||
|
||||
```sh
|
||||
docker compose -f docker-compose.yml -f docker-compose.rustfs.yml up -d
|
||||
```
|
||||
|
||||
Make sure to review the Storage section in your `.env` file for related configuration options.
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
|
||||
### Using MinIO
|
||||
|
||||
<Admonition type="note">
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
MinIO no longer publishes open source Docker images or maintains their open source repository. The MinIO configuration is provided for backward compatibility and uses images built by [Chainguard](https://images.chainguard.dev/directory/image/minio/overview) (`cgr.dev/chainguard/minio`). For new deployments, consider using [RustFS](#using-rustfs) instead.
|
||||
|
||||
</Admonition>
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
An overlay `docker-compose.s3.yml` configuration can be added to enable MinIO container and provide an S3-compatible API for Storage backend:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
docker compose -f docker-compose.yml -f docker-compose.s3.yml up -d
|
||||
```
|
||||
|
||||
@@ -100,7 +121,7 @@ Make sure to review the Storage section in your `.env` file for related configur
|
||||
|
||||
Create an S3 bucket and an IAM user with access to it. Then configure the storage service:
|
||||
|
||||
```yaml docker-compose.yml
|
||||
```yaml name=docker-compose.yml
|
||||
storage:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -118,7 +139,7 @@ For AWS S3, you do not need `GLOBAL_S3_ENDPOINT` or `GLOBAL_S3_FORCE_PATH_STYLE`
|
||||
{/* supa-mdx-lint-disable-next-line Rule003Spelling */}
|
||||
Use the same configuration as MinIO, but point to your provider's endpoint, e.g.:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
storage:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
@@ -174,6 +195,8 @@ const client = new S3Client({
|
||||
|
||||
S3 clients sign requests using the access key ID and secret. If you see `SignatureDoesNotMatch`, verify that the `REGION`, `S3_PROTOCOL_ACCESS_KEY_ID` and `S3_PROTOCOL_ACCESS_KEY_SECRET` in your `.env` file match what your S3 client is using.
|
||||
|
||||
**If you use a custom reverse proxy**: with the [new API keys and auth](/docs/guides/self-hosting/self-hosted-auth-keys) configuration, requests to Storage should be forwarded to the API gateway (Kong) for proper handling. If you are still using legacy API keys and proxy directly to Storage, make sure your proxy sets the `X-Forwarded-Prefix` header to `/storage/v1` so that signed URLs are generated correctly. In both cases, `STORAGE_PUBLIC_URL` must be [set properly](https://github.com/supabase/supabase/blob/a5f4a59e0e262394b345600e8d8a2241d6ac3b64/docker/docker-compose.yml#L369) in `docker-compose.yml`.
|
||||
|
||||
### TUS upload errors on Cloudflare R2
|
||||
|
||||
If resumable (TUS) uploads fail with HTTP 500 and a message about `x-amz-tagging`, add `TUS_ALLOW_S3_TAGS: "false"` to the storage service environment. Cloudflare R2 does not implement this S3 feature.
|
||||
|
||||
@@ -75,7 +75,7 @@ For a production deployment, consider using a 4096-bit key by adding `-pkeyopt r
|
||||
|
||||
Add the following to your `.env` file:
|
||||
|
||||
```sh
|
||||
```sh name=.env
|
||||
############
|
||||
# SAML SSO
|
||||
############
|
||||
@@ -101,7 +101,7 @@ SAML_PRIVATE_KEY=<your-base64-encoded-private-key>
|
||||
|
||||
In `docker-compose.yml`, add the SAML environment variables to the `auth` service. Auth expects the `GOTRUE_` prefix for all of its configuration variables:
|
||||
|
||||
```yaml
|
||||
```yaml name=docker-compose.yml
|
||||
auth:
|
||||
environment:
|
||||
# ... existing variables ...
|
||||
|
||||
+9
-1
@@ -1,3 +1,10 @@
|
||||
<div align="center">
|
||||
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://deepwiki.com/supabase/supabase/3-self-hosted-deployment)
|
||||
|
||||
</div>
|
||||
|
||||
# Self-Hosted Supabase with Docker
|
||||
|
||||
This is the official Docker Compose setup for self-hosted Supabase. It provides a complete stack with all Supabase services running locally or on your infrastructure.
|
||||
@@ -33,9 +40,10 @@ This Docker Compose configuration includes the following services:
|
||||
|
||||
## Documentation
|
||||
|
||||
- **[Documentation](https://supabase.com/docs/guides/self-hosting/docker)** - Setup and configuration guides
|
||||
- **[Self-Hosting with Docker](https://supabase.com/docs/guides/self-hosting/docker)** - Setup and configuration guides
|
||||
- **[CHANGELOG.md](./CHANGELOG.md)** - Track recent updates and changes to services
|
||||
- **[versions.md](./versions.md)** - Complete history of Docker image versions for rollback reference
|
||||
- **[Ask DeepWiki / Supabase](https://deepwiki.com/supabase/supabase/3-self-hosted-deployment)** - DeepWiki-generated description of self-hosted configuration
|
||||
|
||||
## Updates
|
||||
|
||||
|
||||
@@ -283,6 +283,7 @@ allow_list = [
|
||||
"OpenAI",
|
||||
"OpenID",
|
||||
"OpenMetrics",
|
||||
"[Oo]pen[Ss]l",
|
||||
"Opsgenie",
|
||||
"OrbStack",
|
||||
"OrioleDB",
|
||||
|
||||
Reference in new issue
Block a user