Skip to main content

Hardening self-hosted Langfuse

Hardening

Langfuse ships with safe defaults and is penetration-tested for the same configuration that runs on Langfuse Cloud. This guide collects the additional operator-facing knobs that self-hosters typically want to turn on for production: locking down sign-ups, enforcing SSO, restricting which destinations user-configured integrations may reach, and tightening admin surfaces.

For related operational guides, see Authentication and SSO, Networking, Encryption, and Deployment Strategies.

Hardening for Government

Where is this feature available?

  • Hobby: Not Available
  • Core: Not Available
  • Pro: Not Available
  • Enterprise: Not Available
  • Self Hosted: Enterprise Edition

Langfuse Self-Hosted Enterprise supports government and other highly regulated environments with:

  • FIPS mode: Langfuse runs its cryptography on FIPS 140-3 validated cryptographic modules operated in approved mode, and refuses to start when it cannot.
  • Hardened images: the web and worker images are built on Iron Bank's hardened Red Hat Universal Base Image (UBI) 9.

We are also working on end-to-end documentation for operating Langfuse and all required subcomponents as a complete air-gapped deployment stack. Contact our sales team to discuss your requirements.

FIPS mode

See FIPS mode for supported cryptographic modules, requirements, and setup.

Hardened images

From v4.55.0, the langfuse/langfuse (web) and langfuse/langfuse-worker images:

  • Are built on Iron Bank's hardened Red Hat UBI 9 images (registry1.dso.mil/ironbank/redhat/ubi/ubi9 and ubi9-micro, version 9.8).
  • Run Node.js 24 from Red Hat's packages, which links the system OpenSSL library and its FIPS provider.
  • Ship no package manager, curl, or Python. The runtime contains bash, sed, and wget; use wget for container health checks.
  • Run as a non-root user with the numeric UID 1001.
  • Keep the RPM database, so image scanners such as Trivy, Grype, or Syft can list every OS package.
  • Are published for linux/amd64 and linux/arm64.

Images that extend the Langfuse images cannot install packages with a package manager. Use a multi-stage build to copy additional files in.

The Dockerfiles default to Red Hat's public UBI 9 images, so you can build the images yourself without credentials. To build on the Iron Bank images instead, log in to registry1.dso.mil and pass both base images:

docker build -f web/Dockerfile \
  --build-arg BASE_IMAGE=registry1.dso.mil/ironbank/redhat/ubi/ubi9:9.8 \
  --build-arg MICRO_BASE_IMAGE=registry1.dso.mil/ironbank/redhat/ubi/ubi9-micro:9.8 \
  .

Restrict who can sign in

By default, anyone who can reach the Langfuse web container can sign up with email and password. Pick one of the following profiles before exposing the instance. For more details on authentication configuration, see Authentication and SSO.

Disable open sign-up

AUTH_DISABLE_SIGNUP=true blocks any new account creation, including users who have an open project invite but no account yet. Combine with headless initialization or invite existing users from inside the app. Nobody signs up on such an instance, so nobody sees the newsletter step that new users get after sign-up either. To get the self-hosting updates, subscribe on the OSS newsletter page.

Force SSO for specific email domains

AUTH_DOMAINS_WITH_SSO_ENFORCEMENT=acme.com,corp.example rejects email/password sign-in (including the password-reset OTP path) for the listed domains and directs those users to sign in through your configured SSO provider instead. Use this when only part of your user base is on SSO.

Require email verification on signup

AUTH_EMAIL_VERIFICATION_REQUIRED=true adds a one-time-password step before a new email/password user can set their password. SSO sign-in is unaffected. Requires transactional emails to be configured. See Email verification on signup for the full flow.

Session lifetime

AUTH_SESSION_MAX_AGE controls how long a signed-in session (JWT) stays valid, in minutes. Default is 43200 (30 days); the value must be greater than 5 minutes because the front-end refreshes its session every 5 minutes. Lower this for shared or kiosk environments.

Disable email/password entirely

If every user signs in via SSO, set AUTH_DISABLE_USERNAME_PASSWORD=true. Account linking can be enabled per-provider with AUTH_<PROVIDER>_ALLOW_ACCOUNT_LINKING=true — only enable it when your IdP guarantees verified emails.

