Files
fail2ban-ui/development/oidc

OIDC Authentication Development Setup

This setup provides a complete OIDC authentication testing environment with Keycloak, Pocket-ID, and Authentik.

Available OIDC Providers

1. Keycloak (Primary - Default)

  • Container: DEV_keycloak
  • Port: 3000 (mapped from internal 8080)
  • Management Port: 9000 (for health checks)
  • URL: http://localhost:3000
  • Admin Console: http://localhost:3000
  • Purpose: Enterprise-grade OIDC provider (recommended)
  • Data: Stored in ./keycloak-data/ and ./keycloak-db/
  • Database: PostgreSQL (container: DEV_keycloak-db)

2. Pocket-ID (Alternative 1)

  • Container: DEV_pocket-id (commented out by default)
  • Port: 3005 (when enabled)
  • URL: http://localhost:3005
  • Purpose: Lightweight OIDC provider with passkey support
  • Data: Stored in ./pocket-id-data/
  • Note: Uncomment in container-compose.yml to use

3. Authentik (Alternative 2)

  • Containers: DEV_authentik-server, DEV_authentik-worker (commented out by default)
  • Ports: 3007 (HTTP), 3008 (HTTPS) (when enabled)
  • URL: http://localhost:3007
  • Purpose: Full-featured identity provider with OIDC support
  • Data: Stored in ./authentik-media/ and ./authentik-db/
  • Note: Requires migrations and initial setup. Uncomment in container-compose.yml to use

4. Fail2ban-UI

  • Container: DEV_fail2ban-ui-oidc
  • Port: 3080
  • URL: http://localhost:3080
  • Purpose: Main application with OIDC authentication enabled
  • OIDC Provider: Keycloak (default, configurable)
  • Network: Uses host network mode to access Keycloak on localhost

Quick Start

Automatic Setup: The OIDC client is automatically configured for Keycloak! Just start the containers and everything should work.

Note: All services bind to 0.0.0.0 for easy access from any network interface.

For Remote Server Access

Default Configuration: The setup defaults to localhost for local development. For remote server access, you need to create a .env file with your server's IP address or hostname.

Option 1: Using .env file (Recommended)

  1. Copy the example file:

    cd /opt/fail2ban-ui/development/oidc
    cp .env.example .env
    
  2. Edit .env and update with your server's IP address or hostname:

    # Example: If your server IP is 172.16.10.18
    PUBLIC_FRONTEND_URL=http://172.16.10.18:3080
    KEYCLOAK_URL=http://172.16.10.18:3000
    KEYCLOAK_PUBLIC_URL=http://172.16.10.18:3000
    
  3. Start containers (docker-compose/podman-compose will automatically load .env):

    podman compose up -d
    

Option 2: Using environment variables

# Set your server's IP address or hostname
export PUBLIC_FRONTEND_URL=http://YOUR_SERVER_IP:3080
export KEYCLOAK_URL=http://YOUR_SERVER_IP:3000
export KEYCLOAK_PUBLIC_URL=http://YOUR_SERVER_IP:3000

# Then start containers
cd /opt/fail2ban-ui/development/oidc
podman compose up -d

Important:

  • Without setting these, redirect URIs will use localhost which won't work from remote browsers
  • After changing these values, you may need to recreate the Keycloak client:
    podman compose down
    rm -rf config/keycloak-client-secret
    podman compose up -d
    

Setup Instructions

1. Build the Fail2ban-UI Image

cd /opt/fail2ban-ui
podman build -t localhost/fail2ban-ui:dev .
# or
docker build -t localhost/fail2ban-ui:dev .

2. Start the Services

cd /opt/fail2ban-ui/development/oidc
podman compose up -d
# or
docker-compose up -d

Important Notes:

  • Keycloak startup time: Keycloak takes 30-60 seconds to fully start. Be patient!
  • Container status: The fail2ban-ui container will wait for Keycloak to start
  • If fail2ban-ui is stuck in "Created" status:
    • Wait for Keycloak to show "healthy" status: podman compose ps
    • Or manually start fail2ban-ui: podman start DEV_fail2ban-ui-oidc (it will retry connecting)

3. Automatic Keycloak Client Configuration

Automatic: The OIDC client is automatically created by the keycloak-init container. No manual configuration needed!

