环境变量
可选客服聊天没有新的环境密钥:support.websiteId 是公开站点标识,放在产品配置;真实支持邮箱用 metadata.supportEmail。默认关闭,未知供应商、非法 ID 和开启后缺少邮件回退会被配置 / 构建检查拒绝。不要把 Crisp REST API 凭据放入前端配置。
文件与安全边界
根目录 .env 是仓库已有的共享默认值和占位符;真实凭据只放被忽略的 .env.local。从 .env.example 复制,不能把生产值提交回 .env。新站工厂不复制任何本地凭据、数据库或 Git 历史。
API 契约:apps/api/lib/env.ts。local.ts、dev.ts 和 worker.ts 都通过 parseEnv 检查基础字段及 OAuth / Stripe 组合;报错仅包含变量名和问题类别。Bun 本地加载环境文件,部署后的 Worker 从 Secrets 与绑定读取数据,不会读取电脑上的 .env.local。
核心与构建
| 变量 | 可见性 / 使用位置 | 要求 |
|---|---|---|
ENVIRONMENT | 服务端 | development / staging / production |
APP_NAME | 非秘密品牌;Wrangler / API / 构建兼容 | 与 websiteConfig.metadata.name 同步;工作台实际品牌取配置 |
APP_ORIGIN | 非秘密;API、OAuth、邮件链接 | 裸 origin;非开发环境必须 HTTPS |
PUBLIC_SITE_URL | 公开;Astro 构建 | canonical、OG、RSS、sitemap;线上与 APP_ORIGIN 相同,本地可预览线上 canonical |
API_ORIGIN | 本地开发 | Vite 代理目标;完整预览默认 http://127.0.0.1:4600 |
PORT | 本地开发 | API 端口,完整预览为 4600;更改需同步网关 |
DOCS_SITE_URL | 公开;文档构建 | 可选文档域名;缺省文档 noindex 且不生成 sitemap |
PUBLIC_* 会进入公开网页。VITE_APP_NAME、VITE_DEFAULT_MODE、VITE_SITE_LANGUAGE 由工作台构建从网站配置派生,不需要手工配置。不要把私钥或账号级 Cloudflare token 放进这些变量。
数据库与绑定
| 变量 / 绑定 | 使用位置 | 要求 |
|---|---|---|
DATABASE_URL | 本地预览、Drizzle CLI | 含凭据,服务端保密;本地完整预览限制 loopback 数据库 |
STORAGE | API Worker 资源绑定 | 私有 R2 对象;本地文件 API 与定时清理已验收,预览数据库需具备迁移 0002 / 0003;测试 / 正式环境已分别声明,资源创建与云端验收待做 |
TASK_QUEUE | API Worker 资源绑定 | 队列对象,名称在 Wrangler 各环境分别声明;任务消费者与实际本地验收已接入,数据库需迁移至 0006 |
TASK_DEAD_QUEUE_NAME | API Worker 服务端变量 | 必须与死信消费者队列名一致,用于区分业务 / 死信批次;开发运行时从 Wrangler 派生,生成器同步重命名;云端资源仍待验收 |
DISCORD_NOTIFICATION_WEBHOOK_URL | API 秘密 | 可选站主频道地址,启用需明确起点与完整迁移 0021;仅允许标准 Discord 服务地址 |
LOCAL_OPERATIONS | 仅本地运行时注入 | 站主消息捕获,开发缺失不回退外网;非开发环境不得携带 |
LOCAL_MAIL | 仅本地运行时注入 | 邮件捕获绑定,不作为云端变量或公开配置 |
LOCAL_MARKETING | 仅受控本地验收注入 | Contacts 测试绑定;开发环境缺少时明确失败,禁止回退到外部请求 |
HYPERDRIVE_CACHED / HYPERDRIVE_UNCACHED | 生产 Worker 资源绑定 | 配置 ID 在 API Wrangler 中;数据库原始凭据保存在 Hyperdrive 服务 |
APP_SERVICE / API_SERVICE / ASSETS | Web Worker 资源绑定 | 服务绑定与静态资产,不是环境变量字符串 |
可选任务邮件复用现有邮件变量,不引入新密钥或新队列绑定;启用前完整升级 0022,重建 API / 工作台 / 公共页,并核对定时维护。APP_NAME、APP_ORIGIN、发信地址或密钥变化会停止旧通知重试,接收地址和内容不能由客户端指定。正常预览仍关闭,两张通知表尚未应用到主库。
可选站主通知使用独立服务端频道地址和 notifications.operator 起点 / 开关;不复用个人邮件选择。启用前完整升级 0021 并重建。开发环境始终捕获;主库未升级,默认关闭。
迁移 CLI 与生产 API 的连接路径不同。运行 db:migrate 前核实 CLI 的数据库目标;不因配置检查通过就自动执行生产迁移。
线上应用使用独立业务角色,迁移连接使用实际所有者。更换数据库密码时更新该环境两个 Hyperdrive 的源凭据,并核对已有连接池;改本机 DATABASE_URL 不会更新云端。授权脚本与隔离复验见数据库角色与凭据。
bun dev 与完整预览均从 DATABASE_URL 派生两个本地 Hyperdrive 绑定,不再使用旧的 CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_* 覆盖。支持 loopback PostgreSQL 的 trust 认证;模拟器要求非空密码,因此空密码仅在内存中补本地占位值,不改环境文件或数据库用户。
资源对象类型集中在 apps/api/lib/bindings.ts,与 parseEnv 的普通字段分开。本地 R2 / 队列持久化目录为本项目 .local/workerd/,重启保留,生成站不复制或共享该目录。开发、测试、正式环境已分别声明存储、任务 / 死信队列与定时维护;云端资源尚未创建或验收。bun deploy:check --target staging 检查资源关系与占位配置,不能验证资源存在,见部署与验收。
bun dev 监听 API、数据库模型、公共产品配置及已构建邮件模板,重新打包并重载 Worker。修改本地运行器本身、启动变量或邮件模板源码后,重启开发命令以重新加载运行器和构建邮件模板。完整预览使用构建产物,修改后按快速开始重建并重启。
认证与邮件
| 变量 | 规则 |
|---|---|
BETTER_AUTH_SECRET | 至少 32 字符,每站每环境独立;非开发环境拒绝已知占位符 |
BETTER_AUTH_SECRETS | 可选、按顺序排列的 版本:密钥;未设置时明确使用版本 0。切换当前密钥需重新登录,基础密钥仍影响邮件选择与营销链接,见认证密钥轮换 |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | 两个一起设置或一起留空;仅服务端读取 |
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET | 两个一起设置或一起留空;仅服务端读取 |
RESEND_API_KEY | 线上邮件必须有值;bun dev / 完整本地预览由捕获器提供临时测试密钥,不会真实发送 |
RESEND_EMAIL_FROM | 合法邮箱,线上使用已验证发信域;本地可用 preview@example.test |
本地完整预览会把邮件写到 .local/outbox.jsonl,里面有 OTP / 验证链接,应只留在本机。Google / GitHub 的 Client ID 不是前端直接用的登录密钥,本站仍统一由服务端管理。
营销联系人
marketing.contactsSync 默认关闭,独立于两个申请页面开关。开启时复用具备 Full access 的 RESEND_API_KEY,以下三项一起设置:
| 变量 | 规则 |
|---|---|
RESEND_MARKETING_WEBHOOK_SECRET | 营销回调独立签名 secret,whsec_ 后为供应商提供的 Base64 内容 |
RESEND_NEWSLETTER_TOPIC_ID | 邮件订阅主题 UUID |
RESEND_WAITLIST_TOPIC_ID | 候补名单主题 UUID;必须与邮件订阅不同 |
当前名单 API 需完整迁移至 0016,同步时两个供应商主题的默认订阅必须为 opt_out。配置检查不联网验证权限或默认订阅。主预览保持 0012 与关闭状态;--contacts 使用独立数据库、完整迁移和测试绑定。完整说明见邮件订阅与候补名单。
支付
以下四项全部设置或全部留空。即使网站配置停用了支付,也不接受半组凭据,以便暴露部署错误。
| 变量 | 格式 / 职责 |
|---|---|
STRIPE_SECRET_KEY | sk_ 前缀,服务端调用 Stripe |
STRIPE_WEBHOOK_SECRET | whsec_ 前缀,验证 Better Auth 订阅 webhook |
STRIPE_CREDITS_WEBHOOK_SECRET | 可选 whsec_ 前缀,积分包独立回调;必须与订阅 endpoint secret 不同,启用积分包时必填 |
STRIPE_STARTER_PRICE_ID | price_ 前缀,对应 Starter 月度价格 |
STRIPE_PRO_PRICE_ID | price_ 前缀,对应 Pro 月度价格 |
STRIPE_PRO_ANNUAL_PRICE_ID | 可选 price_ 前缀,需前四项完整;独立的 Pro 年度价格,启用设置页年付选项 |
测试和生产使用各自的 Stripe 密钥、价格及 webhook secret,不混用。一次性积分包还需公开目录 creditPacks、独立回调 secret,并完整迁移至 0024、重建工作台 / API;当前仍要求前四项订阅凭据完整,不能仅配两个积分包变量。退款扣回、争议恢复和八连接并发已本地验收,真实沙箱待验收,见支付教程。当前没有 Creem、Waffo 运行时变量。
三个订阅 Price ID 必须不同,配置校验只报告字段要求,不输出实际 ID。月付商品需要一月一个周期,年付 Pro 需要一年一个周期;目前仅支持已启用、同测试 / 正式模式、固定正整数金额、按单位计价的 licensed 订阅商品,不支持多年月期、计量、阶梯价或一次性商品冒充订阅。创建 Checkout 前通过 SDK 核对实际收费项,配置存在不代表供应商商品已核实。
不配置年付 ID 时,设置页只提供月付;config:check 的 StripeAnnual 显示是否已配置。离线检查不连接 Stripe,实际收费金额和周期须在 Checkout 核对,真实付款仍需沙箱验收。
联盟营销
Rewardful 后台核查默认关闭。REWARDFUL_API_SECRET 与 REWARDFUL_WEBHOOK_SECRET 一起设置或一起留空,分别用于只读 REST API 与原始字节签名验证。开启还需 sk_test_ / sk_live_ 的 Stripe 私钥,以及已有 Stripe 四项完整凭据组;推广计划 UUID 和商户账户 ID 放在 websiteConfig.affiliates。这些服务密钥不放入前端配置。先完整升级至 0033 并重建 API,正常主预览不自动迁移。
浏览器追踪默认关闭;仅公开推荐页明确同意后加载 SDK,工作台仅读取本地候选并分别确认个人 / 团队绑定。tracking.publicKey 只能填写公开浏览器 key,不能填写服务密钥;200 回调只表示持久接收,供应商 paid 不证明银行到账。配置、有限恢复、退款 / 结算复核与受控本地验收见联盟营销教程。
统计
PUBLIC_CF_ANALYTICS_TOKEN 是 Web Analytics 的公开 beacon token。只有 websiteConfig.analytics.provider === "cloudflare" 才构建统计脚本;缺失 token 会使检查和 Astro 构建失败。它不是 Cloudflare API / 账号权限 token。私有工作台没有植入该脚本。
检查方式
bun run config:check
bun --env-file .env.staging.local scripts/config-check.ts --target staging
bun --env-file .env.production.local scripts/config-check.ts --target production
bun run config:check --json命令读取当前本地准备的环境,--target 不会把开发变量自动转换成生产变量。会检查匹配的 ENVIRONMENT、必需字段、凭据组、网站范围、域名和 .env.example 字段覆盖。只输出变量名与模块状态,不输出值;错误返回非零退出码。
该命令不联网,不验证账户权限、价格真实性、邮件可送达性、Hyperdrive / R2 绑定或 Worker 部署。生产 Worker 请求入口也做环境校验,但它不能代替部署前的沙箱验收。
模板官网与预览端口
WEBSITE_ORIGIN、WEBSITE_DOCS_URL、WEBSITE_DEMO_URL 只作用于模板官网构建,均为公开地址,不是服务凭据。生成产品不需要这些变量。
官网域名已确认为 stack.agentbuff.dev,专用示例为 .env.website.example;当前只配置、暂不发布。公开教程和模板演示地址尚未确定,示例留空,正式构建会拒绝未补齐的地址。它不设置产品 APP_ORIGIN,也不要求先接入真实模型或产品数据库。
preview.config.json 是构建产物预览的端口来源。bun preview:build 和 bun preview:start 派生产品 origin 与内部端口;生成器的 --port 设置新项目入口。生产构建仍以实际公开域名配置为准。
可选上传验证
PUBLIC_TURNSTILE_SITE_KEY 是 widget 的公开键,由文件配置 API 提供给工作台;TURNSTILE_SECRET_KEY 只供 API 调用 Siteverify。两个值成对配置。security.turnstile.enabled 默认关闭;开启后缺配置会拒绝启动。已知官方测试键只允许 development。详细操作与验收范围见执行限制与验证。
营销确认邮件复用以上邮件变量;启用名单前完整迁移至 0023,重建公共页与 API。语言来自每代主动同意的记录,不能用环境变量或请求头改写重试语言,详见邮件订阅。