Configure Reverse Proxy and HTTPS
Set up a reverse proxy with HTTPS for self-hosted Supabase.
HTTPS is required for production self-hosted Supabase deployments. This guide covers two production approaches using a reverse proxy in front of self-hosted Supabase API gateway, plus a self-signed certificate option for development environment.
Before you begin#
You need:
- A working self-hosted Supabase installation. See Self-Hosting with 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#
Below are two options for adding a reverse proxy with automatic HTTPS in front of your self-hosted Supabase: Caddy (simpler, zero-config TLS) and Nginx + Let's Encrypt (more control over proxy settings). Both sit in front of Kong and terminate TLS, so internal traffic stays on HTTP.
Using a different reverse proxy?
If you already run HAProxy, Traefik, Nginx Proxy Manager, or another reverse proxy for your infrastructure, you can use it instead of Caddy or Nginx above. The key requirements are:
- Proxy to Kong on port
8000(or<your-ip>:8000if 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-Forwardedheaders to all requests - Comment out Kong's host port bindings in
docker-compose.ymlif the proxy runs in the same Docker network - Update
SUPABASE_PUBLIC_URL,API_EXTERNAL_URL, andSITE_URLin.envto your HTTPS URL
Step 1: Remove public port bindings for API gateway#
Comment out Kong's host port mappings in docker-compose.yml so that it's not exposed to the Internet:
1kong:2 # ...3 ports:4 # - ${KONG_HTTP_PORT}:8000/tcp5 # - ${KONG_HTTPS_PORT}:8443/tcpKong remains accessible to other containers on the internal Docker network.
Step 2: Update environment variables#
Update the URL configuration in your .env file to use your HTTPS domain:
1SUPABASE_PUBLIC_URL=https://<your-domain>2API_EXTERNAL_URL=https://<your-domain>3SITE_URL=https://<your-domain>Change the following to your domain name and a valid email address:
1PROXY_DOMAIN=your-domain.example.com2CERTBOT_EMAIL=admin@your-domain.example.comStep 3: Start the reverse proxy#
Pick one of the options below and use the corresponding Docker Compose overlay.
Caddy automatically provisions and renews Let's Encrypt TLS certificates with zero configuration. It also handles HTTP-to-HTTPS redirects, WebSocket upgrades, and HTTP/2 and HTTP/3 out of the box.
Start Caddy by using the pre-configured docker-compose.caddy.yml overlay:
1docker compose -f docker-compose.yml -f docker-compose.caddy.yml up -dCaddy configuration is in volumes/proxy/caddy/Caddyfile.
Step 4: Verify HTTPS connection#
1curl -I https://<your-domain>/auth/v1/You should receive a 401 response confirming you could connect to Auth.
Self-signed certificates (development only)#
Self-signed certificates trigger browser warnings and are rejected by most OAuth providers. Use this approach only in development environment or internal networks.
For development or internal networks where you cannot use Let's Encrypt, you can configure Kong to serve HTTPS directly using self-signed certificates.
Step 1: Generate a self-signed certificate#
Change <your-domain> in the example below, and create certificates with openssl:
1openssl req -x509 -nodes -days 365 -newkey rsa:2048 \2 -keyout volumes/api/server.key \3 -out volumes/api/server.crt \4 -subj "/CN=<your-domain>" && \5 chmod 640 volumes/api/server.key && \6 chgrp 65533 volumes/api/server.keyStep 2: Configure Kong for SSL#
Comment out Kong's HTTP port mapping in docker-compose.yml:
1kong:2 # ...3 ports:4 # - ${KONG_HTTP_PORT}:8000/tcpUncomment the certificate volume mounts and SSL environment variables in docker-compose.yml:
1kong:2 # ... existing configuration ...3 volumes:4 - ./volumes/api/kong.yml:/home/kong/temp.yml:ro,z5 - ./volumes/api/server.crt:/home/kong/server.crt:ro6 - ./volumes/api/server.key:/home/kong/server.key:ro7 environment:8 # ... existing environment variables ...9 KONG_SSL_CERT: /home/kong/server.crt10 KONG_SSL_CERT_KEY: /home/kong/server.keyStep 3: Update configuration variables in .env#
Edit your .env file to use HTTPS with the Kong HTTPS port:
1SUPABASE_PUBLIC_URL=https://<your-domain>:84432API_EXTERNAL_URL=https://<your-domain>:84433SITE_URL=https://<your-domain>:8443Step 4: Restart and verify#
1docker compose down && docker compose up -d1curl -I -k https://<your-domain>:8443/auth/v1/The -k flag tells curl to accept the self-signed certificate.
Troubleshooting#
Certificate not issued#
If Caddy or Certbot fails to obtain a certificate:
- Verify that ports 80 and 443 are open on your firewall
- Verify that your domain's DNS A record points to your server's public IP
- Check proxy logs via
docker logs supabase-caddyordocker logs supabase-nginx - Let's Encrypt has rate limits - if you hit them, wait before retrying
WebSocket connection failed#
If Realtime subscriptions fail to connect:
- Caddy handles WebSocket upgrades automatically - check that Kong is healthy
- Nginx requires explicit
UpgradeandConnectionheaders on the/realtime/v1/location. Verify yournginx.confincludes these headers as shown above
OAuth callback URL mismatch#
If OAuth redirects fail with a callback URL error:
- Verify
API_EXTERNAL_URLin.envis set to your HTTPS URL - Verify the callback URL registered with your OAuth provider matches
API_EXTERNAL_URLfollowed by/auth/v1/callback - After changing
API_EXTERNAL_URL, restart all services withdocker compose down && docker compose up -d
Mixed content warnings#
If the browser console shows mixed content errors:
- Verify
SUPABASE_PUBLIC_URLis set to your HTTPS URL - Verify
SITE_URLis also set to HTTPS - Clear your browser cache after making changes
ERR_CERT_AUTHORITY_INVALID#
This is expected when using self-signed certificates. For production, use Caddy or Nginx with Let's Encrypt. If you need to use self-signed certificates, add the certificate to your system's trust store or use a browser flag to bypass the warning.
Additional resources#
- Caddy documentation
- Nginx documentation (on nginx.org)
- docker-nginx-certbot on GitHub