From 6098bbc2093cc43199a0f4a00a30355e0a97a147 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Jan 2026 03:36:54 +0000 Subject: [PATCH 1/3] Add Keycloak proxy configuration fix script - Fixes deprecated KC_PROXY warning - Updates to KC_PROXY_HEADERS=xforwarded (v2) - Migrates credentials to .env file - Preserves existing passwords - Automatic backup and restart - Resolves 'Hostname v1 options [proxy] are still in use' warning --- fix-keycloak-proxy.sh | 212 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 fix-keycloak-proxy.sh diff --git a/fix-keycloak-proxy.sh b/fix-keycloak-proxy.sh new file mode 100644 index 0000000..d4ffd62 --- /dev/null +++ b/fix-keycloak-proxy.sh @@ -0,0 +1,212 @@ +#!/bin/bash +# +# Fix Keycloak proxy configuration +# This updates Keycloak to use v2 proxy headers (KC_PROXY_HEADERS) +# instead of deprecated v1 (KC_PROXY) +# + +set -e + +KC_DIR="$HOME/docker/keycloak" + +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "Keycloak Proxy Configuration Fix" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "This script will:" +echo " 1. Backup your current configuration" +echo " 2. Create .env file for credentials" +echo " 3. Update docker-compose.yml to use env_file" +echo " 4. Replace deprecated KC_PROXY with KC_PROXY_HEADERS" +echo " 5. Restart Keycloak with new configuration" +echo "" + +if [ ! -d "$KC_DIR" ]; then + echo "❌ Error: Keycloak directory not found at $KC_DIR" + exit 1 +fi + +cd "$KC_DIR" + +# Check if docker-compose.yml exists +if [ ! -f "docker-compose.yml" ]; then + echo "❌ Error: docker-compose.yml not found in $KC_DIR" + exit 1 +fi + +# Backup existing configuration +BACKUP_DIR="$KC_DIR/backups" +mkdir -p "$BACKUP_DIR" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +cp docker-compose.yml "$BACKUP_DIR/docker-compose.yml.backup.$TIMESTAMP" +echo "✓ Backed up docker-compose.yml to $BACKUP_DIR/docker-compose.yml.backup.$TIMESTAMP" + +# Extract passwords from existing docker-compose.yml +echo "" +echo "Extracting credentials from existing configuration..." + +KC_ADMIN_PASS=$(grep "KEYCLOAK_ADMIN_PASSWORD" docker-compose.yml | head -1 | sed 's/.*KEYCLOAK_ADMIN_PASSWORD[=:]\s*//' | tr -d '"' | tr -d "'" | xargs) +KC_DB_PASS=$(grep "POSTGRES_PASSWORD" docker-compose.yml | head -1 | sed 's/.*POSTGRES_PASSWORD[=:]\s*//' | tr -d '"' | tr -d "'" | xargs) +KC_HOSTNAME=$(grep "KC_HOSTNAME[=:]" docker-compose.yml | grep -v STRICT | head -1 | sed 's/.*KC_HOSTNAME[=:]\s*//' | tr -d '"' | tr -d "'" | xargs) +KC_START_CMD=$(grep -A 2 "keycloak:" docker-compose.yml | grep "command:" -A 1 | tail -1 | sed 's/.*- //' | xargs) + +# Validate we got the passwords +if [ -z "$KC_ADMIN_PASS" ] || [ -z "$KC_DB_PASS" ]; then + echo "❌ Error: Could not extract passwords from docker-compose.yml" + echo " Please check your configuration manually" + exit 1 +fi + +echo "✓ Admin password: ${KC_ADMIN_PASS:0:4}***${KC_ADMIN_PASS: -4}" +echo "✓ Database password: ${KC_DB_PASS:0:4}***${KC_DB_PASS: -4}" +[ -n "$KC_HOSTNAME" ] && echo "✓ Hostname: $KC_HOSTNAME" +echo "✓ Start command: $KC_START_CMD" + +# Determine hostname strict mode +if [ "$KC_START_CMD" = "start" ]; then + KC_HOSTNAME_STRICT="false" +else + KC_HOSTNAME_STRICT="false" +fi + +# Create .env file +echo "" +echo "Creating .env file..." + +cat > .env << KC_ENV +# Keycloak Environment Variables +# ⚠ KEEP THIS FILE SECURE - Contains sensitive passwords +# Generated: $TIMESTAMP + +# Admin Credentials +KEYCLOAK_ADMIN=admin +KEYCLOAK_ADMIN_PASSWORD=$KC_ADMIN_PASS + +# Database Credentials +POSTGRES_DB=keycloak +POSTGRES_USER=keycloak +POSTGRES_PASSWORD=$KC_DB_PASS +KC_DB=postgres +KC_DB_URL=jdbc:postgresql://postgres:5432/keycloak +KC_DB_USERNAME=keycloak +KC_DB_PASSWORD=$KC_DB_PASS + +# Keycloak Configuration (v2 Proxy Headers) +KC_PROXY_HEADERS=xforwarded +KC_HTTP_ENABLED=true +KC_HOSTNAME_STRICT=$KC_HOSTNAME_STRICT +KC_LOG_LEVEL=INFO +KC_HEALTH_ENABLED=true +KC_METRICS_ENABLED=true +KC_ENV + +# Add hostname if it was configured +if [ -n "$KC_HOSTNAME" ]; then + echo "KC_HOSTNAME=$KC_HOSTNAME" >> .env +fi + +# Set proper ownership +chown "$USER:$USER" .env +chmod 600 .env + +echo "✓ Created .env file with secure permissions (600)" + +# Create new docker-compose.yml +echo "" +echo "Creating new docker-compose.yml..." + +cat > docker-compose.yml << KC_COMPOSE +name: keycloak + +services: + postgres: + image: postgres:16-alpine + container_name: keycloak-db + restart: unless-stopped + env_file: + - .env + volumes: + - ./postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U keycloak"] + interval: 10s + timeout: 5s + retries: 5 + + keycloak: + image: quay.io/keycloak/keycloak:latest + container_name: keycloak + restart: unless-stopped + command: + - $KC_START_CMD + env_file: + - .env + ports: + - "8180:8080" + volumes: + - ./data:/opt/keycloak/data + depends_on: + postgres: + condition: service_healthy + labels: + - "io.podman.annotations.label/fail2ban.enable=true" + - "io.podman.annotations.label/fail2ban.filter=caddy-auth" +KC_COMPOSE + +echo "✓ Created new docker-compose.yml with v2 proxy headers" + +# Restart Keycloak +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "Restarting Keycloak with new configuration..." +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +docker compose down +echo "✓ Stopped Keycloak" + +echo "" +echo "Starting Keycloak (this may take a minute)..." +docker compose up -d + +# Wait for Keycloak to be ready +echo "" +echo "Waiting for Keycloak to be ready..." +KC_READY=false +for i in {1..60}; do + if docker exec keycloak curl -sf http://localhost:8080/health/ready > /dev/null 2>&1; then + KC_READY=true + echo "✓ Keycloak is ready" + break + fi + echo -n "." + sleep 2 +done +echo "" + +if [ "$KC_READY" = true ]; then + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "✅ Keycloak successfully updated!" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + echo "Configuration changes:" + echo " • Deprecated KC_PROXY removed" + echo " • New KC_PROXY_HEADERS=xforwarded added" + echo " • Credentials moved to .env file" + echo " • docker-compose.yml uses env_file" + echo "" + echo "Your Keycloak instance is now using v2 proxy configuration." + echo "The warnings about deprecated proxy options should be gone." + echo "" + [ -n "$KC_HOSTNAME" ] && echo "Access URL: https://$KC_HOSTNAME" || echo "Access URL: http://localhost:8180" + echo "" +else + echo "" + echo "⚠ Keycloak may still be starting. Check logs:" + echo " docker compose logs -f keycloak" +fi + +echo "" +echo "Backup location: $BACKUP_DIR/docker-compose.yml.backup.$TIMESTAMP" +echo "" From 736c53b1db4c6170c49966b7260ab73b31b38bdd Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Jan 2026 03:39:08 +0000 Subject: [PATCH 2/3] Update Keycloak to use v2 proxy headers (KC_PROXY_HEADERS) - Replace deprecated KC_PROXY=edge with KC_PROXY_HEADERS=xforwarded - Fixes 'Hostname v1 options [proxy] are still in use' warning - Convert docker-compose-keycloak.yml to use .env file - Remove hardcoded passwords from docker-compose.yml - Add comprehensive .env template in comments - Update deployment instructions and production checklist - Resolves CORS and secure context warnings - All credentials now in .env with proper security --- docker-compose-keycloak.yml | 90 +++++++++++++++++-------------------- ubuntu-post-install.sh | 3 +- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/docker-compose-keycloak.yml b/docker-compose-keycloak.yml index 010de83..dced564 100644 --- a/docker-compose-keycloak.yml +++ b/docker-compose-keycloak.yml @@ -4,10 +4,29 @@ # DEPLOYMENT INSTRUCTIONS: # 1. Create directory: mkdir -p ~/docker/keycloak # 2. Copy this file: cp docker-compose-keycloak.yml ~/docker/keycloak/docker-compose.yml -# 3. IMPORTANT: Update KEYCLOAK_ADMIN_PASSWORD below! +# 3. Create .env file with credentials (see .env template below) # 4. Start the service: cd ~/docker/keycloak && docker compose up -d # 5. Access at: http://localhost:8180/admin (admin console) # +# .ENV FILE TEMPLATE: +# Create a file named .env in ~/docker/keycloak/ with: +# KEYCLOAK_ADMIN=admin +# KEYCLOAK_ADMIN_PASSWORD= +# POSTGRES_DB=keycloak +# POSTGRES_USER=keycloak +# POSTGRES_PASSWORD= +# KC_DB=postgres +# KC_DB_URL=jdbc:postgresql://postgres:5432/keycloak +# KC_DB_USERNAME=keycloak +# KC_DB_PASSWORD= +# KC_PROXY_HEADERS=xforwarded +# KC_HTTP_ENABLED=true +# KC_HOSTNAME_STRICT=false +# KC_LOG_LEVEL=INFO +# KC_HEALTH_ENABLED=true +# KC_METRICS_ENABLED=true +# # KC_HOSTNAME=auth.yourdomain.com # Uncomment for production +# # REVERSE PROXY SETUP (with Caddy): # Add to your Caddyfile: # auth.yourdomain.com { @@ -30,10 +49,8 @@ services: image: postgres:16-alpine container_name: keycloak-db restart: unless-stopped - environment: - POSTGRES_DB: keycloak - POSTGRES_USER: keycloak - POSTGRES_PASSWORD: keycloak_db_password_CHANGE_THIS + env_file: + - .env volumes: - ./postgres-data:/var/lib/postgresql/data healthcheck: @@ -48,33 +65,8 @@ services: restart: unless-stopped command: - start-dev # Use 'start' for production mode - environment: - # Admin credentials - CHANGE THESE! - - KEYCLOAK_ADMIN=admin - - KEYCLOAK_ADMIN_PASSWORD=CHANGE_THIS_SECURE_PASSWORD - - # Database configuration (PostgreSQL) - - KC_DB=postgres - - KC_DB_URL=jdbc:postgresql://postgres:5432/keycloak - - KC_DB_USERNAME=keycloak - - KC_DB_PASSWORD=keycloak_db_password_CHANGE_THIS - - # Hostname configuration - # For production, set to your domain: - # - KC_HOSTNAME=auth.yourdomain.com - # - KC_HOSTNAME_STRICT=true - - KC_HOSTNAME_STRICT=false - - # Proxy configuration (required when behind Caddy/nginx) - - KC_PROXY=edge - - KC_HTTP_ENABLED=true - - # Logging - - KC_LOG_LEVEL=INFO - - # Health check - - KC_HEALTH_ENABLED=true - - KC_METRICS_ENABLED=true + env_file: + - .env ports: - "8180:8080" # HTTP port (use reverse proxy for HTTPS) # - "8787:8787" # Debug port (uncomment if needed) @@ -94,34 +86,36 @@ services: # NOTES: # - Admin console: http://localhost:8180/admin -# - Default credentials: admin / CHANGE_THIS_SECURE_PASSWORD +# - Credentials: Stored in .env file # - Database: PostgreSQL (persistent data in ./postgres-data) -# - For H2 database (dev only), remove postgres service and database env vars +# - Proxy: Uses KC_PROXY_HEADERS=xforwarded (v2 config, no deprecated warnings) # # FIRST-TIME SETUP: -# 1. Login to admin console -# 2. Create a realm (e.g., "myrealm") -# 3. Create clients for your applications -# 4. Configure authentication flows -# 5. Add users or configure identity providers (LDAP, SAML, OAuth) +# 1. Create .env file with secure passwords (see template above) +# 2. Start containers: docker compose up -d +# 3. Login to admin console at http://localhost:8180/admin +# 4. Create a realm (e.g., "homelab" or "myrealm") +# 5. Create clients for your applications (OAuth2/OIDC) +# 6. Add users or configure identity providers (LDAP, SAML, Social) # # COMMON USE CASES: # - Single Sign-On (SSO) for multiple applications -# - OAuth2/OIDC provider for custom apps +# - OAuth2/OIDC provider for custom apps (ActualBudget, etc.) # - SAML 2.0 identity provider # - User federation with LDAP/Active Directory # - Multi-factor authentication (MFA/2FA) -# - Social login (Google, GitHub, etc.) +# - Social login (Google, GitHub, Facebook, etc.) # # PRODUCTION CHECKLIST: -# [ ] Change admin password -# [ ] Change database password -# [ ] Set KC_HOSTNAME to your domain -# [ ] Use 'start' instead of 'start-dev' command -# [ ] Configure HTTPS via reverse proxy (Caddy) -# [ ] Enable hostname strict mode +# [ ] Create .env file with secure passwords (12+ chars, alphanumeric only) +# [ ] Set KC_HOSTNAME in .env to your domain (e.g., auth.yourdomain.com) +# [ ] Use 'start' instead of 'start-dev' command in docker-compose.yml +# [ ] Configure HTTPS via reverse proxy (Caddy/nginx) +# [ ] Set KC_HOSTNAME_STRICT=true in .env for production +# [ ] Configure DNS A record for your hostname +# [ ] Set proper file permissions: chmod 600 .env # [ ] Configure backup strategy for PostgreSQL -# [ ] Set up monitoring (metrics on port 9000) +# [ ] Set up monitoring (metrics enabled via KC_METRICS_ENABLED=true) # # BACKUP: # docker compose down diff --git a/ubuntu-post-install.sh b/ubuntu-post-install.sh index 10215ca..7028c99 100644 --- a/ubuntu-post-install.sh +++ b/ubuntu-post-install.sh @@ -3758,7 +3758,8 @@ KC_DB_USERNAME=keycloak KC_DB_PASSWORD=$KC_DB_PASS # Keycloak Configuration -KC_PROXY=edge +# Proxy settings (v2) - Trust X-Forwarded-* headers from Caddy2 +KC_PROXY_HEADERS=xforwarded KC_HTTP_ENABLED=true KC_HOSTNAME_STRICT=$KC_HOSTNAME_STRICT KC_LOG_LEVEL=INFO From b4cb82c0d7ff9b7001be358974f7920be0c42b8c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Jan 2026 03:40:18 +0000 Subject: [PATCH 3/3] Make fix-keycloak-proxy.sh executable --- fix-keycloak-proxy.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 fix-keycloak-proxy.sh diff --git a/fix-keycloak-proxy.sh b/fix-keycloak-proxy.sh old mode 100644 new mode 100755