Skip to content

Add Langfuse template - #1072

Merged
Siumauricio merged 2 commits into
Dokploy:canaryfrom
huseyincenik:add-langfuse-template
Aug 9, 2026
Merged

Add Langfuse template#1072
Siumauricio merged 2 commits into
Dokploy:canaryfrom
huseyincenik:add-langfuse-template

Conversation

@huseyincenik

@huseyincenik huseyincenik commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Closes #1071

Summary

Adds a self-hosted Langfuse template. Langfuse is an open-source LLM engineering platform: tracing/observability for LLM calls, versioned prompt management, an in-browser playground, dataset-based evaluation, and cost/usage analytics.

Stack

Adapted from the official docker-compose.yml:

  • langfuse-web / langfuse-workerlangfuse/langfuse:4 / langfuse/langfuse-worker:4
  • postgres:17 — relational metadata store
  • clickhouse/clickhouse-server:25.12 — analytics/trace storage
  • redis:7 — cache/queue
  • MinIO (cgr.dev/chainguard/minio) — S3-compatible blob storage for trace/media payloads

Changes vs. upstream compose:

  • Dropped all host port publishing (ports:) per this repo's conventions — Dokploy handles routing via template.toml domains.
  • All secrets (POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, MINIO_ROOT_PASSWORD, REDIS_AUTH, NEXTAUTH_SECRET, SALT, ENCRYPTION_KEY) are generated via Dokploy's ${password:32} / ${hash:64} helpers instead of upstream's hardcoded # CHANGEME defaults.
  • Two domains: the main one serves langfuse-web; a second is bound to minio (port 9000) because Langfuse's web UI issues presigned S3 URLs that the browser fetches directly (e.g. media attached to traces) — the internal minio hostname isn't reachable from outside. langfuse-web's LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT is overridden to that public domain while langfuse-worker keeps the internal one, mirroring how upstream's own compose file distinguishes the two.

Testing

  • node build-scripts/generate-meta.js --check511 templates validated
  • tsx build-scripts/validate-template.ts --dir blueprints/langfuse --verbose → structure valid, 11 variables processed, both domains resolved correctly
  • tsx build-scripts/validate-docker-compose.ts --file blueprints/langfuse/docker-compose.yml --verbose → structure valid, all 6 services detected
  • docker compose config with sample env values → confirmed the YAML anchor/override setup resolves correctly (langfuse-web picks up the public MinIO endpoint, langfuse-worker keeps the internal one; DATABASE_URL interpolates the generated Postgres password correctly)

Not yet deployed on a live Dokploy instance — relying on the PR preview this repo generates for that. Will test the preview once it's up and report back.

Notes for reviewers

  • Core Langfuse (tracing, prompt management, evals, playground) is MIT-licensed and works self-hosted without a license key. Some enterprise-only features (SSO/SAML, fine-grained RBAC) require a separate commercial license even self-hosted — documented in instructions.md, no license key is configured by this template.
  • Logo is Langfuse's official icon.svg from their repo.

Open-source LLM engineering platform: tracing, prompt management,
evaluation and cost/usage analytics for LLM apps.

Stack: langfuse-web + langfuse-worker (image tag 4), Postgres 17,
ClickHouse 25.12, Redis 7, MinIO. Adapted from the official
docker-compose.yml at https://github.com/langfuse/langfuse/blob/main/docker-compose.yml,
with all secrets generated via Dokploy's template.toml helpers instead
of the upstream hardcoded defaults.

MinIO gets its own domain because Langfuse's web UI issues presigned
S3 URLs that the browser fetches directly (media attached to traces),
so that endpoint has to be reachable from outside the internal network.

Validated locally with build-scripts/validate-template.ts,
validate-docker-compose.ts and generate-meta.js --check (all pass),
plus `docker compose config` with sample secrets to confirm the
langfuse-web override of LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT resolves
correctly. Not yet deployed on a live Dokploy instance.
Copilot AI lite review requested due to automatic review settings August 7, 2026 09:52
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. template New template request labels Aug 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
built with Refined Cloudflare Pages Action

