Deploy Keycloak on Thalassa Cloud Kubernetes
Keycloak is an open-source identity and access management solution that provides single sign-on (SSO), social login, user federation, and fine-grained authorization. By deploying Keycloak on Thalassa Cloud Kubernetes using FluxCD and Cloud Native PostgreSQL, you can run a production-ready identity management platform with high availability, automated deployments, and seamless integration with Kubernetes features.
This guide walks you through deploying Keycloak using FluxCD for GitOps-based deployment, configuring it to use Cloud Native PostgreSQL for the database, and setting up ingress with TLS certificates.
Understanding Keycloak on Kubernetes
On Kubernetes, Keycloak benefits from the platform’s orchestration features like automatic scaling, health checks, and persistent storage. The use of the Helm chart makes deploying Keycloak straightforward and repeatable. Keycloak requires a database for storing user and configuration data, and PostgreSQL is recommended for its reliability and strong integration with Kubernetes.
Cloud Native PostgreSQL provides high availability, automated backups, and seamless database operation within your cluster. To manage Keycloak deployment in a version-controlled and automated way, FluxCD enables GitOps workflows—so every change to your configuration goes through Git and can be automatically applied to your cluster. To learn more about using FluxCD for GitOps, see the Installing FluxCD guide.
Prerequisites
Before deploying Keycloak, ensure you have a few things in place.
- First, you need a running Kubernetes cluster in Thalassa Cloud. Keycloak works with Kubernetes 1.24 or later, and Thalassa Cloud clusters meet this requirement. If you’re new to Thalassa Cloud Kubernetes, see the Getting Started guide for cluster creation and basic setup.
- You’ll also need cluster access configured using
kubectl. Usetcloud kubernetes connectto configure access, or set up kubeconfig manually. You’ll need cluster administrator permissions to install FluxCD and create namespaces. - FluxCD must be installed in your cluster. If you haven’t installed it yet, follow the Installing FluxCD guide to set it up. This guide assumes you have FluxCD installed and configured with access to a Git repository where you’ll store your Keycloak configuration.
- For the database, you’ll need Cloud Native PostgreSQL installed in your cluster. If you haven’t installed it yet, follow the Cloud Native PostgreSQL guide to set it up. This guide assumes you have Cloud Native PostgreSQL installed and ready to use.
- For TLS certificates, you’ll need Cert Manager installed with Let’s Encrypt configured. See the Cert Manager and Let’s Encrypt guide for installation and configuration instructions.
Finally, ensure your cluster has sufficient resources. Keycloak requires CPU, memory, and storage for the application and database. Plan for at least one node with adequate resources, and consider using dedicated node pools for database instances. For information about storage options, see the Storage documentation and Persistent Volumes documentation.
Setting Up PostgreSQL Database
Before deploying Keycloak, set up a PostgreSQL database cluster using Cloud Native PostgreSQL. This provides a reliable, high-availability database for your Keycloak instance. This section provides a quick setup; for PostgreSQL configuration options, high availability setup, and backup configuration, see the Cloud Native PostgreSQL guide.
Step 1: Create Namespace
Create a namespace for Keycloak resources with pod security labels:
apiVersion: v1
kind: Namespace
metadata:
name: keycloak
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/warn: restrictedApply the namespace:
kubectl apply -f namespace.yamlAlternatively, you can create the namespace using kubectl:
kubectl create namespace keycloak
kubectl label namespace keycloak pod-security.kubernetes.io/enforce=baseline pod-security.kubernetes.io/warn=restrictedStep 2: Create Database Credentials Secret
Create a Kubernetes Secret for the database user credentials. CloudNativePG will use this secret to set the password for the database user:
apiVersion: v1
kind: Secret
metadata:
name: keycloak-database-app
namespace: keycloak
type: Opaque
stringData:
username: keycloak
password: your-secure-passwordApply the secret:
kubectl apply -f db-credentials-secret.yamlSecure Password Management
Use a strong, unique password for the database user. Store the password in a Kubernetes Secret rather than hardcoding it. CloudNativePG will use this secret to set up the database user automatically.
Create a PostgreSQL cluster for Keycloak. This example creates a cluster with 2 instances for high availability:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: keycloak-database
namespace: keycloak
spec:
instances: 2
imageName: ghcr.io/cloudnative-pg/postgresql:16
primaryUpdateStrategy: unsupervised
postgresql:
parameters:
max_connections: "100"
bootstrap:
initdb:
database: keycloak
owner: keycloak
dataChecksums: true
secret:
name: keycloak-database-app
storage:
size: 5Gi
storageClass: tc-block
resources:
requests:
memory: "512Mi"
cpu: "50m"
limits:
memory: "1Gi"
cpu: "1000m"
monitoring:
enablePodMonitor: falseThe bootstrap.initdb section tells CloudNativePG to automatically create a database named keycloak with an owner keycloak, using the credentials from the secret. CloudNativePG will create the database and user during cluster initialization, so you don’t need to run SQL commands manually.
Save this to postgres-cluster.yaml and apply it:
kubectl apply -f postgres-cluster.yamlStep 4: Wait for Cluster to be Ready
Wait for the cluster to be ready:
kubectl wait --for=condition=Ready cluster/keycloak-database -n keycloak --timeout=300sCloudNativePG automatically creates the database and user during cluster initialization. The credentials are stored in the secret you created, and CloudNativePG uses them to set up the database owner.
Automatic Database and User Creation
CloudNativePG’s bootstrap configuration automatically creates the database and user specified in the bootstrap.initdb section. This eliminates the need to manually run SQL commands to create the database, user, and grant privileges. The database and user are ready to use once the cluster is ready.
Deploying Keycloak with FluxCD
Using FluxCD for Keycloak deployment provides GitOps-based management, allowing you to version control your configuration and automate deployments. This approach is recommended for production deployments as it provides better control, audit trails, and consistency.
Step 1: Create HelmRepository
Create a HelmRepository resource that tells FluxCD where to find the Keycloak Helm chart:
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: keycloakx
namespace: keycloak
spec:
type: oci
interval: 60m
url: oci://ghcr.io/codecentric/helm-chartsThis creates a HelmRepository that points to the Codecentric Helm charts repository, which contains the Keycloak chart. The interval specifies how often FluxCD should check for chart updates.
Save this to helm-repository.yaml and apply it, or commit it to your Git repository if you’re using FluxCD with Git:
kubectl apply -f helm-repository.yamlIf using FluxCD with Git, commit this file to your repository and FluxCD will automatically apply it.
Step 2: Create HelmRelease
Create a HelmRelease resource that defines how Keycloak should be deployed:
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: keycloakx
namespace: keycloak
spec:
releaseName: keycloakx
chart:
spec:
chart: keycloakx
version: 7.1.5
sourceRef:
kind: HelmRepository
name: keycloakx
namespace: keycloak
interval: 30m
values:
command:
- "/opt/keycloak/bin/kc.sh"
- "start"
- "--http-port=8080"
- "--hostname-strict=false"
replicas: 2
ingress:
enabled: false
database:
vendor: postgres
hostname: keycloak-database-rw
port: "5432"
username: keycloak
existingSecret: keycloak-database-app
existingSecretKey: password
proxy:
enabled: false
mode: edge
http:
relativePath: "/"
cache:
stack: jdbc-ping
serviceMonitor:
enabled: false
externalDatabase:
host: keycloak-database-rw
database: keycloak
port: "5432"
existingSecret: keycloak-database-app
existingSecretUserKey: username
existingSecretPasswordKey: password
proxyHeaders: "xforwarded"
extraEnv: |
- name: KC_BOOTSTRAP_ADMIN_USERNAME
value: admin
- name: KC_BOOTSTRAP_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: keycloak
key: admin-password
- name: KC_PROXY
value: edge
- name: KC_HTTP_ENABLED
value: "true"
- name: KC_HOSTNAME_STRICT
value: "false"
- name: KC_HOSTNAME_STRICT_HTTPS
value: "false"
- name: KC_PROXY_HEADERS
value: xforwarded
- name: KEYCLOAK_PRODUCTION
value: "false"
resources:
requests:
cpu: 20m
memory: 1536M
limits:
cpu: 4
memory: 1536MThis HelmRelease configures Keycloak with:
- 2 replicas for high availability
- PostgreSQL database connection using the CloudNativePG cluster
- Edge proxy mode for use behind a reverse proxy
- JDBC-Ping cache for clustering
- Resource limits and requests
Step 3: Create Admin Password Secret
Create a Secret for the Keycloak admin password:
apiVersion: v1
kind: Secret
metadata:
name: keycloak
namespace: keycloak
type: Opaque
stringData:
admin-password: your-secure-admin-passwordStep 4: Apply Resources
Apply the HelmRelease and secret:
kubectl apply -f helm-release.yaml
kubectl apply -f keycloak-secret.yamlIf using FluxCD with Git, commit these files to your repository and FluxCD will automatically apply them.
Step 5: Verify Deployment
Verify that Keycloak is deploying:
kubectl get helmrelease -n keycloak
kubectl get pods -n keycloakFluxCD will automatically install and manage the Keycloak Helm release based on your configuration. Wait for the pods to be in the Running state before proceeding.
Configuring Ingress and TLS
Keycloak needs to be accessible from outside the cluster. Configure ingress resources to expose Keycloak, and use Cert Manager to automatically provision TLS certificates.
Creating TLS Certificate
First, create a Certificate resource for TLS:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: login-ingress-tls
namespace: keycloak
spec:
secretName: login-ingress-tls
dnsNames:
- account.example.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuerReplace account.example.com with your actual domain name. Cert Manager will automatically create and manage the TLS certificate. For more information about Cert Manager, see the Cert Manager and Let’s Encrypt guide.
Creating Ingress Resources
Create ingress resources to expose Keycloak. This example creates two ingress resources: one for general access and one for the admin console with IP whitelisting:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: login-keycloak
namespace: keycloak
labels:
app.kubernetes.io/name: keycloak
app.kubernetes.io/component: app
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-buffer-size: "20k"
nginx.ingress.kubernetes.io/client-body-buffer-size: 1M
spec:
ingressClassName: nginx
rules:
- host: account.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: keycloakx-http
port:
name: http
tls:
- hosts:
- account.example.com
secretName: login-ingress-tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: login-admin
namespace: keycloak
labels:
app.kubernetes.io/name: keycloak
app.kubernetes.io/component: app
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: "<example-ip/32>"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-buffer-size: "20k"
nginx.ingress.kubernetes.io/client-body-buffer-size: 1M
spec:
ingressClassName: nginx
rules:
- host: account.example.com
http:
paths:
- path: /admin
pathType: Prefix
backend:
service:
name: keycloakx-http
port:
name: http
- path: /realms/master
pathType: Prefix
backend:
service:
name: keycloakx-http
port:
name: http
tls:
- hosts:
- account.example.com
secretName: login-ingress-tlsThe first ingress exposes Keycloak for general access. The second ingress exposes the admin console and master realm with IP whitelisting for additional security.
Admin Console Security
The admin console ingress includes IP whitelisting to restrict access to trusted IP addresses. Update the whitelist-source-range annotation with your trusted IP addresses. For production deployments, consider using additional security measures such as VPN access or network policies.
Apply the ingress resources:
kubectl apply -f ingress.yamlVerify that the ingress is configured correctly:
kubectl get ingress -n keycloakOnce Cert Manager has issued the certificate, you can access Keycloak at your configured domain.
Initial Setup
Once Keycloak is accessible, complete the initial setup through the web interface. Navigate to your configured domain in a web browser.
You can log in to the admin console using the credentials you configured:
- Username:
admin(or the value fromKC_BOOTSTRAP_ADMIN_USERNAME) - Password: The password from the
keycloaksecret
The admin console allows you to:
- Create realms for different applications or organizations
- Configure identity providers for social login
- Set up clients for OAuth2 and OpenID Connect
- Configure user federation
- Manage users and roles
First Login
On first login, Keycloak may prompt you to set up additional security features such as two-factor authentication for the admin account. This is recommended for production deployments.
Backup Configuration
Regular backups are essential for production Keycloak deployments. Cloud Native PostgreSQL handles database backups automatically when configured. For Keycloak file storage, implement a backup strategy.
Database Backups
Configure automated backups for the PostgreSQL cluster. See the Cloud Native PostgreSQL guide for detailed backup configuration, including automated backup schedules, retention policies, and restore procedures.
Configuration Backups
Keycloak configuration is stored in the database, so database backups include your Keycloak configuration. However, consider exporting realm configurations regularly for additional safety:
kubectl exec -it sts/keycloakx -n keycloak -- \
/opt/keycloak/bin/kc.sh export --dir /tmp/exportThis exports realm configurations that you can import later if needed.
Upgrading Keycloak
To upgrade Keycloak to a newer version, update the HelmRelease with the new chart version:
spec:
chart:
spec:
chart: keycloakx
version: 7.2.0 # Updated versionCommit the change to your Git repository, and FluxCD will automatically upgrade Keycloak. For more information about FluxCD upgrades, see the Installing FluxCD guide.
Backup Before Upgrades
Always create backups of both the database and configuration before upgrading Keycloak. This ensures you can roll back if the upgrade causes issues.
Conclusion
Deploying Keycloak on Thalassa Cloud Kubernetes using FluxCD and Cloud Native PostgreSQL provides a production-ready identity and access management platform. FluxCD provides GitOps-based deployment management, Cloud Native PostgreSQL provides reliable database management, and Thalassa Cloud’s infrastructure features ensure high performance and availability. By following this guide, you’ve set up Keycloak with persistent storage, high-availability database, GitOps-based deployment, and proper ingress configuration with TLS.
For more information about Keycloak features and configuration, see the official Keycloak documentation. For details about the Helm chart, see the Keycloak Helm chart repository.