Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
a2b5e37
keycloak deploying. API endpoints not working
Oct 6, 2025
8c0ca6c
startup script was deprecated. Add nebari-bot in python
Oct 6, 2025
29348f6
nebari deploying fully now. Auth not working for apps
Oct 6, 2025
ba57293
add openid scope to fix jhub keycloak
Oct 7, 2025
e2f142d
add openid to fix grafana
Oct 7, 2025
60976bd
updates for conda-store to access keycloak
Oct 7, 2025
954a0fd
add retry mechanism for nebari bot
Oct 9, 2025
7e74f58
remove force replacement that was used for dev
Oct 9, 2025
3c4e90d
add database configuration into values for keycloak
Oct 10, 2025
cede549
add standalone postgres because new keycloak doesn't bundle
Oct 11, 2025
04b7094
Release 2025.10.1: Major Keycloak upgrade with PostgreSQL migration
Oct 11, 2025
042c736
bump helm provider version, add standalone postgres
Oct 14, 2025
8f24426
add upgrade command leveraging python-kubernetes
Oct 14, 2025
a165286
use python kubernetes for keycloak backup instead of kubectl
Oct 15, 2025
e1264fa
add code to automatically restore database in post_deploy
Oct 25, 2025
a4c2416
update upgrade step version
Nov 3, 2025
2c56491
copy sql restore file as tar instead of standard in
Nov 3, 2025
c4c1ead
clean up unneeded notes and documentation
Nov 4, 2025
d3cf6e3
add templating for keycloak external URL
Nov 4, 2025
c394eb5
Clean up step naming in restore function
Nov 4, 2025
b434ffd
add random password for keycloak
Nov 4, 2025
12d9f27
comment out theme code, change metrics volume name back to "data"
Nov 4, 2025
092efad
remove unneeded clustering config
Nov 4, 2025
f92a639
refine upgrade script language
Nov 4, 2025
d75d8eb
add back required cache mechanism
Nov 4, 2025
5095098
[pre-commit.ci] Apply automatic pre-commit fixes
pre-commit-ci[bot] Nov 5, 2025
aca9fd2
corrections for precommit warnings
Nov 5, 2025
ce565c0
[pre-commit.ci] Apply automatic pre-commit fixes
pre-commit-ci[bot] Nov 5, 2025
ec1ab30
make firstname and lastname optional in keycloak
Nov 10, 2025
534322b
pre-commit edits for terraform fmt
Nov 10, 2025
364ac3a
add playwright test updates for new keycloak logout flow
Nov 10, 2025
d4350a7
update all keycloak providers in Nebari
Nov 12, 2025
a3d4f96
add context choices for upgrade step, sleep for keycloak restart
Nov 13, 2025
9b77ba9
update test_upgrade file for latest upgrade command
Nov 14, 2025
9828d4d
mock helm subprocess, only check for keycloak if version>2025.11.1
Nov 18, 2025
0494ee2
add proper scopes to forwardauth to fix dask gateway
Nov 19, 2025
8c26204
clean up upgrade notice
Nov 19, 2025
cd09090
add backup failure handling
Nov 26, 2025
ea07ef1
change stateful set to always be 1
Nov 26, 2025
04e22c1
mask postgres passwords in console output
Nov 26, 2025
d47364b
move imports to top of file
Nov 26, 2025
167b85e
add logic for finding postgres and keycloak podnames
Nov 26, 2025
dfb12dc
raise error on failure to get database password
Nov 26, 2025
2f58538
Merge branch 'main' into 2495_rebased
tylerpotts Nov 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
432 changes: 430 additions & 2 deletions src/_nebari/stages/kubernetes_keycloak/__init__.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
# Standalone PostgreSQL database for Keycloak
# Deployed separately to allow safe upgrade from keycloak to keycloakx chart
resource "helm_release" "keycloak_postgresql" {
name = "keycloak-postgres-standalone"
namespace = var.namespace
repository = "oci://registry-1.docker.io/bitnamicharts"
chart = "postgresql"
version = "18.0.15"

values = [
jsonencode({
primary = {
nodeSelector = {
"${var.node_group.key}" = var.node_group.value
}
}
auth = {
username = "keycloak"
# password is auto-generated by Helm chart and stored in secret
database = "keycloak"
}
})
]
}

