Provide three tiers of the install script for both 24.04 and 26.04: - Originals (ubuntu-post-install-24.04.sh / -26.04.sh): restored to their true original state, with Keycloak intact, as a fallback baseline. (This reverts the in-place Keycloak removal from the previous commit; the cleanup now lives in the -no-keycloak variants instead.) - -no-keycloak.sh: Keycloak fully removed, Authelia as the SSO/2FA option. - -crowdsec.sh: builds on -no-keycloak and replaces fail2ban entirely with CrowdSec (SSH via auth.log/sshd collection, Caddy via caddy collection + log acquisition, firewall bouncer for enforcement, plus geo-blocking and community IP-reputation blocklists). Add SCRIPT-VARIANTS.md documenting the three tiers and how the Authelia / fail2ban / CrowdSec security layers differ. All variants pass 'bash -n'. https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
18 KiB
Keycloak Setup Guide
Complete Manual and Automated Configuration Guide
This guide explains Keycloak concepts and how to configure it both automatically (via the script) and manually (via the web UI).
Table of Contents
- What is Keycloak?
- Key Concepts
- Automated Setup (via Script)
- Manual Setup (via Web UI)
- Configuring External Services
- Reconfiguration & Adding Realms
- Common Use Cases
- Troubleshooting
What is Keycloak?
Keycloak is an Identity and Access Management (IAM) system that provides:
- Single Sign-On (SSO): Log in once, access all your services
- User Management: Create, manage, and authenticate users in one place
- OAuth2/OIDC: Industry-standard authentication for web apps
- Social Login: Allow login via Google, GitHub, etc.
- Multi-Factor Authentication (MFA): Add extra security with 2FA/TOTP
- LDAP/Active Directory Integration: Connect to existing user directories
Think of Keycloak as: A centralized login system for all your self-hosted services.
Key Concepts
1. Realm
A realm is an isolated container for users, clients, and configuration.
Analogy: Think of a realm like a "company" or "organization" in Keycloak.
Why you need it:
- The default
masterrealm is for Keycloak admin only - You create a separate realm (e.g.,
homelab) for your actual users and applications - Realms are completely isolated - users in one realm can't access another
Example:
masterrealm: Only for Keycloak administratorshomelabrealm: For your personal services (ActualBudget, Jellyfin, etc.)familyrealm: Separate realm for family members (optional)
2. OAuth2/OpenID Connect (OIDC) Client
A client is an application that uses Keycloak for authentication.
Analogy: Each service (ActualBudget, Jellyfin, etc.) is a "client" that asks Keycloak "Is this user allowed to log in?"
Required information:
- Client ID: Name of the application (e.g.,
actualbudget) - Client Secret: Password for the application (auto-generated, 64-char hex)
- Redirect URIs: Where Keycloak sends users after login
- Example:
https://budget.yourdomain.com/* - Must match EXACTLY or login will fail
- Example:
Flow:
- User clicks "Login" in ActualBudget
- ActualBudget redirects to Keycloak:
https://auth.yourdomain.com/login - User logs in with username/password
- Keycloak redirects back to ActualBudget:
https://budget.yourdomain.com/callback - ActualBudget gets user info and logs them in
3. Users
A user is a person who can log in to your services.
User attributes:
- Username (required, unique)
- Email (optional but recommended)
- First name / Last name (optional)
- Password (set via Credentials tab)
- Email verified (set to true to skip verification)
- Enabled (must be true for user to log in)
4. Redirect URIs
Critical concept: The redirect URI is where Keycloak sends the user after successful login.
Common mistakes:
- ❌
http://localhost:5006(won't work for external services) - ❌
https://budget.example.com(missing wildcard or path) - ✅
https://budget.example.com/*(correct - allows all paths)
For external services (like Pikapod):
- Pikapod gives you a URL like:
https://actualbudget-abc123.pikapod.net - Your redirect URI:
https://actualbudget-abc123.pikapod.net/* - Your Keycloak URL:
https://auth.yourdomain.com(must be publicly accessible)
Automated Setup (via Script)
The script automates everything for you. Here's what it does:
Step 1: Install Keycloak
./ubuntu-post-install.sh
# Select KEYCLOAK in whiptail menu
Prompts:
- Admin password (for Keycloak admin console)
- Database password (for PostgreSQL)
Step 2: Automated Configuration
Configure Keycloak with initial realm and clients? (y/n): y
This automatically:
- ✅ Waits for Keycloak to start (health check)
- ✅ Logs in using admin CLI (
kcadm.sh) - ✅ Creates a realm (e.g.,
homelab) - ✅ Creates OAuth client for ActualBudget (if selected)
- ✅ Creates generic OAuth client template
- ✅ Saves all credentials to
~/docker/keycloak/*.txt - ✅ Optionally creates initial user
Step 3: What Gets Created
Realm: homelab (or your custom name)
ActualBudget OAuth Client:
- Client ID:
actualbudget - Client Secret: (saved to
actualbudget-oauth.txt) - Redirect URIs:
http://localhost:5006/*(local development)http://yourdomain.com:5006/*(local with domain)https://yourdomain.com/*(production - any subdomain)https://budget.yourdomain.com/*(specific subdomain)
Generic OAuth Client:
- Client ID:
generic-app - Client Secret: (saved to
generic-oauth.txt) - Can be cloned for other services
Initial User:
- Username, email, password you provide
- Immediately active
- Can log in to all services
Step 4: Configuration Files
All credentials saved to:
~/docker/keycloak/actualbudget-oauth.txt
~/docker/keycloak/generic-oauth.txt
These files contain:
- Client ID
- Client Secret
- Authorization URL
- Token URL
- User Info URL
- Instructions for configuring each service
Manual Setup (via Web UI)
If you prefer to configure Keycloak manually, or want to add services later:
Access Admin Console
URL: http://localhost:8180/admin
Username: admin
Password: [your admin password]
Step 1: Create a Realm
- Click dropdown in top-left corner (shows "Master")
- Click "Create Realm"
- Realm name:
homelab(or your choice) - Click "Create"
Settings to configure:
-
Login tab:
- ✅ User registration: OFF (you create users manually)
- ✅ Forgot password: ON (allows password resets)
- ✅ Remember me: ON (convenience)
- ✅ Login with email: ON (users can use email instead of username)
-
Email tab: (optional, for password resets)
- Configure SMTP settings if you want email features
Step 2: Create an OAuth2 Client (for ActualBudget)
- Switch to your realm (
homelab) via dropdown - Go to Clients (left menu)
- Click "Create client"
General Settings:
- Client type: OpenID Connect
- Client ID:
actualbudget - Name:
ActualBudget - Description:
Personal Finance Management - Click "Next"
Capability config:
- ✅ Client authentication: ON (creates a secret)
- ✅ Authorization: OFF (not needed)
- ✅ Standard flow: ON (authorization code flow)
- ✅ Direct access grants: ON (allows username/password)
- ❌ Implicit flow: OFF (deprecated)
- ❌ Service accounts: OFF (not needed for web apps)
- Click "Next"
Login settings:
Important: Adjust these for your setup!
For local ActualBudget:
Root URL: http://localhost:5006
Home URL: http://localhost:5006
Valid redirect URIs:
http://localhost:5006/*
http://localhost:5006/callback
Valid post logout redirect URIs: +
Web origins:
http://localhost:5006
For external ActualBudget (Pikapod, etc.):
Root URL: https://actualbudget-abc123.pikapod.net
Home URL: https://actualbudget-abc123.pikapod.net
Valid redirect URIs:
https://actualbudget-abc123.pikapod.net/*
https://actualbudget-abc123.pikapod.net/callback
Valid post logout redirect URIs: +
Web origins:
https://actualbudget-abc123.pikapod.net
For self-hosted with domain:
Root URL: https://budget.yourdomain.com
Home URL: https://budget.yourdomain.com
Valid redirect URIs:
https://budget.yourdomain.com/*
https://budget.yourdomain.com/callback
Valid post logout redirect URIs: +
Web origins:
https://budget.yourdomain.com
- Click "Save"
Step 3: Get Client Secret
- Go to "Credentials" tab
- Copy "Client secret" (you'll need this for ActualBudget)
- Save it somewhere safe!
Step 4: Create a User
- Go to Users (left menu)
- Click "Create user"
User details:
- Username:
john(required) - Email:
john@example.com(optional but recommended) - Email verified: ✅ ON (skip email verification)
- First name:
John - Last name:
Doe - Enabled: ✅ ON (user can log in)
- Click "Create"
Set password:
- Go to "Credentials" tab
- Click "Set password"
- Enter password (twice)
- Temporary: ❌ OFF (user won't be forced to change it)
- Click "Save"
- Confirm in popup
Step 5: Test Login
- Go to Realm Settings → Endpoints
- Click "OpenID Endpoint Configuration" (opens JSON)
- Find:
authorization_endpoint - Copy URL and open in browser
- Add:
?client_id=actualbudget&response_type=code&redirect_uri=http://localhost:5006/callback - Log in with your user
- You should see: Redirect to callback URL (may error if ActualBudget not configured, but login works)
Configuring External Services
Keycloak MUST be Publicly Accessible
Critical: For external services like Pikapod, your Keycloak must be accessible from the internet.
Requirements:
- ✅ Domain name (e.g.,
yourdomain.com) - ✅ DNS A record pointing to your server
- ✅ Caddy reverse proxy with HTTPS
- ✅ Port 80/443 open in firewall
- ✅ Keycloak accessible at
https://auth.yourdomain.com
Setup Caddy for Keycloak
Add to Caddyfile:
auth.yourdomain.com {
log {
output file /var/log/caddy/keycloak-access.log
format json
level INFO
}
reverse_proxy localhost:8180
# Security headers
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
X-XSS-Protection "1; mode=block"
Referrer-Policy "strict-origin-when-cross-origin"
}
}
Reload Caddy:
cd ~/docker/caddy
docker exec -w /etc/caddy caddy caddy reload
Test:
https://auth.yourdomain.com/admin
Configure DNS
Add A record:
auth.yourdomain.com → [Your Server IP]
Or use CNAME:
auth → yourdomain.com
Example: ActualBudget on Pikapod
Scenario:
- Keycloak:
https://auth.yourdomain.com(your server) - ActualBudget:
https://actualbudget-abc123.pikapod.net(Pikapod)
In Keycloak:
- Create client:
actualbudget-pikapod - Redirect URIs:
https://actualbudget-abc123.pikapod.net/* https://actualbudget-abc123.pikapod.net/callback - Web origins:
https://actualbudget-abc123.pikapod.net
In ActualBudget (Pikapod):
Settings → Authentication:
Client ID: actualbudget-pikapod
Client Secret: [from Keycloak credentials tab]
Authorization URL: https://auth.yourdomain.com/realms/homelab/protocol/openid-connect/auth
Token URL: https://auth.yourdomain.com/realms/homelab/protocol/openid-connect/token
User Info URL: https://auth.yourdomain.com/realms/homelab/protocol/openid-connect/userinfo
Flow:
- User visits
https://actualbudget-abc123.pikapod.net - Clicks "Login"
- Redirects to
https://auth.yourdomain.com/realms/homelab/... - User logs in
- Redirects back to
https://actualbudget-abc123.pikapod.net/callback - User is logged in!
Reconfiguration & Adding Realms
You can re-run the script to add more realms or clients!
Option 1: Re-run the Script
cd ~/docker/keycloak
docker compose down
cd ~
./ubuntu-post-install.sh
# Select KEYCLOAK again
# Choose "Configure Keycloak..." → Yes
# Enter new realm name: "family"
# Create new users
This creates:
- New realm with new users
- New OAuth clients for that realm
- Separate from your existing realm
Option 2: Add Realm Manually
Via Web UI:
- Go to admin console
- Click realm dropdown
- "Create Realm"
- Name:
family - Repeat client/user creation steps
Option 3: Use Script Helper
The script can be extended to add a helper:
cd ~/docker/keycloak
# Login to admin CLI
docker exec keycloak /opt/keycloak/bin/kcadm.sh config credentials \
--server http://localhost:8080 \
--realm master \
--user admin \
--password [YOUR_ADMIN_PASSWORD]
# Create new realm
docker exec keycloak /opt/keycloak/bin/kcadm.sh create realms \
-s realm=family \
-s enabled=true
# Create new client
docker exec keycloak /opt/keycloak/bin/kcadm.sh create clients -r family \
-s clientId=my-new-service \
-s enabled=true \
-s clientAuthenticatorType=client-secret \
-s secret=$(openssl rand -hex 32) \
-s 'redirectUris=["https://service.yourdomain.com/*"]'
# Create new user
docker exec keycloak /opt/keycloak/bin/kcadm.sh create users -r family \
-s username=alice \
-s email=alice@example.com \
-s enabled=true
# Set password
docker exec keycloak /opt/keycloak/bin/kcadm.sh set-password -r family \
--username alice \
--new-password 'AlicePassword123!'
Common Use Cases
Use Case 1: All Local Services
Setup:
- Keycloak:
http://localhost:8180 - ActualBudget:
http://localhost:5006 - Jellyfin:
http://localhost:8096
Configuration:
- No domain needed
- Use
localhostURLs everywhere - Redirect URIs:
http://localhost:PORT/*
Use Case 2: Self-Hosted with Domain
Setup:
- Keycloak:
https://auth.yourdomain.com - ActualBudget:
https://budget.yourdomain.com - Jellyfin:
https://jellyfin.yourdomain.com
Configuration:
- Requires domain + Caddy
- Use HTTPS URLs
- Redirect URIs:
https://service.yourdomain.com/*
Use Case 3: Mixed (Local + External)
Setup:
- Keycloak:
https://auth.yourdomain.com(self-hosted) - ActualBudget:
https://actualbudget-abc.pikapod.net(Pikapod) - Jellyfin:
https://jellyfin.yourdomain.com(self-hosted)
Configuration:
- Keycloak MUST be publicly accessible
- Each service gets its own client
- ActualBudget redirect:
https://actualbudget-abc.pikapod.net/* - Jellyfin redirect:
https://jellyfin.yourdomain.com/*
Troubleshooting
Issue: "Invalid redirect URI"
Cause: Redirect URI in Keycloak doesn't match what the app is using.
Fix:
- Check error message for actual redirect URI
- Add EXACT URI to Keycloak client settings
- Include wildcard:
https://domain.com/*
Issue: "Client not found"
Cause: Client ID doesn't match.
Fix:
- Check client ID in Keycloak
- Ensure it matches exactly in application
- Case-sensitive!
Issue: "Invalid client secret"
Cause: Wrong secret or expired.
Fix:
- Go to Keycloak → Clients → Credentials
- Copy secret again (or regenerate)
- Update in application
Issue: External service can't reach Keycloak
Cause: Keycloak not publicly accessible.
Fix:
- Ensure Caddy is running:
docker ps | grep caddy - Check DNS:
dig auth.yourdomain.com - Test URL:
curl https://auth.yourdomain.com - Check firewall:
sudo ufw status(80/443 open?)
Issue: Login succeeds but redirect fails
Cause: CORS or redirect URI mismatch.
Fix:
- Add domain to "Web Origins" in client settings
- Check redirect URI includes protocol (https://)
- Check for typos in domain name
Issue: Can't login to Keycloak admin console
Cause: Container not started or wrong password.
Fix:
# Check if running
docker ps | grep keycloak
# Check logs
docker logs keycloak --tail 50
# Restart
cd ~/docker/keycloak
docker compose restart
# Reset admin password (if needed)
docker exec keycloak /opt/keycloak/bin/kcadm.sh config credentials \
--server http://localhost:8080 \
--realm master \
--user admin \
--password NEW_PASSWORD_HERE
Quick Reference
Important URLs
Local:
Admin Console: http://localhost:8180/admin
Realm Endpoints: http://localhost:8180/realms/{realm-name}/.well-known/openid-configuration
Production:
Admin Console: https://auth.yourdomain.com/admin
Realm Endpoints: https://auth.yourdomain.com/realms/{realm-name}/.well-known/openid-configuration
OAuth URLs (for realm "homelab")
Local:
Authorization: http://localhost:8180/realms/homelab/protocol/openid-connect/auth
Token: http://localhost:8180/realms/homelab/protocol/openid-connect/token
User Info: http://localhost:8180/realms/homelab/protocol/openid-connect/userinfo
Logout: http://localhost:8180/realms/homelab/protocol/openid-connect/logout
Production:
Authorization: https://auth.yourdomain.com/realms/homelab/protocol/openid-connect/auth
Token: https://auth.yourdomain.com/realms/homelab/protocol/openid-connect/token
User Info: https://auth.yourdomain.com/realms/homelab/protocol/openid-connect/userinfo
Logout: https://auth.yourdomain.com/realms/homelab/protocol/openid-connect/logout
Common Commands
# Start Keycloak
cd ~/docker/keycloak
docker compose up -d
# Stop Keycloak
docker compose down
# View logs
docker logs keycloak -f
# Access shell
docker exec -it keycloak bash
# Login to admin CLI
docker exec keycloak /opt/keycloak/bin/kcadm.sh config credentials \
--server http://localhost:8080 \
--realm master \
--user admin \
--password YOUR_PASSWORD
# Export realm configuration (backup)
docker exec keycloak /opt/keycloak/bin/kc.sh export \
--dir /opt/keycloak/data/export \
--realm homelab
# Copy export to host
docker cp keycloak:/opt/keycloak/data/export ./backup/
Summary
Keycloak provides:
- ✅ Single Sign-On for all your services
- ✅ Centralized user management
- ✅ OAuth2/OIDC authentication
- ✅ Works with local and external services
- ✅ Professional-grade security
Automated setup does:
- ✅ Creates realm
- ✅ Creates OAuth clients
- ✅ Creates initial user
- ✅ Saves all credentials
- ✅ Ready to use immediately
Manual setup allows:
- ✅ Full control over configuration
- ✅ Multiple realms (family, work, etc.)
- ✅ Custom client settings
- ✅ Advanced features (LDAP, MFA, etc.)
For external services:
- ✅ Keycloak must be publicly accessible
- ✅ Use Caddy with HTTPS
- ✅ Configure proper redirect URIs
- ✅ Test OAuth flow before production
For questions or issues, check the Keycloak documentation: https://www.keycloak.org/documentation