A Kubernetes operator for managing Keycloak instances, realms, and OAuth2/OIDC clients declaratively with full GitOps compatibility.
Get a complete Keycloak setup running in under 10 minutes:
# 1. Install the operator (OCI registry)
# Note: The chart creates the namespace by default, don't use --create-namespace
helm install keycloak-operator \
oci://ghcr.io/vriesdemichael/charts/keycloak-operator \
--namespace keycloak-system
# Or install from local charts:
# helm install keycloak-operator ./charts/keycloak-operator \
# --namespace keycloak-system
# 2. Deploy Keycloak with database
kubectl apply -f examples/01-keycloak-instance.yaml
# 3. Create an identity realm
kubectl apply -f examples/02-realm-example.yaml
# 4. Create an OAuth2 client
kubectl apply -f examples/03-client-example.yamlπ Full Quick Start Guide β
- Declarative Configuration - Manage Keycloak entirely through Kubernetes resources
- Admission Webhooks - Immediate validation feedback with clear error messages (docs)
- GitOps Ready - Full observability with status conditions and
observedGenerationtracking - Drift Detection - Automatic detection of orphaned resources and configuration drift (docs)
- Cross-Namespace Support - Secure delegation model for multi-tenant environments
- Production Ready - Rate limiting, exponential backoff, and comprehensive monitoring
- Comprehensive Test Coverage - Unit and integration tests with coverage tracking
- Resource Quotas - Namespace-level limits on realms and clients via admission webhooks
- Rate Limiting - Two-level throttling (global + per-namespace) protects Keycloak from overload
- High Availability - Multi-replica Keycloak with PostgreSQL clustering via CloudNativePG
- OAuth2/OIDC Clients - Automated client provisioning with credential management
- Service Accounts - Declarative role assignment for machine-to-machine authentication
- OIDC Endpoint Discovery - Automatic population of all OIDC/OAuth2 endpoints in realm status
π Full Documentation - Versioned documentation with version selector
- Quick Start Guide - Get started in 10 minutes
- Architecture - How the operator works
- Admission Webhooks - Resource validation and quotas
- Security Model - Secret-based authorization explained
- Drift Detection - Orphan detection and auto-remediation
- Observability - Metrics, logs, and status conditions
- Versioning - How to access older documentation and chart versions
- Development Guide - Contributing to the project
Note: Version-Specific Documentation Use the version selector in the documentation to view docs for your installed version. See the Versioning Guide for details.
The operator manages three custom resources:
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Keycloak β β KeycloakRealm β β KeycloakClient β
β (Instance) ββββββ€ (Identity) ββββββ€ (OAuth2/OIDC) β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
- Keycloak: The identity server instance with database and networking
- KeycloakRealm: Identity domain with users, roles, and authentication settings
- KeycloakClient: OAuth2/OIDC applications with automated credential management
Create a complete OAuth2 setup:
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/Keycloak.json
# Keycloak instance with PostgreSQL database
apiVersion: vriesdemichael.github.io/v1
kind: Keycloak
metadata:
name: keycloak
namespace: keycloak-system
spec:
replicas: 3
image: quay.io/keycloak/keycloak:26.0.0
database:
type: postgresql
host: keycloak-postgres-rw
port: 5432
database: app
username: app
passwordSecret:
name: keycloak-postgres-app
key: password
---
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakRealm.json
# Identity realm with client authorization grants
apiVersion: vriesdemichael.github.io/v1
kind: KeycloakRealm
metadata:
name: my-app-realm
namespace: my-app
spec:
realmName: my-app
operatorRef:
namespace: keycloak-system
# Namespaces authorized to create clients in this realm
clientAuthorizationGrants:
- my-app
---
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakClient.json
# OAuth2 client (namespace must be in realm's clientAuthorizationGrants)
apiVersion: vriesdemichael.github.io/v1
kind: KeycloakClient
metadata:
name: my-app-client
namespace: my-app
spec:
clientId: my-app
realmRef:
name: my-app-realm
namespace: my-app
publicClient: false
redirectUris:
- "https://my-app.example.com/callback"See examples/ for complete manifests with detailed configuration options.
Get autocompletion, validation, and inline documentation in your IDE using published JSON schemas:
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakRealm.json
apiVersion: vriesdemichael.github.io/v1
kind: KeycloakRealm
# ... IDE will autocomplete fields with descriptions!Features:
- β Autocomplete for all CRD fields
- β Inline validation with error messages
- β Field descriptions from CRD schema
- β Enum value suggestions
Supported IDEs:
- VS Code (with YAML extension)
- IntelliJ IDEA / PyCharm (built-in)
- Neovim (with yaml-language-server)
Available schemas:
https://vriesdemichael.github.io/keycloak-operator/schemas/v1/Keycloak.jsonhttps://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakRealm.jsonhttps://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakClient.json
Add the schema annotation as the first line of your YAML files to enable IDE features.
The operator uses a namespace grant authorization model combining Kubernetes RBAC with declarative access control:
- Realm Creation: Controlled by standard Kubernetes RBAC (who can create
KeycloakRealmresources) - Client Creation: Controlled by realm's
clientAuthorizationGrantslist (which namespaces can create clients) - Self-service: Teams can create realms and clients without platform team intervention
- GitOps Native: All authorization is declarative and stored in Git
- Auditability: All access changes tracked in Git history and Kubernetes audit logs
Read the Security Model documentation for detailed authorization architecture.
The operator exposes Prometheus metrics and includes a Grafana dashboard:
# Enable monitoring in Helm chart
helm install keycloak-operator ./charts/keycloak-operator \
--set monitoring.enabled=true \
--set monitoring.prometheusRules.enabled=true \
--set monitoring.grafanaDashboard.enabled=trueKey metrics:
- Reconciliation success/failure rates
- Rate limiting wait times and timeouts
- Reconciliation duration (p50/p95/p99)
- Resource counts by phase
See Observability for full details.
The operator implements two-level rate limiting to protect Keycloak from API overload:
env:
# Global rate limit (all namespaces combined)
- name: KEYCLOAK_API_GLOBAL_RATE_LIMIT_TPS
value: "50" # requests per second
- name: KEYCLOAK_API_GLOBAL_BURST
value: "100" # burst capacity
# Per-namespace rate limit (fair sharing)
- name: KEYCLOAK_API_NAMESPACE_RATE_LIMIT_TPS
value: "5" # requests per second
- name: KEYCLOAK_API_NAMESPACE_BURST
value: "10" # burst capacity
# Jitter to prevent thundering herd
- name: RECONCILE_JITTER_MAX_SECONDS
value: "5.0" # 0-5 second random delay| Scenario | Protection |
|---|---|
| Spam 1000 realms in one namespace | Limited to 5 req/s = 200s minimum |
| Multiple teams overwhelming Keycloak | Global 50 req/s enforced |
| Operator restart (50+ resources) | Jitter + rate limiting prevents flood |
Prometheus metrics available at :8081/metrics:
keycloak_api_rate_limit_wait_seconds- Time waiting for tokenskeycloak_api_rate_limit_acquired_total- Successful token acquisitionskeycloak_api_rate_limit_timeouts_total- Rate limit timeout errorskeycloak_api_tokens_available- Current available tokens per namespace
Contributions welcome!
To set up a development environment:
# Clone the repository
git clone https://github.com/vriesdemichael/keycloak-operator.git
cd keycloak-operator
# Install dependencies
make install
# Run quality checks
make quality
# Run unit tests
make test-unitSee Development Guide and CLAUDE.md for more details.
MIT License - see LICENSE for details.