# langfuse self-hosting: default secrets, localhost binding, and logs that never rotate

> langfuse is an open source LLM engineering platform for tracing, evaluation, prompt management and datasets, written in TypeScript and shipped as a multi-service Docker Compose stack on Postgres, ClickHouse, Redis and MinIO. The self-host path is quick to start and the README names Helm as the preferred production deployment, but the compose file it hands you ships with working default credentials, binds almost nothing to the network, and inherits a log driver that does not rotate.

**langfuse/langfuse** — GitHub describes it as 🪢 Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. 🍊YC W23. The repository metadata lists TypeScript as its primary language. The metadata lists the NOASSERTION license. This article stays within the project description and details documented in the GitHub repository README.

- Repository: https://github.com/langfuse/langfuse
- Website: https://langfuse.com
- Stars: 35,105 · Forks: 3,854
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-08-13 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/langfuse-langfuse

## The worker will not start until Postgres, MinIO, Redis and ClickHouse all report healthy

The default compose file defines a langfuse-worker service whose depends_on block names four backing services, postgres, minio, redis and clickhouse, and each one carries condition: service_healthy rather than a plain start order. The worker also sets restart: always and maps port 3030 to 127.0.0.1 only. The effect is that startup is gated on health checks rather than on process launch, which is the right default for a stack where the worker writes to Postgres, reads blobs from MinIO, uses Redis for queues, and stores traces in ClickHouse. The cost is that there is no partial mode. If one of the four never reports healthy, the worker simply is not there, and the symptom you see is a missing service rather than an error explaining which dependency failed. You debug by reading health check output, not by reading a startup trace.

## Credential placeholders ship with values that actually work, and nothing fails if you keep them

The environment block for the worker sets real defaults rather than blanks. DATABASE_URL falls back to postgresql://postgres:postgres@postgres:5432/postgres, SALT falls back to mysalt, and ENCRYPTION_KEY falls back to a string of sixty-four zeros, with a comment telling you to generate it via openssl rand -hex 32. The file marks each of these with a CHANGEME comment and opens by telling you to replace the placeholders with your own secrets. The mechanical problem is that nothing enforces the instruction. A stack that boots with the shipped values is fully functional and looks healthy, so the mistake is silent until you need the encryption key to be one only you hold. For a self-hoster this is the first thing to change, because a default salt and a zero key are published in the repository and in every copy of the compose file derived from it.

## Everything binds to 127.0.0.1 except the web port and the minio port

A comment at the top of the compose file recommends restricting inbound traffic on the host to langfuse-web on port 3000 and minio on port 9090, and states that all other components are bound to localhost to only accept connections from the local machine. The worker mapping, 127.0.0.1:3030:3030, follows that rule. Two things follow for the reader. First, the project's own recommended posture puts the object store on a reachable interface, so minio becomes a network service you have to think about rather than a private helper, and the file does not include credentials guidance for it the way it does for the database. Second, NEXTAUTH_URL defaults to http://localhost:3000, and a comment elsewhere in the file notes that this value also builds links for users. Move the deployment to a real hostname and any link the product generates still points at localhost until you change that variable.

## The compose file inherits a Docker log driver that never rotates, and the fix is at the daemon

The README spends a dedicated section on this. The default docker-compose.yml inherits the Docker daemon's logging configuration, and Docker's default json-file driver does not rotate logs unless configured, which can exhaust disk space. The guidance is to set the driver's max-size and max-file options, or to keep your chosen logging backend and configure retention there, and explicitly not to rotate or truncate Docker-managed JSON log files with external tools. Two constraints make this more than a one-line change. After changing daemon logging defaults you must restart Docker and recreate existing containers, because restarting containers alone is insufficient. And the daemon settings cover container stdout and stderr only, not database data volumes or ClickHouse's internal log files, so a stack that survives container log growth can still fill a disk from inside ClickHouse. Plan for the interruption and preserve the data volumes.

## The five minute local path and the preferred production path are different artifacts

Self-hosting is offered in five shapes: local Docker Compose on your own machine in 5 minutes, a single virtual machine with Docker Compose, Kubernetes with Helm, and Terraform templates for AWS, Azure and GCP. The Kubernetes option is the one the page calls the preferred production deployment. That ranking matters because the artefact you start with is not the artefact you are meant to run. The local path is two commands and a container start:

