📊 feat: Improve Helm Chart (#3638)

* Replaced Helm Charts with Blue Atlas Charts

* Fix Workflow

* improve docs

* update gitignore

* Update docs

* change values order, add hpa

* change tls example domain

* Default: Enable liveness and readiness

* chore: bump base chart

* apply requested changes

* add Release fix

* add: error handling

* chore: cleanup and testing

* fix: adjust Chart.yaml

---------

Co-authored-by: hofq <gregorspalme@protonmail.com>
Co-authored-by: Ruben Talstra <RubenTalstra1211@outlook.com>
This commit is contained in:
hofq 2025-05-17 21:52:16 +02:00 committed by GitHub
parent 26780bddf0
commit 844bbbb162
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 1047 additions and 0 deletions

View file

@ -0,0 +1,33 @@
apiVersion: v2
name: librechat-rag-api
description: A Helm chart for LibreChat
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.5.2
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
# renovate: image=ghcr.io/danny-avila/librechat-rag-api-dev
appVersion: "v0.4.0"
home: https://www.librechat.ai
dependencies:
- name: postgresql
version: "15.5.38"
condition: postgresql.enabled
repository: "https://charts.bitnami.com/bitnami"

View file

@ -0,0 +1,4 @@
# Librechat RAG API Helm CHart
> [!WARNING]
> This Helm-Chart is needed for LibreChat and Deployment information is documented in (the librechat chart)[../librechat/readme.md]

View file

@ -0,0 +1,65 @@
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "rag.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "rag.fullname" -}}
{{- if $.Values.fullnameOverride }}
{{- $.Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "rag.labels" -}}
helm.sh/chart: {{ include "rag.chart" . }}
{{ include "rag.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
RAG Selector labels
*/}}
{{- define "rag.selectorLabels" -}}
app.kubernetes.io/name: {{ include "rag.fullname" . }}-rag
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "rag.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "rag.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{- define "rag.dbsecretValue" -}}
{{- $secret := .Values.postgresql.auth.existingSecret -}}
{{- $key := "password" -}}
{{- printf "%s" (include "exec" (dict "command" "kubectl" "args" (list "get" "secret" $secret "-o=jsonpath={.data." $key "}"))) | b64enc -}}
{{- end -}}

View file

@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "rag.fullname" $ | lower}}-config
data:
POSTGRES_DB: {{ .Values.postgresql.auth.database }}
POSTGRES_USER: {{ .Values.postgresql.auth.username }}
DB_HOST: {{ .Release.Name }}-postgresql.{{ .Release.Namespace | lower }}.svc.cluster.local
{{- toYaml .Values.rag.configEnv | nindent 2 }}

View file

@ -0,0 +1,94 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "rag.fullname" $ }}
labels:
{{- include "rag.labels" . | nindent 4 }}
rag-component: rag
spec:
replicas: {{ .Values.rag.replicaCount }}
selector:
matchLabels:
{{- include "rag.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
{{- with .Values.rag.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "rag.selectorLabels" . | nindent 8 }}
{{- with .Values.rag.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ include "rag.fullname" $ }}-rag
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
envFrom:
- configMapRef:
name: {{ include "rag.fullname" $ }}-config
{{- if .Values.rag.existingSecret }}
- secretRef:
name: {{ .Values.rag.existingSecret }}
{{- end }}
env:
{{- if .Values.postgresql.auth.existingSecret }}
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.postgresql.auth.existingSecret }}
key: {{ .Values.postgresql.auth.existingSecretKey }}
{{- end }}
{{- if .Values.global.librechat.existingSecretName }}
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.global.librechat.existingSecretName }}
key: {{ .Values.global.librechat.existingSecretApiKey }}
optional: true
{{- end }}
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.extraContainers }}
{{ toYaml . | nindent 8 }}
{{- end }}
volumes:
{{- 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 }}

View file

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "rag.fullname" . }}
labels:
{{- include "rag.labels" . | nindent 4 }}
annotations:
{{- toYaml .Values.service.annotations | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "rag.selectorLabels" . | nindent 4 }}

