apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "nextcloud-mcp-server.fullname" . }} labels: {{- include "nextcloud-mcp-server.labels" . | nindent 4 }} spec: strategy: type: Recreate {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }} selector: matchLabels: {{- include "nextcloud-mcp-server.selectorLabels" . | nindent 6 }} template: metadata: annotations: checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} labels: {{- include "nextcloud-mcp-server.labels" . | nindent 8 }} {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ include "nextcloud-mcp-server.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} {{- with .Values.initContainers }} initContainers: {{- toYaml . | nindent 8 }} {{- end }} containers: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ include "nextcloud-mcp-server.imageTag" . }}" imagePullPolicy: {{ .Values.image.pullPolicy }} args: - "--transport" - "{{ .Values.mcp.transport }}" {{- if eq .Values.auth.mode "oauth" }} - "--oauth" - "--oauth-token-type" - "{{ .Values.auth.oauth.tokenType }}" {{- end }} {{- with .Values.mcp.extraArgs }} {{- toYaml . | nindent 12 }} {{- end }} ports: - name: http containerPort: {{ include "nextcloud-mcp-server.port" . }} protocol: TCP {{- if .Values.observability.metrics.enabled }} - name: metrics containerPort: {{ .Values.observability.metrics.port }} protocol: TCP {{- end }} env: # Nextcloud connection - name: NEXTCLOUD_HOST value: {{ .Values.nextcloud.host | quote }} {{- if eq .Values.auth.mode "basic" }} # Basic auth mode (single-user) - name: NEXTCLOUD_USERNAME valueFrom: secretKeyRef: name: {{ include "nextcloud-mcp-server.basicAuthSecretName" . }} key: {{ .Values.auth.basic.usernameKey }} - name: NEXTCLOUD_PASSWORD valueFrom: 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 (replaces deprecated ENABLE_OFFLINE_ACCESS) - name: ENABLE_BACKGROUND_OPERATIONS 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 value: {{ include "nextcloud-mcp-server.mcpServerUrl" . | quote }} - name: NEXTCLOUD_PUBLIC_ISSUER_URL value: {{ include "nextcloud-mcp-server.publicIssuerUrl" . | quote }} - name: NEXTCLOUD_OIDC_SCOPES value: {{ .Values.auth.oauth.scopes | quote }} {{- if or .Values.auth.oauth.clientId .Values.auth.oauth.existingSecret }} - name: NEXTCLOUD_OIDC_CLIENT_ID valueFrom: secretKeyRef: name: {{ include "nextcloud-mcp-server.oauthSecretName" . }} key: {{ .Values.auth.oauth.clientIdKey }} - name: NEXTCLOUD_OIDC_CLIENT_SECRET valueFrom: secretKeyRef: name: {{ include "nextcloud-mcp-server.oauthSecretName" . }} key: {{ .Values.auth.oauth.clientSecretKey }} {{- end }} {{- end }} {{- if .Values.documentProcessing.enabled }} # Document processing - name: ENABLE_DOCUMENT_PROCESSING value: {{ .Values.documentProcessing.enabled | quote }} - name: DOCUMENT_PROCESSOR value: {{ .Values.documentProcessing.defaultProcessor | quote }} - name: PROGRESS_INTERVAL value: {{ .Values.documentProcessing.progressInterval | quote }} {{- if .Values.documentProcessing.unstructured.enabled }} - name: ENABLE_UNSTRUCTURED value: "true" - name: UNSTRUCTURED_API_URL value: {{ .Values.documentProcessing.unstructured.apiUrl | quote }} - name: UNSTRUCTURED_TIMEOUT value: {{ .Values.documentProcessing.unstructured.timeout | quote }} - name: UNSTRUCTURED_STRATEGY value: {{ .Values.documentProcessing.unstructured.strategy | quote }} - name: UNSTRUCTURED_LANGUAGES value: {{ .Values.documentProcessing.unstructured.languages | quote }} {{- end }} {{- if .Values.documentProcessing.tesseract.enabled }} - name: ENABLE_TESSERACT value: "true" {{- if .Values.documentProcessing.tesseract.cmd }} - name: TESSERACT_CMD value: {{ .Values.documentProcessing.tesseract.cmd | quote }} {{- end }} - name: TESSERACT_LANG value: {{ .Values.documentProcessing.tesseract.lang | quote }} {{- end }} {{- if .Values.documentProcessing.custom.enabled }} - name: ENABLE_CUSTOM_PROCESSOR value: "true" - name: CUSTOM_PROCESSOR_NAME value: {{ .Values.documentProcessing.custom.name | quote }} - name: CUSTOM_PROCESSOR_URL value: {{ .Values.documentProcessing.custom.url | quote }} {{- if .Values.documentProcessing.custom.apiKey }} - name: CUSTOM_PROCESSOR_API_KEY value: {{ .Values.documentProcessing.custom.apiKey | quote }} {{- end }} - name: CUSTOM_PROCESSOR_TIMEOUT value: {{ .Values.documentProcessing.custom.timeout | quote }} - name: CUSTOM_PROCESSOR_TYPES value: {{ .Values.documentProcessing.custom.types | quote }} {{- end }} {{- end }} # Semantic Search (replaces deprecated VECTOR_SYNC_ENABLED) - name: ENABLE_SEMANTIC_SEARCH value: {{ .Values.semanticSearch.enabled | quote }} {{- if .Values.semanticSearch.enabled }} - name: VECTOR_SYNC_SCAN_INTERVAL value: {{ .Values.semanticSearch.scanInterval | quote }} - name: VECTOR_SYNC_PROCESSOR_WORKERS value: {{ .Values.semanticSearch.processorWorkers | quote }} - name: VECTOR_SYNC_QUEUE_MAX_SIZE value: {{ .Values.semanticSearch.queueMaxSize | quote }} {{- end }} # Document Chunking (always set, used by vector sync processor) - name: DOCUMENT_CHUNK_SIZE value: {{ .Values.documentChunking.chunkSize | quote }} - name: DOCUMENT_CHUNK_OVERLAP value: {{ .Values.documentChunking.chunkOverlap | quote }} # Qdrant Vector Database {{- if eq .Values.qdrant.mode "network" }} # Network mode: Use dedicated Qdrant service {{- if .Values.qdrant.networkMode.deploySubchart }} - name: QDRANT_URL value: "http://{{ .Release.Name }}-qdrant:6333" {{- else if .Values.qdrant.networkMode.externalUrl }} - name: QDRANT_URL value: {{ .Values.qdrant.networkMode.externalUrl | quote }} {{- end }} {{- if or .Values.qdrant.networkMode.apiKey .Values.qdrant.networkMode.existingSecret }} - name: QDRANT_API_KEY valueFrom: secretKeyRef: name: {{ .Values.qdrant.networkMode.existingSecret | default (printf "%s-qdrant" .Release.Name) }} key: {{ .Values.qdrant.networkMode.secretKey }} {{- end }} {{- else if eq .Values.qdrant.mode "persistent" }} # Persistent local mode: File-based storage - name: QDRANT_LOCATION value: {{ .Values.qdrant.localPersistence.dataPath | quote }} {{- else }} # In-memory mode (default): Ephemeral storage - name: QDRANT_LOCATION value: ":memory:" {{- end }} - name: QDRANT_COLLECTION value: {{ .Values.qdrant.collection | quote }} # Ollama Embedding Service {{- if or .Values.ollama.enabled .Values.ollama.url }} - name: OLLAMA_BASE_URL value: {{ .Values.ollama.url | default (printf "http://%s-ollama:11434" .Release.Name) | quote }} - name: OLLAMA_EMBEDDING_MODEL value: {{ .Values.ollama.embeddingModel | quote }} - name: OLLAMA_VERIFY_SSL value: {{ .Values.ollama.verifySsl | quote }} {{- end }} # OpenAI Embedding Provider (alternative to Ollama) {{- if .Values.openai.enabled }} - name: OPENAI_API_KEY valueFrom: secretKeyRef: name: {{ .Values.openai.existingSecret | default (printf "%s-openai" (include "nextcloud-mcp-server.fullname" .)) }} key: {{ .Values.openai.secretKey }} {{- if .Values.openai.baseUrl }} - name: OPENAI_BASE_URL value: {{ .Values.openai.baseUrl | quote }} {{- end }} {{- end }} # Observability - name: METRICS_ENABLED value: {{ .Values.observability.metrics.enabled | quote }} - name: METRICS_PORT value: {{ .Values.observability.metrics.port | quote }} {{- if .Values.observability.tracing.enabled }} - name: OTEL_EXPORTER_OTLP_ENDPOINT value: {{ .Values.observability.tracing.endpoint | quote }} - name: OTEL_SERVICE_NAME value: {{ .Values.observability.tracing.serviceName | quote }} - name: OTEL_TRACES_SAMPLER_ARG value: {{ .Values.observability.tracing.samplingRate | quote }} {{- end }} - name: LOG_FORMAT value: {{ .Values.observability.logging.format | quote }} - name: LOG_LEVEL value: {{ .Values.observability.logging.level | quote }} - name: LOG_INCLUDE_TRACE_CONTEXT value: {{ .Values.observability.logging.includeTraceContext | quote }} {{- with .Values.extraEnv }} {{- toYaml . | nindent 12 }} {{- end }} {{- with .Values.extraEnvFrom }} envFrom: {{- toYaml . | nindent 12 }} {{- end }} livenessProbe: {{- toYaml .Values.livenessProbe | nindent 12 }} readinessProbe: {{- toYaml .Values.readinessProbe | nindent 12 }} resources: {{- toYaml .Values.resources | nindent 12 }} volumeMounts: - name: tmp mountPath: /tmp {{- if and (eq .Values.auth.mode "oauth") .Values.auth.oauth.persistence.enabled }} - 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 {{- end }} {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} volumes: - name: tmp emptyDir: {} {{- if and (eq .Values.auth.mode "oauth") .Values.auth.oauth.persistence.enabled }} - name: oauth-storage 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: claimName: {{ include "nextcloud-mcp-server.qdrantPvcName" . }} {{- end }} {{- with .Values.volumes }} {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} {{- end }}