From ca5c681f5b30a9a8bb5936216b643b4eb3e7a73d Mon Sep 17 00:00:00 2001 From: phact Date: Tue, 9 Dec 2025 23:35:05 -0500 Subject: [PATCH] v0 --- helm/openrag/Chart.yaml | 18 + helm/openrag/templates/NOTES.txt | 80 ++++ helm/openrag/templates/_helpers.tpl | 163 +++++++ .../openrag/templates/backend/deployment.yaml | 273 ++++++++++++ helm/openrag/templates/backend/service.yaml | 18 + .../configmaps/app-config-configmap.yaml | 39 ++ .../configmaps/flow-ids-configmap.yaml | 14 + .../templates/dashboards/deployment.yaml | 81 ++++ .../openrag/templates/dashboards/service.yaml | 18 + .../templates/frontend/deployment.yaml | 80 ++++ helm/openrag/templates/frontend/hpa.yaml | 33 ++ helm/openrag/templates/frontend/service.yaml | 18 + helm/openrag/templates/ingress/ingress.yaml | 104 +++++ .../templates/langflow/deployment.yaml | 211 +++++++++ helm/openrag/templates/langflow/service.yaml | 18 + .../openrag/templates/secrets/aws-secret.yaml | 13 + .../templates/secrets/langflow-secret.yaml | 14 + .../secrets/llm-providers-secret.yaml | 22 + .../templates/secrets/oauth-secret.yaml | 19 + .../templates/secrets/opensearch-secret.yaml | 13 + helm/openrag/templates/serviceaccount.yaml | 13 + .../openrag/templates/storage/config-pvc.yaml | 18 + .../templates/storage/documents-pvc.yaml | 18 + helm/openrag/templates/storage/keys-pvc.yaml | 18 + .../templates/storage/langflow-pvc.yaml | 18 + helm/openrag/values.yaml | 407 ++++++++++++++++++ 26 files changed, 1741 insertions(+) create mode 100644 helm/openrag/Chart.yaml create mode 100644 helm/openrag/templates/NOTES.txt create mode 100644 helm/openrag/templates/_helpers.tpl create mode 100644 helm/openrag/templates/backend/deployment.yaml create mode 100644 helm/openrag/templates/backend/service.yaml create mode 100644 helm/openrag/templates/configmaps/app-config-configmap.yaml create mode 100644 helm/openrag/templates/configmaps/flow-ids-configmap.yaml create mode 100644 helm/openrag/templates/dashboards/deployment.yaml create mode 100644 helm/openrag/templates/dashboards/service.yaml create mode 100644 helm/openrag/templates/frontend/deployment.yaml create mode 100644 helm/openrag/templates/frontend/hpa.yaml create mode 100644 helm/openrag/templates/frontend/service.yaml create mode 100644 helm/openrag/templates/ingress/ingress.yaml create mode 100644 helm/openrag/templates/langflow/deployment.yaml create mode 100644 helm/openrag/templates/langflow/service.yaml create mode 100644 helm/openrag/templates/secrets/aws-secret.yaml create mode 100644 helm/openrag/templates/secrets/langflow-secret.yaml create mode 100644 helm/openrag/templates/secrets/llm-providers-secret.yaml create mode 100644 helm/openrag/templates/secrets/oauth-secret.yaml create mode 100644 helm/openrag/templates/secrets/opensearch-secret.yaml create mode 100644 helm/openrag/templates/serviceaccount.yaml create mode 100644 helm/openrag/templates/storage/config-pvc.yaml create mode 100644 helm/openrag/templates/storage/documents-pvc.yaml create mode 100644 helm/openrag/templates/storage/keys-pvc.yaml create mode 100644 helm/openrag/templates/storage/langflow-pvc.yaml create mode 100644 helm/openrag/values.yaml diff --git a/helm/openrag/Chart.yaml b/helm/openrag/Chart.yaml new file mode 100644 index 00000000..ac9d0df3 --- /dev/null +++ b/helm/openrag/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: openrag +description: A Helm chart for deploying OpenRAG - an open-source agentic RAG platform +type: application +version: 0.1.0 +appVersion: "0.1.52" +keywords: + - openrag + - rag + - langflow + - opensearch + - ai + - llm +home: https://github.com/langflow-ai/openrag +sources: + - https://github.com/langflow-ai/openrag +maintainers: + - name: OpenRAG Team diff --git a/helm/openrag/templates/NOTES.txt b/helm/openrag/templates/NOTES.txt new file mode 100644 index 00000000..932754ba --- /dev/null +++ b/helm/openrag/templates/NOTES.txt @@ -0,0 +1,80 @@ +OpenRAG has been deployed successfully! + +{{- if .Values.global.tenant.name }} +Tenant: {{ .Values.global.tenant.name }} +Namespace: {{ include "openrag.namespace" . }} +{{- end }} + +=== Services Deployed === + +{{- if .Values.langflow.enabled }} +Langflow: + - Internal URL: http://{{ include "openrag.fullname" . }}-langflow:{{ .Values.langflow.service.port }} + {{- if and .Values.ingress.enabled .Values.ingress.hosts.langflow.enabled .Values.ingress.hosts.langflow.host }} + - External URL: http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.hosts.langflow.host }} + {{- end }} +{{- end }} + +{{- if .Values.backend.enabled }} +Backend API: + - Internal URL: http://{{ include "openrag.fullname" . }}-backend:{{ .Values.backend.service.port }} + {{- if and .Values.ingress.enabled .Values.ingress.hosts.backend.host }} + - External URL: http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.hosts.backend.host }} + {{- end }} +{{- end }} + +{{- if .Values.frontend.enabled }} +Frontend UI: + - Internal URL: http://{{ include "openrag.fullname" . }}-frontend:{{ .Values.frontend.service.port }} + {{- if and .Values.ingress.enabled .Values.ingress.hosts.frontend.host }} + - External URL: http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.hosts.frontend.host }} + {{- end }} +{{- end }} + +{{- if .Values.dashboards.enabled }} +OpenSearch Dashboards: + - Internal URL: http://{{ include "openrag.fullname" . }}-dashboards:{{ .Values.dashboards.service.port }} + {{- if and .Values.ingress.enabled .Values.ingress.hosts.dashboards.enabled .Values.ingress.hosts.dashboards.host }} + - External URL: http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.hosts.dashboards.host }} + {{- end }} +{{- end }} + +=== External Dependencies === + +OpenSearch (External SaaS): + - Host: {{ .Values.global.opensearch.host }} + - Port: {{ .Values.global.opensearch.port }} + - Scheme: {{ .Values.global.opensearch.scheme }} + +=== Credentials === + +To retrieve the Langflow superuser credentials: + + kubectl get secret {{ include "openrag.fullname" . }}-langflow -n {{ include "openrag.namespace" . }} -o jsonpath='{.data.superuser}' | base64 -d + kubectl get secret {{ include "openrag.fullname" . }}-langflow -n {{ include "openrag.namespace" . }} -o jsonpath='{.data.superuser-password}' | base64 -d + +=== Quick Start === + +{{- if and .Values.ingress.enabled .Values.ingress.hosts.frontend.host }} +1. Access the OpenRAG UI at: http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.ingress.hosts.frontend.host }} +{{- else }} +1. Port-forward the frontend service: + kubectl port-forward svc/{{ include "openrag.fullname" . }}-frontend {{ .Values.frontend.service.port }}:{{ .Values.frontend.service.port }} -n {{ include "openrag.namespace" . }} + Then access: http://localhost:{{ .Values.frontend.service.port }} +{{- end }} + +2. Upload documents to your knowledge base + +3. Start chatting with your documents using the AI-powered chat interface + +=== Troubleshooting === + +Check pod status: + kubectl get pods -n {{ include "openrag.namespace" . }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Check pod logs: + kubectl logs -n {{ include "openrag.namespace" . }} -l app.kubernetes.io/component=langflow + kubectl logs -n {{ include "openrag.namespace" . }} -l app.kubernetes.io/component=backend + kubectl logs -n {{ include "openrag.namespace" . }} -l app.kubernetes.io/component=frontend + +For more information, visit: https://github.com/langflow-ai/openrag diff --git a/helm/openrag/templates/_helpers.tpl b/helm/openrag/templates/_helpers.tpl new file mode 100644 index 00000000..c0a49b85 --- /dev/null +++ b/helm/openrag/templates/_helpers.tpl @@ -0,0 +1,163 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "openrag.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +If tenant name is provided, prefix with tenant name. +*/}} +{{- define "openrag.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if .Values.global.tenant.name }} +{{- printf "%s-%s" .Values.global.tenant.name $name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s" $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create the namespace name. +Uses tenant namespace if specified, otherwise tenant name, otherwise release namespace. +*/}} +{{- define "openrag.namespace" -}} +{{- if .Values.global.tenant.namespace }} +{{- .Values.global.tenant.namespace }} +{{- else if .Values.global.tenant.name }} +{{- .Values.global.tenant.name }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "openrag.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "openrag.labels" -}} +helm.sh/chart: {{ include "openrag.chart" . }} +{{ include "openrag.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.global.tenant.name }} +openrag.io/tenant: {{ .Values.global.tenant.name }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "openrag.selectorLabels" -}} +app.kubernetes.io/name: {{ include "openrag.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "openrag.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "openrag.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Langflow component labels +*/}} +{{- define "openrag.langflow.labels" -}} +{{ include "openrag.labels" . }} +app.kubernetes.io/component: langflow +{{- end }} + +{{/* +Langflow selector labels +*/}} +{{- define "openrag.langflow.selectorLabels" -}} +{{ include "openrag.selectorLabels" . }} +app.kubernetes.io/component: langflow +{{- end }} + +{{/* +Backend component labels +*/}} +{{- define "openrag.backend.labels" -}} +{{ include "openrag.labels" . }} +app.kubernetes.io/component: backend +{{- end }} + +{{/* +Backend selector labels +*/}} +{{- define "openrag.backend.selectorLabels" -}} +{{ include "openrag.selectorLabels" . }} +app.kubernetes.io/component: backend +{{- end }} + +{{/* +Frontend component labels +*/}} +{{- define "openrag.frontend.labels" -}} +{{ include "openrag.labels" . }} +app.kubernetes.io/component: frontend +{{- end }} + +{{/* +Frontend selector labels +*/}} +{{- define "openrag.frontend.selectorLabels" -}} +{{ include "openrag.selectorLabels" . }} +app.kubernetes.io/component: frontend +{{- end }} + +{{/* +Dashboards component labels +*/}} +{{- define "openrag.dashboards.labels" -}} +{{ include "openrag.labels" . }} +app.kubernetes.io/component: dashboards +{{- end }} + +{{/* +Dashboards selector labels +*/}} +{{- define "openrag.dashboards.selectorLabels" -}} +{{ include "openrag.selectorLabels" . }} +app.kubernetes.io/component: dashboards +{{- end }} + +{{/* +Generate the Langflow service URL +*/}} +{{- define "openrag.langflow.url" -}} +http://{{ include "openrag.fullname" . }}-langflow:{{ .Values.langflow.service.port }} +{{- end }} + +{{/* +Generate the Backend service URL +*/}} +{{- define "openrag.backend.url" -}} +http://{{ include "openrag.fullname" . }}-backend:{{ .Values.backend.service.port }} +{{- end }} + +{{/* +Generate the OpenSearch URL +*/}} +{{- define "openrag.opensearch.url" -}} +{{ .Values.global.opensearch.scheme }}://{{ .Values.global.opensearch.host }}:{{ .Values.global.opensearch.port }} +{{- end }} diff --git a/helm/openrag/templates/backend/deployment.yaml b/helm/openrag/templates/backend/deployment.yaml new file mode 100644 index 00000000..aa6077ba --- /dev/null +++ b/helm/openrag/templates/backend/deployment.yaml @@ -0,0 +1,273 @@ +{{- if .Values.backend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "openrag.fullname" . }}-backend + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.backend.labels" . | nindent 4 }} +spec: + replicas: 1 # Single pod for vertical scaling + strategy: + type: Recreate # Required for RWO PVCs + selector: + matchLabels: + {{- include "openrag.backend.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "openrag.backend.selectorLabels" . | nindent 8 }} + annotations: + checksum/secret-opensearch: {{ include (print $.Template.BasePath "/secrets/opensearch-secret.yaml") . | sha256sum }} + checksum/secret-langflow: {{ include (print $.Template.BasePath "/secrets/langflow-secret.yaml") . | sha256sum }} + checksum/config-flows: {{ include (print $.Template.BasePath "/configmaps/flow-ids-configmap.yaml") . | sha256sum }} + checksum/config-app: {{ include (print $.Template.BasePath "/configmaps/app-config-configmap.yaml") . | sha256sum }} + spec: + serviceAccountName: {{ include "openrag.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.langflow.enabled }} + initContainers: + - name: wait-for-langflow + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for Langflow to be ready..." + until nc -z {{ include "openrag.fullname" . }}-langflow {{ .Values.langflow.service.port }}; do + echo "Langflow not ready, sleeping 5s..." + sleep 5 + done + echo "Langflow is ready!" + {{- end }} + containers: + - name: backend + image: "{{ .Values.backend.image.repository }}:{{ .Values.backend.image.tag | default .Values.global.imageTag }}" + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: 8000 + protocol: TCP + env: + # OpenSearch connection (external SaaS) + - name: OPENSEARCH_HOST + value: {{ .Values.global.opensearch.host | quote }} + - name: OPENSEARCH_PORT + value: {{ .Values.global.opensearch.port | quote }} + - name: OPENSEARCH_USERNAME + value: {{ .Values.global.opensearch.username | quote }} + {{- if .Values.global.opensearch.password }} + - name: OPENSEARCH_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-opensearch + key: password + {{- end }} + # Langflow connection + - name: LANGFLOW_URL + value: {{ include "openrag.langflow.url" . | quote }} + {{- if .Values.backend.langflowPublicUrl }} + - name: LANGFLOW_PUBLIC_URL + value: {{ .Values.backend.langflowPublicUrl | quote }} + {{- end }} + - name: LANGFLOW_AUTO_LOGIN + value: {{ .Values.langflow.auth.autoLogin | quote }} + - name: LANGFLOW_SUPERUSER + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-langflow + key: superuser + - name: LANGFLOW_SUPERUSER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-langflow + key: superuser-password + # Flow IDs from ConfigMap + - name: LANGFLOW_CHAT_FLOW_ID + valueFrom: + configMapKeyRef: + name: {{ include "openrag.fullname" . }}-flow-ids + key: chat-flow-id + - name: LANGFLOW_INGEST_FLOW_ID + valueFrom: + configMapKeyRef: + name: {{ include "openrag.fullname" . }}-flow-ids + key: ingest-flow-id + - name: LANGFLOW_URL_INGEST_FLOW_ID + valueFrom: + configMapKeyRef: + name: {{ include "openrag.fullname" . }}-flow-ids + key: url-ingest-flow-id + - name: NUDGES_FLOW_ID + valueFrom: + configMapKeyRef: + name: {{ include "openrag.fullname" . }}-flow-ids + key: nudges-flow-id + # Feature flags + - name: DISABLE_INGEST_WITH_LANGFLOW + value: {{ .Values.backend.features.disableIngestWithLangflow | quote }} + # LLM Provider keys + {{- if .Values.llmProviders.openai.enabled }} + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: openai-api-key + {{- end }} + {{- if .Values.llmProviders.anthropic.enabled }} + - name: ANTHROPIC_API_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: anthropic-api-key + {{- end }} + {{- if .Values.llmProviders.watsonx.enabled }} + - name: WATSONX_API_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: watsonx-api-key + - name: WATSONX_ENDPOINT + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: watsonx-endpoint + - name: WATSONX_PROJECT_ID + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: watsonx-project-id + {{- end }} + {{- if .Values.llmProviders.ollama.enabled }} + - name: OLLAMA_ENDPOINT + value: {{ .Values.llmProviders.ollama.endpoint | quote }} + {{- end }} + # OAuth credentials + {{- if .Values.global.oauth.google.enabled }} + - name: GOOGLE_OAUTH_CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-oauth + key: google-client-id + - name: GOOGLE_OAUTH_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-oauth + key: google-client-secret + {{- end }} + {{- if .Values.global.oauth.microsoft.enabled }} + - name: MICROSOFT_GRAPH_OAUTH_CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-oauth + key: microsoft-client-id + - name: MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-oauth + key: microsoft-client-secret + {{- end }} + # AWS credentials + {{- if .Values.backend.aws.enabled }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-aws + key: access-key-id + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-aws + key: secret-access-key + {{- end }} + # Webhook configuration + {{- if .Values.backend.webhook.enabled }} + - name: WEBHOOK_BASE_URL + value: {{ .Values.backend.webhook.baseUrl | quote }} + {{- end }} + volumeMounts: + {{- if .Values.backend.persistence.documents.enabled }} + - name: documents + mountPath: {{ .Values.backend.persistence.documents.mountPath }} + {{- end }} + {{- if .Values.backend.persistence.keys.enabled }} + - name: keys + mountPath: {{ .Values.backend.persistence.keys.mountPath }} + {{- end }} + {{- if .Values.backend.persistence.config.enabled }} + - name: config + mountPath: {{ .Values.backend.persistence.config.mountPath }} + {{- end }} + {{- if .Values.langflow.persistence.enabled }} + - name: flows + mountPath: /app/flows + subPath: {{ .Values.langflow.persistence.flowsSubPath }} + readOnly: true + {{- end }} + resources: + {{- toYaml .Values.backend.resources | nindent 12 }} + {{- if .Values.backend.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: {{ .Values.backend.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.backend.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.backend.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.backend.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.backend.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: {{ .Values.backend.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.backend.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.backend.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.backend.readinessProbe.failureThreshold }} + {{- end }} + volumes: + {{- if .Values.backend.persistence.documents.enabled }} + - name: documents + persistentVolumeClaim: + claimName: {{ include "openrag.fullname" . }}-documents + {{- end }} + {{- if .Values.backend.persistence.keys.enabled }} + - name: keys + persistentVolumeClaim: + claimName: {{ include "openrag.fullname" . }}-keys + {{- end }} + {{- if .Values.backend.persistence.config.enabled }} + - name: config + persistentVolumeClaim: + claimName: {{ include "openrag.fullname" . }}-config + {{- end }} + {{- if .Values.langflow.persistence.enabled }} + - name: flows + persistentVolumeClaim: + claimName: {{ include "openrag.fullname" . }}-langflow + {{- 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 }} +{{- end }} diff --git a/helm/openrag/templates/backend/service.yaml b/helm/openrag/templates/backend/service.yaml new file mode 100644 index 00000000..d105de86 --- /dev/null +++ b/helm/openrag/templates/backend/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.backend.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "openrag.fullname" . }}-backend + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.backend.labels" . | nindent 4 }} +spec: + type: {{ .Values.backend.service.type }} + ports: + - port: {{ .Values.backend.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "openrag.backend.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/openrag/templates/configmaps/app-config-configmap.yaml b/helm/openrag/templates/configmaps/app-config-configmap.yaml new file mode 100644 index 00000000..e04dea4c --- /dev/null +++ b/helm/openrag/templates/configmaps/app-config-configmap.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "openrag.fullname" . }}-app-config + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} +data: + config.yaml: | + agent: + llm_model: {{ .Values.appConfig.agent.llmModel | quote }} + llm_provider: {{ .Values.appConfig.agent.llmProvider | quote }} + {{- if .Values.appConfig.agent.systemPrompt }} + system_prompt: {{ .Values.appConfig.agent.systemPrompt | quote }} + {{- end }} + edited: false + knowledge: + chunk_overlap: {{ .Values.appConfig.knowledge.chunkOverlap }} + chunk_size: {{ .Values.appConfig.knowledge.chunkSize }} + embedding_model: {{ .Values.appConfig.knowledge.embeddingModel | quote }} + embedding_provider: {{ .Values.appConfig.knowledge.embeddingProvider | quote }} + ocr: {{ .Values.appConfig.knowledge.ocr }} + picture_descriptions: {{ .Values.appConfig.knowledge.pictureDescriptions }} + table_structure: {{ .Values.appConfig.knowledge.tableStructure }} + providers: + anthropic: + configured: {{ .Values.llmProviders.anthropic.enabled }} + ollama: + configured: {{ .Values.llmProviders.ollama.enabled }} + {{- if .Values.llmProviders.ollama.endpoint }} + endpoint: {{ .Values.llmProviders.ollama.endpoint | quote }} + {{- end }} + openai: + configured: {{ .Values.llmProviders.openai.enabled }} + watsonx: + configured: {{ .Values.llmProviders.watsonx.enabled }} + {{- if .Values.llmProviders.watsonx.endpoint }} + endpoint: {{ .Values.llmProviders.watsonx.endpoint | quote }} + {{- end }} diff --git a/helm/openrag/templates/configmaps/flow-ids-configmap.yaml b/helm/openrag/templates/configmaps/flow-ids-configmap.yaml new file mode 100644 index 00000000..4e4dfb9c --- /dev/null +++ b/helm/openrag/templates/configmaps/flow-ids-configmap.yaml @@ -0,0 +1,14 @@ +{{- if .Values.langflow.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "openrag.fullname" . }}-flow-ids + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} +data: + chat-flow-id: {{ .Values.langflow.flows.chatFlowId | quote }} + ingest-flow-id: {{ .Values.langflow.flows.ingestFlowId | quote }} + url-ingest-flow-id: {{ .Values.langflow.flows.urlIngestFlowId | quote }} + nudges-flow-id: {{ .Values.langflow.flows.nudgesFlowId | quote }} +{{- end }} diff --git a/helm/openrag/templates/dashboards/deployment.yaml b/helm/openrag/templates/dashboards/deployment.yaml new file mode 100644 index 00000000..49d87d3a --- /dev/null +++ b/helm/openrag/templates/dashboards/deployment.yaml @@ -0,0 +1,81 @@ +{{- if .Values.dashboards.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "openrag.fullname" . }}-dashboards + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.dashboards.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.dashboards.replicaCount }} + selector: + matchLabels: + {{- include "openrag.dashboards.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "openrag.dashboards.selectorLabels" . | nindent 8 }} + annotations: + checksum/secret: {{ include (print $.Template.BasePath "/secrets/opensearch-secret.yaml") . | sha256sum }} + spec: + serviceAccountName: {{ include "openrag.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: dashboards + image: "{{ .Values.dashboards.image.repository }}:{{ .Values.dashboards.image.tag }}" + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + ports: + - name: http + containerPort: 5601 + protocol: TCP + env: + # OpenSearch connection (external SaaS) + - name: OPENSEARCH_HOSTS + value: '["{{ include "openrag.opensearch.url" . }}"]' + - name: OPENSEARCH_USERNAME + value: {{ .Values.global.opensearch.username | quote }} + {{- if .Values.global.opensearch.password }} + - name: OPENSEARCH_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-opensearch + key: password + {{- end }} + resources: + {{- toYaml .Values.dashboards.resources | nindent 12 }} + {{- if .Values.dashboards.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /api/status + port: http + initialDelaySeconds: {{ .Values.dashboards.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.dashboards.livenessProbe.periodSeconds }} + {{- end }} + {{- if .Values.dashboards.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /api/status + port: http + initialDelaySeconds: {{ .Values.dashboards.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.dashboards.readinessProbe.periodSeconds }} + {{- 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 }} +{{- end }} diff --git a/helm/openrag/templates/dashboards/service.yaml b/helm/openrag/templates/dashboards/service.yaml new file mode 100644 index 00000000..91830518 --- /dev/null +++ b/helm/openrag/templates/dashboards/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.dashboards.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "openrag.fullname" . }}-dashboards + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.dashboards.labels" . | nindent 4 }} +spec: + type: {{ .Values.dashboards.service.type }} + ports: + - port: {{ .Values.dashboards.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "openrag.dashboards.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/openrag/templates/frontend/deployment.yaml b/helm/openrag/templates/frontend/deployment.yaml new file mode 100644 index 00000000..4c7ec937 --- /dev/null +++ b/helm/openrag/templates/frontend/deployment.yaml @@ -0,0 +1,80 @@ +{{- if .Values.frontend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "openrag.fullname" . }}-frontend + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.frontend.labels" . | nindent 4 }} +spec: + {{- if not .Values.frontend.autoscaling.enabled }} + replicas: {{ .Values.frontend.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "openrag.frontend.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "openrag.frontend.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "openrag.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: frontend + image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag | default .Values.global.imageTag }}" + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: 3000 + protocol: TCP + env: + # Backend connection (uses internal service name) + - name: OPENRAG_BACKEND_HOST + value: "{{ include "openrag.fullname" . }}-backend" + resources: + {{- toYaml .Values.frontend.resources | nindent 12 }} + {{- if .Values.frontend.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: {{ .Values.frontend.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frontend.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.frontend.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.frontend.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.frontend.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: {{ .Values.frontend.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frontend.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.frontend.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.frontend.readinessProbe.failureThreshold }} + {{- 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 }} +{{- end }} diff --git a/helm/openrag/templates/frontend/hpa.yaml b/helm/openrag/templates/frontend/hpa.yaml new file mode 100644 index 00000000..306b0108 --- /dev/null +++ b/helm/openrag/templates/frontend/hpa.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.frontend.enabled .Values.frontend.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "openrag.fullname" . }}-frontend + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.frontend.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "openrag.fullname" . }}-frontend + minReplicas: {{ .Values.frontend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.frontend.autoscaling.maxReplicas }} + metrics: + {{- if .Values.frontend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.frontend.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.frontend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.frontend.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/openrag/templates/frontend/service.yaml b/helm/openrag/templates/frontend/service.yaml new file mode 100644 index 00000000..1a3b7c8c --- /dev/null +++ b/helm/openrag/templates/frontend/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.frontend.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "openrag.fullname" . }}-frontend + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.frontend.labels" . | nindent 4 }} +spec: + type: {{ .Values.frontend.service.type }} + ports: + - port: {{ .Values.frontend.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "openrag.frontend.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/openrag/templates/ingress/ingress.yaml b/helm/openrag/templates/ingress/ingress.yaml new file mode 100644 index 00000000..5e03e5bd --- /dev/null +++ b/helm/openrag/templates/ingress/ingress.yaml @@ -0,0 +1,104 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "openrag.fullname" . }} + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.ingress.tls.certManager.enabled }} + cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.certManager.issuerRef.name }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls.enabled }} + tls: + {{- if .Values.ingress.hosts.frontend.host }} + - hosts: + - {{ .Values.ingress.hosts.frontend.host }} + secretName: {{ .Values.ingress.tls.secretName | default (printf "%s-frontend-tls" (include "openrag.fullname" .)) }} + {{- end }} + {{- if .Values.ingress.hosts.backend.host }} + - hosts: + - {{ .Values.ingress.hosts.backend.host }} + secretName: {{ .Values.ingress.tls.secretName | default (printf "%s-backend-tls" (include "openrag.fullname" .)) }} + {{- end }} + {{- if and .Values.ingress.hosts.langflow.enabled .Values.ingress.hosts.langflow.host }} + - hosts: + - {{ .Values.ingress.hosts.langflow.host }} + secretName: {{ .Values.ingress.tls.secretName | default (printf "%s-langflow-tls" (include "openrag.fullname" .)) }} + {{- end }} + {{- if and .Values.dashboards.enabled .Values.ingress.hosts.dashboards.enabled .Values.ingress.hosts.dashboards.host }} + - hosts: + - {{ .Values.ingress.hosts.dashboards.host }} + secretName: {{ .Values.ingress.tls.secretName | default (printf "%s-dashboards-tls" (include "openrag.fullname" .)) }} + {{- end }} + {{- end }} + rules: + {{- if .Values.ingress.hosts.frontend.host }} + # Frontend ingress rule + - host: {{ .Values.ingress.hosts.frontend.host }} + http: + paths: + {{- range .Values.ingress.hosts.frontend.paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "openrag.fullname" $ }}-frontend + port: + number: {{ $.Values.frontend.service.port }} + {{- end }} + {{- end }} + {{- if .Values.ingress.hosts.backend.host }} + # Backend API ingress rule + - host: {{ .Values.ingress.hosts.backend.host }} + http: + paths: + {{- range .Values.ingress.hosts.backend.paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "openrag.fullname" $ }}-backend + port: + number: {{ $.Values.backend.service.port }} + {{- end }} + {{- end }} + {{- if and .Values.ingress.hosts.langflow.enabled .Values.ingress.hosts.langflow.host }} + # Optional Langflow direct access + - host: {{ .Values.ingress.hosts.langflow.host }} + http: + paths: + {{- range .Values.ingress.hosts.langflow.paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "openrag.fullname" $ }}-langflow + port: + number: {{ $.Values.langflow.service.port }} + {{- end }} + {{- end }} + {{- if and .Values.dashboards.enabled .Values.ingress.hosts.dashboards.enabled .Values.ingress.hosts.dashboards.host }} + # Optional Dashboards access + - host: {{ .Values.ingress.hosts.dashboards.host }} + http: + paths: + {{- range .Values.ingress.hosts.dashboards.paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "openrag.fullname" $ }}-dashboards + port: + number: {{ $.Values.dashboards.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/openrag/templates/langflow/deployment.yaml b/helm/openrag/templates/langflow/deployment.yaml new file mode 100644 index 00000000..f583f9a1 --- /dev/null +++ b/helm/openrag/templates/langflow/deployment.yaml @@ -0,0 +1,211 @@ +{{- if .Values.langflow.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "openrag.fullname" . }}-langflow + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.langflow.labels" . | nindent 4 }} +spec: + replicas: 1 # Always 1 for SQLite-based Langflow + strategy: + type: Recreate # Required for RWO PVC + selector: + matchLabels: + {{- include "openrag.langflow.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "openrag.langflow.selectorLabels" . | nindent 8 }} + annotations: + checksum/secret: {{ include (print $.Template.BasePath "/secrets/langflow-secret.yaml") . | sha256sum }} + checksum/config: {{ include (print $.Template.BasePath "/configmaps/flow-ids-configmap.yaml") . | sha256sum }} + spec: + serviceAccountName: {{ include "openrag.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: langflow + image: "{{ .Values.langflow.image.repository }}:{{ .Values.langflow.image.tag | default .Values.global.imageTag }}" + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: 7860 + protocol: TCP + env: + # Langflow core settings + - name: LANGFLOW_LOAD_FLOWS_PATH + value: {{ .Values.langflow.persistence.mountPath }}/{{ .Values.langflow.persistence.flowsSubPath }} + - name: LANGFLOW_DATABASE_URL + value: "sqlite:///{{ .Values.langflow.persistence.mountPath }}/{{ .Values.langflow.persistence.dbSubPath }}" + - name: LANGFLOW_DEACTIVATE_TRACING + value: {{ .Values.langflow.deactivateTracing | quote }} + - name: LANGFLOW_LOG_LEVEL + value: {{ .Values.langflow.logLevel | quote }} + - name: HIDE_GETTING_STARTED_PROGRESS + value: "true" + # Auth settings + - name: LANGFLOW_AUTO_LOGIN + value: {{ .Values.langflow.auth.autoLogin | quote }} + - name: LANGFLOW_NEW_USER_IS_ACTIVE + value: {{ .Values.langflow.auth.newUserIsActive | quote }} + - name: LANGFLOW_ENABLE_SUPERUSER_CLI + value: {{ .Values.langflow.auth.enableSuperuserCli | quote }} + # Variables to expose to flows + - name: LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT + value: {{ .Values.langflow.variablesToGetFromEnvironment | quote }} + # Flow context variables (defaults for flow execution) + - name: JWT + value: "None" + - name: OWNER + value: "None" + - name: OWNER_NAME + value: "None" + - name: OWNER_EMAIL + value: "None" + - name: CONNECTOR_TYPE + value: "system" + - name: CONNECTOR_TYPE_URL + value: "url" + - name: OPENRAG-QUERY-FILTER + value: "{}" + - name: FILENAME + value: "None" + - name: MIMETYPE + value: "None" + - name: FILESIZE + value: "0" + - name: SELECTED_EMBEDDING_MODEL + value: "" + # Secrets from langflow secret + - name: LANGFLOW_SECRET_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-langflow + key: secret-key + - name: LANGFLOW_SUPERUSER + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-langflow + key: superuser + - name: LANGFLOW_SUPERUSER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-langflow + key: superuser-password + # OpenSearch password (for flows) + {{- if .Values.global.opensearch.password }} + - name: OPENSEARCH_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-opensearch + key: password + {{- end }} + # LLM Provider keys + {{- if .Values.llmProviders.openai.enabled }} + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: openai-api-key + {{- else }} + - name: OPENAI_API_KEY + value: "None" + {{- end }} + {{- if .Values.llmProviders.anthropic.enabled }} + - name: ANTHROPIC_API_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: anthropic-api-key + {{- else }} + - name: ANTHROPIC_API_KEY + value: "None" + {{- end }} + {{- if .Values.llmProviders.watsonx.enabled }} + - name: WATSONX_API_KEY + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: watsonx-api-key + - name: WATSONX_ENDPOINT + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: watsonx-endpoint + - name: WATSONX_PROJECT_ID + valueFrom: + secretKeyRef: + name: {{ include "openrag.fullname" . }}-llm-providers + key: watsonx-project-id + {{- else }} + - name: WATSONX_API_KEY + value: "None" + - name: WATSONX_ENDPOINT + value: "None" + - name: WATSONX_PROJECT_ID + value: "None" + {{- end }} + {{- if .Values.llmProviders.ollama.enabled }} + - name: OLLAMA_BASE_URL + value: {{ .Values.llmProviders.ollama.endpoint | quote }} + {{- else }} + - name: OLLAMA_BASE_URL + value: "None" + {{- end }} + volumeMounts: + - name: langflow-data + mountPath: {{ .Values.langflow.persistence.mountPath }} + resources: + {{- toYaml .Values.langflow.resources | nindent 12 }} + {{- if .Values.langflow.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: {{ .Values.langflow.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.langflow.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.langflow.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.langflow.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.langflow.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: {{ .Values.langflow.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.langflow.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.langflow.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.langflow.readinessProbe.failureThreshold }} + {{- end }} + volumes: + - name: langflow-data + {{- if .Values.langflow.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "openrag.fullname" . }}-langflow + {{- else }} + emptyDir: {} + {{- 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 }} +{{- end }} diff --git a/helm/openrag/templates/langflow/service.yaml b/helm/openrag/templates/langflow/service.yaml new file mode 100644 index 00000000..ae9c98e1 --- /dev/null +++ b/helm/openrag/templates/langflow/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.langflow.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "openrag.fullname" . }}-langflow + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.langflow.labels" . | nindent 4 }} +spec: + type: {{ .Values.langflow.service.type }} + ports: + - port: {{ .Values.langflow.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "openrag.langflow.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/openrag/templates/secrets/aws-secret.yaml b/helm/openrag/templates/secrets/aws-secret.yaml new file mode 100644 index 00000000..b20ad07a --- /dev/null +++ b/helm/openrag/templates/secrets/aws-secret.yaml @@ -0,0 +1,13 @@ +{{- if .Values.backend.aws.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "openrag.fullname" . }}-aws + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} +type: Opaque +stringData: + access-key-id: {{ .Values.backend.aws.accessKeyId | quote }} + secret-access-key: {{ .Values.backend.aws.secretAccessKey | quote }} +{{- end }} diff --git a/helm/openrag/templates/secrets/langflow-secret.yaml b/helm/openrag/templates/secrets/langflow-secret.yaml new file mode 100644 index 00000000..e43e07b1 --- /dev/null +++ b/helm/openrag/templates/secrets/langflow-secret.yaml @@ -0,0 +1,14 @@ +{{- if .Values.langflow.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "openrag.fullname" . }}-langflow + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} +type: Opaque +stringData: + secret-key: {{ .Values.langflow.auth.secretKey | default (randAlphaNum 32) | quote }} + superuser: {{ .Values.langflow.auth.superuser | quote }} + superuser-password: {{ .Values.langflow.auth.superuserPassword | default (randAlphaNum 16) | quote }} +{{- end }} diff --git a/helm/openrag/templates/secrets/llm-providers-secret.yaml b/helm/openrag/templates/secrets/llm-providers-secret.yaml new file mode 100644 index 00000000..9c394c2a --- /dev/null +++ b/helm/openrag/templates/secrets/llm-providers-secret.yaml @@ -0,0 +1,22 @@ +{{- if or .Values.llmProviders.openai.enabled .Values.llmProviders.anthropic.enabled .Values.llmProviders.watsonx.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "openrag.fullname" . }}-llm-providers + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} +type: Opaque +stringData: + {{- if .Values.llmProviders.openai.enabled }} + openai-api-key: {{ .Values.llmProviders.openai.apiKey | quote }} + {{- end }} + {{- if .Values.llmProviders.anthropic.enabled }} + anthropic-api-key: {{ .Values.llmProviders.anthropic.apiKey | quote }} + {{- end }} + {{- if .Values.llmProviders.watsonx.enabled }} + watsonx-api-key: {{ .Values.llmProviders.watsonx.apiKey | quote }} + watsonx-endpoint: {{ .Values.llmProviders.watsonx.endpoint | quote }} + watsonx-project-id: {{ .Values.llmProviders.watsonx.projectId | quote }} + {{- end }} +{{- end }} diff --git a/helm/openrag/templates/secrets/oauth-secret.yaml b/helm/openrag/templates/secrets/oauth-secret.yaml new file mode 100644 index 00000000..4742c42b --- /dev/null +++ b/helm/openrag/templates/secrets/oauth-secret.yaml @@ -0,0 +1,19 @@ +{{- if or .Values.global.oauth.google.enabled .Values.global.oauth.microsoft.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "openrag.fullname" . }}-oauth + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} +type: Opaque +stringData: + {{- if .Values.global.oauth.google.enabled }} + google-client-id: {{ .Values.global.oauth.google.clientId | quote }} + google-client-secret: {{ .Values.global.oauth.google.clientSecret | quote }} + {{- end }} + {{- if .Values.global.oauth.microsoft.enabled }} + microsoft-client-id: {{ .Values.global.oauth.microsoft.clientId | quote }} + microsoft-client-secret: {{ .Values.global.oauth.microsoft.clientSecret | quote }} + {{- end }} +{{- end }} diff --git a/helm/openrag/templates/secrets/opensearch-secret.yaml b/helm/openrag/templates/secrets/opensearch-secret.yaml new file mode 100644 index 00000000..07909041 --- /dev/null +++ b/helm/openrag/templates/secrets/opensearch-secret.yaml @@ -0,0 +1,13 @@ +{{- if .Values.global.opensearch.password }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "openrag.fullname" . }}-opensearch + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} +type: Opaque +stringData: + password: {{ .Values.global.opensearch.password | quote }} + username: {{ .Values.global.opensearch.username | quote }} +{{- end }} diff --git a/helm/openrag/templates/serviceaccount.yaml b/helm/openrag/templates/serviceaccount.yaml new file mode 100644 index 00000000..aa4f377b --- /dev/null +++ b/helm/openrag/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "openrag.serviceAccountName" . }} + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm/openrag/templates/storage/config-pvc.yaml b/helm/openrag/templates/storage/config-pvc.yaml new file mode 100644 index 00000000..d5ced07f --- /dev/null +++ b/helm/openrag/templates/storage/config-pvc.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.backend.enabled .Values.backend.persistence.config.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "openrag.fullname" . }}-config + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.backend.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.backend.persistence.config.accessMode }} + {{- if .Values.backend.persistence.config.storageClass }} + storageClassName: {{ .Values.backend.persistence.config.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backend.persistence.config.size }} +{{- end }} diff --git a/helm/openrag/templates/storage/documents-pvc.yaml b/helm/openrag/templates/storage/documents-pvc.yaml new file mode 100644 index 00000000..03ee3401 --- /dev/null +++ b/helm/openrag/templates/storage/documents-pvc.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.backend.enabled .Values.backend.persistence.documents.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "openrag.fullname" . }}-documents + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.backend.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.backend.persistence.documents.accessMode }} + {{- if .Values.backend.persistence.documents.storageClass }} + storageClassName: {{ .Values.backend.persistence.documents.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backend.persistence.documents.size }} +{{- end }} diff --git a/helm/openrag/templates/storage/keys-pvc.yaml b/helm/openrag/templates/storage/keys-pvc.yaml new file mode 100644 index 00000000..6d2acd4c --- /dev/null +++ b/helm/openrag/templates/storage/keys-pvc.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.backend.enabled .Values.backend.persistence.keys.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "openrag.fullname" . }}-keys + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.backend.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.backend.persistence.keys.accessMode }} + {{- if .Values.backend.persistence.keys.storageClass }} + storageClassName: {{ .Values.backend.persistence.keys.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.backend.persistence.keys.size }} +{{- end }} diff --git a/helm/openrag/templates/storage/langflow-pvc.yaml b/helm/openrag/templates/storage/langflow-pvc.yaml new file mode 100644 index 00000000..b1a7e21c --- /dev/null +++ b/helm/openrag/templates/storage/langflow-pvc.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.langflow.enabled .Values.langflow.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "openrag.fullname" . }}-langflow + namespace: {{ include "openrag.namespace" . }} + labels: + {{- include "openrag.langflow.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.langflow.persistence.accessMode }} + {{- if .Values.langflow.persistence.storageClass }} + storageClassName: {{ .Values.langflow.persistence.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.langflow.persistence.size }} +{{- end }} diff --git a/helm/openrag/values.yaml b/helm/openrag/values.yaml new file mode 100644 index 00000000..c589ea74 --- /dev/null +++ b/helm/openrag/values.yaml @@ -0,0 +1,407 @@ +# OpenRAG Helm Chart Values +# This chart deploys OpenRAG with external OpenSearch SaaS connection + +# Override names +nameOverride: "" +fullnameOverride: "" + +# Global settings +global: + # Tenant identification - used for resource naming and namespace + tenant: + name: "" # Required for multi-tenant: tenant identifier (e.g., "acme") + namespace: "" # Optional: override namespace (defaults to tenant name or release namespace) + + # Image settings + imageRegistry: "langflowai" + imagePullPolicy: IfNotPresent + imageTag: "latest" # Override with specific version in production + imagePullSecrets: [] + + # External OpenSearch SaaS connection (OpenSearch is NOT deployed by this chart) + opensearch: + host: "" # Required: OpenSearch SaaS endpoint (e.g., "my-cluster.us-east-1.es.amazonaws.com") + port: 443 # Default HTTPS port for managed OpenSearch + scheme: "https" # https for production SaaS + username: "admin" # OpenSearch username + password: "" # OpenSearch password (stored in secret) + + # Shared OAuth credentials (same across all tenants) + oauth: + google: + enabled: false + clientId: "" # Google OAuth client ID + clientSecret: "" # Google OAuth client secret + microsoft: + enabled: false + clientId: "" # Microsoft Graph OAuth client ID + clientSecret: "" # Microsoft Graph OAuth client secret + +# ============================================================================ +# Langflow Configuration +# ============================================================================ +langflow: + enabled: true + + image: + repository: langflowai/openrag-langflow + tag: "" # Uses global.imageTag if empty + + # Single pod - vertical scaling only (SQLite requires single writer) + replicaCount: 1 + + # Resource requests/limits for vertical scaling + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "4" + memory: "8Gi" + + # Persistence for SQLite DB and flows + persistence: + enabled: true + storageClass: "" # Empty uses cluster default + accessMode: ReadWriteOnce + size: 10Gi + mountPath: /app/data + flowsSubPath: flows + dbSubPath: langflow.db + + # Flow configuration (UUIDs for Langflow workflows) + flows: + chatFlowId: "1098eea1-6649-4e1d-aed1-b77249fb8dd0" + ingestFlowId: "5488df7c-b93f-4f87-a446-b67028bc0813" + urlIngestFlowId: "72c3d17c-2dac-4a73-b48a-6518473d7830" + nudgesFlowId: "ebc01d31-1976-46ce-a385-b0240327226c" + loadPath: /app/flows + + # Authentication settings + auth: + autoLogin: false + superuser: "admin" # Langflow superuser username + superuserPassword: "" # Langflow superuser password (stored in secret) + secretKey: "" # Langflow secret key for JWT (stored in secret) + newUserIsActive: false + enableSuperuserCli: false + + # Runtime settings + deactivateTracing: true + logLevel: "INFO" # DEBUG, INFO, WARNING, ERROR + + # Variables to expose to flows + variablesToGetFromEnvironment: "JWT,OPENRAG-QUERY-FILTER,OPENSEARCH_PASSWORD,OWNER,OWNER_NAME,OWNER_EMAIL,CONNECTOR_TYPE,FILENAME,MIMETYPE,FILESIZE,SELECTED_EMBEDDING_MODEL,OPENAI_API_KEY,ANTHROPIC_API_KEY,WATSONX_API_KEY,WATSONX_ENDPOINT,WATSONX_PROJECT_ID,OLLAMA_BASE_URL" + + # Probes + livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + # Service configuration + service: + type: ClusterIP + port: 7860 + +# ============================================================================ +# OpenRAG Backend Configuration +# ============================================================================ +backend: + enabled: true + + image: + repository: langflowai/openrag-backend + tag: "" # Uses global.imageTag if empty + + # Single pod for vertical scaling + replicaCount: 1 + + # Resource requests/limits + resources: + requests: + cpu: "500m" + memory: "2Gi" + limits: + cpu: "4" + memory: "16Gi" + + # Persistence for documents, keys, and config + persistence: + documents: + enabled: true + storageClass: "" + accessMode: ReadWriteOnce + size: 50Gi + mountPath: /app/openrag-documents + keys: + enabled: true + storageClass: "" + accessMode: ReadWriteOnce + size: 1Gi + mountPath: /app/keys + config: + enabled: true + storageClass: "" + accessMode: ReadWriteOnce + size: 1Gi + mountPath: /app/config + + # Feature flags + features: + disableIngestWithLangflow: false # Set true to use traditional processor instead of Langflow + + # Langflow public URL (for UI links to Langflow) + langflowPublicUrl: "" # e.g., "https://langflow.example.com" + + # Webhook configuration for continuous ingestion + webhook: + enabled: false + baseUrl: "" # DNS routable URL for webhooks (e.g., ngrok URL) + + # AWS credentials for S3 integration + aws: + enabled: false + accessKeyId: "" + secretAccessKey: "" + + # Probes + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + enabled: true + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + # Service configuration + service: + type: ClusterIP + port: 8000 + +# ============================================================================ +# OpenRAG Frontend Configuration +# ============================================================================ +frontend: + enabled: true + + image: + repository: langflowai/openrag-frontend + tag: "" # Uses global.imageTag if empty + + # Can be multiple replicas (stateless) + replicaCount: 2 + + # Resource requests/limits + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "1" + memory: "1Gi" + + # Horizontal Pod Autoscaler + autoscaling: + enabled: false + minReplicas: 2 + maxReplicas: 10 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 80 + + # Probes + livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + + # Service configuration + service: + type: ClusterIP + port: 3000 + +# ============================================================================ +# OpenSearch Dashboards Configuration (Optional) +# ============================================================================ +dashboards: + enabled: false # Enable only if dashboards available in OS SaaS + + image: + repository: opensearchproject/opensearch-dashboards + tag: "3.0.0" + + replicaCount: 1 + + # Resource requests/limits + resources: + requests: + cpu: "100m" + memory: "512Mi" + limits: + cpu: "1" + memory: "2Gi" + + # Probes + livenessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 30 + readinessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + + # Service configuration + service: + type: ClusterIP + port: 5601 + +# ============================================================================ +# Ingress Configuration +# ============================================================================ +ingress: + enabled: true + className: "nginx" # nginx, alb, traefik, etc. + + # Annotations for ingress controller + annotations: {} + # For nginx: + # nginx.ingress.kubernetes.io/proxy-body-size: "100m" + # nginx.ingress.kubernetes.io/proxy-read-timeout: "300" + # For AWS ALB: + # alb.ingress.kubernetes.io/scheme: internet-facing + # alb.ingress.kubernetes.io/target-type: ip + + # Host configuration + hosts: + frontend: + host: "" # e.g., "openrag.example.com" + paths: + - path: / + pathType: Prefix + backend: + host: "" # e.g., "api.openrag.example.com" + paths: + - path: / + pathType: Prefix + langflow: + enabled: false # Optional: expose Langflow directly + host: "" # e.g., "langflow.openrag.example.com" + paths: + - path: / + pathType: Prefix + dashboards: + enabled: false # Only if dashboards.enabled is true + host: "" + paths: + - path: / + pathType: Prefix + + # TLS configuration + tls: + enabled: false + # Use existing secret: + # secretName: "openrag-tls" + + # Or use cert-manager: + certManager: + enabled: false + issuerRef: + name: "letsencrypt-prod" + kind: "ClusterIssuer" + +# ============================================================================ +# LLM Provider API Keys +# ============================================================================ +llmProviders: + openai: + enabled: false + apiKey: "" # OpenAI API key (stored in secret) + anthropic: + enabled: false + apiKey: "" # Anthropic API key (stored in secret) + watsonx: + enabled: false + apiKey: "" # WatsonX API key (stored in secret) + endpoint: "https://us-south.ml.cloud.ibm.com" + projectId: "" # WatsonX project ID + ollama: + enabled: false + endpoint: "" # Ollama endpoint URL (e.g., "http://ollama:11434") + +# ============================================================================ +# Application Config (config.yaml contents) +# ============================================================================ +appConfig: + agent: + llmModel: "claude-sonnet-4-5-20250929" + llmProvider: "anthropic" + # System prompt can be customized here + systemPrompt: "" # Leave empty to use default + knowledge: + chunkOverlap: 200 + chunkSize: 1000 + embeddingModel: "text-embedding-3-large" + embeddingProvider: "openai" + ocr: false + pictureDescriptions: false + tableStructure: true + +# ============================================================================ +# Service Account +# ============================================================================ +serviceAccount: + create: true + name: "" + annotations: {} + +# ============================================================================ +# Pod Security +# ============================================================================ +podSecurityContext: + fsGroup: 1000 + runAsNonRoot: true + +securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsUser: 1000 + runAsGroup: 1000 + +# ============================================================================ +# Node Placement +# ============================================================================ +nodeSelector: {} + +tolerations: [] + +affinity: {} + +# ============================================================================ +# Pod Disruption Budgets +# ============================================================================ +podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1