feat(helm): add support for multi-user BasicAuth mode

Adds multi-user-basic authentication mode to the helm chart alongside
existing basic (single-user) and oauth modes.

Multi-user BasicAuth mode enables:
- Pass-through authentication (credentials in request headers)
- Optional background operations using app passwords via Astrolabe
- Optional OAuth client credentials (uses DCR if not provided)
- Token encryption and persistent storage for background sync

Changes:
- values.yaml: Add auth.multiUserBasic configuration section
- deployment.yaml: Add ENABLE_MULTI_USER_BASIC_AUTH and related env vars
- secret.yaml: Add secret template for token encryption key and OAuth credentials
- pvc.yaml: Add PVC template for token database persistence
- _helpers.tpl: Add helper functions for secret/PVC names

Tested with:
  helm template --set auth.mode=multi-user-basic \
    --set auth.multiUserBasic.enableOfflineAccess=true \
    --set auth.multiUserBasic.tokenEncryptionKey=... \
    --set vectorSync.enabled=true

Related: Multi-user deployment support (ADR-020)
This commit is contained in:
Chris Coutinho
2025-12-22 21:03:10 +01:00
parent e49dc2bfc4
commit 04140d671e
5 changed files with 149 additions and 5 deletions
@@ -72,6 +72,28 @@ Create the name of the secret to use for basic auth
{{- end }}
{{- end }}
{{/*
Create the name of the secret to use for multi-user basic auth
*/}}
{{- define "nextcloud-mcp-server.multiUserBasicSecretName" -}}
{{- if .Values.auth.multiUserBasic.existingSecret }}
{{- .Values.auth.multiUserBasic.existingSecret }}
{{- else }}
{{- include "nextcloud-mcp-server.fullname" . }}-multi-user-basic
{{- end }}
{{- end }}
{{/*
Create the name of the PVC to use for multi-user basic token storage
*/}}
{{- define "nextcloud-mcp-server.multiUserBasicPvcName" -}}
{{- if .Values.auth.multiUserBasic.persistence.existingClaim }}
{{- .Values.auth.multiUserBasic.persistence.existingClaim }}
{{- else }}
{{- include "nextcloud-mcp-server.fullname" . }}-token-storage
{{- end }}
{{- end }}
{{/*
Create the name of the secret to use for OAuth
*/}}
@@ -68,7 +68,7 @@ spec:
- name: NEXTCLOUD_HOST
value: {{ .Values.nextcloud.host | quote }}
{{- if eq .Values.auth.mode "basic" }}
# Basic auth mode
# Basic auth mode (single-user)
- name: NEXTCLOUD_USERNAME
valueFrom:
secretKeyRef:
@@ -79,6 +79,41 @@ spec:
secretKeyRef:
name: {{ include "nextcloud-mcp-server.basicAuthSecretName" . }}
key: {{ .Values.auth.basic.passwordKey }}
{{- else if eq .Values.auth.mode "multi-user-basic" }}
# Multi-user BasicAuth mode (pass-through)
- name: ENABLE_MULTI_USER_BASIC_AUTH
value: "true"
- name: NEXTCLOUD_MCP_SERVER_URL
value: {{ include "nextcloud-mcp-server.mcpServerUrl" . | quote }}
- name: NEXTCLOUD_PUBLIC_ISSUER_URL
value: {{ include "nextcloud-mcp-server.publicIssuerUrl" . | quote }}
{{- if .Values.auth.multiUserBasic.enableOfflineAccess }}
# Background operations with app passwords
- name: ENABLE_OFFLINE_ACCESS
value: "true"
- name: TOKEN_STORAGE_DB
value: {{ .Values.auth.multiUserBasic.tokenStorageDb | quote }}
- name: TOKEN_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: {{ include "nextcloud-mcp-server.multiUserBasicSecretName" . }}
key: {{ .Values.auth.multiUserBasic.tokenEncryptionKeyKey }}
- name: NEXTCLOUD_OIDC_SCOPES
value: {{ .Values.auth.multiUserBasic.scopes | quote }}
{{- if or .Values.auth.multiUserBasic.clientId .Values.auth.multiUserBasic.existingSecret }}
# Static OAuth credentials (optional - uses DCR if not provided)
- name: NEXTCLOUD_OIDC_CLIENT_ID
valueFrom:
secretKeyRef:
name: {{ include "nextcloud-mcp-server.multiUserBasicSecretName" . }}
key: {{ .Values.auth.multiUserBasic.clientIdKey }}
- name: NEXTCLOUD_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ include "nextcloud-mcp-server.multiUserBasicSecretName" . }}
key: {{ .Values.auth.multiUserBasic.clientSecretKey }}
{{- end }}
{{- end }}
{{- else if eq .Values.auth.mode "oauth" }}
# OAuth mode
- name: NEXTCLOUD_MCP_SERVER_URL
@@ -251,6 +286,10 @@ spec:
- name: oauth-storage
mountPath: /app/.oauth
{{- end }}
{{- if and (eq .Values.auth.mode "multi-user-basic") .Values.auth.multiUserBasic.enableOfflineAccess .Values.auth.multiUserBasic.persistence.enabled }}
- name: token-storage
mountPath: /app/data
{{- end }}
{{- if and (eq .Values.qdrant.mode "persistent") .Values.qdrant.localPersistence.enabled }}
- name: qdrant-data
mountPath: /app/data
@@ -266,6 +305,11 @@ spec:
persistentVolumeClaim:
claimName: {{ include "nextcloud-mcp-server.oauthPvcName" . }}
{{- end }}
{{- if and (eq .Values.auth.mode "multi-user-basic") .Values.auth.multiUserBasic.enableOfflineAccess .Values.auth.multiUserBasic.persistence.enabled }}
- name: token-storage
persistentVolumeClaim:
claimName: {{ include "nextcloud-mcp-server.multiUserBasicPvcName" . }}
{{- end }}
{{- if and (eq .Values.qdrant.mode "persistent") .Values.qdrant.localPersistence.enabled }}
- name: qdrant-data
persistentVolumeClaim:
@@ -16,6 +16,24 @@ spec:
storage: {{ .Values.auth.oauth.persistence.size }}
{{- end }}
---
{{- if and (eq .Values.auth.mode "multi-user-basic") .Values.auth.multiUserBasic.enableOfflineAccess .Values.auth.multiUserBasic.persistence.enabled (not .Values.auth.multiUserBasic.persistence.existingClaim) }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "nextcloud-mcp-server.fullname" . }}-token-storage
labels:
{{- include "nextcloud-mcp-server.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.auth.multiUserBasic.persistence.accessMode }}
{{- if .Values.auth.multiUserBasic.persistence.storageClass }}
storageClassName: {{ .Values.auth.multiUserBasic.persistence.storageClass }}
{{- end }}
resources:
requests:
storage: {{ .Values.auth.multiUserBasic.persistence.size }}
{{- end }}
---
{{- if and (eq .Values.qdrant.mode "persistent") .Values.qdrant.localPersistence.enabled (not .Values.qdrant.localPersistence.existingClaim) }}
apiVersion: v1
kind: PersistentVolumeClaim
@@ -13,6 +13,24 @@ data:
{{- end }}
{{- end }}
---
{{- if eq .Values.auth.mode "multi-user-basic" }}
{{- if and .Values.auth.multiUserBasic.enableOfflineAccess (not .Values.auth.multiUserBasic.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "nextcloud-mcp-server.fullname" . }}-multi-user-basic
labels:
{{- include "nextcloud-mcp-server.labels" . | nindent 4 }}
type: Opaque
data:
{{ .Values.auth.multiUserBasic.tokenEncryptionKeyKey }}: {{ .Values.auth.multiUserBasic.tokenEncryptionKey | b64enc | quote }}
{{- if .Values.auth.multiUserBasic.clientId }}
{{ .Values.auth.multiUserBasic.clientIdKey }}: {{ .Values.auth.multiUserBasic.clientId | b64enc | quote }}
{{ .Values.auth.multiUserBasic.clientSecretKey }}: {{ .Values.auth.multiUserBasic.clientSecret | b64enc | quote }}
{{- end }}
{{- end }}
{{- end }}
---
{{- if eq .Values.auth.mode "oauth" }}
{{- if and .Values.auth.oauth.clientId (not .Values.auth.oauth.existingSecret) }}
apiVersion: v1