
Langfuse 环境变量配置管理实战Zod 驱动的多包配置体系深度解析【免费下载链接】langfuse Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuseLangfuse 作为一个开源的 AI 工程平台LLM 可观测性、Evals、提示词管理、Playground 等采用 monorepo 架构由 Web、Worker、Shared、EE 等多个包组成。本文将系统讲解 Langfuse 如何用 Zod 构建一套类型安全、启动即校验、默认值完备的环境变量配置体系先剖析为什么要用 Zod 校验而非直接读取process.env再逐个深入 web、worker、shared、ee 四个包的配置实现与源码细节随后详解NEXT_PUBLIC_LANGFUSE_CLOUD_REGION、LANGFUSE_EE_LICENSE_KEY、SALT、ENCRYPTION_KEY等关键变量的语义与配置方式最后给出 9 条可直接落地的工程最佳实践。读完本文你将能独立为 Langfuse 的任一部署形态OSS 自托管、EE 自托管、Cloud编写正确的环境变量并为自己的 Node.js 项目复刻这套配置管理范式。本文以仓库内.agents/skills/backend-dev-guidelines/references/configuration.md为骨架结合源码实现展开。为什么不用裸的 process.env而要用 Zod 校验直接读取process.env是每个 Node.js 开发者最熟悉的姿势但它存在一组系统性问题❌没有类型安全process.env的值永远是string | undefined任何字段都要手动断言❌没有校验拼错的变量名、错误的取值如PORTabc直到运行时才暴露❌难以测试测试时需要手动delete/set每个环境变量极易互相污染❌运行时错误类型错误、缺失必填项都以隐晦的undefined形式在业务代码深处爆发❌没有默认值开发环境每个变量都要手动补齐。Langfuse 的做法是引入Zod schema 对全部环境变量做集中声明在进程启动时一次性parse从而获得✅ 类型安全env.DATABASE_URL自动推导为stringenv.PORT推导为number✅ 启动时校验配置错误会在应用启动瞬间以清晰的错误信息失败而不是在某个请求里 500✅ 清晰的错误信息指出哪个变量缺失/格式错误/越界✅ 默认值z.default()让开发环境零配置起步✅ 环境相关转换用z.coerce、z.transform把字符串变成数字、Map、数组等复杂结构。从源码结构看Langfuse 将这套模式固化为每个包一个 env 文件的约定langfuse/ ├── web/src/env.mjs # Next.js 应用t3-env 模式 ├── worker/src/env.ts # Worker 服务纯 Zod schema ├── packages/shared/src/env.ts # 共享配置纯 Zod schema └── ee/src/env.ts # 企业版纯 Zod schema四个文件分别对应web、worker、packages/shared、ee四个包职责边界清晰web 管 UI 与 API 层worker 管队列消费与批处理shared 管跨服务共享的 Redis/ClickHouse/加密配置ee 管企业版开关。Web 包基于 t3-env 的服务器/客户端分离校验web/src/env.mjs 是 Langfuse 配置体系中结构最复杂的一个文件使用t3-oss/env-nextjst3-env的createEnvAPI专为 Next.js 设计。它的核心价值在于显式区分服务端变量与客户端变量。结构总览import { z } from zod; import { createEnv } from t3-oss/env-nextjs; export const env createEnv({ // 服务端专属变量绝不暴露给浏览器 server: { DATABASE_URL: z.url(), NEXTAUTH_SECRET: process.env.NODE_ENV production ? z.string().min(1) : z.string().min(1).optional(), SALT: z.string({ error: (issue) issue.input undefined ? A strong Salt is required to encrypt API keys securely. See: https://langfuse.com/self-hosting#deploy-the-container : Invalid type, }), CLICKHOUSE_URL: z.url(), // ... 100 服务端变量 }, // 客户端变量会暴露到浏览器必须 NEXT_PUBLIC_ 前缀 client: { NEXT_PUBLIC_LANGFUSE_CLOUD_REGION: z .enum([US, EU, STAGING, DEV, HIPAA, JP]) .optional(), NEXT_PUBLIC_SIGN_UP_DISABLED: z.enum([true, false]).default(false), // ... 客户端变量 }, // 运行时映射Next.js edge runtime 下无法直接解构 process.env必须手动映射全部变量 runtimeEnv: { DATABASE_URL: process.env.DATABASE_URL, NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, NEXT_PUBLIC_LANGFUSE_CLOUD_REGION: process.env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION, // ... 必须覆盖所有变量 }, // Docker 构建阶段环境变量尚不可用跳过校验 skipValidation: process.env.DOCKER_BUILD 1, emptyStringAsUndefined: true, });关键机制1. server / client 分区。server区声明的变量只在服务端可见如DATABASE_URL、NEXTAUTH_SECRET、SALTclient区声明的变量会打进浏览器 bundle因此强制要求NEXT_PUBLIC_前缀。任何又想给浏览器用又不想加前缀的变量都无法通过校验。2. 生产环境必填、开发环境可选的条件化校验。例如NEXTAUTH_SECRET在NODE_ENV production时必须满足z.string().min(1)开发环境则允许缺省见 web/src/env.mjs。这是 t3-env 的典型用法同一套代码在不同环境下拥有不同的严格度。3.SALT是硬性必填项。源码中用z.string({ error: ... })自定义错误消息明确指出SALT 缺失将无法安全加密 API 密钥见 web/src/env.mjs。这是因为 Langfuse 在数据库中加密存储 API Key必须依赖 SALT 派生密钥。4.NEXTAUTH_URL的预处理preprocess。当部署在 Vercel 时NextAuth.js 会自动回退使用VERCEL_URLLangfuse 在 schema 里用z.preprocess复刻了这一行为若VERCEL_URL存在则优先使用它避免 Vercel 部署因未显式设置NEXTAUTH_URL而失败见 web/src/env.mjs。5.runtimeEnv手动映射。这是 t3-env 对 Next.js edge runtime 的适配要求——在 middleware 等 edge 场景中不能把process.env当普通对象解构必须逐个字段手动映射见 web/src/env.mjs。Langfuse 的runtimeEnv区有 200 余行覆盖全部 server 与 client 变量是四个包里最长的映射表。6. Docker 构建逃逸阀。skipValidation: process.env.DOCKER_BUILD 1见 web/src/env.mjs。由于 Docker 镜像构建发生在运行时环境变量注入之前构建阶段若执行校验必然失败因此DOCKER_BUILD1时跳过校验。这与 worker/shared 的process.env.DOCKER_BUILD 1 ? (process.env as any) : EnvSchema.parse(...)是同一设计意图。7.emptyStringAsUndefined: true。将.env文件中的空字符串视为undefined避免OPTIONAL_VAR这类写法触发必填错误。使用方式// 服务端代码tRPC、API 路由 import { env } from /src/env.mjs; const dbUrl env.DATABASE_URL; const salt env.SALT; // 客户端代码React 组件 import { env } from /src/env.mjs; const region env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION;服务端与客户端共用同一个env导出对象类型由 schema 自动推导。Worker 包纯 Zod schema 的 Express 服务配置worker/src/env.ts 是 Langfuse 后台 worker队列消费、Eval 执行、批处理导出等的配置入口使用纯 Zod schema不带 t3-env因为 worker 是普通 Express 服务无需区分 server/client。结构总览import { z } from zod; import { removeEmptyEnvVariables } from langfuse/shared; import { langfuseS3EventKeyMaxSegmentBytesSchema } from langfuse/shared/src/env; const EnvSchema z.object({ BUILD_ID: z.string().optional(), NODE_ENV: z .enum([development, test, production]) .default(development), DATABASE_URL: z.string(), HOSTNAME: z.string().default(0.0.0.0), PORT: z.coerce .number() // .env 文件会把数字转成字符串因此必须强制转换回数字 .positive() .max(65536, options.port should be 0 and 65536) .default(3030), // ClickHouse CLICKHOUSE_URL: z.url(), CLICKHOUSE_USER: z.string(), CLICKHOUSE_PASSWORD: z.string(), // S3 事件上传必填 LANGFUSE_S3_EVENT_UPLOAD_BUCKET: z.string({ error: Langfuse requires a bucket name for S3 Event Uploads., }), // 队列并发设置 LANGFUSE_INGESTION_QUEUE_PROCESSING_CONCURRENCY: z.coerce .number() .positive() .default(20), LANGFUSE_EVAL_EXECUTION_WORKER_CONCURRENCY: z.coerce .number() .positive() .default(5), // 队列消费者开关 QUEUE_CONSUMER_INGESTION_QUEUE_IS_ENABLED: z .enum([true, false]) .default(true), QUEUE_CONSUMER_BATCH_EXPORT_QUEUE_IS_ENABLED: z .enum([true, false]) .default(true), // ... 150 worker 专属变量 }); export const env: z.infertypeof EnvSchema process.env.DOCKER_BUILD 1 ? (process.env as any) : EnvSchema.parse(removeEmptyEnvVariables(process.env));源码级亮点1. 端口校验带边界。PORT使用z.coerce.number().positive().max(65536).default(3030)见 worker/src/env.ts并保留了.env文件字符串转数字的经典注释——这是z.coerce存在的根本原因。2. S3 事件上传桶必填。LANGFUSE_S3_EVENT_UPLOAD_BUCKET是 worker 的硬性要求缺失时抛出Langfuse requires a bucket name for S3 Event Uploads见 worker/src/env.ts。S3 事件上传承担着 trace/observation 事件数据的持久化是 worker 正常工作的前提。3. 跨包共享的校验 schema。LANGFUSE_S3_EVENT_KEY_MAX_SEGMENT_BYTES直接复用 shared 包导出的langfuseS3EventKeyMaxSegmentBytesSchema见 worker/src/env.ts。这个 schema 在 packages/shared/src/env.ts 中定义限定了每个 S3 key 段的字节预算min(64)max(2048)默认 2048降到 255 可兼容 ext4 上的 MinIO。注释明确指出生产者和消费者必须对同一 id 写出相同的 S3 key校验规则必须一致这正是把它抽到 shared 包的原因。4. 消费队列开关枚举。worker 有 30 个QUEUE_CONSUMER_*_IS_ENABLED开关覆盖 ingestion、batch export、eval execution、monitor、webhook、通知等全部队列见 worker/src/env.ts全部以true/false枚举 默认值的形式声明让运维可以按需裁剪 worker 角色。5. 超越 schema 的组合校验。worker 的 env 文件还包含两段 schema 之外的业务校验逻辑这是原文档未展开的深度细节validateV4Flags校验 V4 迁移相关的三个 flag 组合LANGFUSE_MIGRATION_V4_WRITE_MODE、LANGFUSE_MIGRATION_V4_NATIVE_OTEL_BEHAVIOUR、LANGFUSE_MIGRATION_V4_ALLOW_PREVIEW_OPT_IN对会静默丢数据的组合如legacydirect直接抛错见 worker/src/env.tsvalidateInAppAgentSandboxConfig当LANGFUSE_IN_APP_AGENT_SANDBOX_PROVIDERlambda-microvm时强制要求镜像标识、执行角色 ARN 与区域三个变量齐全见 worker/src/env.ts。这说明 Langfuse 的配置校验不仅做字段级校验还做跨字段业务约束校验保证配置在语义上自洽。使用方式import { env } from ./env; const concurrency env.LANGFUSE_INGESTION_QUEUE_PROCESSING_CONCURRENCY; const s3Bucket env.LANGFUSE_S3_EVENT_UPLOAD_BUCKET;Shared 包跨服务共享配置与加密密钥管理packages/shared/src/env.ts 保存 web 与 worker 两个服务共用的配置Redis、ClickHouse、日志、加密、S3 等。它是四个包中变量种类最丰富的200 个web 和 worker 各自通过依赖langfuse/shared获得同一套校验规则。结构总览import { z } from zod; import { removeEmptyEnvVariables } from ./utils/environment; const EnvSchema z.object({ NODE_ENV: z .enum([development, test, production]) .default(development), // Redis 配置 REDIS_HOST: z.string().nullish(), REDIS_PORT: z.coerce.number().positive().max(65536).default(6379).nullable(), REDIS_AUTH: z.string().nullish(), REDIS_CONNECTION_STRING: z.string().nullish(), REDIS_CLUSTER_ENABLED: z.enum([true, false]).default(false), // ClickHouse CLICKHOUSE_URL: z.url(), CLICKHOUSE_USER: z.string(), CLICKHOUSE_PASSWORD: z.string(), CLICKHOUSE_MAX_OPEN_CONNECTIONS: z.coerce.number().int().default(25), // S3 事件上传 LANGFUSE_S3_EVENT_UPLOAD_BUCKET: z.string(), LANGFUSE_S3_EVENT_UPLOAD_REGION: z.string().optional(), // 日志 LANGFUSE_LOG_LEVEL: z .enum([trace, debug, info, warn, error, fatal]) .optional(), LANGFUSE_LOG_FORMAT: z.enum([text, json]).default(text), // 加密 ENCRYPTION_KEY: z .string() .length( 64, ENCRYPTION_KEY must be 256 bits, 64 string characters in hex format, generate via: openssl rand -hex 32, ) .optional(), // ... 80 共享变量 }); export const env: z.infertypeof EnvSchema process.env.DOCKER_BUILD 1 ? (process.env as any) : EnvSchema.parse(removeEmptyEnvVariables(process.env));源码级亮点1. Redis 全家桶。shared 包对 Redis 的覆盖极为完整基础连接REDIS_HOST/REDIS_PORT/REDIS_AUTH/REDIS_CONNECTION_STRING、集群模式REDIS_CLUSTER_ENABLED、REDIS_CLUSTER_NODES、REDIS_CLUSTER_SLOTS_REFRESH_TIMEOUT默认 5000ms、哨兵模式REDIS_SENTINEL_ENABLED及一系列REDIS_SENTINEL_*、TLSREDIS_TLS_ENABLED及 10 个REDIS_TLS_*子项、key 前缀REDIS_KEY_PREFIX用于多租户共享 Redis。REDIS_PORT默认 6379 且可空。2. 内置的 socket 级看门狗配置。REDIS_SOCKET_TIMEOUT_MS使用自定义 schemaredisSocketTimeoutMsSchema见 packages/shared/src/env.ts通过z.refine强制该值要么为 0禁用要么 ≥ 10000ms。注释解释了原因——BullMQ 的阻塞命令BZPOPMIN合法地会有约 5 秒的空闲过低的值会让健康的空闲 worker 反复重连因此默认 30000ms。3. 加密密钥的严格格式校验。ENCRYPTION_KEY用z.string().length(64, ...)强制 64 位十六进制字符串即 256-bit错误消息直接给出生成命令openssl rand -hex 32见 packages/shared/src/env.ts。4. 日志级别与格式。LANGFUSE_LOG_LEVEL限定为trace/debug/info/warn/error/fatal六档LANGFUSE_LOG_FORMAT限定text/json且默认text。5. 类型导出。文件末尾导出export type SharedEnv z.infertypeof EnvSchema见 packages/shared/src/env.ts让其他包可以引用完整配置类型。使用方式import { env } from langfuse/shared/src/env; const redisHost env.REDIS_HOST; const clickhouseUrl env.CLICKHOUSE_URL;EE 包最小化的企业版配置ee/src/env.ts 是四个包中最简的一个只有两个变量import { z } from zod; import { removeEmptyEnvVariables } from langfuse/shared; const EnvSchema z.object({ NEXT_PUBLIC_LANGFUSE_CLOUD_REGION: z.string().optional(), LANGFUSE_EE_LICENSE_KEY: z.string().optional(), }); export const env EnvSchema.parse(removeEmptyEnvVariables(process.env));EEEnterprise Edition功能开关本质上就依赖两个信号Cloud 区域或EE License Key。二者任一存在即认为 EE 可用——这一点在 ee/src/ee-license-check/index.ts 有明确实现import { env } from ../env; export const isEeAvailable: boolean env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION ! undefined || env.LANGFUSE_EE_LICENSE_KEY ! undefined;也就是说EE 能力自定义 SSO、高级 RBAC、审计日志、自定义品牌等在两种场景下被激活Langfuse Cloud通过 region 标识和持有 License 的自托管部署。特殊环境变量详解NEXT_PUBLIC_LANGFUSE_CLOUD_REGION云部署区域标识作用标识 Langfuse Cloud 的部署区域同时用于触发云专属功能用量计量与计费、云消费告警、免费额度执行、Stripe 集成、PostHog 分析等。类型US | EU | STAGING | DEV | HIPAA | JP | undefined。在 web 侧用z.enum([...]).optional()严格限定见 web/src/env.mjsworker 侧同样以枚举限定见 worker/src/env.ts。使用位置web客户端可见、ee、shared、worker 四个包均有引用。取值场景环境取值用途开发者笔记本DEV或STAGING本地联调云端基础设施Langfuse Cloud USUS生产 US 区域Langfuse Cloud EUEU生产 EU 区域Langfuse Cloud HIPAAHIPAAHIPAA 合规区域Langfuse Cloud JPJP生产 JP 区域OSS 自托管不设置undefined自托管没有区域概念典型代码模式// 判断是否运行在云环境 if (env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION) { // 启用云专属功能 // - 用量计量与计费 // - 云消费告警 // - 免费额度执行 // - Stripe 集成 // - PostHog 分析 } // 区域专属行为 if (env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION HIPAA) { // HIPAA 合规功能 } // 开发/预发检查 if (env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION DEV) { // 启用调试功能 }配置示例# 开发者笔记本上的 .env NEXT_PUBLIC_LANGFUSE_CLOUD_REGIONDEV # Cloud US 部署 NEXT_PUBLIC_LANGFUSE_CLOUD_REGIONUS # OSS 自托管部署不设置该变量注意该变量是NEXT_PUBLIC_前缀属于编译期变量——在 Docker 镜像预构建场景下它会在构建时被打进客户端 bundle修改后需要重新构建镜像这一点在 web/src/env.mjs 的注释中专门强调。LANGFUSE_EE_LICENSE_KEY企业版许可证作用在自托管部署中启用 Enterprise Edition 功能。类型string | undefined。使用位置web 与 ee 包。取值场景部署形态取值生效功能Langfuse Cloud不设置云功能由NEXT_PUBLIC_LANGFUSE_CLOUD_REGION控制OSS 自托管不设置仅核心开源功能EE 自托管License Key 字符串企业功能开启由 License 控制的企业功能当LANGFUSE_EE_LICENSE_KEY设置且有效时SSO 集成自定义 OIDC、SAML高级 RBAC审计日志自定义品牌SLA 支持高级安全特性使用模式import { env } from /src/env.mjs; // 检查是否存在 EE License if (env.LANGFUSE_EE_LICENSE_KEY) { // 校验 License const isValidLicense await validateEELicense(env.LANGFUSE_EE_LICENSE_KEY); if (isValidLicense) { // 启用 EE 功能 enableCustomSSO(); enableAdvancedRBAC(); } }配置示例# OSS 自托管无 License # LANGFUSE_EE_LICENSE_KEY 不设置 # EE 自托管 LANGFUSE_EE_LICENSE_KEYee_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Langfuse Cloud改用 region NEXT_PUBLIC_LANGFUSE_CLOUD_REGIONUS # LANGFUSE_EE_LICENSE_KEY 不使用其他重要变量DOCKER_BUILD// 在 Docker 构建阶段跳过校验 skipValidation: process.env.DOCKER_BUILD 1;Docker 构建发生在运行时环境变量注入之前此时DATABASE_URL等必然缺失因此必须跳过校验。Langfuse 的 webskipValidation与 worker/shared/eeprocess.env.DOCKER_BUILD 1 ? (process.env as any) : EnvSchema.parse(...)两个包族用不同语法实现了同一个逃逸阀。SALTSALT: z.string({ required_error: A strong Salt is required to encrypt API keys securely., });用于在数据库中加密 API Key生产环境必须设置。缺失时 Langfuse 会拒绝启动并给出指向自托管部署文档的明确提示见 web/src/env.mjs。开发环境可用openssl rand -base64 32之类命令生成。ENCRYPTION_KEYENCRYPTION_KEY: z.string().length(64, Must be 256 bits, 64 hex characters);可选的 256-bit 密钥用于加密敏感数据库字段。必须恰好 64 位十六进制字符。生成命令openssl rand -hex 32九个必须遵守的配置最佳实践1. 永远从 env.mjs/env.ts 导入绝不直接读 process.env// ❌ 永远不要这样做 const dbUrl process.env.DATABASE_URL; // ✅ 永远这样做 import { env } from /src/env.mjs; const dbUrl env.DATABASE_URL; // 类型安全、已校验2. 使用正确的导入路径// Web 包 import { env } from /src/env.mjs; // Worker 包 import { env } from ./env; // Shared 包 import { env } from langfuse/shared/src/env;3. 客户端变量必须以 NEXT_PUBLIC_ 开头// ❌ 浏览器中不可用 API_KEY: z.string(); // 在 server 配置里 // ✅ 浏览器可访问 NEXT_PUBLIC_API_KEY: z.string(); // 在 client 配置里4. 为开发环境提供合理默认值PORT: z.coerce.number().positive().default(3030), NODE_ENV: z.enum([development, test, production]).default(development), REDIS_PORT: z.coerce.number().positive().default(6379),5. 数字使用 z.coerce 强制转换// .env 文件中的值永远是字符串 PORT: z.coerce.number(); // 把 3000 转成 3000Langfuse 的源码注释原话是.env files convert numbers to strings, therefore we have to enforce them to be numbers见 worker/src/env.ts。6. 用 transform 转换复杂值Langfuse 提供了多种复杂转换的现成范例// 逗号分隔值 - 小写字符串数组日志透传头 LANGFUSE_LOG_PROPAGATED_HEADERS: z.string().optional().transform((s) s ? s.split(,).map((s) s.toLowerCase().trim()) : [] ), // project:rate 对 - Mapstring, number按项目采样 LANGFUSE_INGESTION_PROCESSING_SAMPLED_PROJECTS: z.string().optional().transform((val) { const map new Mapstring, number(); val?.split(,).forEach(part { const [projectId, rate] part.split(:); map.set(projectId, parseFloat(rate)); }); return map; }),在 packages/shared/src/env.ts 中采样率转换的实现比文档示例更严谨它会用z.coerce.number().min(0).max(1)二次校验每个采样率非法格式整体回退为空 Map且对projectId:rate缺失部分的情况抛出Invalid format错误。这类解析 校验 兜底的完整闭环是 transform 的最佳形态。此外还有把逗号分隔的 JSON 字符串解析为对象并校验的模式LANGFUSE_AI_EXTRA_HEADERS通过z.refine要求必须是合法的 JSON 对象见 packages/shared/src/env.ts。7. 启动时校验失败即停所有环境变量在应用启动时一次性校验。配置错误会立即失败并给出清晰错误❌ Validation error: - SALT: Required - CLICKHOUSE_URL: Invalid url - PORT: Number must be less than or equal to 655368. 保留 Docker 构建逃逸阀新增 env 文件时始终保留 Docker 构建分支export const env process.env.DOCKER_BUILD 1 ? (process.env as any) : EnvSchema.parse(removeEmptyEnvVariables(process.env));9. 使用 removeEmptyEnvVariables 助手空字符串会被视为undefinedimport { removeEmptyEnvVariables } from langfuse/shared; EnvSchema.parse(removeEmptyEnvVariables(process.env));该函数在 packages/shared/src/utils/environment.ts 中实现逻辑极简遍历runtimeEnv的所有键值把值为的条目直接删除。它等价于 t3-env 的emptyStringAsUndefined选项文件头部注释引用了 t3-env 对应实现但被抽出来是为了在无法安装 t3-env 的 CommonJS 打包环境如 worker中复用同一语义。它避免了.env文件中这类写法引发的诡异错误# .env OPTIONAL_VAR # 视为 undefined而不是空字符串配置文件位置总览langfuse/ ├── .env # 本地开发覆盖 ├── .env.dev.example # 示例开发配置 ├── web/src/env.mjs # Web 应用环境校验 ├── worker/src/env.ts # Worker 环境校验 ├── packages/shared/src/env.ts # 共享环境校验 └── ee/src/env.ts # EE 环境校验仓库根目录确实存在 .env.dev.example315 行它给出了完整的本地开发配置模板docker-compose 端口映射与容器名、DATABASE_URL/DIRECT_URLPostgreSQL 连接串、CLICKHOUSE_URL/CLICKHOUSE_USER/CLICKHOUSE_PASSWORD、NEXTAUTH_URL等并提示新增环境变量时应同步更新/src/env.mjs中的 schema。切勿提交到版本库的文件.env.env.local.env.production总结Langfuse 配置体系的三个设计要点回顾整条配置链路Langfuse 的环境变量体系可以提炼为三个贯穿始终的设计原则集中声明、启动校验每个包一个 env 文件Zod schema 是唯一事实来源进程启动即失败绝不把配置错误拖到运行时。分层共享、规则一致shared 包承载跨服务配置并导出可复用的 schema 片段如langfuseS3EventKeyMaxSegmentBytesSchemaweb 与 worker 复用同一规则避免生产者与消费者校验不一致这类隐性故障。开发友好、部署可控z.coerce 默认值 NEXT_PUBLIC_前缀约定 DOCKER_BUILD逃逸阀 emptyStringAsUndefined/removeEmptyEnvVariables让本地零配置起步同时让生产环境在语义上自洽如 worker 的 V4 flag 组合校验与 sandbox 配置校验。这套Zod schema 驱动配置的范式并不局限于 Langfuse 本身——任何希望获得类型安全、启动期校验与可测试性的 Node.js/TypeScript 服务都可以直接照搬这套模式。延伸阅读backend-dev-guidelines 主指南 —— 配置管理所属的后端开发规范总纲架构总览 —— 理解 web/worker/shared/ee 各包的职责边界【免费下载链接】langfuse Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考