Self-Hosted Deployment#
Self-hosted Langfuse runs the same container as Langfuse Cloud and is architecturally stateless — multiple instances can run behind a load balancer as long as the database connection count is managed . The primary exposure point is the langfuse/langfuse (web) container on port 3000 (configurable via PORT), which is meant to be fronted by a network load balancer for SSL termination .
This article covers the most common failure patterns specific to self-hosted setups: secure-context API failures, Content Security Policy (CSP) misconfigurations, reverse proxy/ingress issues, and path handling.
HTTPS and Secure Contexts#
HTTPS is required for production self-hosted deployments. Langfuse does not terminate TLS itself; handle it at the load balancer (AWS ALB, etc.) or via a service mesh sidecar (Istio/Linkerd) .
crypto.randomUUID() failures#
Several frontend features introduced in v3.195 (PR #14257) call crypto.randomUUID() for dataset item media uploads. This API is only available in secure contexts (HTTPS or localhost). Accessing a self-hosted instance over plain HTTP via a LAN IP or non-localhost hostname causes:
TypeError: crypto.randomUUID is not a function
resulting in a full frontend crash .
Fix: Upgrade to v3.196.0 or later, which adds a fallback for non-secure contexts . Until then, access the instance via localhost or enable HTTPS.
Enforcing HTTPS via CSP#
Once HTTPS is in place, set LANGFUSE_CSP_ENFORCE_HTTPS=true to add upgrade-insecure-requests and block-all-mixed-content to the browser CSP . This variable defaults to "false", so it must be explicitly enabled .
Content Security Policy (CSP)#
The full CSP is defined as a static string in web/next.config.mjs. Key directives for self-hosters:
| Directive | Relevant entries |
|---|---|
connect-src | 'self', https://*.s3.amazonaws.com, https://*.microsoftonline.com, Sentry endpoints |
script-src | 'self' 'unsafe-eval' 'unsafe-inline', Microsoft login domains |
img-src | 'self' https: blob: data: http://localhost:* |
Azure Blob Storage CSP gap#
When using Azure Blob Storage for media uploads (LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT), the browser-side connect-src directive blocks uploads because https://*.blob.core.windows.net is not in the hardcoded CSP . AWS S3 (https://*.s3.amazonaws.com) is covered; Azure is not.
Root cause: The CSP is baked in at image build time, so runtime-injected environment variables (common in Kubernetes/Helm deployments) cannot modify it .
Fix: This was resolved in PR #14665 by adding https://*.blob.core.windows.net to connect-src. Upgrade to the release that includes this fix. Attempts to override the CSP header at the ingress/gateway layer do not reliably solve the problem .
Hugging Face embedded deployments#
CSP is disabled entirely when the origin is a Hugging Face domain to support embedded usage .
Reverse Proxy and Ingress Configuration#
Host header and NEXTAUTH_URL#
The Host header forwarded to the Langfuse container must match the hostname in NEXTAUTH_URL. A mismatch causes 403 Forbidden responses, particularly for the MCP server endpoint . Do not let your proxy rewrite Host to an internal address.
Keep-alive timeout mismatch (502/504 errors)#
The most common networking issue in self-hosted deployments is intermittent 502/504 errors caused by the load balancer (e.g., AWS ALB defaults to 60-second idle timeout) closing connections that the app still considers open .
Fix: Set KEEP_ALIVE_TIMEOUT on the Langfuse web container to at least 5 seconds higher than your load balancer's idle timeout .
SSE and long-lived connections (MCP)#
For SSE endpoints (e.g., MCP server):
- Set
proxy_buffering off(or ensureX-Accel-Buffering: nois not overridden) - Increase
proxy_read_timeoutandproxy_send_timeoutfor long-lived connections
Socket exhaustion#
At scale, the container can exhaust its socket pool. Increase capacity with LANGFUSE_S3_CONCURRENT_WRITES (set higher than 50) or scale horizontally .
Kubernetes / Helm#
The Helm chart deploys a ClusterIP service by default; configure an Ingress or use kubectl port-forward svc/langfuse-web for local access . See the langfuse-k8s README for ingress configuration details.
Path Handling and Custom Base Path#
Deploying on a sub-path#
To serve Langfuse at a sub-path (e.g., https://yourdomain.com/langfuse), set two variables at build time — the prebuilt images do not support runtime configuration of the base path :
NEXT_PUBLIC_BASE_PATH="/langfuse-base-path"NEXTAUTH_URL="https://yourdomain.com/langfuse-base-path/api/auth"
Dataset names with slashes#
Dataset names containing / cannot be fetched via the API route /api/public/datasets/[name] because Next.js single-segment dynamic routes treat encoded slashes (%2F) as path separators, returning 404s . Avoid / in dataset names, or use an alternative separator like __.
A proxy that decodes %2F before forwarding to the container will also break URL-encoded slash lookups .
Key Reference Files and Docs#
| Resource | Description |
|---|---|
web/next.config.mjs | CSP headers, HTTPS enforcement, custom base path |
web/src/env.mjs | LANGFUSE_CSP_ENFORCE_HTTPS and all env var definitions |
| Networking (self-hosted) | Port, load balancer, and exposure guidance |
| Encryption (self-hosted) | HTTPS setup, LANGFUSE_CSP_ENFORCE_HTTPS |
| 502/504 Troubleshooting | Keep-alive timeout fix |
| Custom Base Path | Sub-path deployment setup |
| Kubernetes (Helm) | Helm chart and ingress setup |
| Troubleshooting & FAQ | General self-hosting issues |