Skip to main content

Self-Hosting Guide: Deploy Keycloak for Authentication

·OSSAlt Team
keycloakauthenticationself-hostingdockerguide

Self-Hosting Guide: Deploy Keycloak for Authentication

Keycloak is the most battle-tested open source identity platform. It replaces Auth0, Okta, and Azure AD — providing SSO, OIDC, SAML, LDAP, and social login for all your applications.

Requirements

  • VPS with 2 GB RAM minimum (4 GB recommended)
  • Docker and Docker Compose
  • Domain name (e.g., auth.yourdomain.com)
  • 10+ GB disk

Step 1: Create Docker Compose

# docker-compose.yml
services:
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    container_name: keycloak
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - KC_DB=postgres
      - KC_DB_URL_HOST=db
      - KC_DB_URL_DATABASE=keycloak
      - KC_DB_USERNAME=keycloak
      - KC_DB_PASSWORD=your-strong-password
      - KC_HOSTNAME=auth.yourdomain.com
      - KC_PROXY_HEADERS=xforwarded
      - KC_HTTP_ENABLED=true
      - KEYCLOAK_ADMIN=admin
      - KEYCLOAK_ADMIN_PASSWORD=your-admin-password
    command: start
    depends_on:
      - db

  db:
    image: postgres:16-alpine
    container_name: keycloak-db
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=keycloak
      - POSTGRES_USER=keycloak
      - POSTGRES_PASSWORD=your-strong-password

volumes:
  postgres_data:

Step 2: Start Keycloak

docker compose up -d

Step 3: Reverse Proxy (Caddy)

# /etc/caddy/Caddyfile
auth.yourdomain.com {
    reverse_proxy localhost:8080
}
sudo systemctl restart caddy

Step 4: Initial Configuration

  1. Open https://auth.yourdomain.com
  2. Login with admin credentials
  3. Create a new realm (don't use the master realm for applications)

Recommended realm setup:

  1. Click Create Realm
  2. Name it (e.g., mycompany)
  3. Enable it

Step 5: Configure a Client (Your Application)

  1. Go to your realm → ClientsCreate client
  2. Client type: OpenID Connect
  3. Client ID: my-app
  4. Client authentication: On (for server-side apps) / Off (for SPAs)
  5. Valid redirect URIs: https://myapp.com/callback
  6. Web origins: https://myapp.com

Save and note the client secret from the Credentials tab.

Step 6: Add Social Login Providers

Go to Identity Providers:

ProviderConfiguration
GoogleClient ID + Secret from Google Cloud Console
GitHubClient ID + Secret from GitHub OAuth Apps
MicrosoftClient ID + Secret from Azure App Registration
AppleService ID + Key from Apple Developer Portal

Step 7: Integrate with Your App

Next.js (with NextAuth.js):

// app/api/auth/[...nextauth]/route.js
import NextAuth from 'next-auth'
import KeycloakProvider from 'next-auth/providers/keycloak'

export const authOptions = {
  providers: [
    KeycloakProvider({
      clientId: 'my-app',
      clientSecret: 'your-client-secret',
      issuer: 'https://auth.yourdomain.com/realms/mycompany',
    }),
  ],
}

const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }

React SPA (with keycloak-js):

import Keycloak from 'keycloak-js'

const keycloak = new Keycloak({
  url: 'https://auth.yourdomain.com',
  realm: 'mycompany',
  clientId: 'my-spa',
})

await keycloak.init({ onLoad: 'login-required' })
console.log('Authenticated:', keycloak.authenticated)
console.log('Token:', keycloak.token)

Any OIDC-compatible app:

Issuer URL:    https://auth.yourdomain.com/realms/mycompany
Auth URL:      https://auth.yourdomain.com/realms/mycompany/protocol/openid-connect/auth
Token URL:     https://auth.yourdomain.com/realms/mycompany/protocol/openid-connect/token
Userinfo URL:  https://auth.yourdomain.com/realms/mycompany/protocol/openid-connect/userinfo

Step 8: User Management

Create users manually:

  1. UsersAdd user
  2. Set username, email, first/last name
  3. Credentials tab → set password

LDAP integration:

  1. User FederationAdd LDAP provider
  2. Configure connection URL, bind DN, user DN
  3. Sync users on demand or schedule

Self-registration:

  1. Realm SettingsLogin tab
  2. Enable User registration

Step 9: Configure Email

Go to Realm SettingsEmail:

SettingValue
Hostsmtp.resend.com
Port587
Fromauth@yourdomain.com
Enable StartTLS
Usernameresend
Passwordre_your_api_key

Required for password reset, email verification, and account notifications.

Step 10: Security Settings

Brute force protection:

  • Realm SettingsSecurity Defenses
  • Enable brute force detection
  • Set max login failures (e.g., 5)
  • Set lockout duration (e.g., 15 minutes)

Password policies:

  • AuthenticationPoliciesPassword Policy
  • Add: length(8), digits(1), upperCase(1), specialChars(1)

MFA/2FA:

  • AuthenticationFlows
  • Set OTP as required or conditional for browser flow

Production Hardening

Performance tuning:

environment:
  - KC_CACHE=ispn
  - KC_CACHE_STACK=kubernetes  # For clustered deployments
  - JAVA_OPTS_KC_HEAP=-Xms512m -Xmx1024m

Backups:

# Database backup (daily cron)
docker exec keycloak-db pg_dump -U keycloak keycloak > /backups/keycloak-$(date +%Y%m%d).sql

# Export realm configuration
docker exec keycloak /opt/keycloak/bin/kc.sh export \
  --dir /opt/keycloak/data/export \
  --realm mycompany
docker cp keycloak:/opt/keycloak/data/export /backups/keycloak-realm-$(date +%Y%m%d)

Updates:

docker compose pull
docker compose up -d

Monitoring:

  • Enable health endpoint: KC_HEALTH_ENABLED=true
  • Monitor /health/ready and /health/live
  • Track login failures and token issuance rates

Resource Usage

UsersRAMCPUDisk
1-5002 GB2 cores10 GB
500-5K4 GB4 cores20 GB
5K-50K8 GB8 cores50 GB

VPS Recommendations

ProviderSpec (1K users)Price
Hetzner4 vCPU, 8 GB RAM€8/month
DigitalOcean2 vCPU, 4 GB RAM$24/month
Linode2 vCPU, 4 GB RAM$24/month

Compare authentication platforms on OSSAlt — protocols, features, and pricing side by side.