Self-hosting Supabase gives you complete control over your backend infrastructure, but that control comes with responsibility. When something breaks at 2 AM, there's no support team to page—it's just you and the logs. This guide covers the most common issues you'll encounter when running Supabase on your own server and how to fix them systematically.
Based on community discussions and real deployment experiences from 2026, these are the problems that trip up most self-hosters. Let's get you unstuck.
Quick Diagnosis: Mapping Symptoms to Causes
Before diving into specific fixes, here's a rapid triage guide:
| Symptom | Likely Cause | First Check |
|---|---|---|
| Connection refused | Service not running or wrong port | docker ps and port mappings |
| 500 errors on API | PostgREST misconfiguration | Container logs |
| Auth not working | JWT secrets mismatch | Environment variables |
| Realtime disconnects | Service crashing/restarting | docker logs supabase-realtime |
| Storage uploads fail | S3/MinIO permissions | Storage service logs |
| Empty query results | RLS policies blocking | Check policies in Studio |
Now let's dig into each category.
Connection and Networking Issues
"Connection Refused" Errors
This is the most common issue when first deploying. The database or API appears unreachable.
Check 1: Verify containers are running
docker compose ps
All services should show Up status. If any show Exit or Restarting, check their logs:
docker compose logs <service-name>
Check 2: Port binding conflicts
Supabase uses several ports by default:
- 5432: PostgreSQL
- 8000: Kong (API Gateway)
- 3000: Studio
- 9000: Storage
If another service already uses these ports, Supabase containers will fail to start. Find conflicts with:
sudo lsof -i :5432 sudo lsof -i :8000
Fix: Modify port mappings in your docker-compose.yml or stop conflicting services.
Check 3: Firewall rules
On cloud VPS instances, ensure your firewall allows traffic:
# UFW (Ubuntu) sudo ufw allow 8000/tcp sudo ufw allow 5432/tcp # Or check current rules sudo ufw status
"Max Clients" Connection Errors
Error: No more connections allowed (max_client_conn)
This happens when too many connections hit PostgreSQL or the connection pooler simultaneously.
Quick fix: Restart the database (temporary):
docker compose restart db
Proper fix: Tune your connection pooling settings. In your PostgreSQL configuration:
-- Check current connections SELECT count(*) FROM pg_stat_activity; -- See who's connected SELECT client_addr, usename, application_name, state FROM pg_stat_activity WHERE state != 'idle';
Increase max_connections in postgresql.conf or use PgBouncer/Supavisor more aggressively. For production, aim for connection pooling that handles 80% of your traffic.
Temporary IP Blocks
If you see connection refused after failed login attempts, Supabase's brute-force protection may have blocked your IP. Wait 30 minutes or check your network configuration.
Realtime Service Problems
The Realtime service is notoriously finicky in self-hosted deployments. GitHub discussions are full of "Realtime keeps restarting" posts.
Service Restart Loop
Symptom: docker logs supabase-realtime shows the service starting and immediately crashing.
Common cause: Missing or incorrect RLIMIT_NOFILE settings.
Fix: Add this to your Realtime service in docker-compose.yml:
realtime:
ulimits:
nofile:
soft: 10000
hard: 10000
environment:
- SEED_SELF_HOST=true
The SEED_SELF_HOST: true environment variable ensures proper initialization in self-hosted environments.
Realtime Connection Drops
If clients connect but disconnect unexpectedly:
- Check WebSocket proxy settings
If you're using Nginx or Traefik as a reverse proxy, ensure WebSocket upgrades are configured:
# Nginx example
location /realtime/ {
proxy_pass http://realtime:4000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
- Verify JWT configuration
Realtime requires valid JWTs. Check that your SUPABASE_JWT_SECRET matches across all services:
# In your .env file, verify these match: JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters ANON_KEY=eyJ... # Generated with the same secret SERVICE_ROLE_KEY=eyJ... # Generated with the same secret
Authentication Failures
"Invalid JWT" or Token Errors
Root cause: JWT secrets don't match between services.
Every Supabase service that validates tokens needs the same JWT secret. Check your environment variables:
# All these must use the same secret grep JWT_SECRET .env grep ANON_KEY .env grep SERVICE_ROLE_KEY .env
If you've regenerated keys, you must restart all services:
docker compose down && docker compose up -d
OAuth Provider Not Working
Social logins failing in self-hosted Supabase usually stem from:
Missing callback URLs: Your OAuth provider (Google, GitHub) needs the correct redirect URI. For self-hosted, this is typically:
https://your-domain.com/auth/v1/callback
Kong routing issues: Ensure the auth service is properly routed. Check your Kong configuration.
Missing provider configuration: See our guide on setting up OAuth providers for complete setup instructions.
Users Can't Sign Up
If sign-ups work but users never receive confirmation emails:
Check SMTP configuration: Self-hosted Supabase requires external SMTP. See our SMTP configuration guide.
Verify the auth logs:
docker compose logs auth
Temporarily disable email confirmation for testing: In Studio, go to Authentication → Settings → Email and disable "Confirm email."
Storage Service Issues
Upload Failures
Error: Storage: resource not found
This usually means RLS policies aren't configured for your bucket.
Fix: Add appropriate policies in Studio → Storage → Policies, or via SQL:
-- Allow authenticated users to upload to a bucket CREATE POLICY "Allow uploads" ON storage.objects FOR INSERT TO authenticated WITH CHECK (bucket_id = 'your-bucket-name');
S3/MinIO Backend Connection Issues
If you're using S3-compatible storage:
Verify MinIO is running:
docker compose logs minio
Check storage service can reach MinIO: The storage service needs to access MinIO via Docker's internal network, not localhost:
storage: environment: - STORAGE_BACKEND=s3 - GLOBAL_S3_ENDPOINT=http://minio:9000Test MinIO directly:
# Access MinIO console (usually port 9001) curl http://localhost:9001/minio/health/live
PostgREST and API Problems
Empty Results from API
Symptom: API returns [] when you know data exists.
Cause: 99% of the time, this is Row Level Security (RLS).
Debug steps:
Disable RLS temporarily to confirm:
ALTER TABLE your_table DISABLE ROW LEVEL SECURITY;
Check your policies:
SELECT * FROM pg_policies WHERE tablename = 'your_table';
Verify the JWT contains the expected claims:
// Decode your JWT at jwt.io to inspect claims
For complete RLS debugging, see our Row Level Security guide.
PostgREST Not Reflecting Schema Changes
After adding tables or columns, the API doesn't expose them.
Fix: Reload the PostgREST schema cache:
docker compose kill -s SIGUSR1 rest
Or restart the service:
docker compose restart rest
In production, consider setting PGRST_DB_SCHEMA_RELOAD_INTERVAL for automatic reloading.
Docker-Specific Issues
Container Disk Space
Supabase generates substantial logs. Check disk usage:
docker system df
Clean up old containers and images:
docker system prune -a
For ongoing log management, configure Docker's logging driver or implement proper log management.
Database Corruption After Improper Shutdown
If you hard-reset your server, PostgreSQL might not recover cleanly.
Symptoms: Database won't start, error mentions WAL or corruption.
Recovery:
- Check PostgreSQL logs:
docker compose logs db - Try
pg_resetwalas a last resort (data loss possible) - Restore from backup (you have backups, right?)
This is why proper backup procedures are non-negotiable.
Systematic Debugging Approach
When nothing obvious is wrong, follow this systematic approach:
1. Check Service Health
# View all container status docker compose ps # Check resource usage docker stats --no-stream
2. Review Logs in Order
Start with the service most likely to be the problem:
# API issues docker compose logs kong docker compose logs rest # Auth issues docker compose logs auth # Database issues docker compose logs db # Full stack docker compose logs --tail=100
3. Verify Environment Configuration
Many issues stem from misconfigured environment variables:
# Print effective configuration docker compose config
4. Test Components in Isolation
# Test database directly docker compose exec db psql -U postgres -c "SELECT 1" # Test PostgREST health curl http://localhost:3000/rest/v1/
When to Use a Management Platform
Debugging self-hosted Supabase is educational, but it's also time you're not spending on your actual product. The community consensus in 2026 is clear: self-hosting becomes cost-effective at scale if you have DevOps capacity.
If you don't have dedicated DevOps resources, tools like Supascale can significantly reduce operational burden. With features like automated health checks, one-click backups, and proper monitoring dashboards, you spend less time debugging container crashes and more time building features.
Check our pricing page to see if managed self-hosting makes sense for your situation. Many teams find the $39.99 one-time cost pays for itself after the first 2 AM incident you don't have to handle.