Outbound URL allowlists (SSRF defense)

Several features let project members configure a URL that Langfuse then calls on their behalf — LLM API base URLs, webhook targets, blob storage integration endpoints, and external media storage endpoints. Langfuse rejects URLs whose resolved IPs fall into private, link-local, loopback, or special-use ranges (including NAT64 and 6to4 IPv6 ranges), rejects URLs with embedded credentials (user:password@), and re-validates the IP at request time and on every redirect hop to defend against DNS rebinding.

On Langfuse Cloud this is always strict. Self-hosted instances validate LLM connection, webhook, and external media storage URLs by default too; blob storage endpoint validation only activates once one of its allowlist variables is set (see below). The allowlist variables let user-configured integrations reach internal services or restrict outbound traffic to specific hosts:

Use caseAllowlist variables
User-configured LLM connectionsLANGFUSE_LLM_CONNECTION_WHITELISTED_HOST
LANGFUSE_LLM_CONNECTION_WHITELISTED_IPS
LANGFUSE_LLM_CONNECTION_WHITELISTED_IP_SEGMENTS
LANGFUSE_LLM_CONNECTION_ALLOWED_HOSTS
User-configured webhooksLANGFUSE_WEBHOOK_WHITELISTED_HOST
LANGFUSE_WEBHOOK_WHITELISTED_IPS
LANGFUSE_WEBHOOK_WHITELISTED_IP_SEGMENTS
LANGFUSE_WEBHOOK_ALLOWED_HOSTS
User-configured blob storage integrationsLANGFUSE_BLOB_STORAGE_ENDPOINT_WHITELISTED_HOST
LANGFUSE_BLOB_STORAGE_ENDPOINT_WHITELISTED_IPS
LANGFUSE_BLOB_STORAGE_ENDPOINT_WHITELISTED_IP_SEGMENTS
User-configured external media integrationsLANGFUSE_EXTERNAL_MEDIA_STORAGE_ENDPOINT_WHITELISTED_HOST
LANGFUSE_EXTERNAL_MEDIA_STORAGE_ENDPOINT_WHITELISTED_IPS
LANGFUSE_EXTERNAL_MEDIA_STORAGE_ENDPOINT_WHITELISTED_IP_SEGMENTS
LANGFUSE_EXTERNAL_MEDIA_STORAGE_ENDPOINT_ALLOWED_HOSTS

Each variable accepts a comma-separated list. Hostnames in _WHITELISTED_HOST short-circuit the IP check entirely; _WHITELISTED_IPS / _WHITELISTED_IP_SEGMENTS are matched against every IP a hostname resolves to while keeping public hosts allowed. Setting *_ALLOWED_HOSTS to a non-empty list of exact lowercase hostnames (no scheme or port; unset or empty keeps default-allow behavior) switches that surface to a positive allowlist where only listed hosts are permitted and all other hosts — including public ones — are rejected. You can also set LANGFUSE_OUTBOUND_BLOCKED_IP_SEGMENTS to a comma-separated list of IPv4 or IPv6 CIDR ranges to block additional IP ranges across outbound checks. Set _WHITELISTED_* values only for trusted internal endpoints (your in-cluster SeaweedFS or MinIO, an internal LLM gateway, …), and note that every host listed in _WHITELISTED_HOST or *_ALLOWED_HOSTS (including public provider hosts) is trusted even if its DNS resolves to a private IP, bypassing the private-IP and DNS-rebinding checks for that host. Blob storage validation activates only once one of its variables is set on a self-hosted instance; this default will change to strict in a future major release.

Webhook deliveries are additionally restricted to ports 80 and 443, and sensitive headers (Authorization, Cookie, Proxy-Authorization, x-langfuse-signature) are dropped on cross-origin redirects. Provide webhook credentials via headers configured in the webhook UI rather than in the URL.

Code evaluators