```bash
  # Get a copy of the latest Langfuse repository
  git clone --depth=1 https://github.com/langfuse/langfuse.git
  cd langfuse

  # Run the langfuse docker compose
  docker compose up
```

What that sequence does not tell you is that the clone is shallow, so you get the tip of main with no history to diff or bisect, and that the same four services, the same health gates and the same credential placeholders arrive with it. A single VM keeps the compose model and changes only the host. Moving to Kubernetes is a different deployment model rather than a different compose file, and the Terraform templates are a third path with their own resource layout. Choosing between them is a decision about who operates the platform, and the page resolves it in one line by pointing production at Helm.

## Node 24 and pnpm 12.6.0 are enforced, and npm install is blocked on purpose

The root package.json is marked private, declares version 4.48.0, sets license to MIT, and pins engines to node 24 and pnpm 12.6.0. Its preinstall script is npx only-allow pnpm, so an install started with another package manager aborts before anything else happens. The repository is a pnpm workspace, with pnpm-workspace.yaml, turbo.json for task running, vitest.workspace.ts for tests, and separate web and worker packages alongside packages, ee, ai-gateway, fern, specs, scripts and patches directories. Several scripts are workspace scoped rather than root scoped, for example the ClickHouse migration steps run through pnpm --filter @langfuse/shared. The consequence is that you cannot follow generic JavaScript instructions against this repository. Clone it, use pnpm, and use the script names as written, because a renamed or substituted command lands in a different workspace than the one the authors maintain.

## The worker image tracks a major line while the application version moves daily

Three releases landed inside the last week: v4.46.0 on 2026-09-25, v4.47.0 on 2026-09-29, and v4.48.0 on 2026-09-30, and the version field in package.json reads 4.48.0. The compose file, though, references the worker as docker.langfuse.com/langfuse/langfuse-worker:4, a major line tag rather than a patch tag. So the application version moves several times a week while the worker image reference in the default compose file names a moving target one level up. The last push to main is dated 2026-09-27. For an operator this means upgrade policy has to be written by you: decide whether the image tag follows the line automatically or whether you pin it, decide how a daily release reaches your environment, and remember that the compose file in the repository is not the thing that decides when your worker changes. The environment is shared across at least six templates, with separate example files for dev, prod, test, Azure, OCI and a Redis cluster, so the file you start from also determines which infrastructure your stack expects.

## Conclusion

Pick it if you want the tracing, evaluation and prompt versioning surfaces in one place and can operate a four service stack. Do not pick it if you need a single process to run, or if your team has no capacity to own Postgres, ClickHouse, Redis and object storage together. Before you expose anything, replace the credential placeholders, decide whether the minio port really belongs on your network interface, and set log rotation on the Docker daemon rather than on the compose file.

## FAQ

### Who owns Langfuse?

The project says that since January 2026 it is part of ClickHouse, and it says the platform is made with the ClickHouse open source database. ClickHouse also appears as one of the four services the default compose file waits on before starting the worker.

### Is Langfuse free or paid?

There are two deployment paths. Langfuse Cloud is a managed deployment by the Langfuse team with a generous free tier and no credit card required, and self-hosting runs the same platform on your own infrastructure through Docker Compose, Helm, or Terraform templates for AWS, Azure and GCP. The root package.json declares the license as MIT.

### how to install langfuse locally

The local path is a Docker Compose run on your own machine, which the page puts at 5 minutes: clone the repository, change into the langfuse directory, and run docker compose up. Before the stack is reachable, replace the credential placeholders marked CHANGEME in the compose file, which include DATABASE_URL, SALT and ENCRYPTION_KEY.

### how to use langfuse for prompt management

Prompt Management lets you centrally manage, version control and collaboratively iterate on your prompts, and the page attributes the lack of added latency to strong caching on both the server and the client side. The LLM Playground is the companion surface for iterating on prompts and model configurations.

### how to use langfuse api

The platform is used to power bespoke LLMOps workflows through its building blocks exposed via the API. An OpenAPI spec, a Postman collection, and typed SDKs for Python and JS/TS are available.

## Sources

- [Official documentation](https://langfuse.com)
- [Official README](https://github.com/langfuse/langfuse#readme)
- [Project repository](https://github.com/langfuse/langfuse)
- [Release notes](https://github.com/langfuse/langfuse/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/langfuse-langfuse
