From 51a265d026060579fb91fef3b00c9495fa9afb56 Mon Sep 17 00:00:00 2001 From: cmdoret Date: Wed, 12 Aug 2026 16:26:46 +0200 Subject: [PATCH 1/9] doc(postgres): external secrets usage --- docs/postgresql.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/postgresql.md b/docs/postgresql.md index a1f6eb0..e173a25 100644 --- a/docs/postgresql.md +++ b/docs/postgresql.md @@ -39,6 +39,38 @@ it is safe to re-run: existing roles and databases are left untouched. The postgres values must be specified for `authentik` and `openwebui`. They may use the same server, but should have different roles and databases. +## Passwords + +The openwebui postgres password is read from Kubernetes `Secret` resources. +Simply specify the resource name: + +```yaml +openwebui: + postgres: + passwordSecret: + name: vllm-openwebui-pg +``` + +For the Authentik subchart to also use an external secret, the password must be injected via `global.env`, which covers server and worker at +once: + +```yaml +authentik: + authentik: + postgresql: + password: # unset on purpose, supplied below + global: + env: + - name: AUTHENTIK_POSTGRESQL__PASSWORD + valueFrom: + secretKeyRef: { name: vllm-authentik-pg, key: password } +``` + +> [!IMPORTANT] +> +> Use alphanumeric passwords. OpenWebUI's is interpolated into a connection URI in the pod, +> where nothing percent-encodes it, so `@ : / ? # %` would corrupt the DSN. + ## Sharing a server between releases The names default to `vllm-openwebui` and `vllm-authentik`, if multiple From dcc8e890d899d2adf11f1f0db337324e1d19ce73 Mon Sep 17 00:00:00 2001 From: cmdoret Date: Wed, 12 Aug 2026 16:27:20 +0200 Subject: [PATCH 2/9] feat(postgres): external secret for postgres password in default values --- tools/helm/lint-values.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/helm/lint-values.yaml b/tools/helm/lint-values.yaml index 6f3f8ed..cd22008 100644 --- a/tools/helm/lint-values.yaml +++ b/tools/helm/lint-values.yaml @@ -14,7 +14,8 @@ openwebui: password: dummy postgres: host: pg.example.invalid - password: dummy + passwordSecret: + name: dummy-pg models: lint: &model fullName: org/lint-model From 3ccebef3a7cc903e267cc9cbe558a5181e8aa661 Mon Sep 17 00:00:00 2001 From: cmdoret Date: Wed, 12 Aug 2026 16:34:23 +0200 Subject: [PATCH 3/9] refactor(openwebui): postgres credentials from existing secret --- templates/openwebui/deployment.yaml | 13 ++++++++++--- templates/postgres_secret.yaml | 18 ------------------ 2 files changed, 10 insertions(+), 21 deletions(-) delete mode 100644 templates/postgres_secret.yaml diff --git a/templates/openwebui/deployment.yaml b/templates/openwebui/deployment.yaml index a2fc638..354580a 100644 --- a/templates/openwebui/deployment.yaml +++ b/templates/openwebui/deployment.yaml @@ -34,11 +34,18 @@ spec: value: "true" - name: OPENAI_API_BASE_URL value: https://gateway.{{ .Values.envoy.baseDomain }}/v1 - - name: DATABASE_URL + {{- $pg := .Values.openwebui.postgres }} + {{- $ps := $pg.passwordSecret }} + {{- /* Must precede DATABASE_URL: $(VAR) only expands earlier entries. */}} + - name: PG_PASSWORD valueFrom: secretKeyRef: - name: {{ include "openwebui.fullname" . }}-postgres - key: OPENWEBUI_DATABASE_URL + name: {{ $ps.name | required ".Values.openwebui.postgres.passwordSecret.name is required" }} + key: {{ $ps.key }} + {{- $db := $pg.database | required ".Values.openwebui.postgres.database is required" }} + {{- /* One value fills both db and role. */}} + - name: DATABASE_URL + value: "postgresql://{{ $db }}:$(PG_PASSWORD)@{{ $pg.host | required ".Values.openwebui.postgres.host is required" }}:5432/{{ $db }}?sslmode=require" - name: ENABLE_OAUTH_SIGNUP value: "true" - name: ENABLE_LOGIN_FORM diff --git a/templates/postgres_secret.yaml b/templates/postgres_secret.yaml deleted file mode 100644 index 219fc6c..0000000 --- a/templates/postgres_secret.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.authentik.enabled }} - {{- /* The subchart defaults this to "-postgresql", which will not resolve. */}} - {{- $_ := .Values.authentik.authentik.postgresql.host | required ".Values.authentik.authentik.postgresql.host is required: the chart does not deploy PostgreSQL" }} -{{- end }} -{{- if .Values.openwebui.enabled }} -apiVersion: v1 -kind: Secret -metadata: - name: "{{ include "openwebui.fullname" . }}-postgres" -type: Opaque - {{- $pg := .Values.openwebui.postgres }} - {{- /* One value fills both db and role. */}} - {{- $db := $pg.database | required ".Values.openwebui.postgres.database is required" }} - {{- $host := $pg.host | required ".Values.openwebui.postgres.host is required" }} - {{- $password := $pg.password | required ".Values.openwebui.postgres.password is required" }} -stringData: - OPENWEBUI_DATABASE_URL: "postgresql://{{ $db }}:{{ $password }}@{{ $host }}:5432/{{ $db }}?sslmode={{ $pg.sslMode }}" -{{- end }} From 34b067f69636c841dae60ba15a81fb17573ace25 Mon Sep 17 00:00:00 2001 From: cmdoret Date: Wed, 12 Aug 2026 16:54:15 +0200 Subject: [PATCH 4/9] refactor(postgres): hardcode secret key `password` --- docs/postgresql.md | 4 ++-- templates/authentik_validate.yaml | 5 +++++ templates/openwebui/deployment.yaml | 7 +++---- 3 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 templates/authentik_validate.yaml diff --git a/docs/postgresql.md b/docs/postgresql.md index e173a25..169603b 100644 --- a/docs/postgresql.md +++ b/docs/postgresql.md @@ -41,8 +41,8 @@ server, but should have different roles and databases. ## Passwords -The openwebui postgres password is read from Kubernetes `Secret` resources. -Simply specify the resource name: +The openwebui postgres password is read from a Kubernetes `Secret`, under the key `password`. +The chart does not create it. Simply specify the resource name: ```yaml openwebui: diff --git a/templates/authentik_validate.yaml b/templates/authentik_validate.yaml new file mode 100644 index 0000000..1170d08 --- /dev/null +++ b/templates/authentik_validate.yaml @@ -0,0 +1,5 @@ +{{- /* Renders nothing. Guards a subchart value the parent has no template of its own for. */}} +{{- if .Values.authentik.enabled }} + {{- /* The subchart defaults this to "-postgresql", which will not resolve. */}} + {{- $_ := .Values.authentik.authentik.postgresql.host | required ".Values.authentik.authentik.postgresql.host is required: the chart does not deploy PostgreSQL" }} +{{- end }} diff --git a/templates/openwebui/deployment.yaml b/templates/openwebui/deployment.yaml index 354580a..9af5762 100644 --- a/templates/openwebui/deployment.yaml +++ b/templates/openwebui/deployment.yaml @@ -35,14 +35,13 @@ spec: - name: OPENAI_API_BASE_URL value: https://gateway.{{ .Values.envoy.baseDomain }}/v1 {{- $pg := .Values.openwebui.postgres }} - {{- $ps := $pg.passwordSecret }} {{- /* Must precede DATABASE_URL: $(VAR) only expands earlier entries. */}} - name: PG_PASSWORD valueFrom: secretKeyRef: - name: {{ $ps.name | required ".Values.openwebui.postgres.passwordSecret.name is required" }} - key: {{ $ps.key }} - {{- $db := $pg.database | required ".Values.openwebui.postgres.database is required" }} + name: {{ $pg.passwordSecret.name | required ".Values.openwebui.postgres.passwordSecret.name is required" }} + key: password + {{- $db := $pg.database }} {{- /* One value fills both db and role. */}} - name: DATABASE_URL value: "postgresql://{{ $db }}:$(PG_PASSWORD)@{{ $pg.host | required ".Values.openwebui.postgres.host is required" }}:5432/{{ $db }}?sslmode=require" From c6b738f3b4c32919598ee3d1217fc396119ff74c Mon Sep 17 00:00:00 2001 From: cmdoret Date: Wed, 12 Aug 2026 17:20:08 +0200 Subject: [PATCH 5/9] chore: move guard to NOTES.txt --- templates/NOTES.txt | 6 ++++++ templates/authentik_validate.yaml | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) delete mode 100644 templates/authentik_validate.yaml diff --git a/templates/NOTES.txt b/templates/NOTES.txt index 128a5ac..7106f0c 100644 --- a/templates/NOTES.txt +++ b/templates/NOTES.txt @@ -2,3 +2,9 @@ VLLM Gateway and models have been successfully deployed on your cluster. You can access the gateway at https://gateway.{{ .Values.envoy.baseDomain }}/v1/chat/completions You can access Open-WebUI at https://openwebui.{{ .Values.envoy.baseDomain }}/ +{{- /* The subchart defaults it to "-postgresql", a plausible name that resolves +to nothing, so an omission would otherwise surface as an authentik CrashLoopBackOff. +*/}} +{{- if .Values.authentik.enabled }} + {{- $_ := .Values.authentik.authentik.postgresql.host | required ".Values.authentik.authentik.postgresql.host is required: the chart does not deploy PostgreSQL" }} +{{- end }} diff --git a/templates/authentik_validate.yaml b/templates/authentik_validate.yaml deleted file mode 100644 index 1170d08..0000000 --- a/templates/authentik_validate.yaml +++ /dev/null @@ -1,5 +0,0 @@ -{{- /* Renders nothing. Guards a subchart value the parent has no template of its own for. */}} -{{- if .Values.authentik.enabled }} - {{- /* The subchart defaults this to "-postgresql", which will not resolve. */}} - {{- $_ := .Values.authentik.authentik.postgresql.host | required ".Values.authentik.authentik.postgresql.host is required: the chart does not deploy PostgreSQL" }} -{{- end }} From cdd78ba077013549c1b1b6b4d4495bc10d2697f1 Mon Sep 17 00:00:00 2001 From: cmdoret Date: Wed, 12 Aug 2026 17:21:16 +0200 Subject: [PATCH 6/9] fix(openwebui): panic on null --- templates/openwebui/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/openwebui/deployment.yaml b/templates/openwebui/deployment.yaml index 9af5762..889d841 100644 --- a/templates/openwebui/deployment.yaml +++ b/templates/openwebui/deployment.yaml @@ -39,7 +39,7 @@ spec: - name: PG_PASSWORD valueFrom: secretKeyRef: - name: {{ $pg.passwordSecret.name | required ".Values.openwebui.postgres.passwordSecret.name is required" }} + name: {{ (default dict $pg.passwordSecret).name | required ".Values.openwebui.postgres.passwordSecret.name is required" }} key: password {{- $db := $pg.database }} {{- /* One value fills both db and role. */}} From 773dbe4c6ba6eb804b5f8ca27de23e5b33e4b850 Mon Sep 17 00:00:00 2001 From: cmdoret Date: Thu, 13 Aug 2026 11:17:28 +0200 Subject: [PATCH 7/9] fix: update default values to use existing secret --- values.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/values.yaml b/values.yaml index 7644f0f..d891bf3 100644 --- a/values.yaml +++ b/values.yaml @@ -62,7 +62,9 @@ openwebui: database: vllm-openwebui # "disable" puts every query on the wire in cleartext. sslMode: require - password: + # Existing secret holding the role's password under the key "password". + passwordSecret: + name: admin: user: admin email: admin@sdsc.ethz.ch From 46e92d0921eca8402b27aae7c984bcddb0785acc Mon Sep 17 00:00:00 2001 From: cmdoret Date: Thu, 13 Aug 2026 11:17:52 +0200 Subject: [PATCH 8/9] fix(openwebui): restore sslmode templating --- templates/openwebui/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/openwebui/deployment.yaml b/templates/openwebui/deployment.yaml index 889d841..2f8b369 100644 --- a/templates/openwebui/deployment.yaml +++ b/templates/openwebui/deployment.yaml @@ -44,7 +44,7 @@ spec: {{- $db := $pg.database }} {{- /* One value fills both db and role. */}} - name: DATABASE_URL - value: "postgresql://{{ $db }}:$(PG_PASSWORD)@{{ $pg.host | required ".Values.openwebui.postgres.host is required" }}:5432/{{ $db }}?sslmode=require" + value: "postgresql://{{ $db }}:$(PG_PASSWORD)@{{ $pg.host | required ".Values.openwebui.postgres.host is required" }}:5432/{{ $db }}?sslmode={{ $pg.sslMode }}" - name: ENABLE_OAUTH_SIGNUP value: "true" - name: ENABLE_LOGIN_FORM From b6579f877e932c5d873ece4914a750ad8c95c446 Mon Sep 17 00:00:00 2001 From: cmdoret Date: Thu, 13 Aug 2026 11:24:36 +0200 Subject: [PATCH 9/9] fix: add required guards for db --- templates/openwebui/deployment.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/templates/openwebui/deployment.yaml b/templates/openwebui/deployment.yaml index 2f8b369..f472915 100644 --- a/templates/openwebui/deployment.yaml +++ b/templates/openwebui/deployment.yaml @@ -41,10 +41,12 @@ spec: secretKeyRef: name: {{ (default dict $pg.passwordSecret).name | required ".Values.openwebui.postgres.passwordSecret.name is required" }} key: password - {{- $db := $pg.database }} - {{- /* One value fills both db and role. */}} + {{- /* One value fills both db and role. Guarded: an explicit null or "" deletes the + chart default, and an unset part of a DSN fails at connect time, not render time. */}} + {{- $db := $pg.database | required ".Values.openwebui.postgres.database is required" }} + {{- $ssl := $pg.sslMode | required ".Values.openwebui.postgres.sslMode is required" }} - name: DATABASE_URL - value: "postgresql://{{ $db }}:$(PG_PASSWORD)@{{ $pg.host | required ".Values.openwebui.postgres.host is required" }}:5432/{{ $db }}?sslmode={{ $pg.sslMode }}" + value: "postgresql://{{ $db }}:$(PG_PASSWORD)@{{ $pg.host | required ".Values.openwebui.postgres.host is required" }}:5432/{{ $db }}?sslmode={{ $ssl }}" - name: ENABLE_OAUTH_SIGNUP value: "true" - name: ENABLE_LOGIN_FORM