Skip to content

Configuration reference

This document covers all configuration surfaces for the nebari-langfuse pack.

For installation instructions and quick-start examples, see README.md.


  1. NebariApp values reference
  2. Langfuse passthrough values
  3. Authentication setup
  4. Secrets
  5. External datastores
  6. Telemetry and security
  7. OTel Collector export to Langfuse

These values configure the NebariApp CRD resource and the Nebari-specific integration layer. They have no effect when nebariapp.enabled: false.

ValueTypeDefaultDescription
nebariapp.enabledboolfalseCreate a NebariApp resource. Set true on Nebari clusters.
nebariapp.namestringlangfuseNebariApp resource name. Changing this also changes the OIDC secret name (<name>-oidc-client); update the secretKeyRef names in your auth values to match.
nebariapp.hostnamestring(required when enabled)FQDN at which Langfuse is reachable, e.g. langfuse.nebari.example.com. Must match langfuse.langfuse.nextauth.url.
nebariapp.service.namestringlangfuse-webKubernetes Service name the NebariApp routes traffic to. Pinned by langfuse.fullnameOverride.
nebariapp.service.portint3000Port on the target Service.
nebariapp.auth.enabledboolfalseEnable Keycloak OAuth integration. Set true on Nebari to provision the OIDC client.
nebariapp.auth.providerstringkeycloakOAuth provider. Only keycloak is supported.
nebariapp.auth.provisionClientbooltrueLet the nebari-operator create and manage the Keycloak client. Set false if you manage the Keycloak client manually.
nebariapp.auth.enforceAtGatewayboolfalseApply an Envoy SecurityPolicy to enforce auth at the gateway layer. Left false because Langfuse handles OAuth natively.
nebariapp.auth.redirectURIstring/api/auth/callback/keycloakOAuth redirect path registered on the Keycloak client. Must match Langfuse’s NextAuth callback path.
nebariapp.auth.scopeslist[openid, profile, email]OIDC scopes requested. These are the minimum required for Langfuse user identity.
nebariapp.auth.groupslist[](Optional) Restrict access to users in these Keycloak groups.
nebariapp.landingPage.enabledboolfalseShow Langfuse on the Nebari landing page.
nebariapp.landingPage.displayNamestringLangfuseDisplay name on the landing page tile.
nebariapp.landingPage.descriptionstringLLM observability, tracing, and prompt management.Short description shown on the tile.
nebariapp.landingPage.iconstringgrafanaIcon identifier for the landing page tile.
nebariapp.landingPage.categorystringMonitoringLanding page category grouping.
nebariapp.landingPage.priorityint100Sort order within the category (lower number = higher position).
nebariapp.gatewaystringpublicEnvoy Gateway to attach the HTTPRoute to.

Values under langfuse.* are passed through to the upstream langfuse/langfuse chart dependency. Because the dependency is named langfuse and the upstream chart also uses a top-level langfuse app-config key, app configuration is double-nested:

langfuse.langfuse.* -> upstream chart's langfuse.* (app config)
langfuse.postgresql.* -> upstream chart's postgresql.* (sub-chart)
langfuse.redis.* -> upstream chart's redis.* (sub-chart)
langfuse.clickhouse.* -> upstream chart's clickhouse.* (sub-chart)
langfuse.s3.* -> upstream chart's s3.* (sub-chart)
langfuse.fullnameOverride -> upstream chart's fullnameOverride
ValueDefaultDescription
langfuse.langfuse.nextauth.urlhttp://localhost:3000The public URL of your Langfuse instance. Must equal https://<nebariapp.hostname> on Nebari. The upstream chart cannot template this from nebariapp.hostname, so set it explicitly.
langfuse.langfuse.auth.disableUsernamePasswordtrueSet false to allow email/password login alongside SSO. Default true forces SSO-only on Nebari.
langfuse.langfuse.auth.providers.keycloak.issuer"https://REPLACE-ME/realms/nebari"Keycloak realm URL (the issuer, AUTH_KEYCLOAK_ISSUER). Must be set to your actual realm URL. See Authentication setup below.
langfuse.langfuse.auth.providers.keycloak.allowAccountLinking"true"Allow linking existing accounts to the Keycloak identity.

Each datastore can be bundled (default, dev) or external (recommended for production).

ValueDefaultDescription
langfuse.postgresql.deploytrueDeploy bundled PostgreSQL. Set false to use an external instance.
langfuse.postgresql.host(unset)External PostgreSQL hostname (required when deploy: false).
langfuse.postgresql.auth.usernamepostgresDatabase user.
langfuse.postgresql.auth.databasepostgres_langfuseDatabase name.
langfuse.postgresql.auth.existingSecretlangfuse-secretsSecret containing the password.
langfuse.redis.deploytrueDeploy bundled Redis. Set false to use an external instance.
langfuse.redis.host(unset)External Redis hostname (required when deploy: false).
langfuse.redis.auth.existingSecretlangfuse-secretsSecret containing the Redis password.
langfuse.clickhouse.deploytrueDeploy bundled ClickHouse. Set false to use an external instance.
langfuse.clickhouse.host(unset)External ClickHouse hostname (required when deploy: false).
langfuse.clickhouse.replicaCount3Number of ClickHouse replicas. Reduce to 1 on small clusters.
langfuse.clickhouse.auth.existingSecretlangfuse-secretsSecret containing the ClickHouse password.
langfuse.s3.deploytrueDeploy bundled MinIO. Set false to use an external S3-compatible store.
langfuse.s3.bucketlangfuseS3 bucket name.