⚡ Cloudflare Pages Deployment

Name Status Preview Last Commit
templates ✅ Ready (View Log) Visit Preview e2c3a24

@huseyincenik

Copy link
Copy Markdown
Contributor Author

Ran this locally with plain `docker compose` (temporarily publishing `langfuse-web:3000` and `minio:9000` via an override file, not committed) to actually boot the stack rather than only statically validate it:

  • All 6 services reach a healthy/running state.
  • `GET /api/public/health` on `langfuse-web` → `{"status":"OK","version":"4.6.0"}`
  • `/auth/sign-in` renders (200).
  • `minio`'s health endpoint responds (200).
  • `langfuse-worker` runs its scheduled jobs (blob storage sync, event propagation, experiment backfill) without errors once given a correctly-shaped env.

One thing worth flagging for reviewers: langfuse-worker/langfuse-web hard-validate ENCRYPTION_KEY via zod as exactly 64 hex characters and crash-loop otherwise (my first test run used a 62-char placeholder and hit exactly that). I checked Dokploy's own generateHash implementation to confirm ${hash:64} in template.toml outputs randomBytes(32).toString("hex") truncated to 64 chars — i.e. exactly what this needs, so the real Dokploy-generated value is fine. Also confirmed generatePassword only emits alphanumerics, so it's safe embedded directly in DATABASE_URL and the redis --requirepass arg with no escaping concerns.

Only thing I still can't verify without a live Dokploy instance is the actual domain-routing (Traefik) layer for the two config.domains entries — happy to test against the PR preview once it's up.

Docker sets HOSTNAME to the container id, and Next.js standalone binds to
it, which resolves to a single network's IP. With Dokploy's proxy network
attached as a second network, Traefik got connection refused (502).
Setting HOSTNAME=0.0.0.0 fixes routing; verified with a live deploy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 9, 2026 05:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

@Siumauricio

Copy link
Copy Markdown
Contributor

Reviewed and deploy-tested on a live Dokploy instance. The template is a faithful adaptation of the official docker-compose.yml — same images and tags (langfuse/langfuse:4, langfuse/langfuse-worker:4, clickhouse/clickhouse-server:25.12, postgres:17, redis:7, and yes, upstream really does use cgr.dev/chainguard/minio), all six services present, secrets correctly templated (ENCRYPTION_KEY as ${hash:64} = exactly the 64 hex chars the zod validation requires), and the web-only LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT override mirrors upstream's public-endpoint pattern. generate-meta.js --check passes (511 templates).

One bug found and fixed (pushed to this branch as e2c3a24): the first deploy came up with every container running/healthy but the web domain returned a sustained 502. Logs showed Next.js was actually ready:

▲ Next.js 16.2.11
- Local:  http://95f26e46b9cc:3000
✓ Ready in 0ms

That log line is the tell — Docker sets HOSTNAME to the container id and Next.js standalone binds to it, which resolves to a single network's IP. Dokploy attaches its Traefik proxy network as a second network on the container, so Traefik got connection refused. This never shows up with plain docker compose + published ports (single network), which is why your local test passed. Fix: HOSTNAME: "0.0.0.0" on langfuse-web — same pattern other Next.js templates in this repo use.

Deploy evidence (after fix):

  • All 6 containers running, postgres/clickhouse/redis/minio healthy
  • GET /api/public/health{"status":"OK","version":"4.6.0"} (200)
  • GET / → 200, GET /auth/sign-in → 200
  • MinIO domain: GET /minio/health/live → 200; anonymous bucket listing correctly denied (AccessDenied), confirming presigned-URL-only access
  • langfuse-worker logs clean: ClickHouse migrations completed, background migrations finished, scheduled jobs (event propagation, experiment backfill) running with no errors

LGTM after the fix — ready to merge.

@Siumauricio
Siumauricio merged commit bbd0817 into Dokploy:canary Aug 9, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files. template New template request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New Template Request: Langfuse (Open Source LLM Engineering Platform)

4 participants