When you self-host Supabase, you're not just running a database—you're running an entire backend stack that your applications will talk to. And that means you need a proper domain setup with HTTPS. Unlike Supabase Cloud, where custom domains are a premium feature you enable with a click, self-hosting gives you complete control over your domain configuration. The trade-off? You have to set it up yourself.
This guide walks you through configuring custom domains with automatic SSL certificates for your self-hosted Supabase instance. We'll cover the three most popular reverse proxy options—Nginx, Caddy, and Traefik—so you can pick what fits your stack.
Why Custom Domains Matter for Self-Hosted Supabase
Running Supabase on http://your-ip:8000 might work for local development, but production deployments need proper domain configuration for several reasons:
Security: HTTPS encrypts all traffic between your clients and Supabase. This protects user credentials, API keys, and sensitive data from interception. In 2026, there's no excuse for running production workloads over plain HTTP.
OAuth requirements: Most OAuth providers (Google, GitHub, Discord) require HTTPS callback URLs. Without SSL, you can't configure social authentication for your applications.
Browser compatibility: Modern browsers increasingly block mixed content and warn users about insecure connections. Your users will see scary warnings if you're not using HTTPS.
Professional appearance: api.yourdomain.com looks a lot better than 143.198.xxx.xxx:8000 in your documentation and client code.
The Architecture: Reverse Proxy in Front of Kong
Self-hosted Supabase uses Kong as its internal API gateway. Kong handles routing between Supabase services—REST API, Auth, Storage, and Realtime. The recommended approach for SSL termination is placing another reverse proxy in front of Kong:
Client → Reverse Proxy (SSL) → Kong (:8000) → Supabase Services
This separation provides several benefits:
- Easier certificate management: Your reverse proxy handles Let's Encrypt automatically
- Centralized SSL configuration: One place to manage certificates for all services
- Flexibility: You can add other services behind the same reverse proxy later
- Proven patterns: This is how most production deployments work
Don't try to configure SSL directly in Kong for a self-hosted setup—it's more complicated and harder to maintain.
Prerequisites
Before configuring custom domains, ensure you have:
- A running self-hosted Supabase instance (see our deployment guide)
- A domain name pointing to your server's IP address
- Ports 80 and 443 open in your firewall
- A VPS with at least the minimum system requirements
For DNS, create an A record pointing your domain to your server:
api.yourdomain.com → YOUR_SERVER_IP
If you're using multiple subdomains for different Supabase services, you might want a wildcard record:
*.supabase.yourdomain.com → YOUR_SERVER_IP
Option 1: Caddy (Recommended for Simplicity)
Caddy is the easiest option for most self-hosted Supabase deployments. It automatically obtains and renews SSL certificates from Let's Encrypt without any additional configuration. If you just want things to work, start here.
Installation
Add Caddy to your existing docker-compose.yml or create a separate file:
services:
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
- supabase_network
volumes:
caddy_data:
caddy_config:
Caddyfile Configuration
Create a Caddyfile in the same directory:
api.yourdomain.com {
reverse_proxy kong:8000
}
That's it. Caddy automatically:
- Obtains an SSL certificate from Let's Encrypt
- Redirects HTTP to HTTPS
- Renews certificates before they expire
Update Supabase Environment Variables
Modify your .env file to use the new domain:
API_EXTERNAL_URL=https://api.yourdomain.com SITE_URL=https://yourapp.com SUPABASE_PUBLIC_URL=https://api.yourdomain.com
Restart your Supabase stack for changes to take effect.
Option 2: Nginx with Certbot
Nginx is the battle-tested choice. It handles massive traffic loads and gives you fine-grained control over caching, compression, and headers. The trade-off is more manual configuration.
Installation
Install Nginx and Certbot on your server:
# Ubuntu/Debian sudo apt update sudo apt install nginx certbot python3-certbot-nginx
Nginx Configuration
Create /etc/nginx/sites-available/supabase:
server {
listen 80;
server_name api.yourdomain.com;
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
# SSL certificates (managed by Certbot)
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
# SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# WebSocket support for Realtime
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
# Timeout settings for long-running requests
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
Enable the site and obtain certificates:
sudo ln -s /etc/nginx/sites-available/supabase /etc/nginx/sites-enabled/ sudo certbot --nginx -d api.yourdomain.com sudo systemctl restart nginx
Certbot automatically configures certificate renewal via a systemd timer.
Option 3: Traefik (Best for Docker-Native Setups)
Traefik integrates directly with Docker and automatically discovers services via labels. If you're running multiple Docker services and want centralized routing, Traefik is excellent.
Docker Compose Configuration
Create a docker-compose.traefik.yml:
services:
traefik:
image: traefik:v3.0
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "[email protected]"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
networks:
- supabase_network
Add labels to your Kong service in the Supabase docker-compose.yml:
kong:
# ... existing configuration ...
labels:
- "traefik.enable=true"
- "traefik.http.routers.supabase.rule=Host(`api.yourdomain.com`)"
- "traefik.http.routers.supabase.entrypoints=websecure"
- "traefik.http.routers.supabase.tls.certresolver=letsencrypt"
- "traefik.http.services.supabase.loadbalancer.server.port=8000"
Traefik automatically obtains certificates and routes traffic to Kong.
Common Configuration Gotchas
After setting up your reverse proxy, you'll need to update several environment variables in your Supabase .env file. Missing even one can cause subtle authentication issues.
Required Environment Variable Updates
# Public-facing URL for your API API_EXTERNAL_URL=https://api.yourdomain.com # URL where your application lives (used for OAuth redirects) SITE_URL=https://yourapp.com # Public URL for Supabase Studio (if exposed) SUPABASE_PUBLIC_URL=https://api.yourdomain.com # GoTrue (Auth) configuration GOTRUE_SITE_URL=https://yourapp.com GOTRUE_API_EXTERNAL_URL=https://api.yourdomain.com
OAuth Redirect URI Updates
If you've configured OAuth providers, update the redirect URIs in your provider dashboards to use HTTPS:
https://api.yourdomain.com/auth/v1/callback
This is a common source of "redirect_uri_mismatch" errors after enabling SSL.
WebSocket Configuration
Supabase Realtime uses WebSockets. Make sure your reverse proxy configuration includes the Upgrade and Connection headers. The Nginx configuration above handles this, but if you're customizing, don't skip these headers.
Verifying Your Setup
After configuration, verify everything works:
1. Check HTTPS is working:
curl -I https://api.yourdomain.com/rest/v1/
You should see a 200 response with proper headers.
2. Test the REST API:
curl https://api.yourdomain.com/rest/v1/ \ -H "apikey: YOUR_ANON_KEY"
3. Verify OAuth callbacks: Try logging in with a social provider. If you get redirect errors, double-check your callback URLs in both your OAuth provider dashboard and Supabase environment variables.
4. Test Realtime: Open Supabase Studio and verify the Realtime inspector shows a connected state.
Automating with Supascale
Manually configuring reverse proxies, SSL certificates, and environment variables works, but it's tedious and error-prone. If you're managing multiple Supabase instances or want to avoid the operational overhead, Supascale handles custom domains automatically.
With Supascale, you:
- Bind domains through a simple UI instead of editing config files
- Get automatic SSL certificates with Let's Encrypt integration
- Update all related environment variables in one place
- Avoid common configuration mistakes
Check out our domain binding documentation to see how it works. For teams running multiple projects, this automation saves significant time compared to manual configuration.
Troubleshooting Common Issues
Certificate not issued: Ensure ports 80 and 443 are open and your DNS is properly configured. Let's Encrypt needs to reach your server to verify domain ownership.
502 Bad Gateway: Your reverse proxy can't reach Kong. Verify Kong is running on port 8000 and your proxy configuration points to the correct address.
OAuth redirect fails: Check that SITE_URL, GOTRUE_SITE_URL, and OAuth provider callback URLs all use HTTPS and match exactly.
WebSocket connection drops: Missing Upgrade headers in your reverse proxy configuration. Compare your config against the Nginx example above.
Mixed content warnings: You have some URLs still using HTTP. Search your .env file for any remaining http:// URLs and update them.
What's Next?
With custom domains configured, your self-hosted Supabase instance is ready for production traffic. Consider these next steps:
- Set up automated backups to protect your data
- Configure OAuth providers for social authentication
- Review the true cost breakdown of running self-hosted Supabase
Custom domains are just one piece of the production-ready puzzle. The combination of proper SSL, automated backups, and monitoring gives you a self-hosted Supabase deployment you can rely on.
