Validate Helm Charts / Detect changed charts (pull_request) Successful in 3s
Validate Helm Charts / Resource quantities (pull_request) Successful in 9s
Validate Helm Charts / Build keycloak (pull_request) Successful in 4s
Validate Helm Charts / Trivy config keycloak (pull_request) Successful in 11s
Install-test / Install-test keycloak (pull_request) Successful in 2m23s
Validate Helm Charts / Install-test (pull_request) Successful in 2m23s
Two replicas with cache=ispn, clustered through Keycloak's default jdbc-ping stack: discovery runs over the PostgreSQL that is there anyway, so no headless Service and no JGroups wiring. Deployment rather than StatefulSet - Keycloak 26 keeps everything in the database, user sessions included. The chart's defining property is that it has TWO INIT CONTAINERS and needs both. db, health-enabled and metrics-enabled are Keycloak BUILD options (verified in the 26.8.0 option table), the published image is augmented with their defaults, and supplying different ones at runtime makes Keycloak rewrite /opt/keycloak/lib/quarkus at start - which readOnlyRootFilesystem: true forbids and which upstream describes as a start that "creates an image that is mutable". Not setting db is no way out: the probes alone force it, because health-enabled is a build option too. An empty emptyDir over that path fails as well, because QuarkusEntryPoint loads quarkus/quarkus-application.dat before it dispatches any command, `build` included. So one init container seeds the directory into a volume, the next runs `kc.sh build` into it, and the serving container runs `start --optimized` - every container keeping the full hardening baseline, with no documented deviation to carry. Build options therefore exist in exactly one place, and the asymmetry is enforced rather than trusted: the serving container passes no build option at all, and a build option's variable name in keycloak.env fails the render with a message naming it. Hostname handling is the security-relevant part. KC_HOSTNAME is derived from ingress.domain as a full URL (which upstream requires alongside hostname-admin), hostname-strict stays at its default true, and proxy-headers is set rather than optional. The admin hostname is NOT presented as an access control: upstream states that hostname-admin "does not prevent accessing the Administration REST API endpoints via the frontend URL specified by the hostname option", so the chart renders no /admin deny rule and values.yaml, NOTES.txt and the wiki all say in the same words that restricting that API is reverse-proxy work. The management port 9000 is a containerPort and a ClusterIP Service for in-cluster scraping, and is in no Ingress: it serves /health/* and optionally /metrics without authentication. Liveness uses /health/live and deliberately not /health or /health/ready - those include the database, and a liveness probe on them would restart the whole cluster for as long as the database is away. Also in this change: - First PodDisruptionBudget in this repository, which makes it a convention (README section 11): minAvailable as a value, and rendered only while the computed replica count is >= 2, because minAvailable: 1 with one replica blocks every node drain forever with a message that names the PDB rather than the replica count. - First quay.io image, so quay.io joins the trusted registries in ci/trivy/data/ksv0125.yaml - configured rather than suppressed, so AVD-KSV-0125 keeps being able to say something. - Renovate block with NO version constraint, which is the counter-case to garage and stalwart and is measured rather than assumed: docker versioning already excludes the -N rebuild tags, the floating minors and latest/nightly. Three dry-run fixtures are recorded at the block, and against the committed config 26.7.4 offers exactly 26.7.5 (patch) and 26.8.0 (minor). - No automerge exception, by decision (Gitea #83): the global automerge applies, and the minor-upgrade procedure plus `kc.sh update-compatibility` is documented in NOTES.txt instead. - Two upstream defaults deviated from, each with its reason at the value: db-pool-max-size 20 instead of 100 (two replicas at 100 ask a default PostgreSQL for twice its max_connections), and uid 1000 / gid 0 instead of this repo's 20000/1000, because the image declares keycloak:x:1000:0 and chowns its install tree to that pair. Part of #83
51 lines
2.5 KiB
YAML
51 lines
2.5 KiB
YAML
apiVersion: v2
|
|
name: keycloak
|
|
description: A Helm chart to deploy Keycloak, an OpenID Connect and SAML identity provider, as a two-node cluster on Kubernetes
|
|
icon: https://www.keycloak.org/resources/images/icon.svg
|
|
|
|
type: application
|
|
|
|
# appVersion is the exact image tag of quay.io/keycloak/keycloak. No "v"
|
|
# prefix here - upstream tags are plain three-part versions (26.8.0).
|
|
#
|
|
# THE TAG LANDSCAPE, AND WHY THIS CHART NEEDS NO VERSION CONSTRAINT. Measured
|
|
# on 2026-10-04 against quay.io's tag API, this registry carries four shapes
|
|
# side by side:
|
|
#
|
|
# 1. release tags 26.8.0, 26.7.5, ... <- what we track
|
|
# 2. REBUILD tags 26.8.0-0, 26.7.3-1, 26.7.2-2 - the same app
|
|
# version rebuilt (base image or CVE fix) without an app-version bump.
|
|
# 26.8.0-0 resolves to the SAME manifest digest as 26.8.0.
|
|
# 3. floating minor tags 26.8, 26.7, 26.6, ... - they move
|
|
# 4. floating names latest, nightly - they move daily
|
|
#
|
|
# This is the same GENUS of trap as garage's commit-SHA tags and stalwart's
|
|
# moving names, and it is the one case in this repo where the answer came out
|
|
# the other way: plain `docker` versioning already excludes all three unwanted
|
|
# shapes, so the renovate.json5 block carries NO versioningTemplate. Docker
|
|
# versioning splits a tag at the first dash and only ever offers candidates
|
|
# with the SAME suffix - our value has none, so the -N rebuilds are invisible
|
|
# to it - and 26.8 fails on the missing third part while latest/nightly parse
|
|
# as no version at all.
|
|
#
|
|
# THAT IS MEASURED, NOT ASSUMED, and the measurement is written down because
|
|
# the next round will otherwise add a constraint "to be safe" (renovate 44.132.5,
|
|
# --platform=local --dry-run=lookup against the real registry):
|
|
# appVersion 26.8.0 -> updates [], warnings []
|
|
# appVersion 26.7.0 -> exactly one: 26.8.0 (minor)
|
|
# appVersion 26.7.4 -> exactly two: 26.7.5 (patch), 26.8.0 (minor)
|
|
# No run offered a rebuild tag, a floating minor, latest or nightly.
|
|
#
|
|
# AND THE OTHER HALF, WHICH THE VERSION NUMBER CANNOT CARRY: Keycloak supports
|
|
# a rolling update only WITHIN a minor line. A minor jump needs the cluster
|
|
# shut down. The global `automerge: true` in renovate.json5 applies here
|
|
# anyway - a deliberate acceptance of that risk, not an oversight - so the
|
|
# procedure lives in NOTES.txt and on the wiki page instead of in a
|
|
# packageRules entry. Read the "MINOR UPGRADES" section of NOTES.txt before
|
|
# merging an app-version PR that changes the minor.
|
|
version: 1.0.0+up26.8.0
|
|
appVersion: "26.8.0"
|
|
|
|
maintainers:
|
|
- name: jklein
|