Bind address, and the reason this matters most. Langfuse is a Next.js standalone server: it binds to whatever $HOSTNAME resolves to, not to all interfaces. The container is on two networks and its hostname resolved to the proxy address, so it listened on proxy only - HTTP 200 from proxy, HTTP 000 from ai-internal. Caddy is on proxy, so the public URL worked perfectly and nothing looked wrong, but ai-api runs on ai-internal and every trace it sent would have failed silently in Phase 6. HOSTNAME=0.0.0.0 fixes it; both networks now return 200. External network name. ai-internal does not exist - Compose created it as azureuser_ai-internal under the host's shared project name. Verified both ways on the host: with name: a container joins and reaches pg-ai, without it up fails with "network ai-internal declared as external, but could not be found". Healthcheck. Was probing localhost, which failed for the bind reason above and marked the container unhealthy while it served fine. Restored to 127.0.0.1, which now works because the bind is genuinely fixed rather than worked around. Signup policy. AUTH_DISABLE_SIGNUP false. Langfuse keeps its own user table behind Authelia; closed signup with no seeded user means nobody can log in at all. Accepted for the PoC because Authelia is the real gate - revisit before handover. Phase 2 gate passed on the host with these applied: 302 to the auth portal, certificate issued, AD + Duo login confirmed, and a test trace verified in the database rather than trusted from the API response. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
84 lines
3.3 KiB
YAML
84 lines
3.3 KiB
YAML
# =============================================================================
|
|
# langfuse-compose.yml -> deployed to ~/langfuse-compose.yml on lin001
|
|
#
|
|
# Deployed early, deliberately (spec Phase 2): from here on, every experiment is
|
|
# traced. MIT licensed, self-hosted, no licence cost.
|
|
#
|
|
# ai-internal is created by ai-compose.yml - bring that up first.
|
|
#
|
|
# docker compose -f ~/langfuse-compose.yml up -d
|
|
# =============================================================================
|
|
|
|
services:
|
|
|
|
lf-db:
|
|
image: postgres:16-alpine
|
|
container_name: lf-db
|
|
restart: unless-stopped
|
|
networks: [ai-internal]
|
|
env_file:
|
|
- /home/azureuser/ai/langfuse.env # 0600, not in Git
|
|
environment:
|
|
POSTGRES_DB: langfuse
|
|
POSTGRES_USER: langfuse
|
|
PGDATA: /var/lib/postgresql/data/pgdata
|
|
# POSTGRES_PASSWORD comes from langfuse.env.
|
|
volumes:
|
|
- /datadisk/langfuse/db:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U langfuse -d langfuse"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
logging:
|
|
driver: json-file
|
|
options: { max-size: "10m", max-file: "3" }
|
|
|
|
langfuse:
|
|
image: langfuse/langfuse:2
|
|
container_name: langfuse
|
|
restart: unless-stopped
|
|
depends_on:
|
|
lf-db:
|
|
condition: service_healthy
|
|
networks: [ai-internal, proxy]
|
|
env_file:
|
|
- /home/azureuser/ai/langfuse.env # 0600, not in Git
|
|
environment:
|
|
NEXTAUTH_URL: https://lf.yokogawa.tech
|
|
TELEMETRY_ENABLED: "false"
|
|
# Langfuse is a Next.js standalone server: it binds to whatever $HOSTNAME
|
|
# resolves to, NOT to all interfaces. This container is on two networks, and
|
|
# the container hostname resolves to its PROXY address - so without this it
|
|
# listens on proxy only and is unreachable from ai-internal, where ai-api
|
|
# will run. Verified on the host: proxy HTTP 200, ai-internal HTTP 000.
|
|
# Binding 0.0.0.0 makes it listen on both, and on loopback.
|
|
HOSTNAME: "0.0.0.0"
|
|
# Langfuse keeps its own user table behind Authelia. Signup is left OPEN so
|
|
# anyone who has already cleared AD + Duo can create their own account -
|
|
# with it closed and no user seeded, nobody can log in at all. Accepted
|
|
# for the PoC because Authelia is the real gate. Revisit before handover.
|
|
AUTH_DISABLE_SIGNUP: "false"
|
|
# DATABASE_URL, NEXTAUTH_SECRET and SALT come from langfuse.env.
|
|
healthcheck:
|
|
# Works because HOSTNAME=0.0.0.0 above makes it bind all interfaces including
|
|
# loopback. Without that env var this probe fails while the app serves fine.
|
|
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3000/api/public/health || exit 1"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
logging:
|
|
driver: json-file
|
|
options: { max-size: "10m", max-file: "3" }
|
|
|
|
networks:
|
|
# Created by ai-compose.yml, which runs under the shared 'azureuser' project,
|
|
# so Compose named it azureuser_ai-internal. Without the name: line the lookup
|
|
# is for a network literally called 'ai-internal' and up fails with
|
|
# "network ai-internal declared as external, but could not be found".
|
|
ai-internal:
|
|
external: true
|
|
name: azureuser_ai-internal
|
|
# proxy was created by hand, not by Compose, so it carries no project prefix.
|
|
proxy:
|
|
external: true
|