A drop-in Keycloak distribution that runs on Redis instead of Infinispan, so you can operate it with a managed cache your cloud already provides.
Locke is a distribution of Keycloak that ships with both cache backends (the upstream embedded Infinispan and a Redis backend) and lets the operator pick one at boot. When you don't pick Redis, Locke is the Keycloak it was built from, unchanged.
Keycloak gives you the key. Locke gives you the choice.
Why does this exist? See WHY.md.
Both backends ship in the same binary. Choose with one environment variable.
# Default: embedded Infinispan, identical to upstream Keycloak
docker run --rm -p 8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
ghcr.io/sky-cloak/locke:26.6.3-1 start-dev
# Redis backend: point it at any Redis / Valkey / wire-compatible store
docker run --rm -p 8080:8080 \
-e KC_CACHE=redis -e KC_CACHE_REDIS_URL=redis://my-redis:6379 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
ghcr.io/sky-cloak/locke:26.6.3-1 start-dev
# Managed Redis with TLS (AWS ElastiCache, Azure Cache, Upstash, Redis Cloud, ...)
docker run --rm -p 8080:8080 \
-e KC_CACHE=redis \
-e KC_CACHE_REDIS_URL=rediss://my-redis.example.com:6380 \
-e KC_CACHE_REDIS_PASSWORD=$REDIS_PASSWORD \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
ghcr.io/sky-cloak/locke:26.6.3-1 start-devFor TLS + auth options (custom CA, hostname verification, env-var precedence), see docs/redis-security.md.
Or with compose (Postgres + Redis + Locke):
docker compose -f docker-compose-redis.yml up HTTP request (login / refresh / token)
│
▼
Keycloak SPI dispatch (Realm / User / Client / AuthSession / …)
│
▼
Cache adapter layer (model/redis) no JGroups cluster
├─ Local caches (realm / user / client / authz / keys):
│ L1 Caffeine in-JVM, DB on miss, invalidation over Redis pub/sub
└─ Distributed caches (auth sessions / login failures / single-use tokens):
stored in shared Redis / Valkey (cross-pod)
│
▼
PostgreSQL (source of truth) · user sessions persist to JPA
KC_CACHE=infinispan swaps the adapter layer back to the upstream embedded
Infinispan stack with no other change. Full design notes:
docs/redis-cache-architecture.md.
Locke uses composite versioning: the Locke version is the upstream Keycloak
version it was built from, plus a build number. 26.6.1-1 means "Keycloak 26.6.1,
Locke build 1." This is the Percona Server / Amazon Corretto convention.
| Locke | Built from Keycloak | Status |
|---|---|---|
26.6.3-1 |
26.6.3 | current |
26.6.2-3 |
26.6.2 | superseded |
26.6.1-2 |
26.6.1 | maintained |
26.3.5-3 |
26.3.5 | maintained |
26.6.3-1 rebases Locke onto Keycloak 26.6.3 with no Locke-side functional changes;
it carries the same TLS support (rediss://) and runtime KC_CACHE_REDIS_PASSWORD /
_USERNAME handling introduced in 26.6.2-3. See CHANGELOG.md and
docs/redis-security.md. The 26.6.1 and 26.3.5 maintenance
lines stay on plaintext for now; open an issue to request a backport.
See COMPATIBILITY.md for the full matrix and support window.
| Option | Default | Purpose |
|---|---|---|
KC_CACHE |
infinispan |
Cache backend: infinispan or redis |
KC_CACHE_REDIS_URL |
(none) | Redis connection URL. Use rediss:// (note the second s) for TLS. |
KC_CACHE_REDIS_USERNAME |
(none) | Redis ACL username. Optional. |
KC_CACHE_REDIS_PASSWORD |
(none) | Redis password. Wins over URL-embedded userinfo when both are set. |
KC_CACHE_REDIS_TLS_CA_FILE |
(none) | PEM file of CA(s) that signed the Redis server cert. Only needed for private CAs. |
KC_CACHE_REDIS_TLS_VERIFY_HOSTNAME |
true |
Verify the cert's CN/SAN matches the host. The chain is always validated. |
Every other Keycloak option works exactly as upstream. Locke adds no new database, no new admin API, and no new operational concept beyond "you may point the cache at Redis." TLS + auth details: docs/redis-security.md; Sentinel / Cluster / ElastiCache setup: docs/redis-modes.md.
In a 3-pod production cluster (start --optimized) on isolated nodes, the Redis
backend delivers ~100% throughput parity with embedded Infinispan (within ~0.1%
to 250 logins/sec, zero errors on both). The trade is a little read latency for a
large resilience gain: when a node is lost, Infinispan stalls ~31-40s rebalancing
(JGroups state transfer) while Locke keeps serving from Redis at sub-second p99.
On an upgrade that crosses an Infinispan-version boundary, Locke can roll the
cluster as a rolling update (no JGroups version handshake to break), where the
embedded path would otherwise want a brief planned restart (Keycloak starts in
well under 10 seconds). Keycloak does not guarantee no-downtime minor upgrades
in general, so this is one fewer constraint, not a blanket promise. Full
methodology, per-operation latency, resilience, upgrade, and memory numbers are in
benchmark/k8s-ovh/REPORT.md (and
benchmark/RESULTS.md for the local runs).
Skycloak runs managed Keycloak (and Locke) for you: the "I want the choice without the on-call" option.
Apache License 2.0, inherited from upstream Keycloak. See LICENSE.txt and NOTICE. "Keycloak" is a trademark of Red Hat / CNCF; see TRADEMARK.md. Contributions: CONTRIBUTING.md. Security: SECURITY.md.