This pack uses Langfuse’s app-native OAuth (NextAuth.js) with Keycloak as the provider. The NebariApp CRD and nebari-operator handle Keycloak client provisioning.

How the provider environment variables are set

Section titled “How the provider environment variables are set”

The upstream chart translates the following values into environment variables on the web and worker containers:

Value pathEnvironment variableSource
langfuse.langfuse.auth.providers.keycloak.clientIdAUTH_KEYCLOAK_IDlangfuse-oidc-client Secret, key client-id (operator-provisioned)
langfuse.langfuse.auth.providers.keycloak.clientSecretAUTH_KEYCLOAK_SECRETlangfuse-oidc-client Secret, key client-secret (operator-provisioned)
langfuse.langfuse.auth.providers.keycloak.issuerAUTH_KEYCLOAK_ISSUERMust be set statically in your values file
langfuse.langfuse.auth.providers.keycloak.allowAccountLinkingAUTH_KEYCLOAK_ALLOW_ACCOUNT_LINKINGDefaults to "true"

The clientId and clientSecret are read automatically from the langfuse-oidc-client Secret that the nebari-operator creates when nebariapp.auth.provisionClient: true.

The issuer cannot be read automatically because the operator does not reliably emit the issuer URL into the OIDC Secret. Set it explicitly in your values file:

langfuse:
langfuse:
auth:
providers:
keycloak:
issuer: "https://keycloak.<your-domain>/realms/nebari"

When nebariapp.auth.provisionClient: true, the nebari-operator calls the Keycloak API to register the redirect URI on the provisioned client. The operator reads nebariapp.auth.redirectURI (default /api/auth/callback/keycloak) and registers exactly:

https://<nebariapp.hostname>/api/auth/callback/keycloak
http://<nebariapp.hostname>/api/auth/callback/keycloak

This matches Langfuse’s NextAuth callback path. No manual Keycloak configuration step is needed when provisionClient: true.

If you use provisionClient: false with a manually created Keycloak client, add the URI https://<hostname>/api/auth/callback/keycloak to that client’s Valid Redirect URIs in the Keycloak admin console.

By default (auth.disableUsernamePassword: true), email/password login is disabled and users must authenticate via Keycloak. For local development without SSO, set:

langfuse:
langfuse:
auth:
disableUsernamePassword: false
providers: {}

When secrets.generate: true (the default), the pack generates a Kubernetes Secret named langfuse-secrets on first install using Helm’s lookup function with randAlphaNum. The secret is annotated with helm.sh/resource-policy: keep so it is not deleted on helm uninstall and is not rotated on helm upgrade.

KeyUsage
saltLangfuse password hashing salt
encryptionKey64-character hex key for encrypting stored integration credentials
nextauth-secretNextAuth.js session signing key
postgres-passwordPostgreSQL user password
redis-passwordRedis auth password
clickhouse-passwordClickHouse user password
root-userMinIO root username
root-passwordMinIO root password

Do not rotate encryptionKey unless you are prepared to re-enter all integrations. Langfuse uses this key to encrypt credentials stored in its database (e.g., Slack, cloud provider keys). Rotating the key orphans all previously encrypted data - the credentials will be unreadable and must be re-entered manually.

ArgoCD’s helm template renderer runs without cluster access, so the lookup-based secret generation path does not execute. The secret will not be created, and pods will fail to start.

Production and GitOps path:

  1. Set secrets.generate: false in your values or ArgoCD Application spec.

  2. Create the langfuse-secrets Secret before the first ArgoCD sync:

    Terminal window
    kubectl create secret generic langfuse-secrets \
    --from-literal=salt=$(openssl rand -hex 16) \
    --from-literal=encryptionKey=$(openssl rand -hex 32) \
    --from-literal=nextauth-secret=$(openssl rand -hex 32) \
    --from-literal=postgres-password=$(openssl rand -hex 16) \
    --from-literal=redis-password=$(openssl rand -hex 16) \
    --from-literal=clickhouse-password=$(openssl rand -hex 16) \
    --from-literal=root-user=langfuse \
    --from-literal=root-password=$(openssl rand -hex 16) \
    -n <namespace>
  3. To prevent ArgoCD from flagging the pre-created Secret as out-of-sync, add an ignoreDifferences entry to your ArgoCD Application:

    ignoreDifferences:
    - group: ""
    kind: Secret
    name: langfuse-secrets
    jsonPointers:
    - /data

See examples/argocd-app.yaml for a full ArgoCD Application manifest.