resource "helm_release" "keycloak" {
name = "keycloak"
namespace = var.namespace

repository = "https://codecentric.github.io/helm-charts"
chart = "keycloak"
version = "15.0.2"
chart = "keycloakx"
version = "7.1.3"

depends_on = [
helm_release.keycloak_postgresql
]

values = concat([
# https://github.com/codecentric/helm-charts/blob/keycloak-15.0.2/charts/keycloak/values.yaml
Expand All @@ -13,22 +42,7 @@ resource "helm_release" "keycloak" {
nodeSelector = {
"${var.node_group.key}" = var.node_group.value
}
postgresql = {
# TODO: Remove hardcoded image values after Helm chart update
# This is a workaround due to bitnami charts deprecation
# See: https://github.com/bitnami/charts/issues/35164
# See: https://github.com/nebari-dev/nebari/issues/3120
image = {
registry = "docker.io"
repository = "bitnamilegacy/postgresql"
tag = "11.14.0"
}
primary = {
nodeSelector = {
"${var.node_group.key}" = var.node_group.value
}
}
}

customThemes = var.themes
})
], var.overrides)
Expand All @@ -43,6 +57,15 @@ resource "helm_release" "keycloak" {
value = var.initial_root_password
}

set {
name = "external_url"
value = var.external-url
}
}

# Track changes to values.yaml
resource "terraform_data" "values_hash" {
input = filesha256("${path.module}/values.yaml")
}


