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 internal8080) - 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.ymlto 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.ymlto 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)
-
Copy the example file:
cd /opt/fail2ban-ui/development/oidc cp .env.example .env -
Edit
.envand 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 -
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
localhostwhich won't work from remote browsers - After changing these values, you may need to recreate the Keycloak client to update redirect URIs:
Or manually update the client in Keycloak admin console:
podman compose down rm -rf config/keycloak-client-secret podman compose up -d- Go to Clients → fail2ban-ui (name of the client)
- Update "Valid redirect URIs" and "Valid post logout redirect URIs"
- Save
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)
- Wait for Keycloak to show "healthy" status:
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-uiOIDC client - Configure redirect URIs and web origins
- Configure post-logout redirect URI (for proper logout flow)
- Save the client secret to
/config/keycloak-client-secret - Fail2ban-ui will automatically read the secret from this file
Note: If you update PUBLIC_FRONTEND_URL after the client has been created, you may need to delete the existing client and let keycloak-init recreate it, or manually update the client in Keycloak's admin console to include the new post-logout redirect URI.
If you see "Client not found" error:
This means the keycloak-init container hasn't run yet or failed. To fix:
-
Check if Keycloak is running:
podman compose ps keycloak # Should show "healthy" status -
Run keycloak-init manually:
cd /opt/fail2ban-ui/development/oidc podman compose run --rm keycloak-init -
Verify the client secret was created:
ls -la config/keycloak-client-secret cat config/keycloak-client-secret -
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):
-
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
- Check logs:
-
Access Keycloak Admin Console:
- Open
http://localhost:3000in your browser (or use your host's IP address) - Login with:
- Username:
admin - Password:
admin
- Username:
- Open
-
Select Realm:
- The default configuration uses the
masterrealm (already selected) - Optional: Create a custom realm for production use (see below)
- The default configuration uses the
-
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 matchOIDC_CLIENT_IDin 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
-
-
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-secretwith the actual secret you copied - Save the file
-
Restart fail2ban-ui:
podman compose restart fail2ban-ui -
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:3080in 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:
- In Keycloak admin console, click the realm dropdown (top left, shows "master")
- Click Create Realm
- Realm name: Enter
myrealm(or any name) - Enabled: Toggle ON
- Click Create
- Update
container-compose.yml:- OIDC_ISSUER_URL=http://localhost:3000/realms/myrealm - Restart fail2ban-ui:
podman compose restart fail2ban-ui - Create the OIDC client in the new realm (follow steps 4-6 above)
4. Test Authentication
-
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
- Check logs:
-
Access Fail2ban UI:
- Open
http://localhost:3080 - You should be redirected to Keycloak login
- Open
-
Login:
- Use your Keycloak test user credentials
- After successful authentication, you'll be redirected back to Fail2ban UI
-
Verify Session:
- Check the header for your user information
- Verify logout functionality
Switching Between Providers
Using Pocket-ID Instead of Keycloak
-
Stop current services:
podman compose down -
Edit
container-compose.yml:- Comment out the
keycloakandpostgresservices - Uncomment the
pocket-idservice - 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)
- Comment out the
-
Start services:
podman compose up -d -
Configure Pocket-ID:
- Access
http://localhost:3005 - Create admin account
- Create OIDC client with redirect URI:
http://localhost:3080/auth/callback
- Access
Using Authentik Instead of Keycloak
-
Stop current services:
podman compose down -
Edit
container-compose.yml:- Comment out the
keycloakandpostgresservices - 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)
- Comment out the
-
Start services:
podman compose up -d -
Run migrations and setup:
podman compose run --rm authentik-server migrate -
Access initial setup:
- Open
http://localhost:3007/if/flow/initial-setup/ - Create initial admin user
- Open
-
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.ymlto remove thecondition: service_healthyfromdepends_onand 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:
- Wait longer (Keycloak takes 30-60 seconds to start)
- Manually start fail2ban-ui:
podman start DEV_fail2ban-ui-oidc(it will retry connecting) - Temporarily remove
condition: service_healthyfromdepends_onincontainer-compose.yml
- This means it's waiting for Keycloak to start (via
-
"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_URLdoesn't match the issuer in Keycloak's discovery document - Keycloak is configured with
KC_HOSTNAME=localhost, so it returnshttp://localhost:3000/realms/masteras issuer - Ensure
OIDC_ISSUER_URLis 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
- This happens when
-
"Realm does not exist" errors:
- The default configuration uses the
masterrealm which always exists - If you see this error, check that
OIDC_ISSUER_URLincontainer-compose.ymlmatches 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
- The default configuration uses the
-
Check fail2ban-ui logs:
podman logs DEV_fail2ban-ui-oidcfor detailed error messages -
Check Keycloak is ready: Wait for log message "Keycloak ... started" and verify health endpoint responds
Authentication Fails
-
Check OIDC Configuration:
- Verify
OIDC_ISSUER_URLmatches provider URL exactly - Ensure client ID and secret match provider configuration
- Check redirect URI matches exactly
- Verify
-
Check Fail2ban-UI Logs:
podman logs DEV_fail2ban-ui-oidc -
Verify Provider Client:
- Ensure client is active in provider admin (accessible at
http://localhost:3000for Keycloak) - Check redirect URI is exactly:
http://localhost:3080/auth/callback
- Ensure client is active in provider admin (accessible at
Session Issues
- Check
OIDC_SESSION_SECRETis set (or auto-generated) - Verify session cookie settings (should work with
OIDC_SKIP_VERIFY=truein dev) - Clear browser cookies and try again
Keycloak Realm Not Found
- Default Configuration: The setup uses the
masterrealm 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_URLmatches exactly (case-sensitive) - The realm is enabled in Keycloak admin console
- Update
OIDC_ISSUER_URLincontainer-compose.ymlto:http://localhost:3000/realms/myrealm
- The realm name in
- Check Realm: Access
http://localhost:3000/realms/<realm-name>/.well-known/openid-configurationto 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