Configurable Keycloak Docker image and bash setup scripts.
This project provides a docker image which extends the production-oriented keycloak and adds features for development and testing. The Jefferson Lab image sets up a Docker healthcheck and Docker entrypoint, installs client tools (see kc-lib.sh), and adds some default configuration for the Jefferson Lab environment. The entrypoint integrates with the healthcheck such that the container is "healthy" only when keycloak is both running and configured. Configuration is supported via environment variables and a conventional directory named /container-entrypoint-initdb.d of bash scripts that can be overwritten by mounting a volume.
- 1.x version based on Keycloak 20.x
- 2.x version based on Keycloak 26.x
- Grab project
git clone https://github.com/JeffersonLab/keycloak
cd keycloak
- Launch Compose
docker compose up
- Navigate to admin console
http://localhost:8081/auth
Note: Login with username admin and password admin
Mount a volume at /container-entrypoint-initdb.d containing bash scripts to run, ordered by name ascending. See example. Mount a subdirectory (e.g. 99-conf.d) or individual files in this location to keep default config as overriding the /container-entrypoint-initdb.d/ will overwrite the default configuration.
Environment variables:
| Name | Description |
|---|---|
| KC_FRONTEND_URL | Front end scheme, hostname, port, and relative path |
| KC_BACKEND_URL | Back end scheme, hostname, port, and relative path |
| KC_HTTP_RELATIVE_PATH | Relative path, probably must match KC_FRONTEND_URL and KC_BACKEND_URL |
| KC_BOOTSTRAP_ADMIN_USERNAME | Admin username |
| KC_BOOTSTRAP_ADMIN_PASSWORD | Admin password |
| KC_CLIENT_NAME | Client ID, e.g. 'my-app'. Used in creating client roles and service accounts |
| KC_RESOURCE | Controls default role name prefix, e.g., ${KC_RESOURCE}-user. Typically same as KC_CLIENT_NAME |
| KC_REDIRECT_URIS | Allowed redirect URIs for the client |
| KC_UPDATE_CLIENT_ROLES_MAPPER | If set to true, adds 'roles' claims to ID token and user info endpoint (optional) |
| KC_TOKEN_AUDIENCES | Space separated list of client IDs to name as audiences (aud) in the access tokens issued to the client, e.g. 'my-app' (optional). Needed by an app that checks the audience of its bearer tokens, such as one on Wildfly with verify-token-audience: give its own client, and each client that calls it, the app's client ID here |
| KC_ASSIGNED_REALM_ROLES | Space separated listed of realm roles assigned to client's service account. Created if missing. |
| KC_PROVIDES_CLIENT_ROLES | Space separated listed of client roles (e.g, 'role') to create that are associated with this client. Assigned as 'client_id/role'. |
| KC_ASSIGNED_CLIENT_ROLES | Space separated listed of client roles (e.g, 'client_id/role') assigned to client's service account. NOT created if missing. |
| KC_PROVIDER_ID | The LDAP provider's component ID (optional). Defaults to 22 characters derived from KC_REALM, the same on every install. Must be a UUID or exactly 22 letters, digits, _ and -. See Notes on LDAP |
| KC_SKIP_DEFAULT_SETUP | If set to true, skips the default setup scripts (the unmodified copies of defaults in /container-entrypoint-initdb.d), so Keycloak starts with only the master realm and bootstrap admin. Other scripts in /container-entrypoint-initdb.d still run (optional) |
Notes on Default Configuration:
- Additional environment variables are set in 00_config.env. These can only be overridden by replacing this file or providing an additional env file to be sourced after.
- Each client will use the same client_secret:
yHi6W2raPmLvPXoxqMA7VWbLAA2WN0eB - Four users are created all with the password
password: jadams, jdoe, jsmith, and tbrown - All users have ${KC_RESOURCE}-user role. jdoe and tbrown have ${KC_RESOURCE}-admin role
- Client has KC_UPDATE_CLIENT_ROLES_MAPPER unset by default
Notes on Setup and Persistence:
- The setup scripts run once, after Keycloak first starts, and then the entrypoint writes a
setup-completemarker file. The container is healthy only once the marker exists and Keycloak responds at KC_BACKEND_URL. - With the default embedded (dev-file) database the marker is written to
/opt/keycloak/data/setup-complete, next to the database. If you mount a volume at/opt/keycloak/data, a recreated container keeps its realm and skips setup. Without a volume, a new container starts fresh and runs setup again. - With an external database (e.g.
KC_DB=oracle) the marker is written to/opt/keycloak/setup-complete, in the container itself, so a recreated container runs the setup scripts again against the existing database. SetKC_SKIP_DEFAULT_SETUP=true(or make your own scripts idempotent) if the database outlives the container. - The entrypoint runs until Keycloak exits and then exits with Keycloak's status, so Docker restart policies (e.g.
restart: unless-stopped) apply if Keycloak stops.docker stopis passed on to Keycloak for a clean shutdown.
Notes on Client Tools:
/kc-lib.shholds the setup functions. Source it from your own scripts and set the variables each function needs, as the defaults do, or run it with env files and the functions to call, in order:/kc-lib.sh -e /my.env login create_realm create_client. It stops at the first function that fails./kc-lib.sh --helplists the functions and the variables each one needs.- A function whose variables are missing says which, and returns non-zero; it never exits the shell that sourced the library.
- The older wrappers (
/realm-setup.sh,/client-setup.sh,/ldap-setup.sh, ...) still takeENV_FILE [FUNCTION]and sourceCOMMON_ENV_FILE, and run their default functions when none is named. FUNCTION must be akc-lib.shfunction.
Notes on LDAP:
-
create_ldap_storage_providernames the provider${KC_REALM}-ldap-provider, and gives it a component ID fromKC_PROVIDER_IDor else derived fromKC_REALM. WithKC_IMPORToff, each user's ID (thesubclaim) isf:<component ID>:<username>, which stays the same when Keycloak is reinstalled from scripts. Changing the component ID changes every user's ID, which breaks clients that store it. - Keycloak logs
The given key is not a valid key per specificationat each login when the component ID is not a UUID or exactly 22 characters of letters, digits,_and-. - With
KC_IMPORToff, users and their memberships are read from LDAP, but you must sync new LDAP groups by hand. Keycloak's scheduled sync, which also creates roles, only runs with import on, and the admin console disables the provider's sync actions. A new group has no Keycloak role until a sync runs or one of its members logs in. After adding a group, or on your own schedule, callrun_user_storage_sync, or sync only the role mapper, with your realm in place oface:Syncing only adds roles: a role whose group was removed from LDAP stays in Keycloak until you delete it.kcadm.sh create "user-storage/$(kcadm.sh get components -r ace -q name=ace-ldap-provider --fields id | jq -r .[0].id)/mappers/ace-ldap-role-mapper/sync?direction=fedToKeycloak" -r ace
- Bump the version number in the VERSION file and commit and push to GitHub (using Semantic Versioning).
- The CD GitHub Action should run automatically invoking:
- The Create release GitHub Action to tag the source and create release notes summarizing any pull requests. Edit the release notes to add any missing details.
- The Publish docker image GitHub Action to create a new demo Docker image.