For production deployments, disable the bundled bitnamilegacy/* images and configure external managed services. See examples/prod-external-datastores.yaml for a complete worked example.

Set deploy: false for each datastore you are replacing, then provide connection details:

langfuse:
postgresql:
deploy: false
host: <managed-postgres-host>
port: 5432
auth:
username: langfuse
database: langfuse
existingSecret: <your-postgres-secret>
secretKeys:
userPasswordKey: password
redis:
deploy: false
host: <managed-redis-host>
port: 6379
auth:
existingSecret: <your-redis-secret>
existingSecretPasswordKey: password
clickhouse:
deploy: false
host: <managed-clickhouse-host>
port: 9000
auth:
existingSecret: <your-clickhouse-secret>
existingSecretKey: password
s3:
deploy: false
bucket: <your-bucket-name>
region: <aws-region>
endpoint: "" # leave empty for AWS S3; set for S3-compatible services
accessKeyId:
secretKeyRef:
name: <your-s3-secret>
key: access-key-id
secretAccessKey:
secretKeyRef:
name: <your-s3-secret>
key: secret-access-key

When all bundled datastores are disabled, the pack deploys only the Langfuse web and worker containers.


The upstream langfuse/langfuse chart does not expose a native Prometheus /metrics endpoint on the web or worker containers, and ships no ServiceMonitor or PodMonitor.

This pack provides an opt-in metrics.podMonitor.enabled flag (default false) as a hook for a future sidecar exporter. Do not enable it unless you have added a Prometheus-compatible metrics exporter sidecar to the pods, as it will produce scrape errors against a non-existent endpoint.

To enable the PodMonitor (requires Prometheus Operator CRDs installed):

metrics:
podMonitor:
enabled: true
interval: 30s
path: /metrics
port: http

This satisfies the Beta telemetry requirement with a documented justification for default-off behavior.

Langfuse web and worker containers emit JSON-structured logs to stdout and stderr by default. No log-shipping sidecar is required - any standard cluster log aggregator (Fluentd, Vector, Loki promtail, etc.) that reads pod stdout will capture structured logs automatically.

The pack sets the following security context on Langfuse web and worker pods via the upstream chart’s podSecurityContext and securityContext passthrough values:

podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
capabilities:
drop: ["ALL"]

The bundled Bitnami sub-chart images (PostgreSQL, Redis, ClickHouse, MinIO) already run as non-root by default.


The Nebari foundational stack includes an OpenTelemetry Collector deployed as a DaemonSet in the monitoring namespace. Its configuration is managed as a helm.values: block inside an ArgoCD Application at apps/opentelemetry-collector.yaml in the nebari-infrastructure-core-generated foundational-software GitOps repository. It is not an OpenTelemetryCollector CR and not a standalone ConfigMap.

The collector already has a traces pipeline that receives OTLP telemetry and currently exports only to debug (stdout). The steps below add Langfuse as an additional exporter for that pipeline.

1. Create a Langfuse project and API key pair

In the Langfuse UI (Projects - Settings - API Keys), create a new key pair. You will receive:

  • A public key: pk-lf-...
  • A secret key: sk-lf-...

2. Compute the Basic auth header value

Terminal window
echo -n "pk-lf-<your-public-key>:sk-lf-<your-secret-key>" | base64

Note: if your setup supports Kubernetes Secrets and the OTel Collector headers_setter extension, prefer storing the credentials in a Secret rather than committing the base64 value inline.

3. Edit the ArgoCD Application in the foundational-software repo

Open apps/opentelemetry-collector.yaml in your foundational-software GitOps repository and add the otlphttp/langfuse exporter under helm.values.config, then append it to the traces pipeline exporters. The resulting helm.values: block should look like:

helm.values: |
config:
exporters:
debug:
verbosity: detailed
otlp:
endpoint: "localhost:4317"
tls:
insecure: true
otlphttp/langfuse:
endpoint: "https://<langfuse-host>/api/public/otel"
headers:
Authorization: "Basic <base64-public-key:secret-key>"
service:
pipelines:
metrics:
receivers: [otlp, prometheus]
processors: [memory_limiter, batch]
exporters: [debug]
logs:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [debug]
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [debug, otlphttp/langfuse]

Replace <langfuse-host> with your Langfuse hostname (e.g. langfuse.nebari.example.com) and <base64-public-key:secret-key> with the value computed in step 2.

4. Commit and push

Terminal window
git add apps/opentelemetry-collector.yaml
git commit -m "add langfuse otlp exporter to traces pipeline"
git push

ArgoCD (selfHeal: true, prune: true) reconciles automatically and triggers a helm upgrade of the opentelemetry-collector release in the monitoring namespace. No manual kubectl or helm commands are needed.

5. Verify

  • In Langfuse, open Tracing in your project.
  • Within a minute or two of the ArgoCD sync completing, traces from workloads that instrument with OTLP should appear.
  • If no traces appear, check the collector pod logs for errors from the otlphttp/langfuse exporter:
    Terminal window
    kubectl logs -n monitoring -l app.kubernetes.io/name=opentelemetry-collector --tail=50