Code evaluators let project members write evaluator code that Langfuse executes. On self-hosted instances they are disabled until you set LANGFUSE_CODE_EVAL_DISPATCHER, and the dispatcher you pick determines the isolation boundary:

  • insecure-local runs evaluator code in-process on the worker via node:vm, which is not a security boundary — evaluator code can reach everything the worker can, including your databases, queues, and cloud credentials. Only use it when everyone who can create evaluators is fully trusted.
  • aws-lambda dispatches evaluator code to Lambda functions you deploy, keeping execution out of the worker process. Langfuse Cloud uses this dispatcher with executor functions running in an isolated network without egress to internal services; apply the same principle when deploying your own — give the functions no network route back into your infrastructure.

See Code evaluators (self-hosted) for the full dispatcher setup.

Admin API

The self-hosted-only Instance Management API is gated by ADMIN_API_KEY. When you enable it:

  • Pick a high-entropy random value (≥ 32 bytes) — short keys are trivially brute-forceable.
  • Treat the key as you would a root credential — restrict it to a small set of operators, rotate it on personnel changes, and never expose it to the browser or to less-privileged services.
  • Do not expose admin endpoints to the public internet. Bind them to an internal load balancer or restrict them with a reverse proxy.
  • Langfuse Cloud blocks the admin API; nothing in this section applies there.

SSO configuration

A few knobs worth knowing about when configuring SSO providers via environment variables:

  • Issuer validation — set AUTH_<PROVIDER>_ISSUER to your IdP's exact issuer URL. Tokens are validated against it at sign-in rather than silently accepted from the wrong issuer, and AUTH_CUSTOM_ISSUER must additionally be a valid URL and is checked at startup. GitHub's issuer is pinned in code and needs no configuration.
  • ID token signing algorithm — set AUTH_<PROVIDER>_ID_TOKEN_SIGNED_RESPONSE_ALG to align the expected signing algorithm with your IdP if it rejects the default.

See the full reference in Authentication and SSO → Additional configuration.

Network exposure

Only the langfuse/langfuse (web) container needs to be reachable by users, the SDKs, and your application code. Langfuse is designed to be exposed publicly, but for high-security environments you can:

  • Terminate TLS at a load balancer in front of the web container (see Encryption).
  • Put the web container behind a VPN, internal load balancer, or zero-trust proxy.
  • Peer your application VPCs with the Langfuse VPC for private SDK ingestion traffic. Worker, Postgres, ClickHouse, Redis, and blob storage should never be reachable from the public internet.

See Networking for the full architecture diagram and per-component exposure recommendations.

Data protection

  • Encryption at rest — Postgres and ClickHouse should run with disk encryption. Configure server-side encryption on the event-upload and media buckets.
  • Sensitive integration secrets (LLM API keys, blob storage credentials, SSO client secrets, webhook secrets) are encrypted at the application layer using ENCRYPTION_KEY. Rotate the key per the Encryption guide.
  • Data masking — see Data masking to redact sensitive content from ingested traces before it lands in storage.

Data retention

Where is this feature available?

  • Hobby: Not Available
  • Core: Not Available
  • Pro: Available
  • Enterprise: Available
  • Self Hosted: Enterprise Edition

Configure project-level data retention policies to delete traces, observations, and media after N days.

Audit logs

Where is this feature available?

  • Hobby: Not Available
  • Core: Not Available
  • Pro: Not Available
  • Enterprise: Available
  • Self Hosted: Enterprise Edition

Administrative actions, including blob storage integration validate/run-now and public blob-storage deletion, are recorded in the audit_logs Postgres table regardless of plan. The in-app audit log viewer requires the plans above; OSS deployments can query the table directly.

Telemetry

Langfuse self-hosted reports anonymized usage telemetry by default. Set TELEMETRY_ENABLED=false to opt out; note that instances running with an Enterprise Edition license key always report telemetry. See Telemetry for the exact fields collected. TELEMETRY_ENABLED doesn't cover the newsletter step: to stop new users' browsers from contacting langfuse.com for it, set LANGFUSE_DISABLE_SIGNUP_ONBOARDING=true.

Reporting security issues

If you discover a vulnerability, please report it via our responsible disclosure program rather than opening a public GitHub issue.