View file

@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "rag.fullname" . }}-test-connection"
labels:
{{- include "rag.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "rag.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

View file

@ -0,0 +1,12 @@
{{ if not .Values.postgresql.auth.existingSecret }}
apiVersion: v1
kind: Secret
metadata:
name: librechat-vectordb
type: Opaque
data:
# generate 32 chars long random string, base64 encode it and then double-quote the result string.
postgres-password: {{ randAlphaNum 32 | b64enc | quote }}
password: {{ randAlphaNum 32 | b64enc | quote }}
replication-password: {{ randAlphaNum 32 | b64enc | quote }}
{{ end }}

View file

@ -0,0 +1,95 @@
# Required as vectorDB for RAG
# provide context-aware responses based on user-uploaded files
rag:
enabled: true
existingSecret: ''
configEnv:
DB_PORT: '5432'
EMBEDDINGS_PROVIDER: openai
image:
repository: danny-avila/librechat-rag-api-dev-lite # there is rag-api-dev and rag-api-dev-lite. currently only lite is docuimented
registry: ghcr.io
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: latest
postgresql:
enabled: true
# nameOverride: vectordb
image:
registry: ghcr.io
repository: bat-bs/bitnami-pgvector
tag: pg16
auth:
database: librechat-vectordb
username: postgres
# define a secret with values for "postgres-password", "password" (user Password) and "replication-password" or add values directly
existingSecret: librechat-vectordb
# postgres-password is needed to enable pgvector extension. If you enable it manually you can use "password" and user "librechat"
existingSecretKey: postgres-password
imagePullSecrets: []
nameOverride: ''
fullnameOverride: ''
podAnnotations: {}
podLabels: {}
podSecurityContext: {} # fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 8000
annotations: {}
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
# livenessProbe:
# httpGet:
# path: /
# port: http
# readinessProbe:
# httpGet:
# path: /
# port: http
# Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
# Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: {}
tolerations: []
affinity: {}
extraContainers: {}

23
helm/librechat/.helmignore Executable file
View file

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

41
helm/librechat/Chart.yaml Executable file
View file

@ -0,0 +1,41 @@
apiVersion: v2
name: librechat
description: A Helm chart for LibreChat
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.8.8
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
# renovate: image=ghcr.io/danny-avila/librechat
appVersion: "v0.7.7"
home: https://www.librechat.ai
dependencies:
- name: mongodb
version: "16.3.0"
condition: mongodb.enabled
repository: "https://charts.bitnami.com/bitnami"
- name: meilisearch
version: "0.11.0"
condition: meilisearch.enabled
repository: "https://meilisearch.github.io/meilisearch-kubernetes"
- name: librechat-rag-api
version: "0.5.2"
condition: librechat-rag-api.enabled
repository: file://../librechat-rag-api

37
helm/librechat/readme.md Executable file
View file

@ -0,0 +1,37 @@
# LibreChat Helm Chart
This Librechat Helm Chart provides an easy, light weight template to deploy LibreChat on Kubernetes
## Variables
In this Chart, LibreChat will only work with environment Variables. You can Specify Vars and Secret using an existing Secret (This can be generated by [creating an Env File and converting it to a Kubernetes Secret](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-secret-em-) `--from-env-file`)
## Setup
1. Generate Variables
Generate `CREDS_KEY`, `JWT_SECRET`, `JWT_REFRESH_SECRET` and `MEILI_MASTER_KEY` using `openssl rand -hex 32` and `CREDS_IV` using openssl rand -hex 16.
place them in a secret like this (If you want to change the secret name, remember to change it in your helm values):
```yaml
apiVersion: v1
kind: Secret
metadata:
name: librechat-credentials-env
namespace: <librechat-chart-namespace>
type: Opaque
stringData:
CREDS_KEY: <generated value>
JWT_SECRET: <generated value>
JWT_REFRESH_SECRET: <generated value>
MEILI_MASTER_KEY: <generated value>
```
2. Add Credentials to the Secret
Dependant of the Model you want to use, [create Credentials in your provider](https://docs.librechat.ai/install/configuration/ai_setup.html) and add them to the Secret:
```yaml
apiVersion: v1
kind: Secret
. . . .
OPENAI_API_KEY: <your secret value>
```
3. Apply the Secret to the Cluster
4. Fill out values.yaml and apply the Chart to the Cluster

View file

@ -0,0 +1,22 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "librechat.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "librechat.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "librechat.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "librechat.fullname" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}

View file

@ -0,0 +1,4 @@
{{ if hasKey .Values.env }}
{{ fail "The Value env has been renamed and moved to librechat.configEnv. Refer to https://www.librechat.ai/docs/local/helm_chart#migrate for more information" }}
{{ end }}

View file

@ -0,0 +1,65 @@
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "librechat.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "librechat.fullname" -}}
{{- if $.Values.fullnameOverride }}
{{- $.Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "librechat.labels" -}}
helm.sh/chart: {{ include "librechat.chart" . }}
{{ include "librechat.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "librechat.selectorLabels" -}}
app.kubernetes.io/name: {{ include "librechat.fullname" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
RAG Selector labels
*/}}
{{- define "rag.selectorLabels" -}}
app.kubernetes.io/name: {{ include "librechat.fullname" . }}-rag
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "librechat.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "librechat.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,17 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ include "librechat.fullname" $ }}-configenv
data:
{{- if (index .Values "librechat-rag-api" "enabled") }}
RAG_API_URL: http://{{ include "rag.fullname" (index .Subcharts "librechat-rag-api") | lower }}.{{ .Release.Namespace | lower }}.svc.cluster.local:8000
{{- end }}
{{- if and (not (dig "configEnv" "MEILI_HOST" "" .Values.librechat)) .Values.meilisearch.enabled }}
MEILI_HOST: http://{{ include "meilisearch.fullname" .Subcharts.meilisearch }}.{{ .Release.Namespace | lower }}.svc.cluster.local:7700
{{- end }}
{{- if and (not (dig "configEnv" "MONGO_URI" "" .Values.librechat)) .Values.mongodb.enabled }}
MONGO_URI: mongodb://{{ include "mongodb.service.nameOverride" .Subcharts.mongodb }}.{{ .Release.Namespace | lower }}.svc.cluster.local:27017/LibreChat
{{- end }}
{{- if .Values.librechat.configEnv }}
{{- toYaml .Values.librechat.configEnv | nindent 2 }}
{{- end }}

View file

@ -0,0 +1,10 @@
{{- if .Values.librechat.configYamlContent }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "librechat.fullname" $ }}-config
data:
librechat.yaml: |
{{ .Values.librechat.configYamlContent | toYaml | indent 4 }}
{{- end }}

View file

@ -0,0 +1,104 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "librechat.fullname" $ }}
labels:
{{- include "librechat.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
{{- if .Values.updateStrategy }}
strategy: {{- toYaml .Values.updateStrategy | nindent 4 }}
{{- end }}
selector:
matchLabels:
{{- include "librechat.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
{{ if .Values.librechat.configYamlContent }}checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}{{ end }}
checksum/configEnv: {{ include (print $.Template.BasePath "/configmap-env.yaml") . | sha256sum }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "librechat.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ include "librechat.fullname" $ }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
lifecycle:
{{- toYaml .Values.lifecycle | nindent 12 }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
{{- if or .Values.librechat.configYamlContent .Values.librechat.existingConfigYaml }}
- name: config-yaml
mountPath: "/app/librechat.yaml"
subPath: "librechat.yaml"
readOnly: true
{{- end }}
{{- if .Values.librechat.imageVolume.enabled }}
- name: image-volume
mountPath: "/app/client/public/images"
{{- end }}
{{- if .Values.volumeMounts }}
{{- toYaml .Values.volumeMounts | nindent 10 }}
{{- end }}
envFrom:
- configMapRef:
name: {{ include "librechat.fullname" $ }}-configenv
{{- if .Values.global.librechat.existingSecretName }}
- secretRef:
name: {{ .Values.global.librechat.existingSecretName }}
optional: true
{{- end }}
volumes:
{{- if or .Values.librechat.configYamlContent .Values.librechat.existingConfigYaml }}
- name: config-yaml
configMap:
{{- if .Values.librechat.existingConfigYaml }}
name: {{ .Values.librechat.existingConfigYaml }}
{{- else if .Values.librechat.configYamlContent }}
name: {{ include "librechat.fullname" $ }}-config
{{- end }}
{{- end }}
{{- if .Values.librechat.imageVolume.enabled }}
- name: image-volume
persistentVolumeClaim:
claimName: {{ include "librechat.fullname" $ }}-images
{{- end }}
{{- if .Values.volumes }}
{{- toYaml .Values.volumes | nindent 6 }}
{{- 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 }}

View file

@ -0,0 +1,28 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "librechat.fullname" $ }}
labels:
{{- include "librechat.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "librechat.fullname" $ }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,60 @@
{{- if .Values.ingress.enabled -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ include "librechat.fullname" $ }}
labels:
{{- include "librechat.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ include "librechat.fullname" $ }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ include "librechat.fullname" $ }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,16 @@
{{- if .Values.librechat.imageVolume.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "librechat.fullname" $ }}-images
spec:
accessModes:
- {{ .Values.librechat.imageVolume.accessModes }}
{{- if .Values.librechat.imageVolume.storageClassName }}
storageClassName: {{ .Values.librechat.imageVolume.storageClassName }}
{{- end }}
volumeMode: Filesystem
resources:
requests:
storage: {{ .Values.librechat.imageVolume.size }}
{{- end }}

View file

@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "librechat.fullname" . }}
labels:
{{- include "librechat.labels" . | nindent 4 }}
annotations:
{{- toYaml .Values.service.annotations | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "librechat.selectorLabels" . | nindent 4 }}

View file

@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "librechat.fullname" . }}-test-connection"
labels:
{{- include "librechat.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "librechat.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

234
helm/librechat/values.yaml Executable file
View file

@ -0,0 +1,234 @@
# Default values for librechat.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
global:
# existing Secret for all envs/ only Passwords. Can be locally generated with: kubectl create secret generic librechat-secret-envs --from-env-file=.env.example --dry-run=client -o yaml > secret-envs.yaml
# For better maintainabillity, you can put all vars directly in the config Section and only overwrite Secrets with this if nessesary.
# Required Values:
# - MEILI_MASTER_KEY
librechat:
existingSecretName: "librechat-credentials-env"
# Used for Setting the Right Key, can be something like AZURE_API_KEY, if Azure OpenAI is used
existingSecretApiKey: OPENAI_API_KEY
librechat:
configEnv:
PLUGIN_MODELS: gpt-4,gpt-4-turbo-preview,gpt-4-0125-preview,gpt-4-1106-preview,gpt-4-0613,gpt-3.5-turbo,gpt-3.5-turbo-0125,gpt-3.5-turbo-1106,gpt-3.5-turbo-0613
DEBUG_PLUGINS: "true"
# IMPORTANT -- GENERATE your own: openssl rand -hex 32 and openssl rand -hex 16 for CREDS_IV. Best Practise: Put into Secret. See gloobal.librechat.existingSecretName
CREDS_KEY: 9e95d9894da7e68dd69c0046caf5343c8b1e80c89609b5a1e40e6568b5b23ce6
CREDS_IV: ac028c86ba23f4cd48165e0ca9f2c683
JWT_SECRET: 16f8c0ef4a5d391b26034086c628469d3f9f497f08163ab9b40137092f2909ef
JWT_REFRESH_SECRET: eaa5191f2914e30b9387fd84e254e4ba6fc51b4654968a9b0803b456a54b8418
# Set Config Params here
# ENV_NAME: env-value
# existing Secret for all envs/ only Passwords. Can be locally generated with: kubectl create secret generic librechat-secret-envs --from-env-file=.env.example --dry-run=client -o yaml > secret-envs.yaml
# For better maintainabillity, you can put all vars directly in the config Section and only overwrite Secrets with this if nessesary.
# Required Values:
# - MEILI_MASTER_KEY
existingSecretName: "librechat-credentials-env"
# For adding a custom config yaml-file you can set the contents in this var. See https://www.librechat.ai/docs/configuration/librechat_yaml/example
configYamlContent: ""
# configYamlContent: |
# version: 1.0.8
# cache: true
# interface:
# # Privacy policy settings
# privacyPolicy:
# externalUrl: 'https://librechat.ai/privacy-policy'
# openNewTab: true
# # Terms of service
# termsOfService:
# externalUrl: 'https://librechat.ai/tos'
# openNewTab: true
# registration:
# socialLogins: ["discord", "facebook", "github", "google", "openid"]
# endpoints:
# azureOpenAI:
# # Endpoint-level configuration
# titleModel: "gpt-4o"
# plugins: true
# assistants: true
# groups:
# Group-level configuration
# - group: "my-resource-sweden"
# apiKey: "${SWEDEN_API_KEY}"
# instanceName: "my-resource-sweden"
# deploymentName: gpt-4-1106-preview
# version: "2024-03-01-preview"
# assistants: true
# # Model-level configuration
# models:
# gpt-4o: true
# custom:
# # OpenRouter.ai
# - name: "OpenRouter"
# apiKey: "${OPENROUTER_KEY}"
# baseURL: "https://openrouter.ai/api/v1"
# models:
# default: ["openai/gpt-3.5-turbo"]
# fetch: true
# titleConvo: true
# titleModel: "gpt-3.5-turbo"
# summarize: false
# summaryModel: "gpt-3.5-turbo"
# forcePrompt: false
# modelDisplayLabel: "OpenRouter"
# name of existing Yaml configmap, key must be librechat.yaml
existingConfigYaml: ""
# Volume used to store image Files uploaded to the Web UI
imageVolume:
enabled: true
size: 10G
accessModes: ReadWriteOnce
# storageClassName:
# only lite RAG is supported
librechat-rag-api:
enabled: false
# can be azure, openai, huggingface or huggingfacetei
embeddingsProvider: openai
image:
repository: danny-avila/librechat
registry: ghcr.io
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
lifecycle: {}
# # base for adding a custom banner // see https://github.com/danny-avila/LibreChat/pull/3952 for an example
# postStart:
# exec:
# command: ["/bin/sh", "-c", "npm run update-banner <displayFrom(Format: yyyy-mm-ddTHH:MM:SSZ)> <displayTo(Format: yyyy-mm-ddTHH:MM:SSZ)> <message> <isPublic(true/false)>"]
podAnnotations: {}
podLabels: {}
podSecurityContext:
fsGroup: 2000
securityContext:
capabilities:
drop:
- ALL
# readOnlyRootFilesystem: true # not supported yet
runAsNonRoot: true
runAsUser: 1000
service:
type: ClusterIP
port: 3080
annotations: {}
ingress:
enabled: true
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chat.example.com
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chat.example.com
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
livenessProbe:
httpGet:
path: /health
port: http
readinessProbe:
httpGet:
path: /health
port: http
# Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
# Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: {}
tolerations: []
affinity: {}
# Strategy for LibreChat deployment updates
updateStrategy:
type: RollingUpdate
# MongoDB Parameters
mongodb:
enabled: true
auth:
enabled: false
databases:
- LibreChat
# persistence:
# size: 8Gi
meilisearch:
enabled: true
persistence:
enabled: true
storageClass: ""
image:
tag: "v1.7.3"
auth:
# Use an existing Kubernetes secret for the MEILI_MASTER_KEY
existingMasterKeySecret: "librechat-credentials-env"