---
# === IDENTITY ===
id: software/devops/docker-supabase/2026
canonical_question: "Docker Compose reference: Supabase Self-Hosted"
aliases:
  - "self-host Supabase with Docker Compose"
  - "Supabase self-hosted Docker setup"
  - "Supabase docker-compose.yml configuration"
  - "run Supabase locally with Docker"
  - "Supabase self-hosting environment variables"
  - "Supabase Docker services architecture"
  - "deploy Supabase on your own server"
  - "Supabase self-hosted production setup"
entity_type: software_reference
domain: software > devops > Docker Supabase Self-Hosted
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === VERIFICATION ===
last_verified: 2026-02-27
confidence: 0.93
version: 1.0
first_published: 2026-02-27

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "Supavisor replaced PgBouncer as default connection pooler (2024); Kong 2.8.1 is pinned version"
  next_review: 2026-08-26
  change_sensitivity: medium

# === CONSTRAINTS ===
constraints:
  - "NEVER start Supabase with default placeholder passwords from .env.example -- generate unique secrets before first boot"
  - "SERVICE_ROLE_KEY has full database access -- NEVER expose it in client-side code or public repositories"
  - "POSTGRES_PASSWORD must contain only letters and numbers (no special characters) to avoid connection string parsing issues"
  - "JWT_SECRET must be identical across GoTrue, PostgREST, Realtime, and Kong -- mismatched secrets cause silent auth failures"
  - "Docker Compose volumes store persistent data in ./volumes/ -- deleting volumes/db/data destroys all database content irreversibly"
  - "Kong API gateway is the single entry point on port 8000 -- do NOT expose individual service ports to the public internet"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Using Supabase Cloud (hosted platform) rather than self-hosting"
    use_instead: "Supabase official documentation at supabase.com/docs"
  - condition: "Need Supabase CLI for local development only (not production self-hosting)"
    use_instead: "software/devops/supabase-cli/2026"
  - condition: "Need to deploy Supabase on Kubernetes instead of Docker Compose"
    use_instead: "software/devops/supabase-kubernetes/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: "deployment_target"
    question: "Where will you deploy Supabase self-hosted?"
    type: choice
    options: ["Local development", "Single VPS/server", "Production with reverse proxy", "Docker Swarm"]
  - key: "services_needed"
    question: "Which Supabase services do you need?"
    type: choice
    options: ["All services (full stack)", "Core only (DB + Auth + REST)", "Custom selection"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/devops/docker-supabase/2026"
suggested_citation: "Source: knowledgelib.io -- AI Knowledge Library (verified 2026-02-27)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "software/devops/docker-compose-basics/2026"
      label: "Docker Compose Fundamentals"
    - id: "software/devops/reverse-proxy-ssl/2026"
      label: "Reverse Proxy and SSL Configuration"
  solves: []
  alternative_to:
    - id: "software/devops/supabase-kubernetes/2026"
      label: "Supabase on Kubernetes"
  often_confused_with:
    - id: "software/devops/supabase-cli/2026"
      label: "Supabase CLI Local Development"

# === SOURCES (7 authoritative sources) ===
sources:
  - id: src1
    title: "Self-Hosting with Docker"
    author: Supabase
    url: https://supabase.com/docs/guides/self-hosting/docker
    type: official_docs
    published: 2026-02-01
    reliability: authoritative
  - id: src2
    title: "supabase/docker/docker-compose.yml"
    author: Supabase
    url: https://github.com/supabase/supabase/blob/master/docker/docker-compose.yml
    type: official_docs
    published: 2026-02-15
    reliability: authoritative
  - id: src3
    title: "Self-Hosting Overview"
    author: Supabase
    url: https://supabase.com/docs/guides/self-hosting
    type: official_docs
    published: 2026-01-15
    reliability: authoritative
  - id: src4
    title: "Self-Hosted Deployment Architecture (DeepWiki)"
    author: DeepWiki
    url: https://deepwiki.com/supabase/supabase/3-self-hosted-deployment
    type: community_resource
    published: 2025-12-01
    reliability: moderate_high
  - id: src5
    title: "Supabase Self-Hosted Environment Variables: A Complete Guide"
    author: SupaScale
    url: https://www.supascale.app/blog/supabase-selfhosted-environment-variables-a-complete-guide
    type: technical_blog
    published: 2025-10-15
    reliability: moderate_high
  - id: src6
    title: "Kong API Gateway Documentation"
    author: Kong Inc.
    url: https://docs.konghq.com/gateway/2.8.x/
    type: official_docs
    published: 2024-06-01
    reliability: high
  - id: src7
    title: "The Ultimate Supabase Self-Hosting Guide"
    author: ActiveNode
    url: https://activeno.de/blog/2023-08/the-ultimate-supabase-self-hosting-guide/
    type: technical_blog
    published: 2025-08-15
    reliability: moderate_high
---

# Docker Compose Reference: Supabase Self-Hosted

## TL;DR

- **Bottom line**: Supabase self-hosted runs 13 containerized services orchestrated by Docker Compose, with Kong as the single API gateway on port 8000 routing to PostgreSQL, GoTrue (Auth), PostgREST, Realtime, Storage, Edge Functions, Studio, and supporting services.
- **Key tool/command**: `docker compose up -d` after configuring `.env` with unique secrets (JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, POSTGRES_PASSWORD).
- **Watch out for**: Starting with default placeholder passwords from `.env.example` -- this is the #1 security mistake; always run `generate-keys.sh` first.
- **Works with**: Docker Engine 20.10+, Docker Compose v2+, minimum 4 GB RAM / 2 CPU cores (8 GB / 4 cores recommended for production).

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- NEVER start Supabase with default placeholder passwords from .env.example -- generate unique secrets before first boot
- SERVICE_ROLE_KEY has full database access -- NEVER expose it in client-side code or public repositories
- POSTGRES_PASSWORD must contain only letters and numbers (no special characters) to avoid connection string parsing issues
- JWT_SECRET must be identical across GoTrue, PostgREST, Realtime, and Kong -- mismatched secrets cause silent auth failures
- Docker Compose volumes store persistent data in ./volumes/ -- deleting volumes/db/data destroys all database content irreversibly
- Kong API gateway is the single entry point on port 8000 -- do NOT expose individual service ports to the public internet

## Quick Reference

| Service | Image | Ports | Volumes | Key Env |
|---|---|---|---|---|
| **db** (PostgreSQL) | `supabase/postgres:15.8.1.085` | `5432` | `volumes/db/data` | `POSTGRES_PASSWORD` |
| **kong** (API Gateway) | `kong:2.8.1` | `8000:8000, 8443:8443` | `volumes/api/kong.yml` | `DASHBOARD_USERNAME, DASHBOARD_PASSWORD` |
| **auth** (GoTrue) | `supabase/gotrue:v2.186.0` | Internal only | None | `GOTRUE_JWT_SECRET, GOTRUE_DB_DATABASE_URL` |
| **rest** (PostgREST) | `postgrest/postgrest:v14.5` | Internal only | None | `PGRST_DB_URI, PGRST_JWT_SECRET` |
| **realtime** | `supabase/realtime:v2.76.5` | `4000` (internal) | None | `SECRET_KEY_BASE, DB_HOST` |
| **storage** | `supabase/storage-api:v1.37.8` | `5000` (internal) | `volumes/storage` | `STORAGE_BACKEND, FILE_SIZE_LIMIT` |
| **imgproxy** | `darthsim/imgproxy:v3.30.1` | `5001` (internal) | `volumes/storage` (read) | `IMGPROXY_ENABLE_WEBP_DETECTION` |
| **studio** (Dashboard) | `supabase/studio:2026.02.16` | Internal only | None | `STUDIO_DEFAULT_ORGANIZATION` |
| **meta** (pg_meta) | `supabase/postgres-meta:v0.95.2` | `8080` (internal) | None | `PG_META_DB_HOST` |
| **functions** (Edge) | `supabase/edge-runtime:v1.70.3` | Internal only | `volumes/functions` | `SUPABASE_URL, SUPABASE_ANON_KEY` |
| **analytics** (Logflare) | `supabase/logflare:1.31.2` | `4000` (internal) | None | `LOGFLARE_API_KEY` |
| **vector** (Logging) | `timberio/vector:0.53.0-alpine` | `9001` | `volumes/logs/vector.yml` | Vector pipeline config |
| **supavisor** (Pooler) | `supabase/supavisor:2.7.4` | `5432, 6543` | `volumes/pooler.exs` | `POOLER_TENANT_ID, SECRET_KEY_BASE` |

**Key Environment Variables:**

| Variable | Purpose | Requirements |
|---|---|---|
| `POSTGRES_PASSWORD` | Database superuser password | Letters and numbers only |
| `JWT_SECRET` | Signs and verifies all JWTs | Shared across auth, rest, realtime, kong |
| `ANON_KEY` | Client-side API key (anon role) | Generated from JWT_SECRET |
| `SERVICE_ROLE_KEY` | Server-side API key (full access) | Never expose publicly |
| `SECRET_KEY_BASE` | Encrypts Realtime + Supavisor sessions | Minimum 64 characters |
| `VAULT_ENC_KEY` | Configuration encryption | Exactly 32 characters |
| `DASHBOARD_USERNAME` | Studio HTTP basic auth username | Default: supabase |
| `DASHBOARD_PASSWORD` | Studio HTTP basic auth password | Must contain letters |

**Service Endpoints (via Kong on port 8000):**

| Endpoint | Service | Description |
|---|---|---|
| `/rest/v1/` | PostgREST | Auto-generated REST API from PostgreSQL schema |
| `/auth/v1/` | GoTrue | Authentication (signup, login, OAuth, JWT refresh) |
| `/realtime/v1/` | Realtime | WebSocket subscriptions to database changes |
| `/storage/v1/` | Storage API | File upload, download, and management |
| `/functions/v1/` | Edge Runtime | Serverless Deno functions |
| `/` (Studio) | Studio | Web dashboard for database management |

## Decision Tree

```
START: What is your deployment scenario?
+-- Local development only?
|   +-- YES -> Use default ports, skip SSL. Consider Supabase CLI instead.
|   +-- NO v
+-- Single server / VPS?
|   +-- YES -> Full docker-compose + reverse proxy (Nginx/Traefik) + SSL certs
|   +-- NO v
+-- Need to reduce resource usage?
|   +-- YES -> Remove optional services: analytics, imgproxy, functions, vector
|   +-- NO v
+-- Need external S3 storage?
|   +-- YES -> Set STORAGE_BACKEND=s3 + S3 credentials in .env
|   +-- NO v
+-- Production with high availability?
|   +-- YES -> Consider Supabase on Kubernetes or managed Supabase Cloud
|   +-- NO v
+-- DEFAULT -> Full stack docker-compose with all services enabled
```

## Step-by-Step Guide

### 1. Clone and prepare the project directory

Clone the Supabase repository and copy the Docker configuration files to your project directory. [src1]

```bash
# Clone the repository (shallow clone for speed)
git clone --depth 1 https://github.com/supabase/supabase

# Create your project directory and copy Docker files
mkdir supabase-project
cp -rf supabase/docker/* supabase-project/
cp supabase/docker/.env.example supabase-project/.env
cd supabase-project
```

**Verify**: `ls -la .env docker-compose.yml` -> both files should exist in the project directory.

### 2. Generate and configure secrets

Never use the default placeholder values. Generate unique secrets for all sensitive environment variables. [src1]

```bash
# Generate all secrets automatically
sh ./utils/generate-keys.sh

# Or generate manually:
# JWT_SECRET (at least 32 characters)
openssl rand -base64 32

# Generate ANON_KEY and SERVICE_ROLE_KEY from JWT_SECRET
# Use https://supabase.com/docs/guides/self-hosting/docker#generate-api-keys
# or the supabase CLI: supabase gen keys --jwt-secret <your-jwt-secret>
```

Edit `.env` and set at minimum:

```bash
# .env -- REQUIRED changes
POSTGRES_PASSWORD=your_secure_password_here
JWT_SECRET=your-super-secret-jwt-token-minimum-32-chars
ANON_KEY=eyJ...  # Generated from JWT_SECRET
SERVICE_ROLE_KEY=eyJ...  # Generated from JWT_SECRET
DASHBOARD_USERNAME=your_admin_user
DASHBOARD_PASSWORD=your_admin_password
SECRET_KEY_BASE=$(openssl rand -hex 64)
VAULT_ENC_KEY=$(openssl rand -hex 16)
```

**Verify**: `grep -c 'your-super-secret' .env` -> should return 0 (no placeholder values remain).

### 3. Pull images and start services

Pull the latest images and start all services in detached mode. [src2]

```bash
# Pull all Docker images
docker compose pull

# Start all services in detached mode
docker compose up -d

# Check service health (all should show "healthy")
docker compose ps
```

**Verify**: `docker compose ps --format "table {{.Name}}\t{{.Status}}"` -> all services should show `Up` with `(healthy)`.

### 4. Access and verify services

Once all services are healthy, verify each endpoint through the Kong gateway. [src1]

```bash
# Test REST API
curl -s http://localhost:8000/rest/v1/ \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ANON_KEY" | head -c 200

# Test Auth API
curl -s http://localhost:8000/auth/v1/health

# Access Studio dashboard
# Open http://localhost:8000 in browser
# Login with DASHBOARD_USERNAME / DASHBOARD_PASSWORD
```

**Verify**: `curl -s http://localhost:8000/auth/v1/health` -> `{"status":"ok"}`.

### 5. Connect client SDK

Initialize the Supabase client SDK pointing to your self-hosted instance. [src1]

```javascript
// JavaScript / TypeScript
import { createClient } from '@supabase/supabase-js'  // ^2.39.0

const supabase = createClient(
  'http://localhost:8000',  // Your Kong gateway URL
  'your-anon-key-here'     // ANON_KEY from .env
)

// Test the connection
const { data, error } = await supabase.from('_test').select('*').limit(1)
console.log(error ? `Error: ${error.message}` : 'Connected successfully')
```

```python
# Python
from supabase import create_client  # supabase>=2.0.0

supabase = create_client(
    "http://localhost:8000",   # Your Kong gateway URL
    "your-anon-key-here"      # ANON_KEY from .env
)

# Test the connection
result = supabase.table("_test").select("*").limit(1).execute()
print(f"Connected: {result}")
```

**Verify**: The client should connect without JWT or network errors.

### 6. Configure reverse proxy for production

For production, place Nginx or Traefik in front of Kong to handle SSL termination. [src7]

```nginx
# /etc/nginx/sites-available/supabase
server {
    listen 443 ssl http2;
    server_name supabase.yourdomain.com;

    ssl_certificate     /etc/letsencrypt/live/supabase.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/supabase.yourdomain.com/privkey.pem;

    # WebSocket support for Realtime
    location /realtime/v1/ {
        proxy_pass http://localhost:8000/realtime/v1/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    # All other Supabase traffic
    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

Update `.env` for production:

```bash
# .env -- Production overrides
SITE_URL=https://supabase.yourdomain.com
API_EXTERNAL_URL=https://supabase.yourdomain.com
SUPABASE_PUBLIC_URL=https://supabase.yourdomain.com
```

**Verify**: `curl -s https://supabase.yourdomain.com/auth/v1/health` -> `{"status":"ok"}` over HTTPS.

## Code Examples

### Docker Compose: Minimal Core Services

```yaml
# docker-compose.override.yml -- Remove optional services to save resources
# Place alongside docker-compose.yml to override settings
# Input:  Full Supabase stack
# Output: Reduced stack without analytics, imgproxy, functions, vector

services:
  analytics:
    profiles: ["disabled"]    # Disable Logflare
  vector:
    profiles: ["disabled"]    # Disable log collection
  imgproxy:
    profiles: ["disabled"]    # Disable image transforms
  functions:
    profiles: ["disabled"]    # Disable Edge Functions
```

### Bash: Automated Backup Script

```bash
#!/bin/bash
# Input:  Running Supabase Docker Compose stack
# Output: Timestamped PostgreSQL dump in ./backups/

BACKUP_DIR="./backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"

# Dump database using the db container
docker compose exec -T db pg_dump \
  -U postgres \
  --clean \
  --if-exists \
  --no-owner \
  postgres > "${BACKUP_DIR}/supabase_${TIMESTAMP}.sql"

echo "Backup saved: ${BACKUP_DIR}/supabase_${TIMESTAMP}.sql"
echo "Size: $(du -h "${BACKUP_DIR}/supabase_${TIMESTAMP}.sql" | cut -f1)"
```

### JavaScript: Health Check All Services

```javascript
// Input:  Supabase self-hosted base URL
// Output: Health status of all services

const BASE = process.env.SUPABASE_URL || 'http://localhost:8000';
const KEY = process.env.SUPABASE_ANON_KEY;

const endpoints = [
  { name: 'Auth',     path: '/auth/v1/health' },
  { name: 'REST',     path: '/rest/v1/',       headers: { apikey: KEY } },
  { name: 'Realtime', path: '/realtime/v1/',   headers: { apikey: KEY } },
  { name: 'Storage',  path: '/storage/v1/status' },
];

for (const ep of endpoints) {
  try {
    const res = await fetch(`${BASE}${ep.path}`, { headers: ep.headers });
    console.log(`${ep.name}: ${res.ok ? 'OK' : 'FAIL'} (${res.status})`);
  } catch (e) {
    console.log(`${ep.name}: DOWN (${e.message})`);
  }
}
```

## Anti-Patterns

### Wrong: Starting with default secrets

```bash
# BAD -- .env.example has placeholder values that are publicly known
cp .env.example .env
docker compose up -d
# Anyone who reads the Supabase repo now has your JWT_SECRET, ANON_KEY, etc.
```

### Correct: Generate unique secrets before first boot

```bash
# GOOD -- generate unique secrets before starting
cp .env.example .env
sh ./utils/generate-keys.sh  # Auto-generates JWT_SECRET, keys, passwords
# Manually verify: grep -c 'your-super-secret' .env  (should be 0)
docker compose up -d
```

### Wrong: Exposing service ports directly

```yaml
# BAD -- exposing PostgREST, Auth, and DB ports to the host
services:
  rest:
    ports:
      - "3000:3000"   # PostgREST exposed directly
  auth:
    ports:
      - "9999:9999"   # GoTrue exposed directly
  db:
    ports:
      - "5432:5432"   # PostgreSQL exposed to the internet
```

### Correct: Route all traffic through Kong

```yaml
# GOOD -- only Kong is exposed; internal services use Docker networking
services:
  kong:
    ports:
      - "${KONG_HTTP_PORT:-8000}:8000/tcp"
      - "${KONG_HTTPS_PORT:-8443}:8443/tcp"
  # All other services: no port mappings (internal Docker network only)
```

### Wrong: Using special characters in POSTGRES_PASSWORD

```bash
# BAD -- special characters break connection string parsing
POSTGRES_PASSWORD=p@ss!w0rd#2026
# GoTrue, PostgREST, Realtime will fail to connect to PostgreSQL
```

### Correct: Alphanumeric passwords only

```bash
# GOOD -- letters and numbers only
POSTGRES_PASSWORD=SuperSecure2026RandomString
# Or generate: openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32
```

### Wrong: Running docker compose down -v to "restart"

```bash
# BAD -- -v flag removes all named volumes including database data
docker compose down -v
docker compose up -d
# ALL your data is now gone. There is no undo.
```

### Correct: Restart without removing volumes

```bash
# GOOD -- restart services without touching data
docker compose down
docker compose up -d

# Or restart a single service
docker compose restart auth
```

## Common Pitfalls

- **Kong fails to start with "kong.yml is a directory"**: On some platforms, Docker creates `kong.yml` as a directory instead of mounting the file. Fix: Delete the directory (`rm -rf volumes/api/kong.yml`), ensure the `kong.yml` file exists before running `docker compose up`, and specify `platform: linux/amd64` in the Kong service if on ARM. [src6]
- **Auth/REST return 401 on valid tokens**: JWT_SECRET mismatch between services. All services referencing JWT_SECRET must use the exact same value. Fix: Verify `grep JWT_SECRET .env` shows one consistent value, then restart all services with `docker compose down && docker compose up -d`. [src1]
- **Realtime WebSocket connections fail behind reverse proxy**: Nginx or Traefik not configured for WebSocket upgrade. Fix: Add `proxy_http_version 1.1`, `proxy_set_header Upgrade $http_upgrade`, and `proxy_set_header Connection "upgrade"` to the `/realtime/v1/` location block. [src7]
- **Storage uploads fail with "connection refused"**: Storage API cannot reach imgproxy. Fix: Ensure imgproxy service is running (`docker compose ps imgproxy`), or if you disabled imgproxy, set `IMGPROXY_URL=` (empty) in the storage service environment. [src2]
- **Database data lost after docker compose pull**: The `volumes/db/data` directory was not persisted or was accidentally removed. Fix: Always back up `volumes/db/data` before updating. Use `docker compose exec db pg_dump -U postgres postgres > backup.sql` before pulling new images. [src1]
- **Studio shows "Invalid API key" on first access**: ANON_KEY or SERVICE_ROLE_KEY not properly generated from the JWT_SECRET. Fix: Regenerate keys using `supabase gen keys --jwt-secret <your-jwt-secret>` or the Supabase JWT generator at supabase.com/docs/guides/self-hosting/docker#generate-api-keys. [src5]
- **Services fail to start in order**: Docker Compose `depends_on` with `condition: service_healthy` requires health checks to pass. Fix: Check logs with `docker compose logs <service>` and ensure the database is healthy first (`docker compose ps db`). [src2]
- **Connection pooling not working via port 6543**: Supavisor requires `POOLER_TENANT_ID` in the connection string. Fix: Connect using `postgres://postgres.POOLER_TENANT_ID:PASSWORD@host:6543/postgres`. [src4]

## Diagnostic Commands

```bash
# Check health of all services
docker compose ps

# View logs for a specific service (last 100 lines)
docker compose logs --tail 100 auth
docker compose logs --tail 100 kong
docker compose logs --tail 100 db

# Check if PostgreSQL is accepting connections
docker compose exec db pg_isready -U postgres

# Verify JWT_SECRET consistency across services
docker compose exec auth printenv | grep JWT
docker compose exec rest printenv | grep JWT

# Test Kong routing to auth service
curl -v http://localhost:8000/auth/v1/health

# Test PostgREST via Kong
curl -s http://localhost:8000/rest/v1/ \
  -H "apikey: $(grep ANON_KEY .env | cut -d= -f2)"

# Check disk usage of Docker volumes
docker system df -v | grep supabase

# Monitor real-time resource usage
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# Check Kong declarative config for errors
docker compose exec kong kong config parse /var/lib/kong/kong.yml

# Verify database extensions
docker compose exec db psql -U postgres -c "SELECT * FROM pg_extension;"
```

## Version History & Compatibility

| Component | Current Version | Image | Key Change |
|---|---|---|---|
| PostgreSQL | 15.8.1 | `supabase/postgres:15.8.1.085` | Includes pg_net, pg_graphql, pgvector extensions |
| GoTrue (Auth) | v2.186.0 | `supabase/gotrue:v2.186.0` | PKCE flow, anonymous auth, SSO/SAML support |
| PostgREST | v14.5 | `postgrest/postgrest:v14.5` | Improved aggregate functions, spreads |
| Realtime | v2.76.5 | `supabase/realtime:v2.76.5` | Broadcast, Presence, Postgres Changes |
| Storage API | v1.37.8 | `supabase/storage-api:v1.37.8` | S3-compatible backend, resumable uploads |
| Kong | 2.8.1 | `kong:2.8.1` | Pinned version; declarative config via kong.yml |
| Studio | 2026.02 | `supabase/studio:2026.02.16` | SQL editor, table editor, auth UI |
| Edge Runtime | v1.70.3 | `supabase/edge-runtime:v1.70.3` | Deno-based functions, npm compatibility |
| Supavisor | 2.7.4 | `supabase/supavisor:2.7.4` | Replaced PgBouncer; session + transaction modes |
| imgproxy | v3.30.1 | `darthsim/imgproxy:v3.30.1` | WebP/AVIF auto-detection |
| Vector | 0.53.0 | `timberio/vector:0.53.0-alpine` | Log aggregation pipeline |
| Logflare | 1.31.2 | `supabase/logflare:1.31.2` | Analytics and log querying |
| pg_meta | v0.95.2 | `supabase/postgres-meta:v0.95.2` | Database introspection for Studio |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Need full control over data residency and compliance | Quick prototyping or MVP with small team | Supabase Cloud (free tier available) |
| Deploying in air-gapped or restricted networks | Budget under $20/month for infrastructure | Supabase Cloud Pro plan |
| Custom PostgreSQL extensions or configurations needed | No DevOps expertise on the team | Supabase Cloud or managed hosting (Railway, Render) |
| Cost optimization at scale (many projects, high traffic) | Need automatic updates and zero maintenance | Supabase Cloud with automatic upgrades |
| Regulatory requirement for on-premises hosting | Single developer with limited time | Supabase Cloud + CLI for local dev |

## Important Caveats

- Supabase publishes stable Docker Compose releases approximately once a month -- always check the GitHub repository for the latest image tags before updating
- The self-hosted version does not include some Supabase Cloud features: email rate limiting, abuse prevention, automatic backups, and platform-level monitoring
- Updating images with `docker compose pull` may introduce breaking changes -- always read the release notes and back up `volumes/db/data` before upgrading
- Kong 2.8.1 is the pinned version in the official compose file; upgrading Kong independently may break routing configuration
- If using S3-compatible storage (MinIO, Backblaze B2, Cloudflare R2), both the Storage API and imgproxy must be configured with the same S3 credentials
- Edge Functions require mounting the `volumes/functions/` directory -- each function must be in its own subdirectory with an `index.ts` entry point
- Supavisor (connection pooler) listens on port 5432 (session mode) and 6543 (transaction mode) -- do not confuse these with the direct PostgreSQL port on the db container

## Related Units
<!-- Generated from related_kos frontmatter -->

- [Docker Compose Fundamentals](/software/devops/docker-compose-basics/2026)
- [Reverse Proxy and SSL Configuration](/software/devops/reverse-proxy-ssl/2026)
- [Supabase on Kubernetes](/software/devops/supabase-kubernetes/2026)
- [Supabase CLI Local Development](/software/devops/supabase-cli/2026)
