One of the first things developers notice after deploying self-hosted Supabase is the missing Authentication settings in the dashboard. On Supabase Cloud, you click a few buttons to enable Google or GitHub login. On self-hosted instances, those buttons don't exist.
The Auth configuration panel is disabled for self-hosted deployments. Instead, you configure OAuth providers through environment variables in your docker-compose.yml file. This guide walks you through setting up the most popular OAuth providers—Google, GitHub, Discord, and Apple—so your users can sign in with their existing accounts.
If you're new to self-hosting Supabase, start with our step-by-step deployment guide first, then return here to configure authentication.
Why OAuth Configuration Is Different for Self-Hosted
Supabase uses GoTrue, an open-source authentication server written in Go, to handle user registration and authentication. On Supabase Cloud, the dashboard writes configuration changes directly to the managed GoTrue instance. Self-hosted deployments don't have this integration—the dashboard runs in "studio mode" with platform features disabled.
This means OAuth provider configuration requires:
- Creating OAuth applications with each provider (Google, GitHub, etc.)
- Adding environment variables to your
docker-compose.yml - Restarting your Supabase containers
The process is straightforward once you understand the pattern. Every provider follows the same structure: enable it, add the client ID, add the client secret, and set the redirect URI.
Understanding the Environment Variable Pattern
All OAuth providers use the same naming convention:
GOTRUE_EXTERNAL_{PROVIDER}_ENABLED=true
GOTRUE_EXTERNAL_{PROVIDER}_CLIENT_ID=your-client-id
GOTRUE_EXTERNAL_{PROVIDER}_SECRET=your-client-secret
GOTRUE_EXTERNAL_{PROVIDER}_REDIRECT_URI=https://your-domain.com/auth/v1/callback
Replace {PROVIDER} with the uppercase provider name: GOOGLE, GITHUB, DISCORD, APPLE, etc.
The redirect URI is critical. It must match exactly what you configure in each provider's developer console. For self-hosted Supabase, this is your Kong API gateway URL followed by /auth/v1/callback.
Setting Up Google OAuth
Google OAuth is the most common provider. Here's how to configure it.
Step 1: Create a Google Cloud Project
- Go to the Google Cloud Console
- Create a new project or select an existing one
- Navigate to APIs & Services → OAuth consent screen
- Choose External user type and complete the consent screen setup
- Add your domain to the authorized domains list
Step 2: Create OAuth Credentials
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Select Web application
- Add your callback URL to Authorized redirect URIs:
https://your-supabase-domain.com/auth/v1/callback
- Copy the Client ID and Client Secret
Step 3: Add Environment Variables
Add these variables to the auth service in your docker-compose.yml:
auth:
environment:
GOTRUE_EXTERNAL_GOOGLE_ENABLED: "true"
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: "your-google-client-id.apps.googleusercontent.com"
GOTRUE_EXTERNAL_GOOGLE_SECRET: "your-google-client-secret"
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: "https://your-supabase-domain.com/auth/v1/callback"
Alternatively, reference variables from your .env file:
auth:
environment:
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${ENABLE_GOOGLE_SIGNUP}
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOTRUE_EXTERNAL_GOOGLE_SECRET: ${GOOGLE_CLIENT_SECRET}
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: ${SUPABASE_PUBLIC_URL}/auth/v1/callback
For tips on making Google OAuth look professional (showing your app name instead of a random subdomain), see our guide on fixing Google OAuth branding.
Setting Up GitHub OAuth
GitHub OAuth is popular for developer-focused applications. The setup is simpler than Google.
Step 1: Create a GitHub OAuth App
- Go to GitHub Settings → Developer settings → OAuth Apps
- Click New OAuth App
- Fill in the application details:
- Application name: Your app name
- Homepage URL: Your application URL
- Authorization callback URL:
https://your-supabase-domain.com/auth/v1/callback
- Click Register application
- Generate a new client secret and copy both the Client ID and Client Secret
Step 2: Add Environment Variables
auth:
environment:
GOTRUE_EXTERNAL_GITHUB_ENABLED: "true"
GOTRUE_EXTERNAL_GITHUB_CLIENT_ID: "your-github-client-id"
GOTRUE_EXTERNAL_GITHUB_SECRET: "your-github-client-secret"
GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI: "https://your-supabase-domain.com/auth/v1/callback"
GitHub OAuth is straightforward—no consent screen configuration or domain verification required.
Setting Up Discord OAuth
Discord OAuth is common for gaming applications and community platforms.
Step 1: Create a Discord Application
- Go to the Discord Developer Portal
- Click New Application and give it a name
- Navigate to OAuth2 → General
- Copy the Client ID
- Click Reset Secret to generate a client secret and copy it
- Add your redirect URL under Redirects:
https://your-supabase-domain.com/auth/v1/callback
Step 2: Add Environment Variables
auth:
environment:
GOTRUE_EXTERNAL_DISCORD_ENABLED: "true"
GOTRUE_EXTERNAL_DISCORD_CLIENT_ID: "your-discord-client-id"
GOTRUE_EXTERNAL_DISCORD_SECRET: "your-discord-client-secret"
GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI: "https://your-supabase-domain.com/auth/v1/callback"
Setting Up Apple Sign-In
Apple Sign-In requires more setup than other providers but is essential for iOS applications (Apple requires it if you offer any social login).
Step 1: Apple Developer Account Setup
- Sign in to the Apple Developer Portal
- Go to Certificates, Identifiers & Profiles
- Create an App ID with Sign in with Apple capability enabled
- Create a Services ID (this becomes your client ID)
- Configure the Services ID:
- Enable Sign in with Apple
- Add your domain and return URL:
https://your-supabase-domain.com/auth/v1/callback
- Create a Key with Sign in with Apple enabled
- Download the key file (you can only download it once)
Step 2: Generate the Client Secret
Apple uses a JWT as the client secret, which you generate using your private key. The JWT must be regenerated periodically (maximum 6 months validity).
Create the secret using a tool or script:
# Example using Ruby (Apple's recommended approach)
require 'jwt'
key_file = 'AuthKey_XXXXXXXXXX.p8'
team_id = 'YOUR_TEAM_ID'
client_id = 'YOUR_SERVICES_ID'
key_id = 'YOUR_KEY_ID'
ecdsa_key = OpenSSL::PKey::EC.new(File.read(key_file))
headers = {
'kid' => key_id
}
claims = {
'iss' => team_id,
'iat' => Time.now.to_i,
'exp' => Time.now.to_i + 86400 * 180, # 180 days
'aud' => 'https://appleid.apple.com',
'sub' => client_id
}
token = JWT.encode(claims, ecdsa_key, 'ES256', headers)
puts token
Step 3: Add Environment Variables
auth:
environment:
GOTRUE_EXTERNAL_APPLE_ENABLED: "true"
GOTRUE_EXTERNAL_APPLE_CLIENT_ID: "your-services-id"
GOTRUE_EXTERNAL_APPLE_SECRET: "your-generated-jwt-secret"
GOTRUE_EXTERNAL_APPLE_REDIRECT_URI: "https://your-supabase-domain.com/auth/v1/callback"
Remember: The Apple client secret expires. You'll need to regenerate it before expiration and update your configuration.
Applying Configuration Changes
After adding environment variables, restart your Supabase containers:
docker-compose down docker-compose up -d
The auth service reads configuration on startup, so a full restart is required for changes to take effect.
Verify the configuration by checking the auth container logs:
docker-compose logs auth | grep -i "external"
You should see log entries indicating which external providers are enabled.
Testing Your OAuth Setup
Test each provider with a simple sign-in flow:
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://your-supabase-domain.com', 'your-anon-key')
// Test Google OAuth
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'https://your-app.com/auth/callback'
}
})
Common issues to check:
- Redirect URI mismatch: The callback URL must match exactly in both your provider console and environment variables
- Missing protocol: URLs must include
https:// - Trailing slashes: Some providers are sensitive to trailing slashes—be consistent
Troubleshooting Common Problems
"Invalid redirect URI" Error
This almost always means the callback URL in your provider's developer console doesn't match your GOTRUE_EXTERNAL_{PROVIDER}_REDIRECT_URI exactly. Check for:
- Protocol differences (
httpvshttps) - Trailing slashes
- Port numbers
- Typos in the domain
OAuth Works Locally but Not in Production
Check that your production domain is:
- Added to authorized domains in your provider console
- Using HTTPS (most providers require it)
- Correctly set in your
SITE_URLenvironment variable
Users Get Redirected to the Wrong URL After Login
The SITE_URL environment variable controls where users land after authentication. Set it to your application's URL:
auth:
environment:
GOTRUE_SITE_URL: "https://your-app.com"
Provider Not Appearing in Sign-In Options
Ensure the ENABLED variable is set to "true" (as a string, not a boolean in YAML). Restart your containers after any configuration change.
Managing Multiple OAuth Providers
You can enable any combination of providers. Here's a complete example with all four providers configured:
auth:
environment:
# Site configuration
GOTRUE_SITE_URL: "https://your-app.com"
# Google
GOTRUE_EXTERNAL_GOOGLE_ENABLED: "true"
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOTRUE_EXTERNAL_GOOGLE_SECRET: ${GOOGLE_CLIENT_SECRET}
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: ${SUPABASE_PUBLIC_URL}/auth/v1/callback
# GitHub
GOTRUE_EXTERNAL_GITHUB_ENABLED: "true"
GOTRUE_EXTERNAL_GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID}
GOTRUE_EXTERNAL_GITHUB_SECRET: ${GITHUB_CLIENT_SECRET}
GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI: ${SUPABASE_PUBLIC_URL}/auth/v1/callback
# Discord
GOTRUE_EXTERNAL_DISCORD_ENABLED: "true"
GOTRUE_EXTERNAL_DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}
GOTRUE_EXTERNAL_DISCORD_SECRET: ${DISCORD_CLIENT_SECRET}
GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI: ${SUPABASE_PUBLIC_URL}/auth/v1/callback
# Apple
GOTRUE_EXTERNAL_APPLE_ENABLED: "true"
GOTRUE_EXTERNAL_APPLE_CLIENT_ID: ${APPLE_CLIENT_ID}
GOTRUE_EXTERNAL_APPLE_SECRET: ${APPLE_CLIENT_SECRET}
GOTRUE_EXTERNAL_APPLE_REDIRECT_URI: ${SUPABASE_PUBLIC_URL}/auth/v1/callback
Keep secrets in your .env file and reference them using ${VARIABLE_NAME} syntax to avoid committing credentials to version control.
The Easier Way: Using Supascale
Manually editing environment variables and restarting containers works, but it's tedious—especially when managing multiple projects or making frequent changes.
Supascale provides a UI for OAuth configuration that works like the Supabase Cloud dashboard. Add your client credentials through a web interface, and Supascale handles the environment variable updates and container restarts automatically.
You get:
- Visual OAuth configuration: No more editing YAML files
- Multiple projects: Configure different providers for different projects
- Instant updates: Changes apply without manual container restarts
- Credential validation: Catch configuration errors before they break authentication
For teams running multiple self-hosted Supabase instances, this eliminates a significant operational burden. Check out our documentation on configuring auth providers for details.
Additional Providers
Supabase supports many more OAuth providers beyond the four covered here:
- Azure AD
- Bitbucket
- Figma
- GitLab
- Keycloak
- Notion
- Slack
- Spotify
- Twitch
- WorkOS
Each follows the same pattern: enable it, set the client ID, secret, and redirect URI. Check the Supabase auth configuration documentation for provider-specific environment variable names.
Summary
Setting up OAuth for self-hosted Supabase requires manual configuration through environment variables, but the process is consistent across all providers:
- Create an OAuth application in the provider's developer console
- Set the callback URL to
https://your-supabase-domain.com/auth/v1/callback - Add the
GOTRUE_EXTERNAL_{PROVIDER}_*environment variables to yourdocker-compose.yml - Restart your Supabase containers
The lack of a dashboard UI for OAuth configuration is one of the most common complaints about self-hosted Supabase. Understanding the environment variable pattern makes it manageable, and tools like Supascale can automate the process entirely.
