Skip to content

Build a custom Keycloak configuration image

You’ll build a custom uds-identity-config image containing your theme, plugin, or truststore changes, publish it to a container registry, and deploy it to UDS Core using the configImage Helm override. This guide covers the full workflow for any customization that requires an image rebuild.

  • Docker installed and running
  • UDS CLI installed
  • A container registry accessible from your cluster

Most branding changes (logos, T&C content) do not require an image rebuild — they use themeCustomizations bundle overrides. See Customize login page branding for that approach.

An image rebuild is required when you change:

  • CSS or FreeMarker templates in src/theme/
  • Custom Keycloak plugins in src/plugin/
  • The CA truststore (CA zip source in the Dockerfile)
  • Any file directly in the src/ build context
  1. Clone the uds-identity-config repository

    Terminal window
    git clone https://github.com/defenseunicorns/uds-identity-config.git
    cd uds-identity-config
  2. Make your changes to the source

    Apply your changes to the relevant files in the src/ directory. Common change locations:

    Change typeLocation
    Login page CSSsrc/theme/login/resources/css/
    Login page templatessrc/theme/login/ (FreeMarker .ftl files)
    Account themesrc/theme/account/
    Custom plugin codesrc/plugin/src/main/java/
    CA truststore sourcesrc/Dockerfile (CA_ZIP_URL arg) and src/authorized_certs.zip
  3. Build the custom image and Zarf package

    Set IMAGE_NAME to your registry path and VERSION to your desired tag, then run:

    Terminal window
    IMAGE_NAME=registry.example.com/uds/identity-config VERSION=1.0.0 uds run build-zarf-pkg

    This builds the Docker image tagged as registry.example.com/uds/identity-config:1.0.0 and creates zarf-package-keycloak-identity-config-<arch>-dev.zst for airgap transport.

  4. Publish the image or Zarf package

    Push the image to your registry:

    Terminal window
    docker push registry.example.com/uds/identity-config:1.0.0

    For airgapped environments, publish the Zarf package to an OCI registry instead:

    Terminal window
    uds zarf package publish zarf-package-keycloak-identity-config-<arch>-dev.zst oci://registry.example.com
  5. Set configImage in your bundle override

    In your uds-bundle.yaml, override the default identity config image:

    uds-bundle.yaml
    packages:
    - name: core
    repository: registry.defenseunicorns.com/public/core
    ref: x.x.x-upstream
    overrides:
    keycloak:
    keycloak:
    values:
    - path: configImage
    value: registry.example.com/uds/identity-config:1.0.0
  6. Create and deploy your bundle

    Terminal window
    uds create <path-to-bundle-dir>
    uds deploy uds-bundle-<name>-<arch>-<version>.tar.zst

Confirm the custom image was used:

Terminal window
uds zarf tools kubectl get pod -n keycloak -l app.kubernetes.io/name=keycloak \
-o jsonpath='{.items[0].spec.initContainers[0].image}'

The output should match your custom image tag.

For theme changes, navigate to sso.<domain> and confirm your CSS or template changes are visible on the login page.

For truststore changes, verify the gateway is requesting client certificates:

Terminal window
openssl s_client -connect sso.<domain>:443
# Look for your CA in "Acceptable client certificate CA names"

Problem: Init container fails to pull image

Section titled “Problem: Init container fails to pull image”

Symptoms: ImagePullBackOff or ErrImagePull on the Keycloak pod init container.

Solution: Confirm the registry is reachable and the configImage value has no typos. For private registries, verify image pull secrets exist in the keycloak namespace:

Terminal window
uds zarf tools kubectl describe pod -n keycloak -l app.kubernetes.io/name=keycloak

Problem: Theme, truststore, or plugin changes not reflected after deploy

Section titled “Problem: Theme, truststore, or plugin changes not reflected after deploy”

Symptoms: Login page shows old branding, certificate auth fails, or plugin behavior is unchanged despite deploying a new image.

Solution: Themes, truststore, and plugins apply when the init container runs at pod start. Confirm the pod restarted after the image update:

Terminal window
uds zarf tools kubectl rollout status statefulset/keycloak -n keycloak

If the pod did not restart, trigger a rollout:

Terminal window
uds zarf tools kubectl rollout restart statefulset/keycloak -n keycloak

Problem: Plugin JAR missing from providers directory

Section titled “Problem: Plugin JAR missing from providers directory”

Symptoms: Custom plugin behavior is not visible after deploy.

Solution: Check uds run build-zarf-pkg output for Maven build errors. Verify the JAR was copied into the image:

Terminal window
uds zarf tools kubectl exec -n keycloak statefulset/keycloak -- ls /opt/keycloak/providers/

These guides and concepts may be useful to explore next: