Skip to main content
Every feature of a self-hosted Laminar is configured through values in laminar.yaml, the overrides file you pass to helm upgrade -i laminar laminar/laminar -f laminar.yaml. This page covers the settings most deployments need: AI features, Signals, Slack, OAuth login, storage, TLS, PII redaction, secrets, and image pinning. For the full value list, see values.yaml in the chart repo. Apply any change by re-running the install command:

AI features and LLM provider

Chat-with-trace and SQL-with-AI run through one unified LLM provider configuration. Set the provider on all three application pods (they default to gemini), and supply the key:
  • LLM_PROVIDER: gemini (default), openai, or bedrock. Set via frontend.env.llmProvider, appServer.env.llmProvider, and appServerConsumer.env.llmProvider.
  • LLM_API_KEY: the key for gemini or openai. Set via secrets.data.
  • LLM_BASE_URL: optional, for OpenAI-compatible gateways (LiteLLM, OpenRouter, vLLM) or custom Gemini endpoints. Set via *.env.llmBaseUrl.
  • LLM_MODEL_SMALL / LLM_MODEL_MEDIUM / LLM_MODEL_LARGE: optional per-tier model overrides. Per-provider defaults apply when unset. For Bedrock, these are Inference Profile IDs.
AI features in the frontend activate as soon as LLM_API_KEY (or AWS credentials for Bedrock) is populated.
Signals and the playground do not use these values. Each Signal runs on an LLM profile: a workspace-level entry holding a provider, its credentials, and the models you allow. Set LLM_API_KEY for the features above, and add profiles in workspace settings for Signals and the playground.

Gemini (default)

Just supply the key:

OpenAI or OpenAI-compatible gateway

AWS Bedrock

Bedrock uses AWS credentials from secrets.data instead of LLM_API_KEY:

Model overrides

Pin specific models per size tier (for Bedrock, values are Inference Profile IDs):

Signals

Signals extract structured events from your traces. On a self-hosted deployment, each Signal runs on an LLM profile that a workspace member creates in the app: the provider, its credentials, and the models the Signal may use live in the profile, not in laminar.yaml. Signals are enabled by default in the frontend, and no LLM_API_KEY is required to turn them on. Signals created before profiles existed keep running on the LLM_PROVIDER configuration above until you point them at a profile. Signals that use a profile ignore LLM_PROVIDER, LLM_BASE_URL, and the LLM_MODEL_* overrides entirely. To disable Signals:
To disable chat-with-trace independently:
Signal extraction runs in the app-server-consumer pod. For a Signal without a profile, that pod’s llmProvider (and any model overrides) governs how the Signal is computed, so keep the provider consistent across frontend, appServer, and appServerConsumer unless you have a reason to split them. Profile credentials are encrypted by the frontend and decrypted by the app server, both with AEAD_SECRET_KEY, so that value has to match across pods (the chart sets one key for all of them).

Slack notifications

