From 886dac2db3bdb2a6ab4307fd3c1fdfc7bd2f2fa7 Mon Sep 17 00:00:00 2001 From: Stephen Chin <1290231+steveonjava@users.noreply.github.com> Date: Sun, 18 Oct 2026 14:47:25 -0700 Subject: [PATCH 1/4] feat: add Langfuse LXC --- ct/langfuse.sh | 77 +++++++++++++ install/langfuse-install.sh | 213 ++++++++++++++++++++++++++++++++++++ json/langfuse.json | 53 +++++++++ 3 files changed, 343 insertions(+) create mode 100644 ct/langfuse.sh create mode 100644 install/langfuse-install.sh create mode 100644 json/langfuse.json diff --git a/ct/langfuse.sh b/ct/langfuse.sh new file mode 100644 index 0000000000..a91eaf833a --- /dev/null +++ b/ct/langfuse.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/DevScripts/main" +_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func" +source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func") +# Copyright (c) 2021-2026 community-scripts ORG +# Author: Stephen Chin (steveonjava) +# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE +# Source: https://github.com/langfuse/langfuse + +APP="Langfuse" +var_tags="${var_tags:-ai;monitoring;analytics}" +var_cpu="${var_cpu:-4}" +var_ram="${var_ram:-16384}" +var_disk="${var_disk:-100}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +#var_arm64="${var_arm64:-no}" # unset = ask the user; set yes/no only when verified +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d /opt/langfuse || ! -f /opt/langfuse_data/.env ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "langfuse" "langfuse/langfuse"; then + msg_warn "Take a container snapshot before updating Langfuse; database migrations cannot be rolled back by this script." + msg_info "Stopping Langfuse" + systemctl stop langfuse-web langfuse-worker + msg_ok "Stopped Langfuse" + + # Keep the old version marker until the new services pass their health checks. + create_backup "$HOME/.langfuse" + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "langfuse" "langfuse/langfuse" "tarball" + restore_backup + NODE_VERSION="24" NODE_MODULE="pnpm@$(jq -r '.engines.pnpm' /opt/langfuse/package.json)" setup_nodejs + RUST_TOOLCHAIN="$(sed -n 's/^channel = "\(.*\)"/\1/p' /opt/langfuse/packages/native/rust-toolchain.toml)" RUST_PROFILE="minimal" setup_rust + + msg_info "Building Langfuse" + cd /opt/langfuse + HUSKY=0 $STD pnpm install --frozen-lockfile + DOCKER_BUILD=1 NEXT_TELEMETRY_DISABLED=1 CI=true pnpm_config_verify_deps_before_run=false $STD pnpm turbo run build --filter=web... --filter=worker... --concurrency=1 + cp -r web/.next/static web/.next/standalone/web/.next/ + cp -r web/public web/.next/standalone/web/ + msg_ok "Built Langfuse" + + msg_info "Starting Langfuse" + systemctl restart langfuse-migrate + systemctl start langfuse-web langfuse-worker + $STD curl --retry 60 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:3000/api/public/ready + $STD curl --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:3030/api/health + cat <"$HOME/.langfuse" +$(jq -r '.version' /opt/langfuse/package.json) +EOF + msg_ok "Started Langfuse" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW}Access it using the following URL:${CL}" +echo -e "${GATEWAY}${BGN}http://${IP}:3000${CL}" diff --git a/install/langfuse-install.sh b/install/langfuse-install.sh new file mode 100644 index 0000000000..aef21c32cb --- /dev/null +++ b/install/langfuse-install.sh @@ -0,0 +1,213 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2026 community-scripts ORG +# Author: Stephen Chin (steveonjava) +# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE +# Source: https://github.com/langfuse/langfuse + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y build-essential redis-server +msg_ok "Installed Dependencies" + +PG_VERSION="17" setup_postgresql +PG_DB_NAME="langfuse" PG_DB_USER="langfuse" setup_postgresql_db +setup_clickhouse +fetch_and_deploy_gh_release "langfuse" "langfuse/langfuse" "tarball" +NODE_VERSION="24" NODE_MODULE="pnpm@$(jq -r '.engines.pnpm' /opt/langfuse/package.json)" setup_nodejs +RUST_TOOLCHAIN="$(sed -n 's/^channel = "\(.*\)"/\1/p' /opt/langfuse/packages/native/rust-toolchain.toml)" RUST_PROFILE="minimal" setup_rust +fetch_and_deploy_gh_release "migrate" "golang-migrate/migrate" "binary" +fetch_and_deploy_gh_release "seaweedfs" "seaweedfs/seaweedfs" "prebuild" "latest" "/opt/seaweedfs" "linux_$(arch_resolve).tar.gz" + +msg_info "Building Langfuse" +cd /opt/langfuse +HUSKY=0 $STD pnpm install --frozen-lockfile +# Same build environment as upstream's Dockerfiles; DOCKER_BUILD=1 only skips env validation while compiling. +DOCKER_BUILD=1 NEXT_TELEMETRY_DISABLED=1 CI=true pnpm_config_verify_deps_before_run=false $STD pnpm turbo run build --filter=web... --filter=worker... --concurrency=1 +cp -r web/.next/static web/.next/standalone/web/.next/ +cp -r web/public web/.next/standalone/web/ +msg_ok "Built Langfuse" + +msg_info "Configuring Langfuse" +mkdir -p /opt/langfuse_data/storage +chmod 700 /opt/langfuse_data +REDIS_PASS=$(random_password 32) +CLICKHOUSE_PASS=$(random_password 32) +S3_SECRET=$(random_password 48) +cat </opt/langfuse_data/.env +NODE_ENV=production +DOCKER_BUILD=0 +NEXTAUTH_URL=http://${LOCAL_IP}:3000 +NEXTAUTH_SECRET=$(random_password 48) +SALT=$(random_password 48) +ENCRYPTION_KEY=$(openssl rand -hex 32) +DATABASE_URL=postgresql://langfuse:${PG_DB_PASS}@127.0.0.1:5432/langfuse +DIRECT_URL=postgresql://langfuse:${PG_DB_PASS}@127.0.0.1:5432/langfuse +CLICKHOUSE_URL=http://127.0.0.1:8123 +CLICKHOUSE_MIGRATION_URL=clickhouse://127.0.0.1:9000 +CLICKHOUSE_USER=langfuse +CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASS} +CLICKHOUSE_DB=default +CLICKHOUSE_CLUSTER_ENABLED=false +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 +REDIS_AUTH=${REDIS_PASS} +LANGFUSE_S3_EVENT_UPLOAD_BUCKET=langfuse +LANGFUSE_S3_EVENT_UPLOAD_PREFIX=events/ +LANGFUSE_S3_EVENT_UPLOAD_REGION=us-east-1 +LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=http://127.0.0.1:8333 +LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=langfuse +LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=${S3_SECRET} +LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE=true +TELEMETRY_ENABLED=false +NEXT_TELEMETRY_DISABLED=1 +EOF +chmod 600 /opt/langfuse_data/.env +cat </etc/redis/langfuse.conf +bind 127.0.0.1 ::1 +protected-mode yes +requirepass ${REDIS_PASS} +maxmemory-policy noeviction +appendonly yes +EOF +chown root:redis /etc/redis/langfuse.conf +chmod 640 /etc/redis/langfuse.conf +cat <>/etc/redis/redis.conf +include /etc/redis/langfuse.conf +EOF +cat </etc/clickhouse-server/users.d/langfuse.xml + + + + + $(printf '%s' "${CLICKHOUSE_PASS}" | sha256sum | cut -d ' ' -f1) + 127.0.0.1::1 + default + default + 1 + + + +EOF +chown clickhouse:clickhouse /etc/clickhouse-server/users.d/langfuse.xml +chmod 600 /etc/clickhouse-server/users.d/langfuse.xml +cat </etc/clickhouse-server/config.d/langfuse.xml + + 127.0.0.1 + UTC + +EOF +cat </opt/langfuse_data/s3.json +{ + "identities": [ + { + "name": "langfuse", + "credentials": [{"accessKey": "langfuse", "secretKey": "${S3_SECRET}"}], + "actions": ["Admin", "Read", "Write", "List", "Tagging"] + } + ] +} +EOF +chmod 600 /opt/langfuse_data/s3.json +msg_ok "Configured Langfuse" + +msg_info "Creating Services" +cat </etc/systemd/system/langfuse-storage.service +[Unit] +Description=Langfuse S3 Storage (SeaweedFS) +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/langfuse_data/storage +ExecStart=/opt/seaweedfs/weed server -dir=/opt/langfuse_data/storage -ip=127.0.0.1 -ip.bind=127.0.0.1 -s3 -s3.port=8333 -s3.port.iceberg=0 -s3.port.lance=0 -s3.config=/opt/langfuse_data/s3.json -master.telemetry=false +Restart=on-failure +RestartSec=5 +UMask=0077 + +[Install] +WantedBy=multi-user.target +EOF +cat </etc/systemd/system/langfuse-migrate.service +[Unit] +Description=Langfuse Database Migrations +After=network.target postgresql.service clickhouse-server.service redis-server.service langfuse-storage.service +Requires=postgresql.service clickhouse-server.service redis-server.service langfuse-storage.service +Before=langfuse-web.service langfuse-worker.service + +[Service] +Type=oneshot +WorkingDirectory=/opt/langfuse +EnvironmentFile=/opt/langfuse_data/.env +ExecStart=/usr/bin/pnpm --filter @langfuse/shared exec prisma db execute --schema=./prisma/schema.prisma --file=./scripts/cleanup.sql +ExecStart=/usr/bin/pnpm --filter @langfuse/shared exec prisma migrate deploy --schema=./prisma/schema.prisma +ExecStart=/bin/sh /opt/langfuse/packages/shared/clickhouse/scripts/up.sh +RemainAfterExit=yes +TimeoutStartSec=1800 +UMask=0077 +EOF +cat </etc/systemd/system/langfuse-web.service +[Unit] +Description=Langfuse Web +After=network.target langfuse-migrate.service +Requires=langfuse-migrate.service + +[Service] +Type=simple +WorkingDirectory=/opt/langfuse +EnvironmentFile=/opt/langfuse_data/.env +Environment=HOSTNAME=0.0.0.0 +Environment=PORT=3000 +ExecStart=/usr/bin/node /opt/langfuse/web/.next/standalone/web/server.js +SuccessExitStatus=143 +Restart=on-failure +RestartSec=5 +UMask=0077 + +[Install] +WantedBy=multi-user.target +EOF +cat </etc/systemd/system/langfuse-worker.service +[Unit] +Description=Langfuse Worker +After=network.target langfuse-migrate.service +Requires=langfuse-migrate.service + +[Service] +Type=simple +WorkingDirectory=/opt/langfuse +EnvironmentFile=/opt/langfuse_data/.env +Environment=HOSTNAME=127.0.0.1 +Environment=PORT=3030 +ExecStart=/usr/bin/node /opt/langfuse/worker/dist/index.js +Restart=on-failure +RestartSec=5 +UMask=0077 + +[Install] +WantedBy=multi-user.target +EOF +systemctl restart redis-server clickhouse-server +systemctl enable -q --now langfuse-storage +$STD curl --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:9333/cluster/status +$STD /opt/seaweedfs/weed shell -master=127.0.0.1:9333 <<<"s3.bucket.create -name langfuse" +# Pass S3 authentication over stdin, not process arguments or build logs. +$STD curl --config - --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:8333/langfuse < Date: Sun, 18 Oct 2026 17:05:53 -0700 Subject: [PATCH 2/4] feat: create Langfuse admin on first start, update SeaweedFS and migrate - Create the admin, a Default project and its API keys through upstream's LANGFUSE_INIT_* variables on first start, save them to ~/langfuse.creds, then drop the one-time values from .env and keep sign-up disabled. - Update SeaweedFS and golang-migrate from their own releases. - Let langfuse-migrate want, not require, the local PostgreSQL, ClickHouse, Redis and SeaweedFS units, so an external server can replace one. - Explain the build-time DOCKER_BUILD flag and drop it from the runtime .env. --- ct/langfuse.sh | 20 +++++++++++++++++ install/langfuse-install.sh | 43 ++++++++++++++++++++++++++++++++++--- json/langfuse.json | 15 ++++++++++--- 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/ct/langfuse.sh b/ct/langfuse.sh index a91eaf833a..f4020dc2a4 100644 --- a/ct/langfuse.sh +++ b/ct/langfuse.sh @@ -17,6 +17,8 @@ var_version="${var_version:-13}" #var_arm64="${var_arm64:-no}" # unset = ask the user; set yes/no only when verified var_unprivileged="${var_unprivileged:-1}" +export var_admin_email="${var_admin_email:-}" + header_info "$APP" variables color @@ -32,6 +34,23 @@ function update_script() { exit fi + if check_for_gh_release "seaweedfs" "seaweedfs/seaweedfs"; then + msg_info "Stopping SeaweedFS" + systemctl stop langfuse-storage + msg_ok "Stopped SeaweedFS" + + fetch_and_deploy_gh_release "seaweedfs" "seaweedfs/seaweedfs" "prebuild" "latest" "/opt/seaweedfs" "linux_$(arch_resolve).tar.gz" + + msg_info "Starting SeaweedFS" + systemctl start langfuse-storage + $STD curl --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:8333/healthz + msg_ok "Started SeaweedFS" + fi + + if check_for_gh_release "migrate" "golang-migrate/migrate"; then + fetch_and_deploy_gh_release "migrate" "golang-migrate/migrate" "binary" + fi + if check_for_gh_release "langfuse" "langfuse/langfuse"; then msg_warn "Take a container snapshot before updating Langfuse; database migrations cannot be rolled back by this script." msg_info "Stopping Langfuse" @@ -48,6 +67,7 @@ function update_script() { msg_info "Building Langfuse" cd /opt/langfuse HUSKY=0 $STD pnpm install --frozen-lockfile + # DOCKER_BUILD=1 only skips Langfuse's runtime env validation while compiling; no container is involved. DOCKER_BUILD=1 NEXT_TELEMETRY_DISABLED=1 CI=true pnpm_config_verify_deps_before_run=false $STD pnpm turbo run build --filter=web... --filter=worker... --concurrency=1 cp -r web/.next/static web/.next/standalone/web/.next/ cp -r web/public web/.next/standalone/web/ diff --git a/install/langfuse-install.sh b/install/langfuse-install.sh index aef21c32cb..0d1f241d68 100644 --- a/install/langfuse-install.sh +++ b/install/langfuse-install.sh @@ -13,6 +13,15 @@ setting_up_container network_check update_os +if [[ -z "${var_admin_email:-}" ]]; then + var_admin_email=$(prompt_input "Langfuse admin email:" "admin@example.com" 60) +fi +var_admin_email="${var_admin_email:-admin@example.com}" +if [[ ! "$var_admin_email" =~ ^[A-Za-z0-9_+-]+(\.[A-Za-z0-9_+-]+)*@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$ ]]; then + msg_warn "Invalid email '${var_admin_email}', falling back to admin@example.com" + var_admin_email="admin@example.com" +fi + msg_info "Installing Dependencies" $STD apt install -y build-essential redis-server msg_ok "Installed Dependencies" @@ -29,7 +38,7 @@ fetch_and_deploy_gh_release "seaweedfs" "seaweedfs/seaweedfs" "prebuild" "latest msg_info "Building Langfuse" cd /opt/langfuse HUSKY=0 $STD pnpm install --frozen-lockfile -# Same build environment as upstream's Dockerfiles; DOCKER_BUILD=1 only skips env validation while compiling. +# DOCKER_BUILD=1 only skips Langfuse's runtime env validation while compiling; no container is involved. DOCKER_BUILD=1 NEXT_TELEMETRY_DISABLED=1 CI=true pnpm_config_verify_deps_before_run=false $STD pnpm turbo run build --filter=web... --filter=worker... --concurrency=1 cp -r web/.next/static web/.next/standalone/web/.next/ cp -r web/public web/.next/standalone/web/ @@ -41,9 +50,11 @@ chmod 700 /opt/langfuse_data REDIS_PASS=$(random_password 32) CLICKHOUSE_PASS=$(random_password 32) S3_SECRET=$(random_password 48) +ADMIN_PASS=$(random_password 24) +PUBLIC_KEY="pk-lf-$(random_password 32)" +SECRET_KEY="sk-lf-$(random_password 32)" cat </opt/langfuse_data/.env NODE_ENV=production -DOCKER_BUILD=0 NEXTAUTH_URL=http://${LOCAL_IP}:3000 NEXTAUTH_SECRET=$(random_password 48) SALT=$(random_password 48) @@ -66,8 +77,18 @@ LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=http://127.0.0.1:8333 LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=langfuse LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=${S3_SECRET} LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE=true +AUTH_DISABLE_SIGNUP=true TELEMETRY_ENABLED=false NEXT_TELEMETRY_DISABLED=1 +LANGFUSE_INIT_ORG_ID=default-org +LANGFUSE_INIT_ORG_NAME=Default +LANGFUSE_INIT_PROJECT_ID=default-project +LANGFUSE_INIT_PROJECT_NAME=Default +LANGFUSE_INIT_PROJECT_PUBLIC_KEY=${PUBLIC_KEY} +LANGFUSE_INIT_PROJECT_SECRET_KEY=${SECRET_KEY} +LANGFUSE_INIT_USER_EMAIL=${var_admin_email} +LANGFUSE_INIT_USER_NAME=Admin +LANGFUSE_INIT_USER_PASSWORD=${ADMIN_PASS} EOF chmod 600 /opt/langfuse_data/.env cat </etc/redis/langfuse.conf @@ -139,7 +160,7 @@ cat </etc/systemd/system/langfuse-migrate.service [Unit] Description=Langfuse Database Migrations After=network.target postgresql.service clickhouse-server.service redis-server.service langfuse-storage.service -Requires=postgresql.service clickhouse-server.service redis-server.service langfuse-storage.service +Wants=postgresql.service clickhouse-server.service redis-server.service langfuse-storage.service Before=langfuse-web.service langfuse-worker.service [Service] @@ -208,6 +229,22 @@ $STD curl --retry 60 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:3 $STD curl --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:3030/api/health msg_ok "Created Services" +msg_info "Saving Credentials" +# The first start created the admin, project and API keys; later restarts must not re-create them. +sed -i '/^LANGFUSE_INIT_/d' /opt/langfuse_data/.env +cat <>~/langfuse.creds + +Langfuse Admin +Email: ${var_admin_email} +Password: ${ADMIN_PASS} + +Langfuse API Keys (project Default) +Public Key: ${PUBLIC_KEY} +Secret Key: ${SECRET_KEY} +EOF +chmod 600 ~/langfuse.creds +msg_ok "Saved Credentials" + motd_ssh customize cleanup_lxc diff --git a/json/langfuse.json b/json/langfuse.json index c834553f00..bfb0ef250b 100644 --- a/json/langfuse.json +++ b/json/langfuse.json @@ -33,13 +33,22 @@ } ], "default_credentials": { - "username": null, + "username": "admin@example.com", "password": null }, + "app_vars": [ + { + "name": "var_admin_email", + "label": "Admin Email", + "type": "text", + "default": "admin@example.com", + "help": "Login for the generated admin account. Langfuse only uses it to send mail when SMTP is configured." + } + ], "notes": [ { - "text": "There is no default account. Create your account in the web interface, then set AUTH_DISABLE_SIGNUP=true in /opt/langfuse_data/.env and restart langfuse-web.", - "type": "warning" + "text": "The admin login and the Default project's API keys are saved to ~/langfuse.creds inside the container. Sign-up is off, invited users included; set AUTH_DISABLE_SIGNUP=false in /opt/langfuse_data/.env and restart langfuse-web while adding users.", + "type": "info" }, { "text": "Behind a reverse proxy, set NEXTAUTH_URL in /opt/langfuse_data/.env to the external URL and restart langfuse-web.", From 080a14a9fe26469d9e7c682d594af78f0f3f37ef Mon Sep 17 00:00:00 2001 From: Stephen Chin <1290231+steveonjava@users.noreply.github.com> Date: Sun, 18 Oct 2026 17:46:11 -0700 Subject: [PATCH 3/4] feat: accept an admin password for Langfuse - Read var_admin_pass (declared in app_vars, exported from the ct script) and use it for the first-start admin account. - Generate a password when it is empty, or when it is shorter than Langfuse's 8-character minimum or holds spaces, quotes or backslashes that systemd's EnvironmentFile parser would alter. --- ct/langfuse.sh | 1 + install/langfuse-install.sh | 13 ++++++++++--- json/langfuse.json | 7 +++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ct/langfuse.sh b/ct/langfuse.sh index f4020dc2a4..2c39d0fcd5 100644 --- a/ct/langfuse.sh +++ b/ct/langfuse.sh @@ -18,6 +18,7 @@ var_version="${var_version:-13}" var_unprivileged="${var_unprivileged:-1}" export var_admin_email="${var_admin_email:-}" +export var_admin_pass="${var_admin_pass:-}" header_info "$APP" variables diff --git a/install/langfuse-install.sh b/install/langfuse-install.sh index 0d1f241d68..fa6e972d01 100644 --- a/install/langfuse-install.sh +++ b/install/langfuse-install.sh @@ -21,6 +21,14 @@ if [[ ! "$var_admin_email" =~ ^[A-Za-z0-9_+-]+(\.[A-Za-z0-9_+-]+)*@([A-Za-z0-9][ msg_warn "Invalid email '${var_admin_email}', falling back to admin@example.com" var_admin_email="admin@example.com" fi +var_admin_pass="${var_admin_pass:-}" +if [[ -n "$var_admin_pass" ]] && [[ ${#var_admin_pass} -lt 8 || "$var_admin_pass" == *[[:space:][:cntrl:]\"\'\\]* ]]; then + msg_warn "Admin password needs at least 8 characters and no spaces, quotes or backslashes, generating one" + var_admin_pass="" +fi +if [[ -z "$var_admin_pass" ]]; then + var_admin_pass=$(random_password 24) +fi msg_info "Installing Dependencies" $STD apt install -y build-essential redis-server @@ -50,7 +58,6 @@ chmod 700 /opt/langfuse_data REDIS_PASS=$(random_password 32) CLICKHOUSE_PASS=$(random_password 32) S3_SECRET=$(random_password 48) -ADMIN_PASS=$(random_password 24) PUBLIC_KEY="pk-lf-$(random_password 32)" SECRET_KEY="sk-lf-$(random_password 32)" cat </opt/langfuse_data/.env @@ -88,7 +95,7 @@ LANGFUSE_INIT_PROJECT_PUBLIC_KEY=${PUBLIC_KEY} LANGFUSE_INIT_PROJECT_SECRET_KEY=${SECRET_KEY} LANGFUSE_INIT_USER_EMAIL=${var_admin_email} LANGFUSE_INIT_USER_NAME=Admin -LANGFUSE_INIT_USER_PASSWORD=${ADMIN_PASS} +LANGFUSE_INIT_USER_PASSWORD=${var_admin_pass} EOF chmod 600 /opt/langfuse_data/.env cat </etc/redis/langfuse.conf @@ -236,7 +243,7 @@ cat <>~/langfuse.creds Langfuse Admin Email: ${var_admin_email} -Password: ${ADMIN_PASS} +Password: ${var_admin_pass} Langfuse API Keys (project Default) Public Key: ${PUBLIC_KEY} diff --git a/json/langfuse.json b/json/langfuse.json index bfb0ef250b..3af12db29b 100644 --- a/json/langfuse.json +++ b/json/langfuse.json @@ -43,6 +43,13 @@ "type": "text", "default": "admin@example.com", "help": "Login for the generated admin account. Langfuse only uses it to send mail when SMTP is configured." + }, + { + "name": "var_admin_pass", + "label": "Admin Password", + "type": "password", + "secret": true, + "help": "Generated when left empty. At least 8 characters, without spaces, quotes or backslashes." } ], "notes": [ From d0bd9f8b74ff801d58ebafc8cf84b8b956feb800 Mon Sep 17 00:00:00 2001 From: Stephen Chin <1290231+steveonjava@users.noreply.github.com> Date: Wed, 11 Nov 2026 21:41:42 -0800 Subject: [PATCH 4/4] fix: remove comments and set platforms for Langfuse Drop the explanatory comments from the CT and install scripts, as AGENTS.md asks for no comments beyond the header, and declare platforms as pve in the metadata. --- ct/langfuse.sh | 2 -- install/langfuse-install.sh | 3 --- json/langfuse.json | 3 +++ 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ct/langfuse.sh b/ct/langfuse.sh index 2c39d0fcd5..0981e762a5 100644 --- a/ct/langfuse.sh +++ b/ct/langfuse.sh @@ -58,7 +58,6 @@ function update_script() { systemctl stop langfuse-web langfuse-worker msg_ok "Stopped Langfuse" - # Keep the old version marker until the new services pass their health checks. create_backup "$HOME/.langfuse" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "langfuse" "langfuse/langfuse" "tarball" restore_backup @@ -68,7 +67,6 @@ function update_script() { msg_info "Building Langfuse" cd /opt/langfuse HUSKY=0 $STD pnpm install --frozen-lockfile - # DOCKER_BUILD=1 only skips Langfuse's runtime env validation while compiling; no container is involved. DOCKER_BUILD=1 NEXT_TELEMETRY_DISABLED=1 CI=true pnpm_config_verify_deps_before_run=false $STD pnpm turbo run build --filter=web... --filter=worker... --concurrency=1 cp -r web/.next/static web/.next/standalone/web/.next/ cp -r web/public web/.next/standalone/web/ diff --git a/install/langfuse-install.sh b/install/langfuse-install.sh index fa6e972d01..67305ee890 100644 --- a/install/langfuse-install.sh +++ b/install/langfuse-install.sh @@ -46,7 +46,6 @@ fetch_and_deploy_gh_release "seaweedfs" "seaweedfs/seaweedfs" "prebuild" "latest msg_info "Building Langfuse" cd /opt/langfuse HUSKY=0 $STD pnpm install --frozen-lockfile -# DOCKER_BUILD=1 only skips Langfuse's runtime env validation while compiling; no container is involved. DOCKER_BUILD=1 NEXT_TELEMETRY_DISABLED=1 CI=true pnpm_config_verify_deps_before_run=false $STD pnpm turbo run build --filter=web... --filter=worker... --concurrency=1 cp -r web/.next/static web/.next/standalone/web/.next/ cp -r web/public web/.next/standalone/web/ @@ -226,7 +225,6 @@ systemctl restart redis-server clickhouse-server systemctl enable -q --now langfuse-storage $STD curl --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:9333/cluster/status $STD /opt/seaweedfs/weed shell -master=127.0.0.1:9333 <<<"s3.bucket.create -name langfuse" -# Pass S3 authentication over stdin, not process arguments or build logs. $STD curl --config - --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:8333/langfuse <>~/langfuse.creds diff --git a/json/langfuse.json b/json/langfuse.json index 3af12db29b..55da710e1c 100644 --- a/json/langfuse.json +++ b/json/langfuse.json @@ -16,6 +16,9 @@ "architectures": [ "amd64" ], + "platforms": [ + "pve" + ], "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/langfuse.webp", "description": "Langfuse is an open-source LLM engineering platform. It records traces, token usage and costs from LLM applications and agents, and adds evaluations, prompt management and analytics dashboards.", "install_methods": [