# langfuse-k8s
[](https://artifacthub.io/packages/search?repo=langfuse-k8s)
This is a community-maintained repository that contains resources for deploying Langfuse on Kubernetes.
Please feel free to contribute any improvements or suggestions.
Langfuse self-hosting documentation: https://langfuse.com/self-hosting
## Repository Structure
- `examples` directory contains example `yaml` configurations
- `charts/langfuse` directory contains Helm chart for deploying Langfuse with an associated database
## Installing Langfuse v4
Chart **v2.0.0** ships [Langfuse v4](https://langfuse.com/docs/v4) by default. For new installations we recommend adopting v4.
Please follow the [minimal installation](./examples/minimal-installation/).
If you want to upgrade an **existing Langfuse application** from v3 to v4, follow the [application upgrade guide](https://langfuse.com/self-hosting/upgrade/upgrade-guides/upgrade-v3-to-v4). That is a separate step from the Helm chart v1 → v2 migration.
If you still run the **Bitnami-based chart (v1.x)**, migrate the chart first via [`examples/upgrade-v1-to-v2`](./examples/upgrade-v1-to-v2/) (keep the same Langfuse application version while copying data), then follow the application v3 → v4 guide. You can also subscribe to [OSS release updates](https://langfuse.com/self-hosting/upgrade#release-notes) and the [GitHub discussion](https://github.com/orgs/langfuse/discussions/12518).
For all new setups we recommend these minimum versions for Langfuse v4:
- ClickHouse: 25.12 minimum, 26.8 (LTS) recommended
- Postgres: 16 recommended
- Redis: 7.2 recommended
## ℹ️ ClickHouse 26.8 LTS in v2.2.0
Chart **v2.2.0** bumps the bundled ClickHouse server and Keeper images from `26.4` to **`26.8.36.3-lts`** (`clickhouse.cluster.image.tag` / `clickhouse.keeper.image.tag`). The tag is now pinned to an exact LTS patch release instead of a floating minor tag.
- If you deploy ClickHouse via this chart (`clickhouse.deploy: true`) and do not override the image tags, `helm upgrade` will make the clickhouse-operator roll your ClickHouse and Keeper pods onto 26.8. Plan for a short restart window and take a backup first.
- To stay on your current version, pin `clickhouse.cluster.image.tag` and `clickhouse.keeper.image.tag` explicitly before upgrading.
- External ClickHouse setups (`clickhouse.deploy: false`) are unaffected.
## ⚠️ Breaking changes in v2.0.0
v2.0.0 replaces the Bitnami sub-charts with OSS-licensed alternatives and deploys ClickHouse via the upstream [`ClickHouse/clickhouse-operator`](https://github.com/ClickHouse/clickhouse-operator). The chart ships [Langfuse v4](https://langfuse.com/docs/v4) by default (override `langfuse.image.tag` only if you intentionally need another release).
| Component | v1.x | v2.0.0 |
|-----------|------|--------|
| PostgreSQL | `bitnami/postgresql` | [`groundhog2k/postgres`](https://artifacthub.io/packages/helm/groundhog2k/postgres) |
| ClickHouse | `bitnami/clickhouse` | [`ClickHouseCluster` / `KeeperCluster`](https://github.com/ClickHouse/clickhouse-operator) CRs (cluster-wide operator) |
| Redis | `bitnami/valkey` | [`valkey-io/valkey`](https://github.com/valkey-io/valkey-helm) |
| Object storage | `bitnami/minio` | [`seaweedfs/seaweedfs`](https://github.com/seaweedfs/seaweedfs) (allInOne) |
On first install the chart auto-generates credential Secrets for Postgres, ClickHouse, Valkey, SeaweedFS, **and** the three Langfuse application secrets (`salt`, `encryptionKey`, `nextauth.secret`), persisted across upgrades via `lookup`. You can still pin any of them with `value` / `secretKeyRef` when needed (e.g. migrations). The generated Secrets carry `helm.sh/resource-policy: keep`, so they survive `helm uninstall` — delete them manually if you really want a clean slate.
> [!WARNING]
> **GitOps / ArgoCD:** tools that render with `helm template` (ArgoCD, `helm template | kubectl apply` pipelines) cannot use `lookup`, so auto-generated credentials would be **regenerated on every sync** — rotating `salt` breaks all hashed API keys and rotating `encryptionKey` makes previously encrypted data unreadable. In those pipelines, pin **all** credentials explicitly (`value` / `secretKeyRef` / `existingSecret`). Flux's helm-controller performs real Helm installs and is not affected.
**Do not `helm upgrade` v1 → v2 onto empty v2 volumes.** That would replace Bitnami data. The supported path is [`examples/upgrade-v1-to-v2`](./examples/upgrade-v1-to-v2/): in-place upgrade when every store is already external (`*.deploy: false`); otherwise stand up a sibling v2 release, copy data, then shift traffic. The chart blocks an upgrade that would replace leftover Bitnami ClickHouse (`-clickhouse-shard0`), Postgres (`data--postgresql-0`), or MinIO (`-s3`) with empty volumes. Only set `langfuse.allowV1Upgrade=true` if you intentionally need to override that guard.
## Helm Chart
We provide a Helm chart that helps you deploy Langfuse on Kubernetes.
### Prerequisites
- **Helm `v3.17` or newer.** The bundled `seaweedfs` sub-chart uses the `fromToml` template function, which was added in Helm 3.17.0.
- **Kubernetes `v1.28` or newer**, as required by the [ClickHouse operator](https://github.com/ClickHouse/clickhouse-operator).
When `clickhouse.deploy: true` (the default), the chart renders `ClickHouseCluster` / `KeeperCluster` CRs. The operator creates its own cert-manager `Certificate` / `Issuer` resources for webhooks. Both CRD sets must already exist before `helm install`. Install these **once per cluster**:
```bash
# 1. cert-manager (skip if already installed)
helm install cert-manager oci://quay.io/jetstack/charts/cert-manager \
--version v1.20.2 \
--namespace cert-manager --create-namespace \
--set crds.enabled=true
kubectl wait --for=condition=Established \
crd/certificates.cert-manager.io crd/issuers.cert-manager.io \
--timeout=120s
# 2. clickhouse-operator
helm install clickhouse-operator oci://ghcr.io/clickhouse/clickhouse-operator-helm \
--version 0.0.8 \
--namespace clickhouse-operator --create-namespace
kubectl wait --for=condition=Established \
crd/clickhouseclusters.clickhouse.com crd/keeperclusters.clickhouse.com \
--timeout=120s
```
The chart preflights the ClickHouse CRDs when `clickhouse.crdCheck: true` (default). For offline `helm template` / GitOps diff, set `clickhouse.crdCheck=false` or pass `--api-versions clickhouse.com/v1alpha1/ClickHouseCluster`.
### Installation
The fastest path is to follow [`examples/minimal-installation`](./examples/minimal-installation/) — a minimal install of Langfuse with all bundled sub-charts, using a single pre-created Secret for credentials.
```bash
kubectl create namespace langfuse
# Edit examples/minimal-installation/secret.yaml, then:
kubectl apply -f examples/minimal-installation/secret.yaml -n langfuse
helm install langfuse oci://ghcr.io/langfuse/langfuse-k8s/charts/langfuse \
--version 2.0.0 \
--namespace langfuse \
-f examples/minimal-installation/values.yaml
```
Alternatively, the chart is also published via the legacy Helm repo:
```bash
helm repo add langfuse https://langfuse.github.io/langfuse-k8s
helm repo update
helm install langfuse langfuse/langfuse -n langfuse -f values.yaml
```
To use a different Secret or External Secrets Operator, point `langfuse.salt` / `encryptionKey` / `nextauth.secret` (and the datastore `auth.existingSecret` fields) at your Secret — see [`examples/minimal-installation`](./examples/minimal-installation/). To pin a non-default Langfuse image, set `langfuse.image.tag`.
### Upgrading
```bash
helm repo update
helm upgrade langfuse langfuse/langfuse
```
Please validate whether the helm sub-charts in the Chart.yaml were updated between versions.
If yes, follow the guide for the respective sub-chart to upgrade it.
The ClickHouse operator is installed separately, so upgrade it on its own when the [Prerequisites](#prerequisites) move to a new version. Its chart ships the CRDs as templates, so `helm upgrade` updates them too. Review the [operator release notes](https://github.com/ClickHouse/clickhouse-operator/releases) first:
```bash
helm upgrade clickhouse-operator oci://ghcr.io/clickhouse/clickhouse-operator-helm \
--version 0.0.8 \
--namespace clickhouse-operator
```
Upgrading a **v1 (Bitnami) release to v2** onto empty v2 volumes is blocked. Follow [`examples/upgrade-v1-to-v2`](./examples/upgrade-v1-to-v2/): in-place upgrade when every store is already external; otherwise install a sibling v2 release, copy data, then shift traffic.
### Sizing
By default, the chart will run with the minimum resources to provide a stable experience.
For production environments, we recommend to adjust the following parameters in the values.yaml.
See [Langfuse documentation](https://langfuse.com/self-hosting/scaling) for our full sizing guide.
```yaml
langfuse:
resources:
limits:
cpu: "2"
memory: "4Gi"
requests:
cpu: "2"
memory: "4Gi"
postgresql:
resources:
limits:
cpu: "2"
memory: "2Gi"
requests:
cpu: "500m"
memory: "512Mi"
clickhouse:
cluster:
storage:
size: 100Gi
resources:
limits:
cpu: "2"
memory: "8Gi"
requests:
cpu: "2"
memory: "8Gi"
keeper:
storage:
size: 20Gi
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "500m"
memory: "512Mi"
redis:
resources:
limits:
cpu: "1"
memory: "1.5Gi"
requests:
cpu: "1"
memory: "1.5Gi"
s3:
allInOne:
resources:
limits:
cpu: "2"
memory: "4Gi"
requests:
cpu: "2"
memory: "4Gi"
```
### Configuration
No application or datastore credentials are required for a fresh install — the chart auto-generates `salt`, `encryptionKey`, `nextauth.secret`, and the Postgres / ClickHouse / Valkey / SeaweedFS credentials on first install (persisted across upgrades via `lookup`). Pin any of them with `value` / `secretKeyRef` / `existingSecret` when you need stable known credentials.
Provide the Langfuse secrets either inline:
```yaml
langfuse:
salt:
value: ""
encryptionKey:
value: ""
nextauth:
secret:
value: ""
```
…or as references to an existing Kubernetes Secret:
```yaml
langfuse:
salt:
secretKeyRef:
name: langfuse
key: salt
encryptionKey:
secretKeyRef:
name: langfuse
key: encryption-key
nextauth:
secret:
secretKeyRef:
name: langfuse
key: nextauth-secret
```
To pin the sub-component credentials instead of letting the chart generate them, set `.auth.password` (or `.auth.existingSecret`):
```yaml
postgresql:
auth:
username: langfuse
existingSecret: langfuse-postgresql-auth
secretKeys:
userPasswordKey: password
clickhouse:
auth:
existingSecret: langfuse-clickhouse-auth
existingSecretKey: password
redis:
auth:
existingSecret: langfuse-redis-auth
existingSecretPasswordKey: password
s3:
auth:
# If existingSecret is set, both root user and root password must be supplied via the secret
existingSecret: langfuse-s3-auth
rootUserSecretKey: rootUser
rootPasswordSecretKey: rootPassword
```
See the [Helm README](https://github.com/langfuse/langfuse-k8s/blob/main/charts/langfuse/README.md) for a full list of all configuration options.
#### Langfuse AI features
The AI features — the in-app agent and Ask AI — run on one instance-wide Langfuse AI model. Requires Langfuse `>= 4.24` (`langfuse.image.tag`). Set `langfuse.aiFeatures.provider` and `langfuse.aiFeatures.model`.
Helm does not create AWS Lambda MicroVM resources for the agent's code execution sandbox — either let [langfuse-terraform-aws](https://github.com/langfuse/langfuse-terraform-aws) create them, or create them by hand and pass the ARNs into `langfuse.aiFeatures.inAppAgent.sandbox`. See the [self-hosted docs](https://langfuse.com/self-hosting/configuration/langfuse-assistant).
```yaml
langfuse:
image:
tag: "4.24.0" # or newer
aiFeatures:
provider: bedrock
model: eu.anthropic.claude-opus-5
bedrockRegion: eu-west-1
inAppAgent:
enabled: true
mcp:
useInternalWebUrl: true
sandbox:
provider: lambda-microvm
imageIdentifier: arn:aws:lambda:eu-west-1:123456789012:microvm-image:langfuse-in-app-agent-sandbox
executionRoleArn: arn:aws:iam::123456789012:role/langfuse-agent-sandbox-execution
region: eu-west-1
egressNetworkConnectorArn: arn:aws:lambda:eu-west-1:123456789012:network-connector:langfuse-agent-sandbox-egress
```
`egressNetworkConnectorArn` is required with the `lambda-microvm` provider: without it AWS attaches its default `INTERNET_EGRESS` connector and sandboxed code reaches the public internet.
`mcp.useInternalWebUrl` points the worker's MCP calls at the in-cluster web Service. It sets `LANGFUSE_MCP_BASE_URL` and leaves `NEXTAUTH_URL` alone, because the worker also builds links for users out of `NEXTAUTH_URL` in batch export emails and Slack notifications. This one value requires Langfuse `>= 4.25`; the rest of the block works on `>= 4.24`.
#### Storage Provider Options
Langfuse supports multiple blob storage providers through the `s3.storageProvider` configuration:
- **`s3`** (default): Uses S3-compatible interface. Works with AWS S3, MinIO, Cloudflare R2, and other S3-compatible services.
- **`azure`**: Uses Azure Blob Storage native integration. Requires Azure Storage Account credentials.
- **`gcs`**: Uses Google Cloud Storage native integration. Requires GCS service account credentials.
By default, the system uses the S3-compatible method.
When Azure or GCS is selected, the respective native storage integration is enabled with the appropriate environment variables.
See our [self-hosting docs](https://langfuse.com/self-hosting/infrastructure/blobstorage) for more details on Blob Storage configurations.
#### Examples
> [!IMPORTANT]
> External PostgreSQL and ClickHouse instances must use UTC. See the [timezone troubleshooting guide](https://langfuse.com/faq/all/self-hosting-timezone-errors) for verification steps and fixes.
##### With an external Postgres server
```yaml
[...]
postgresql:
deploy: false
auth:
username: my-username
password: my-password
database: my-database
host: my-external-postgres-server.com
directUrl: postgres://my-username:my-password@my-external-postgres-server.com
shadowDatabaseUrl: postgres://my-username:my-password@my-external-postgres-server.com
```
##### With an external ClickHouse cluster
This works for any ClickHouse deployment that runs outside of this chart, e.g. a cluster
managed by the [ClickHouse Operator](#prerequisites) with `clickhouse.deploy: false`
(see also [`examples/external-components/external-clickhouse.yaml`](./examples/external-components/external-clickhouse.yaml)):
```yaml
[...]
clickhouse:
deploy: false
host: my-clickhouse-host
# For a single-node / non-replicated instance, also set:
# cluster:
# enabled: false
auth:
username: default
password: my-password
```
For [ClickHouse Cloud](https://clickhouse.com/cloud), use the HTTPS endpoint of your service together with the secure ports and SSL for migrations:
```yaml
[...]
clickhouse:
deploy: false
host: https://..aws.clickhouse.cloud
httpPort: 8443
nativePort: 9440
auth:
username: default
password: my-password
migration:
ssl: true
```
##### With an external S3 bucket
```yaml
[...]
s3:
deploy: false
bucket: "langfuse-bucket"
region: "eu-west-1"
endpoint: "https://s3.eu-west-1.amazonaws.com"
forcePathStyle: false
accessKeyId:
value: "mykey"
secretAccessKey:
value: "mysecret"
eventUpload:
prefix: "events/"
batchExport:
prefix: "exports/"
mediaUpload:
prefix: "media/"
```
##### With Azure Blob Storage
```yaml
[...]
s3:
deploy: false
storageProvider: "azure"
bucket: "langfuse" # Container name - If it does not exist, Langfuse will attempt to create it
accessKeyId:
value: "devstoreaccount1" # Azure Storage Account name
secretAccessKey:
value: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" # Azure Storage Account key
endpoint: "https://yourstorageaccount.blob.core.windows.net"
eventUpload:
prefix: "events/"
batchExport:
prefix: "exports/"
mediaUpload:
prefix: "media/"
```
##### With Google Cloud Storage
```yaml
[...]
s3:
deploy: false
storageProvider: "gcs"
bucket: "langfuse" # GCS bucket name
gcs:
credentials:
value: |
{
"type": "service_account",
"project_id": "your-project-id",
"private_key_id": "your-private-key-id",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "your-service-account@your-project-id.iam.gserviceaccount.com",
"client_id": "your-client-id",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/your-service-account%40your-project-id.iam.gserviceaccount.com"
}
eventUpload:
prefix: "events/"
batchExport:
prefix: "exports/"
mediaUpload:
prefix: "media/"
```
Alternatively, you can reference the credentials from a secret:
```yaml
[...]
s3:
deploy: false
storageProvider: "gcs"
bucket: "langfuse"
gcs:
credentials:
secretKeyRef:
name: "gcs-credentials"
key: "credentials.json"
eventUpload:
prefix: "events/"
batchExport:
prefix: "exports/"
mediaUpload:
prefix: "media/"
```
##### With Redis Cluster
Langfuse supports Redis Cluster mode for high-availability and scalability. Configure Redis in one of two ways:
**Standalone Mode (Default):**
```yaml
redis:
deploy: false # Set to false for external Redis
host: "my-redis.example.com"
port: 6379
auth:
password: "your-password"
```
**Cluster Mode:**
```yaml
redis:
deploy: false # Must be false - deployed Redis doesn't support cluster mode
cluster:
enabled: true
nodes:
- "redis-node-1:6379"
- "redis-node-2:6379"
- "redis-node-3:6379"
- "redis-node-4:6379"
- "redis-node-5:6379"
- "redis-node-6:6379"
auth:
password: "your-cluster-password"
```
**Redis Cluster with TLS:**
```yaml
redis:
deploy: false
cluster:
enabled: true
nodes:
- "redis-node-1:6379"
- "redis-node-2:6379"
- "redis-node-3:6379"
auth:
password: "your-cluster-password"
tls:
enabled: true
caPath: "/certs/ca.crt"
certPath: "/certs/client.crt"
keyPath: "/certs/client.key"
```
**AWS ElastiCache Example:**
For AWS ElastiCache Redis Cluster, use the configuration endpoint that automatically discovers all cluster nodes:
```yaml
redis:
deploy: false
cluster:
enabled: true
nodes:
- "clustercfg.my-redis-cluster.abc123.cache.amazonaws.com:6379"
auth:
password: "your-auth-token"
tls:
enabled: true
```
#### Use custom deployment strategy
```yaml
[...]
langfuse:
deployment:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 50%
maxUnavailable: 50%
```
##### Enable ingress
```yaml
[...]
langfuse:
ingress:
enabled: true
hosts:
- host: langfuse.your-host.com
paths:
- path: /
pathType: Prefix
annotations: []
```
##### Ingress with custom backend (AWS Load Balancer Controller redirect)
Use custom backends to configure AWS Load Balancer Controller redirects or other advanced routing:
```yaml
[...]
langfuse:
ingress:
enabled: true
className: "alb"
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
# Redirect action annotation
alb.ingress.kubernetes.io/actions.redirect-to-langfuse: |
{
"type": "redirect",
"redirectConfig": {
"protocol": "HTTPS",
"port": "443",
"host": "langfuse.example.com",
"statusCode": "HTTP_301"
}
}
hosts:
# Main service host - uses default backend
- host: langfuse.example.com
paths:
- path: /
pathType: Prefix
# Redirect host - uses custom backend for redirect
- host: langfuse-v3.example.com
paths:
- path: /
pathType: Prefix
backend:
service:
name: redirect-to-langfuse
port:
name: use-annotation
```
##### Ingress with mixed backends
Configure different backends for different paths within the same host:
```yaml
[...]
langfuse:
ingress:
enabled: true
hosts:
- host: langfuse.example.com
paths:
# Default backend for main application
- path: /
pathType: Prefix
# Custom backend for specific path
- path: /api/webhook
pathType: Prefix
backend:
service:
name: webhook-service
port:
number: 8080
```
#### Custom Storage Class Definition
The Langfuse chart supports configuring storage classes for all persistent volumes in the deployment. You can configure storage classes in two ways:
1. **Global Storage Class**: Set a global storage class that will be used for all persistent volumes unless overridden.
```yaml
global:
defaultStorageClass: "your-storage-class"
```
2. **Component-specific Storage Classes**: Override the storage class for specific components.
```yaml
postgresql:
storage:
className: "postgres-storage-class"
redis:
dataStorage:
className: "redis-storage-class"
clickhouse:
cluster:
storage:
className: "clickhouse-storage-class"
keeper:
storage:
className: "clickhouse-keeper-storage-class"
s3:
allInOne:
data:
storageClass: "seaweedfs-storage-class"
```
If no storage class is specified, the cluster's default storage class will be used.
##### With an external Postgres server with client certificates using own secrets and additionalEnv for mappings
The Langfuse application reads `DATABASE_URL`, `SALT`, and `NEXTAUTH_SECRET` from environment variables, so an `additionalEnv` override takes precedence over the chart's defaults. Combine that with `extraVolumes` to mount client certificates from a Secret:
```yaml
langfuse:
salt:
secretKeyRef:
name: langfuse-general
key: salt
nextauth:
secret:
secretKeyRef:
name: langfuse-general
key: nextauth-secret
extraVolumes:
- name: db-keystore # referencing an existing secret to mount server/client certs for postgres
secret:
secretName: langfuse-postgres # contain the following files (server-ca.pem, sslidentity.pk12)
extraVolumeMounts:
- name: db-keystore
mountPath: /secrets/db-keystore # mounting the db-keystore store certs in the pod under the given path
readOnly: true
additionalEnv:
- name: DATABASE_URL # Using the certs in the url eg. postgresql://the-db-user:the-password@postgres-host:5432/langfuse?ssl=true&sslmode=require&sslcert=/secrets/db-keystore/server-ca.pem&sslidentity=/secrets/db-keystore/sslidentity.pk12&sslpassword=the-ssl-identity-pw
valueFrom:
secretKeyRef:
name: langfuse-postgres # referencing an existing secret
key: database-url
postgresql:
deploy: false
# When DATABASE_URL is overridden via additionalEnv above, the auth block is only
# used to render the chart's connection-string env vars (which the additionalEnv
# entry replaces). Leave the defaults or set host/auth.username to match.
host: my-external-postgres-server.com
auth:
username: langfuse
```
##### With SSO provider configuration using secrets and additionalEnv
This example shows how to configure Okta SSO by setting the required environment variables from secrets using the `additionalEnv` pattern:
```yaml
langfuse:
additionalEnv:
- name: AUTH_OKTA_CLIENT_ID
valueFrom:
secretKeyRef:
name: okta-secrets
key: AUTH_OKTA_CLIENT_ID
- name: AUTH_OKTA_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: okta-secrets
key: AUTH_OKTA_CLIENT_SECRET
- name: AUTH_OKTA_ISSUER
valueFrom:
secretKeyRef:
name: okta-secrets
key: AUTH_OKTA_ISSUER
```
You would need to create the corresponding secret:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: okta-secrets
type: Opaque
stringData:
AUTH_OKTA_CLIENT_ID: "your-okta-client-id"
AUTH_OKTA_CLIENT_SECRET: "your-okta-client-secret"
AUTH_OKTA_ISSUER: "https://your-domain.okta.com"
```
This pattern works for any SSO provider supported by Langfuse. See the [Authentication and SSO documentation](https://langfuse.com/self-hosting/authentication-and-sso#sso) for other providers and their required environment variables.
##### With overrides for hostAliases
This is going to add a record to the /etc/hosts file of all containers
under the langfuse-web pod in such a way that every traffic towards "oauth.id.jumpcloud.com" is going to be forwarded to the localhost network.
```yaml
langfuse:
web:
hostAliases:
- ip: 127.0.0.1
hostnames:
- "oauth.id.jumpcloud.com"
```
##### With topology spread constraints
Distribute pods evenly across different zones to improve high availability:
```yaml
langfuse:
# Global topology spread constraints applied to all langfuse pods
pod:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/instance: langfuse
# Component-specific topology spread constraints
web:
pod:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
worker:
pod:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: worker
```
## Testing
This repository includes testing to ensure the Helm chart works correctly across different configurations.
### Setup
Install the helm unittest plugin using
```shell
helm plugin install https://github.com/helm-unittest/helm-unittest.git
```
### Running Tests Locally
```bash
helm unittest charts/langfuse --color
```