Customization
This page will describe how you can customize your Keycloak instance.
Themes and providers
VSHNKeycloak
allows to use custom providers and themes.
Create a custom container image and use it to customize your Keycloak instance as described below.
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNKeycloak
metadata:
name: keycloak-app1-prod
namespace: prod-app
spec:
parameters:
service:
version: "26"
customizationImage:
image: https://registry/user/image:tag (1)
imagePullSecretRef:
name: secret-name (2)
namespace: secret-namespace (3)
size:
plan: standard-2
writeConnectionSecretToRef:
name: keycloak-creds
1 | Container image url. |
2 | Secret name containing credentials for the registry. |
3 | Secret namespace |
Configuration
You can provide a custom configuration to Keycloak using a ConfigMap
.
The content of the ConfigMap
is a JSON file based on the Keycloak export files.
You can logically separate different configurations inside the ConfigMap
by using different keys. However, each key must end in .json
.
The configuration will be read during the startup of Keycloak and loaded into the database.
An extensive set of configuration examples can be found here.
The configuration also supports variable substitution.
Variables exposed by Spring Boot (through configtree or external configuration) can be accessed by $(property.name)
In additional, the string substitution support multiple prefixes for different approaches:
Base64 Decoder: $(base64Decoder:SGVsbG9Xb3JsZCE=)
Base64 Encoder: $(base64Encoder:HelloWorld!)
Java Constant: $(const:java.awt.event.KeyEvent.VK_ESCAPE)
Date: $(date:yyyy-MM-dd)
DNS: $(dns:address|apache.org)
Environment Variable: $(env:USERNAME)
File Content: $(file:UTF-8:src/test/resources/document.properties)
Java: $(java:version)
Localhost: $(localhost:canonical-name)
Properties File: $(properties:src/test/resources/document.properties::mykey)
Resource Bundle: $(resourceBundle:org.example.testResourceBundleLookup:mykey)
Script: $(script:javascript:3 + 4)
System Property: $(sys:user.dir)
URL Decoder: $(urlDecoder:Hello%20World%21)
URL Encoder: $(urlEncoder:Hello World!)
URL Content (HTTP): $(url:UTF-8:http://www.apache.org)
URL Content (HTTPS): $(url:UTF-8:https://www.apache.org)
URL Content (File): $(url:UTF-8:file:///$(sys:user.dir)/src/test/resources/document.properties)
XML XPath: $(xml:src/test/resources/document.xml:/root/path/to/node)
Example
The following example demonstrates how a custom configuration that creates a new realm looks like:
apiVersion: v1
kind: ConfigMap
metadata:
name: keycloak-app1-prod-config
namespace: prod-app
data:
keycloak-config.json: |
{
"enabled": true,
"realm": "prod-app"
}
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNKeycloak
metadata:
name: keycloak-app1-prod
namespace: prod-app
spec:
parameters:
service:
customConfigurationRef: keycloak-app1-prod-config (1)
1 | The name of the ConfigMap . Must be in the same namespace as the Keycloak claim. |
Environment variables
You can pass custom environment variables to your Keycloak instance. Those can then either be used by your custom providers or by your custom configuration.
Example
The following example demonstrates how a custom configuration that creates a new realm and uses environment variables looks like:
apiVersion: v1
kind: Secret
metadata:
name: keycloak-app2-prod-env
namespace: prod-app
stringData:
REALM_NAME: prod-app
type: Opaque
apiVersion: v1
kind: ConfigMap
metadata:
name: keycloak-app2-prod-config
namespace: prod-app
data:
keycloak-config.json: |
{
"enabled": true,
"$(env:REALM_NAME)"
}
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNKeycloak
metadata:
name: keycloak-app2-prod
namespace: prod-app
spec:
parameters:
service:
customConfigurationRef: keycloak-app2-prod-config (1)
customEnvVariablesRef: keycloak-app2-prod-env (2)
1 | The name of the ConfigMap . Must be in the same namespace as the Keycloak claim. |
2 | The name of the Secret that contains the environment variables. Must be in the same namespace as the Keycloak claim. |
Custom Mounts
You can mount additional Kubernetes Secrets and ConfigMaps directly into the Keycloak container’s filesystem by using the customMounts
parameter under spec.parameters.service
.
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNKeycloak
metadata:
name: keycloak-app3-prod
namespace: prod-app
spec:
parameters:
service:
customMounts:
- name: custom-secret1
type: secret
- name: custom-secret2
type: secret
- name: custom-configmap
type: configMap
By default, mounts follow this folder structure:
-
Secrets (
type: secret
) are mounted under/custom/secrets/{name}/…
-
ConfigMaps (
type: configMap
) are mounted under/custom/configs/{name}/…
For example, a Secret named custom-secret1
will be available under /custom/secrets/custom-secret1/
, and a ConfigMap named custom-configmap
under /custom/configs/custom-configmap/
.
Mount names must be unique within the customMounts list to avoid folder name collisions inside the container.
Propagating Changes to Referenced Resources
When you make changes to a ConfigMap
or Secret
that is referenced by your VSHNKeycloak
instance (e.g., via customConfigurationRef
, customEnvVariablesRef
or customMounts
), these changes are not immediately propagated to the running Keycloak instance.
To force a reconciliation and apply the updated configuration or environment variables, you need to annotate the VSHNKeycloak
resource. This tells Crossplane to re-evaluate the resource and apply any changes from its external references.
kubectl annotate vshnkeycloak [NAME] -n [NAMESPACE] crossplane.io/touch="$(date +%s)" --overwrite
Replace [NAME]
with the name of your VSHNKeycloak
instance (e.g., keycloak-app1-prod
or keycloak-app2-prod
), and [NAMESPACE]
with the namespace where the claim was created.