Binding Domains
Connect custom domains to your Supabase projects.
Bind custom domains to your Supabase projects for professional URLs and better branding.
Prerequisites
Before binding a domain:
- Own the domain - Have access to DNS settings
- Point DNS to server - Create A record pointing to your server IP
- Wait for propagation - DNS changes can take up to 48 hours
DNS Configuration
A Record
Create an A record pointing your domain to your server:
| Type | Name | Value | TTL |
|---|---|---|---|
| A | api | 203.0.113.50 | 300 |
For api.example.com pointing to server IP 203.0.113.50.
Verify DNS
Check DNS propagation:
# Check A record dig +short api.example.com # Should return your server IP 203.0.113.50
Bind Domain via Web UI
- Click on a project
- Go to Domain tab
- Enter your domain name
- Select web server (Nginx/Apache/Caddy)
- Click Save Domain
Bind Domain via API
curl -X POST https://supascale.example.com/api/v1/projects/my-project/domain \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "api.example.com",
"sslEnabled": true,
"webServer": "nginx"
}'
Response:
{
"success": true,
"domain": {
"name": "api.example.com",
"sslEnabled": true,
"webServer": "nginx",
"status": "active"
}
}
Web Server Configuration
Supascale automatically generates web server configuration:
Nginx Configuration
Created at /etc/nginx/sites-available/my-project:
server {
listen 80;
server_name api.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1: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_cache_bypass $http_upgrade;
}
}
Apache Configuration
Created at /etc/apache2/sites-available/my-project.conf:
<VirtualHost *:80>
ServerName api.example.com
Redirect permanent / https://api.example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName api.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/api.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/api.example.com/privkey.pem
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/
</VirtualHost>
Caddy Configuration
Added to /etc/caddy/Caddyfile:
api.example.com {
reverse_proxy localhost:8000
}
View Domain Configuration
Via API
curl https://supascale.example.com/api/v1/projects/my-project/domain \ -H "X-API-Key: your-api-key"
Response:
{
"name": "api.example.com",
"sslEnabled": true,
"webServer": "nginx",
"certificate": {
"status": "active",
"expiresAt": "2026-04-19T00:00:00Z"
}
}
Remove Domain
Via Web UI
- Click on a project
- Go to Domain tab
- Click Remove Domain
- Confirm removal
Via API
curl -X DELETE https://supascale.example.com/api/v1/projects/my-project/domain \ -H "X-API-Key: your-api-key"
Multiple Domains
Currently, each project supports one domain. For multiple domains:
- Use a wildcard certificate
- Configure additional server blocks manually
- Or use a load balancer/CDN in front
Updating Your Application
After binding a domain, update your application configuration:
// Before const supabase = createClient( 'http://your-server:8000', 'your-anon-key' ) // After const supabase = createClient( 'https://api.example.com', 'your-anon-key' )
Troubleshooting
Domain Not Resolving
- Verify DNS A record exists
- Check DNS propagation:
dig +short yourdomain.com - Wait for propagation (can take hours)
Web Server Not Responding
- Check web server status:
systemctl status nginx - Verify configuration:
nginx -t - Check logs:
/var/log/nginx/error.log
Connection Refused
- Verify project is running
- Check the proxy port matches project API port
- Test locally:
curl http://localhost:8000