Repository navigation
feat: add Langfuse LXC #2448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
michelroegl-brunner
merged 4 commits into
community-scripts:main
from
steveonjava:langfuse-native-lxc
Nov 12, 2026
+422
−0
Merged
feat: add Langfuse LXC #2448
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
886dac2
feat: add Langfuse LXC
steveonjava 6a22877
feat: create Langfuse admin on first start, update SeaweedFS and migrate
steveonjava 080a14a
feat: accept an admin password for Langfuse
steveonjava d0bd9f8
fix: remove comments and set platforms for Langfuse
steveonjava File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| #!/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}" | ||
|
|
||
| export var_admin_email="${var_admin_email:-}" | ||
| export var_admin_pass="${var_admin_pass:-}" | ||
|
|
||
| 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 "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" | ||
| systemctl stop langfuse-web langfuse-worker | ||
| msg_ok "Stopped Langfuse" | ||
|
|
||
| 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 <<EOF >"$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}" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,254 @@ | ||
| #!/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 | ||
|
|
||
| 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 | ||
| 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 | ||
| 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 | ||
| 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) | ||
| PUBLIC_KEY="pk-lf-$(random_password 32)" | ||
| SECRET_KEY="sk-lf-$(random_password 32)" | ||
| cat <<EOF >/opt/langfuse_data/.env | ||
| NODE_ENV=production | ||
| 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 | ||
| 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=${var_admin_pass} | ||
| EOF | ||
| chmod 600 /opt/langfuse_data/.env | ||
| cat <<EOF >/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 <<EOF >>/etc/redis/redis.conf | ||
| include /etc/redis/langfuse.conf | ||
| EOF | ||
| cat <<EOF >/etc/clickhouse-server/users.d/langfuse.xml | ||
| <clickhouse> | ||
| <users> | ||
| <default remove="remove"/> | ||
| <langfuse> | ||
| <password_sha256_hex>$(printf '%s' "${CLICKHOUSE_PASS}" | sha256sum | cut -d ' ' -f1)</password_sha256_hex> | ||
| <networks><ip>127.0.0.1</ip><ip>::1</ip></networks> | ||
| <profile>default</profile> | ||
| <quota>default</quota> | ||
| <access_management>1</access_management> | ||
| </langfuse> | ||
| </users> | ||
| </clickhouse> | ||
| EOF | ||
| chown clickhouse:clickhouse /etc/clickhouse-server/users.d/langfuse.xml | ||
| chmod 600 /etc/clickhouse-server/users.d/langfuse.xml | ||
| cat <<EOF >/etc/clickhouse-server/config.d/langfuse.xml | ||
| <clickhouse> | ||
| <listen_host replace="replace">127.0.0.1</listen_host> | ||
| <timezone>UTC</timezone> | ||
| </clickhouse> | ||
| EOF | ||
| cat <<EOF >/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 <<EOF >/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 <<EOF >/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 | ||
| Wants=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 <<EOF >/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 <<EOF >/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" | ||
| $STD curl --config - --retry 30 --retry-delay 2 --retry-connrefused -fsS http://127.0.0.1:8333/langfuse <<EOF | ||
| aws-sigv4 = "aws:amz:us-east-1:s3" | ||
| user = "langfuse:${S3_SECRET}" | ||
| EOF | ||
| systemctl enable -q --now 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 | ||
| msg_ok "Created Services" | ||
|
|
||
| msg_info "Saving Credentials" | ||
| sed -i '/^LANGFUSE_INIT_/d' /opt/langfuse_data/.env | ||
| cat <<EOF >>~/langfuse.creds | ||
|
|
||
| Langfuse Admin | ||
| Email: ${var_admin_email} | ||
| Password: ${var_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 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.