Laminar posts alerts and notifications to Slack through a broker run by Laminar Cloud: your instance uses Laminar Cloud’s official Slack app, so you do not register a Slack app of your own. Laminar Cloud runs both legs of the OAuth flow on your behalf; the bot token is returned to your instance server-to-server and encrypted at rest. Your instance authenticates to the broker with an enterprise license key. Set the license key in laminar.yaml:
When the license key is set, the “Connect Slack” button in workspace settings uses the brokered flow. SLACK_BROKER_URL defaults to Laminar Cloud’s origin (https://laminar.sh), so you normally only set the license key. To get a license key, contact founders@lmnr.ai. Slack bot tokens are encrypted at rest with SLACK_ENCRYPTION_KEY. You do not normally set this: when left empty, the chart defaults it to your AEAD_SECRET_KEY so there is one encryption key to manage. Set it explicitly in secrets.data only if you want Slack tokens encrypted under a separate key.

OAuth login

Laminar supports OAuth login with GitHub, Google, Azure AD, Okta, and Keycloak. Add provider credentials to secrets.data and set the frontend URLs to your real domain. Omit a provider’s credentials to disable it.
Callback / redirect URLs must match your nextauthUrl exactly, or the OAuth flow fails after the provider redirects back.
If your provider credentials already live in a Kubernetes Secret (created by the Keycloak operator, sealed-secrets, or external-secrets-operator), reference them with extraEnv instead of inlining them.

Secrets management

The chart reads secrets from three backends:
  1. Kubernetes Secrets (default): values in secrets.data.
  2. AWS Secrets Manager: for EKS with IRSA, via the Secrets Store CSI Driver.
  3. HashiCorp Vault: for on-premises or multi-cloud.
To pull a secret from AWS Secrets Manager, list its keys under secrets.awsSecretsManager and leave placeholders in secrets.data:
You can mix backends (auth tokens from AWS, database passwords from Vault, the rest from secrets.data). See the chart’s Secrets Management guide for the Vault and mixed-source setups.

Referencing existing Secrets with extraEnv

extraEnv injects environment variables into frontend, appServer, or appServerConsumer, supporting plain values, secretKeyRef, configMapKeyRef, and fieldRef. Entries override matching keys from secrets.data, so you can selectively swap individual values without restructuring the secrets config:

Container images

The two Laminar containers (frontend and app server) are pulled from public ghcr.io/lmnr-ai/*-ee images, so most installs never touch this section. For production, pin a specific tag instead of latest so a pod restart does not pick up a newer build. The two are released together: keep their tags in sync.
Chart 0.2.0 and newer require an app-server tag of 0.1.628 or newer and will fail at render time if you pin an older one. Earlier charts shipped a separate query-engine container; it has since been folded into the app-server image, so there is no longer a queryEngine image to pin.
Available tags are listed under the Packages tab on GitHub. To mirror images into a private registry, retag and push each image, point images.repository at the mirror, and attach imagePullSecrets to the default ServiceAccount (the chart does not template this; see the chart reference).

Storage

ClickHouse and Quickwit hold the bulk of Laminar’s data, and both can be backed by S3.

ClickHouse on S3

On GCP, ClickHouse’s S3 backend needs HMAC credentials (the GKE metadata server returns OAuth2 tokens that GCS’s S3 API rejects). Point the endpoint at https://storage.googleapis.com/YOUR_BUCKET/ and supply HMAC keys. The chart is designed for one HMAC key pair to back both ClickHouse and Quickwit. See the chart’s ClickHouse S3 guide. Quickwit powers full-text search over spans. quickwit.s3.defaultIndexRootUri is the master switch for the whole Quickwit stack: leave it empty and the Quickwit workloads are skipped and search degrades gracefully (the rest of the platform is unaffected). Set it to a bucket you own to enable search:
When global.cloudProvider: gcp, the chart auto-fills the GCS flavor and endpoint for you; supply the same HMAC keys used for ClickHouse via quickwit.extraEnv.

Persistent volumes

The chart creates an EBS storage class scoped to the availability zones you list. Pods with persistent volumes can only schedule on nodes in the same zone, so make sure your nodes run in these zones:
Each stateful service (postgres, clickhouse, rabbitmq) can override its storage class and size independently under <service>.persistence.

TLS and ingress

Laminar exposes two public endpoints: the frontend (web UI) and the app server (HTTP trace ingestion on 443, gRPC on 8443). TLS has three paths. cert-manager provisions and renews free Let’s Encrypt certificates. The hostname must be publicly DNS-resolvable so Let’s Encrypt can complete the HTTP-01 challenge:
On AWS, the NLB and ALB terminate TLS via an ACM certificate ARN annotation, with no in-cluster cert management:

Pre-existing certificate

Import a PEM certificate as a Kubernetes TLS secret and reference it with an empty clusterIssuer. See the chart’s NETWORKING guide for the full app-server TLS and DNS options, including external-dns automation.
On AWS, the app server’s NLB already exposes HTTP (443) and gRPC (8443) externally; you usually do not need a separate app-server Ingress. On GCP the load balancer is pure TCP passthrough and cannot terminate TLS: front the app server with Traefik (or another ingress controller) to get TLS on both ports.

PII redaction

The PII redactor is an optional CPU-only gRPC service that detects personally identifiable information in spans at ingest. It backs both redaction modes: On replaces PII before the span is persisted, and Dual stores the original text once and redacts it per reader, so owners and admins see the original while members, API keys, and CLI sessions see placeholders. The service is disabled by default and has no database or secret dependencies (the detection model is baked into the image). When enabled, the chart injects PII_REDACTOR_URL into the app-server and app-server-consumer pods, activating detection during span processing; the mode is then chosen per project under Project Settings → Security.
PII detection is CPU-intensive ONNX inference and the model weighs about 5.5 GB in memory, so pin it to a dedicated compute-optimized node and size it generously. For more throughput, add replicas rather than a bigger node:

Sharing a Postgres database

By default Laminar puts its tables in the public schema. To share a Postgres database with another service, point it at a dedicated schema with global.postgresSchema. The single value is dispatched to all three application pods, so they resolve the same search_path. Set it before the first deploy:
On first boot the frontend runs CREATE SCHEMA IF NOT EXISTS for a non-public schema. If the schema is pre-provisioned or the DB role lacks CREATE, disable that step with frontend.env.postgresCreateSchema: "false".

What’s next

Kubernetes (Helm)

Back to the install walkthrough.

Signals

Outcome and failure extraction over your traces.

PII redaction

How redaction renders in the UI and SQL.

Start tracing

Send your first traces to your instance.