Expand All @@ -62,8 +85,7 @@ resource "kubernetes_manifest" "keycloak-http" {
match = "Host(`${var.external-url}`) && PathPrefix(`/auth`) "
services = [
{
name = "keycloak-headless"
# Really not sure why 8080 works here
name = "keycloak-keycloakx-http"
port = 80
namespace = var.namespace
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# https://github.com/codecentric/helm-charts/blob/keycloak-15.0.2/charts/keycloak/values.yaml
# Updated for keycloakx chart (Quarkus-based Keycloak)
# https://github.com/codecentric/helm-charts/tree/master/charts/keycloakx

ingress:
# Helm chart (14.0 anyway) will only define Ingress records, not IngressRoute as required by Traefik, so
# we will need to define our own IngressRoute elsewhere.
enabled: false

image:
Expand All @@ -10,50 +10,83 @@ image:
imagePullSecrets:
- name: "extcrcreds"

extraEnv: |
- name: PROXY_ADDRESS_FORWARDING
value: "true"
# Database configuration - connect to standalone PostgreSQL
# Points to the standalone PostgreSQL we migrated data to
database:
vendor: postgres
hostname: keycloak-postgres-standalone-postgresql
port: 5432
database: keycloak
username: keycloak
# Password is read from the auto-generated secret
existingSecret: keycloak-postgres-standalone-postgresql
existingSecretPasswordKey: password

# Enable database readiness check
dbchecker:
enabled: true

startupScripts:
keycloak.cli: |
{{- .Files.Get "scripts/keycloak.cli" | nindent 2 }}
# Command to start Keycloak (required for Quarkus-based Keycloak)
command:
- "/opt/keycloak/bin/kc.sh"

nebariadminuser.sh: |
/opt/jboss/keycloak/bin/add-user-keycloak.sh -r master -u root -p "{{ .Values.initial_root_password }}"
/opt/jboss/keycloak/bin/add-user-keycloak.sh -r master -u nebari-bot -p "{{ .Values.nebari_bot_password }}"
# Without this configured get the below error on startup:
# "Error while trying to create a channel using the specified configuration 'kubernetes'"
cache:
stack: jdbc-ping

mv-custom-themes.sh: |
#!/bin/sh
printf '=%.0s' {1..73}
echo "Start moving custom themes to /opt/jboss/keycloak/themes"
args:
- "start"

if [ -d /opt/data/custom-themes/themes ]; then
echo 'Copying custom themes from /opt/data/custom-themes/themes to /opt/jboss/keycloak/themes'
cp -r /opt/data/custom-themes/themes/* /opt/jboss/keycloak/themes/
else
echo 'No custom themes found in /opt/data/custom-themes'
fi
# HTTP configuration
http:
relativePath: "/auth"

echo "Finished moving custom themes"
printf '=%.0s' {1..73}
# Proxy configuration for Keycloak behind Traefik
proxy:
enabled: true
mode: edge

# Environment variables for Keycloak configuration
extraEnv: |
- name: KC_HOSTNAME
value: "{{ .Values.external_url }}"
- name: KC_HOSTNAME_PATH
value: "/auth"
- name: KC_HOSTNAME_STRICT
value: "false"
- name: KC_HOSTNAME_STRICT_HTTPS
value: "false"
- name: KC_HTTP_ENABLED
value: "true"
- name: KC_PROXY_HEADERS
value: "xforwarded"
- name: KEYCLOAK_ADMIN
value: "root"
- name: KEYCLOAK_ADMIN_PASSWORD
value: "{{ .Values.initial_root_password }}"
- name: KC_HEALTH_ENABLED
value: "true"
- name: KC_METRICS_ENABLED
value: "true"

extraInitContainers: |
- command:
- sh
- -c
- |
if [ ! -f /data/keycloak-metrics-spi-2.5.3.jar ]; then
wget https://github.com/aerogear/keycloak-metrics-spi/releases/download/2.5.3/keycloak-metrics-spi-2.5.3.jar -P /data/ &&
export SHA256SUM=9b3f52f842a66dadf5ff3cc3a729b8e49042d32f84510a5d73d41a2e39f29a96 &&
if ! (echo "$SHA256SUM /data/keycloak-metrics-spi-2.5.3.jar" | sha256sum -c)
if [ ! -f /data/keycloak-metrics-spi-7.0.0.jar ]; then
wget https://github.com/aerogear/keycloak-metrics-spi/releases/download/7.0.0/keycloak-metrics-spi-7.0.0.jar -P /data/ &&
export SHA256SUM=e7ec72ab1699e57a25b61cb5e3ef1c532ec9858ed6931c1b491d3368f5d007b8 &&
if ! (echo "$SHA256SUM /data/keycloak-metrics-spi-7.0.0.jar" | sha256sum -c)
then
echo "Error: Checksum not verified" && exit 1
else
chown 1000:1000 /data/keycloak-metrics-spi-2.5.3.jar &&
chmod 777 /data/keycloak-metrics-spi-2.5.3.jar
chown 1000:1000 /data/keycloak-metrics-spi-7.0.0.jar &&
chmod 644 /data/keycloak-metrics-spi-7.0.0.jar
fi
else
echo "File /data/keycloak-metrics-spi-2.5.3.jar already exists. Skipping download."
echo "File /data/keycloak-metrics-spi-7.0.0.jar already exists. Skipping download."
fi
image: busybox:1.36
name: initialize-spi-metrics-jar
Expand All @@ -62,44 +95,73 @@ extraInitContainers: |
volumeMounts:
- name: metrics-plugin
mountPath: /data
{{- if .Values.customThemes.enabled }}
- env:
- name: GIT_SYNC_REPO
value: {{ .Values.customThemes.repository }}
- name: GIT_SYNC_BRANCH
value: {{ .Values.customThemes.branch }}
- name: GIT_SYNC_ONE_TIME
value: "true"
- name: GIT_SYNC_GROUP_WRITE
value: "true"
- name: GIT_SYNC_ROOT
value: /opt/data/custom-themes
- name: GIT_SYNC_DEST
value: themes
- name: GIT_SYNC_SSH
value: "false"
image: k8s.gcr.io/git-sync:v3.1.5
imagePullPolicy: IfNotPresent
name: keycloak-git-sync
resources: {}
securityContext:
runAsGroup: 1000
runAsUser: 0
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt/data/custom-themes
name: custom-themes
{{- end }}
# Custom themes are not supported initially with v26 upgrade
# {{- if .Values.customThemes.enabled }}
# - env:
# - name: GIT_SYNC_REPO
# value: {{ .Values.customThemes.repository }}
# - name: GIT_SYNC_BRANCH
# value: {{ .Values.customThemes.branch }}
# - name: GIT_SYNC_ONE_TIME
# value: "true"
# - name: GIT_SYNC_GROUP_WRITE
# value: "true"
# - name: GIT_SYNC_ROOT
# value: /opt/data/custom-themes
# - name: GIT_SYNC_DEST
# value: themes
# - name: GIT_SYNC_SSH
# value: "false"
# image: registry.k8s.io/git-sync/git-sync:v4.3.0
# imagePullPolicy: IfNotPresent
# name: keycloak-git-sync
# resources: {}
# securityContext:
# runAsGroup: 1000
# runAsUser: 0
# terminationMessagePath: /dev/termination-log
# terminationMessagePolicy: File
# volumeMounts:
# - mountPath: /opt/data/custom-themes
# name: custom-themes
# - command:
# - sh
# - -c
# - |
# if [ -d /opt/data/custom-themes/themes ]; then
# echo 'Copying custom themes from /opt/data/custom-themes/themes to /themes'
# cp -r /opt/data/custom-themes/themes/* /themes/
# else
# echo 'No custom themes found in /opt/data/custom-themes'
# fi
# image: busybox:1.36
# name: move-custom-themes
# securityContext:
# runAsUser: 0
# volumeMounts:
# - mountPath: /opt/data/custom-themes
# name: custom-themes
# - mountPath: /themes
# name: theme-data
# {{- end }}

extraVolumeMounts: |
- name: metrics-plugin
mountPath: /opt/jboss/keycloak/providers/
- mountPath: /opt/data/custom-themes
name: custom-themes
mountPath: /opt/keycloak/providers/
# Custom themes are not supported initially with v26 upgrade
# {{- if .Values.customThemes.enabled }}
# - mountPath: /opt/keycloak/themes
# name: theme-data
# {{- end }}

extraVolumes: |
- name: metrics-plugin
emptyDir: {}
- name: custom-themes
emptyDir: {}

# Custom themes are not supported initially with v26 upgrade
# {{- if .Values.customThemes.enabled }}
# - name: custom-themes
# emptyDir: {}
# - name: theme-data
# emptyDir: {}
# {{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
helm = {
source = "hashicorp/helm"
version = "2.1.2"
version = "~> 2.16.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
Expand Down
Loading
Loading