The keycloak-init container will:

  • Wait for Keycloak to be ready
  • Automatically create the fail2ban-ui OIDC client
  • Configure redirect URIs and web origins
  • Save the client secret to /config/keycloak-client-secret
  • Fail2ban-ui will automatically read the secret from this file

If you see "Client not found" error:

This means the keycloak-init container hasn't run yet or failed. To fix:

  1. Check if Keycloak is running:

    podman compose ps keycloak
    # Should show "healthy" status
    
  2. Run keycloak-init manually:

    cd /opt/fail2ban-ui/development/oidc
    podman compose run --rm keycloak-init
    
  3. Verify the client secret was created:

    ls -la config/keycloak-client-secret
    cat config/keycloak-client-secret
    
  4. Restart fail2ban-ui:

    podman compose restart fail2ban-ui
    

Manual Configuration (Alternative):

If automatic configuration fails, you can manually create the client:

Manual Setup Steps (if needed):

  1. Wait for Keycloak to Start:

    • Check logs: podman logs DEV_keycloak
    • Wait for "Keycloak started" message (may take 30-60 seconds)
    • Check container status: podman compose ps - Keycloak should show "healthy" status
  2. Access Keycloak Admin Console:

    • Open http://localhost:3000 in your browser (or use your host's IP address)
    • Login with:
      • Username: admin
      • Password: admin
  3. Select Realm:

    • The default configuration uses the master realm (already selected)
    • Optional: Create a custom realm for production use (see below)
  4. Create OIDC Client (if auto-configuration failed):

    • In the left sidebar, click Clients

    • Click Create client button (top right)

    • Client ID: Enter fail2ban-ui (must match OIDC_CLIENT_ID in container-compose.yml)

    • Client protocol: Select openid-connect

    • Click Next

    • Client authentication: Toggle ON (this makes it a confidential client)

    • Authorization: Leave OFF (unless you need it)

    • Authentication flow: Leave default settings

    • Click Next

    • Login settings:

      • Root URL: Leave empty
      • Home URL: Leave empty
      • Valid redirect URIs: Add http://localhost:3080/auth/callback (must match exactly)
      • Valid post logout redirect URIs: Leave empty
      • Web origins: Add http://localhost:3080 (for CORS)
    • Click Save

  5. Get Client Secret (REQUIRED):

    • After saving, you'll be on the client settings page
    • Click the Credentials tab
    • Copy the Client secret value (click "Copy" or manually copy)
    • Update container-compose.yml:
      # Edit the file
      nano /opt/fail2ban-ui/development/oidc/container-compose.yml
      # or
      vi /opt/fail2ban-ui/development/oidc/container-compose.yml
      
    • Find the line: - OIDC_CLIENT_SECRET=change-me-secret
    • Replace change-me-secret with the actual secret you copied
    • Save the file
  6. Restart fail2ban-ui:

    podman compose restart fail2ban-ui
    
  7. Create a Test User (Optional but recommended):

    • In Keycloak admin console, click Users in the left sidebar
    • Click Create new user button (top right)
    • Username: testuser (or any username)
    • Email: test@example.com (optional)
    • Email verified: Toggle ON (optional)
    • Click Create
    • Go to the Credentials tab
    • Click Set password
    • Enter a password
    • Temporary: Toggle OFF (so user doesn't need to reset password on first login)
    • Click Save

Now you can access fail2ban-ui:

  • Open http://localhost:3080 in your browser
  • You should be redirected to Keycloak login
  • Login with your test user credentials
  • After successful authentication, you'll be redirected back to fail2ban-ui

Optional: Create Custom Realm (for production):

If you want to use a custom realm instead of master:

  1. In Keycloak admin console, click the realm dropdown (top left, shows "master")
  2. Click Create Realm
  3. Realm name: Enter myrealm (or any name)
  4. Enabled: Toggle ON
  5. Click Create
  6. Update container-compose.yml:
    - OIDC_ISSUER_URL=http://localhost:3000/realms/myrealm
    
  7. Restart fail2ban-ui:
    podman compose restart fail2ban-ui
    
  8. Create the OIDC client in the new realm (follow steps 4-6 above)

4. Test Authentication

  1. Verify Fail2ban-UI Started Successfully:

    • Check logs: podman logs DEV_fail2ban-ui-oidc
    • Look for: "OIDC authentication enabled" (should appear after Keycloak is ready)
    • If you see retry messages, wait a bit longer for Keycloak to fully start
  2. Access Fail2ban UI:

    • Open http://localhost:3080
    • You should be redirected to Keycloak login
  3. Login:

    • Use your Keycloak test user credentials
    • After successful authentication, you'll be redirected back to Fail2ban UI
  4. Verify Session:

    • Check the header for your user information
    • Verify logout functionality

Switching Between Providers

Using Pocket-ID Instead of Keycloak

  1. Stop current services:

    podman compose down
    
  2. Edit container-compose.yml:

    • Comment out the keycloak and postgres services
    • Uncomment the pocket-id service
    • Update fail2ban-ui environment variables:
      - OIDC_PROVIDER=pocketid
      - OIDC_ISSUER_URL=http://localhost:3005
      - OIDC_LOGOUT_URL=http://localhost:3005/logout
      
    • Change fail2ban-ui back to bridge network (remove network_mode: host)
  3. Start services:

    podman compose up -d
    
  4. Configure Pocket-ID:

    • Access http://localhost:3005
    • Create admin account
    • Create OIDC client with redirect URI: http://localhost:3080/auth/callback

Using Authentik Instead of Keycloak

  1. Stop current services:

    podman compose down
    
  2. Edit container-compose.yml:

    • Comment out the keycloak and postgres services
    • Uncomment all authentik-* services
    • Update fail2ban-ui environment variables:
      - OIDC_PROVIDER=authentik
      - OIDC_ISSUER_URL=http://localhost:3007/application/o/fail2ban-ui/
      
    • Change fail2ban-ui back to bridge network (remove network_mode: host)
  3. Start services:

    podman compose up -d
    
  4. Run migrations and setup:

    podman compose run --rm authentik-server migrate
    
  5. Access initial setup:

    • Open http://localhost:3007/if/flow/initial-setup/
    • Create initial admin user
  6. Configure Authentik:

    • Create OIDC Provider
    • Create Provider Application
    • Configure client ID and secret

Configuration Options

OIDC Environment Variables

Edit container-compose.yml to customize OIDC settings:

environment:
  - OIDC_ENABLED=true                    # Enable/disable OIDC
  - OIDC_PROVIDER=keycloak               # Provider: keycloak, authentik, pocketid
  - OIDC_ISSUER_URL=http://localhost:3000/realms/master  # Must match provider's discovery document
  - OIDC_CLIENT_ID=fail2ban-ui
  - OIDC_CLIENT_SECRET=your-secret
  - OIDC_REDIRECT_URL=http://localhost:3080/auth/callback  # External URL for browser redirects
  - OIDC_SCOPES=openid,profile,email     # Comma-separated scopes
  - OIDC_SESSION_MAX_AGE=7200            # Session timeout (seconds)
  - OIDC_USERNAME_CLAIM=preferred_username
  - OIDC_SKIP_VERIFY=true                # Skip TLS verification (dev only)

Note: OIDC_ISSUER_URL must match the issuer returned by the provider's discovery document. For Keycloak with KC_HOSTNAME=localhost, use http://localhost:3000/realms/master.

Provider-Specific Issuer URLs

  • Keycloak: http://localhost:3000/realms/master (or your custom realm name)
  • Pocket-ID: http://localhost:3005
  • Authentik: http://localhost:3007/application/o/<client-slug>/

Troubleshooting

Keycloak Not Accessible / Healthcheck Failing

  • Check if container is running: podman ps | grep keycloak
  • Check container health status: podman inspect DEV_keycloak | grep -A 10 Health
  • Check logs: podman logs DEV_keycloak
  • Verify port mapping: netstat -tlnp | grep 3000
  • Wait for database to be ready (healthcheck)
  • Keycloak takes 30-60 seconds to fully start - wait for "Keycloak started" in logs
  • Healthcheck: Keycloak v26+ uses port 9000 for health endpoints. Verify health endpoint:
    # From host (if port 9000 is exposed):
    curl http://localhost:9000/health/ready
    
    # Or test from inside container:
    podman exec DEV_keycloak bash -c 'exec 3<>/dev/tcp/localhost/9000 && echo -e "GET /health/ready HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n" >&3 && cat <&3'
    
  • If healthcheck keeps failing: You can temporarily modify container-compose.yml to remove the condition: service_healthy from depends_on and let fail2ban-ui's retry logic handle the connection:
    depends_on:
      - keycloak  # Remove condition to start immediately
    

Fail2ban-UI Fails to Start / OIDC Initialization Errors

  • Container stuck in "Created" status:

    • This means it's waiting for Keycloak to start (via depends_on)
    • Check Keycloak status: podman compose ps - should show "healthy" when ready
    • Check Keycloak logs: podman logs DEV_keycloak
    • If Keycloak healthcheck is failing but Keycloak is running, you can:
      1. Wait longer (Keycloak takes 30-60 seconds to start)
      2. Manually start fail2ban-ui: podman start DEV_fail2ban-ui-oidc (it will retry connecting)
      3. Temporarily remove condition: service_healthy from depends_on in container-compose.yml
  • "Connection refused" errors: Keycloak isn't ready yet. The application will retry automatically (up to 10 times with exponential backoff). Wait for Keycloak to fully start (30-60 seconds).

  • "Issuer did not match" errors:

    • This happens when OIDC_ISSUER_URL doesn't match the issuer in Keycloak's discovery document
    • Keycloak is configured with KC_HOSTNAME=localhost, so it returns http://localhost:3000/realms/master as issuer
    • Ensure OIDC_ISSUER_URL is set to: http://localhost:3000/realms/master (or your custom realm)
    • Verify the issuer: curl http://localhost:3000/realms/master/.well-known/openid-configuration | grep issuer
  • "Realm does not exist" errors:

    • The default configuration uses the master realm which always exists
    • If you see this error, check that OIDC_ISSUER_URL in container-compose.yml matches an existing realm
    • Verify the realm exists: curl http://localhost:3000/realms/master/.well-known/openid-configuration
    • Or access Keycloak admin console and check available realms
  • Check fail2ban-ui logs: podman logs DEV_fail2ban-ui-oidc for detailed error messages

  • Check Keycloak is ready: Wait for log message "Keycloak ... started" and verify health endpoint responds

Authentication Fails

  1. Check OIDC Configuration:

    • Verify OIDC_ISSUER_URL matches provider URL exactly
    • Ensure client ID and secret match provider configuration
    • Check redirect URI matches exactly
  2. Check Fail2ban-UI Logs:

    podman logs DEV_fail2ban-ui-oidc
    
  3. Verify Provider Client:

    • Ensure client is active in provider admin (accessible at http://localhost:3000 for Keycloak)
    • Check redirect URI is exactly: http://localhost:3080/auth/callback

Session Issues

  • Check OIDC_SESSION_SECRET is set (or auto-generated)
  • Verify session cookie settings (should work with OIDC_SKIP_VERIFY=true in dev)
  • Clear browser cookies and try again

Keycloak Realm Not Found

  • Default Configuration: The setup uses the master realm by default. This realm always exists in Keycloak.
  • Custom Realm: If you created a custom realm (e.g., myrealm), ensure:
    • The realm name in OIDC_ISSUER_URL matches exactly (case-sensitive)
    • The realm is enabled in Keycloak admin console
    • Update OIDC_ISSUER_URL in container-compose.yml to: http://localhost:3000/realms/myrealm
  • Check Realm: Access http://localhost:3000/realms/<realm-name>/.well-known/openid-configuration to verify the realm exists

Cleanup

To remove all containers and volumes:

podman compose down -v
# or
docker-compose down -v

This will remove:

  • All containers
  • Volume data (Keycloak database, Fail2ban-UI config, etc.)

Note: This deletes all development data. Make sure to backup anything important.

Production Considerations

⚠️ This setup is for development only!

For production:

  • Use HTTPS/TLS (not HTTP)
  • Set OIDC_SKIP_VERIFY=false
  • Use strong, randomly generated secrets
  • Configure proper reverse proxy
  • Use secure session secrets
  • Change default admin passwords
  • Enable proper logging and monitoring
  • Use production-ready database configurations
  • Configure proper backup strategies