完整指南)
OpenWork Den 私有部署初始管理员引导Initial Admin Bootstrap完整指南【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork私有化部署 OpenWork Den 时管理员常常会在尚无任何账号之前就关闭公开注册。此时如何安全地创建第一个账号OpenWork 提供了一条基于「初始管理员引导Initial Administrator Bootstrap」的专用流程不需要开放公开注册、不依赖 SMTP 邮件投递仅凭一枚一次性 setup code 与管理员邮箱即可完成首个账号、单例组织singleton organization与平台管理员授权的一次性建立。读完本文你将掌握该流程的完整原理、环境变量配置、Kubernetes/Docker Compose 落地方式以及轮换与恢复的边界条件。为什么需要初始管理员引导私有 OpenWork Den 部署single_org模式通常会先关闭公开注册DEN_SINGLE_ORG_ALLOW_PUBLIC_SIGNUPfalse这在还没有任何账号时就形成了一个「先有鸡还是先有蛋」的问题公开注册已关闭却没有任何人能登录去创建组织和管理员。此时如果直接配置一个 owner 或 bootstrap 管理员邮箱需要明确三点限制配置邮箱只负责授权只有当账号已经存在后该邮箱才被授予权限不会自动创建账号邮箱本身不会产生账号知道邮箱并不等于能接管部署必须同时持有服务端 setup-code 密钥。初始管理员引导流程正是为了在零用户、零邮件基础设施的前提下安全地创建第一个账号而设计的。工作流程七步完成的引导链路从 docs/initial-admin-bootstrap.md 与实现源码 ee/apps/den-api/src/initial-admin-bootstrap.ts 可以还原出完整的七步链路部署必须拥有零个 Better Auth 用户——引导只对完全空白的部署开放Better Authuser表必须仍然为空——可用性检查使用存在性查询而非计数提交的邮箱必须在可引导名单内——由DEN_SINGLE_ORG_OWNER_EMAILS或DEN_BOOTSTRAP_ADMIN_EMAILS决定提交的一次性 setup code 必须与服务端 secret 匹配——比较使用恒定时间算法timingSafeEqual见 ee/apps/den-api/src/initial-admin-bootstrap.ts服务端签发一枚短期、绑定邮箱的引导授权bootstrap grant——grant 默认 TTL 为 10 分钟INITIAL_ADMIN_BOOTSTRAP_GRANT_TTL_MS 10 * 60 * 1000以ow_bootstrap_为前缀用 HMAC-SHA256 以BETTER_AUTH_SECRET签名最终账号创建仍走 Better Auth 的邮箱/密码注册通道——引导只负责验证不绕过认证机制OpenWork 创建或复用单例组织授予 owner 成员身份写入 platform-admin 授权并自动登录——核心实现在completeInitialAdminBootstrapSignup调用ensureSingletonOrganizationForUser(session.userId, { forceOwner: true })保证 owner 身份通过ensureBootstrappedPlatformAdmin将邮箱写入AdminAllowlistTablenote 标记为Initial administrator bootstrap。一个关键的不可逆语义一旦第一个用户存在轮换或重新添加 setup-code secret 都无法重新打开引导。现有用户也永远不会被删除或被改写用于恢复引导——这是刻意的安全设计而不是配置缺陷。可引导邮箱Eligible Emails的判定顺序对single_org部署引导邮箱的候选名单按以下顺序确定实现见 ee/apps/den-api/src/initial-admin-bootstrap.ts 的configuredBootstrapEmails若DEN_SINGLE_ORG_OWNER_EMAILS已设置则规范化后的这些邮箱有资格认领/setup若DEN_SINGLE_ORG_OWNER_EMAILS为空则回退使用DEN_BOOTSTRAP_ADMIN_EMAILS作为可引导邮箱列表。两种来源的邮箱都会经过trim().toLowerCase()规范化见 ee/apps/den-api/src/env.ts 与normalizeInitialAdminBootstrapEmail。需要注意一个细节即使首个 owner 的邮箱来自DEN_SINGLE_ORG_OWNER_EMAILS引导成功后该邮箱也会被写入 platform-admin 白名单。这意味着它同时获得了单例组织 owner与平台级管理员两种身份而DEN_BOOTSTRAP_ADMIN_EMAILS则另有独立的启动期白名单播种逻辑见下文源码佐证部分。环境变量三件套与文件注入引导流程需要三类环境变量全部由 den-api 的 Zod 环境模式解析见 ee/apps/den-api/src/env.ts 与 ee/apps/den-api/src/env.ts环境变量必填说明DEN_SINGLE_ORG_ALLOW_PUBLIC_SIGNUPfalse是关闭公开注册这是私有部署的前提DEN_SINGLE_ORG_OWNER_EMAILSadminexample.com二选一单例组织 owner 邮箱逗号分隔优先于引导名单DEN_BOOTSTRAP_ADMIN_EMAILSadminexample.com二选一引导管理员邮箱名单DEN_SINGLE_ORG_OWNER_EMAILS为空时生效DEN_INITIAL_ADMIN_BOOTSTRAP_CODEone-time setup code是一次性 setup code明文字符串DEN_INITIAL_ADMIN_BOOTSTRAP_CODE_FILE/run/secrets/initial-admin-bootstrap-code替代基于文件的注入方式关于两种注入方式的取舍从 ee/apps/den-api/src/env.ts 的解析逻辑可以确认环境变量优先DEN_INITIAL_ADMIN_BOOTSTRAP_CODE存在时直接使用文件为回退变量未设置时才读取DEN_INITIAL_ADMIN_BOOTSTRAP_CODE_FILE指向的文件内容会trim()文件不可读即启动失败readOptionalSecretFile在读取失败时抛出DEN_INITIAL_ADMIN_BOOTSTRAP_CODE_FILE must point to a readable file采用 fail-closed 语义。DEN_SINGLE_ORG_OWNER_EMAILS与DEN_BOOTSTRAP_ADMIN_EMAILS均按逗号分隔解析splitCsv会 trim 并过滤空项邮箱统一转小写后参与匹配。重要约定setup code 是纯字符串。请为每个部署生成唯一值并通过你的密钥管理系统提供切勿多个环境复用。安全地生成一次性 Code在操作员工作站或受信任的密钥管理 Shell 中执行以下命令文档原版命令它们可以避免把明文 code 留在 Shell 历史记录中umask 077 code_file$(mktemp) openssl rand -base64 32 | tr -d \n $code_fileumask 077保证临时文件仅当前用户可读写openssl rand -base64 32生成 256 位随机熵tr -d \n去除换行避免破坏后续读取。接下来将code_file中的原始 code 保存到你的密码管理器或 break-glass紧急接管密钥库同时写入 OpenWork 部署的 secret 中第一位管理员登录后删除本地文件rm -f $code_fileKubernetes 落地Secret 与 Helm Chart方式一直接创建 Kubernetes Secret将生成的文件作为 key 注入--from-file会把文件名DEN_INITIAL_ADMIN_BOOTSTRAP_CODE作为 keykubectl create secret generic openwork-ee \ --namespace openwork-ee \ --from-fileDEN_INITIAL_ADMIN_BOOTSTRAP_CODE$code_file \ --dry-runclient -o yaml | kubectl apply -f -方式二由 Helm Chart 管理 Secret如果 Helm Chart 负责创建 Secret在 values 中设置对应 packaging/helm/openwork-ee/values.yaml 与 packaging/helm/openwork-ee/values.yamlsecret: values: initialAdminBootstrapCode: REPLACE_BOOTSTRAP_CODEChart 会把该值映射为DEN_INITIAL_ADMIN_BOOTSTRAP_CODE环境变量见 packaging/helm/openwork-ee/values.yaml 中initialAdminBootstrapCode: DEN_INITIAL_ADMIN_BOOTSTRAP_CODE的 key 映射。方式三复用已有 Secret如果使用已有的 Secret需要确保secret.keys.initialAdminBootstrapCode指向承载 setup code 的那个 keysecret: create: false existingSecret: my-existing-secret keys: initialAdminBootstrapCode: MY_BOOTSTRAP_CODE_KEY红线不要把 setup code 放进 ConfigMap。Chart 的普通配置包括DEN_BOOTSTRAP_ADMIN_EMAILS、DEN_SINGLE_ORG_*走 ConfigMap见 packaging/helm/openwork-ee/templates/configmap.yaml 与 packaging/helm/openwork-ee/templates/configmap.yaml但 setup code 这类凭据必须留在 Secret 中。Docker Compose 与其它容器运行方式对于环境变量注入直接设置DEN_SINGLE_ORG_OWNER_EMAILSadminexample.com DEN_SINGLE_ORG_ALLOW_PUBLIC_SIGNUPfalse DEN_INITIAL_ADMIN_BOOTSTRAP_CODEREPLACE_BOOTSTRAP_CODE对于基于文件的密钥库挂载包含 setup code 的文件并设置DEN_INITIAL_ADMIN_BOOTSTRAP_CODE_FILE/run/secrets/initial-admin-bootstrap-code仓库自带的开发编排 packaging/docker/docker-compose.den-dev.yml 已经预留了全部四个相关变量的透传DEN_SINGLE_ORG_OWNER_EMAILS: ${DEN_SINGLE_ORG_OWNER_EMAILS:-} DEN_SINGLE_ORG_ALLOW_PUBLIC_SIGNUP: ${DEN_SINGLE_ORG_ALLOW_PUBLIC_SIGNUP:-false} DEN_INITIAL_ADMIN_BOOTSTRAP_CODE: ${DEN_INITIAL_ADMIN_BOOTSTRAP_CODE:-} DEN_INITIAL_ADMIN_BOOTSTRAP_CODE_FILE: ${DEN_INITIAL_ADMIN_BOOTSTRAP_CODE_FILE:-}同一套模式同样适用于容器平台 secret store、systemd 环境文件、VM 上的 secret agent、Kubernetes projected Secrets。开发环境下联调示例可见 worlds/acme-docs.ts 与 evals/packages/hosts/src/provision.ts 中对这些变量的引用。访问 Setup 页面配置完成后打开https://openwork.example.com/setupSetup 页面会要求输入有资格的管理员邮箱原始的一次性 setup code。该页面不会展示已配置的特权邮箱列表也不需要邮件投递能力SMTP 全程可选。验证引导可用性状态端点引导的可用性可以通过公开状态端点探测curl -fsS https://api.openwork.example.com/v1/auth/bootstrap/status可能的返回状态为available、complete、unavailable。对应实现见 ee/apps/den-api/src/routes/auth/index.ts状态由getInitialAdminBootstrapAvailability计算ee/apps/den-api/src/initial-admin-bootstrap.ts状态内部 reason触发条件availableready无用户、名单与 code 均配置完成completeusers_existBetter Authuser表已有任意用户unavailablenot_configured缺少邮箱名单或缺少 setup code响应中永远不会包含已配置的邮箱或 setup code 的任何信息这是公开端点必须遵守的保密边界。与之配套的验证端点是POST /v1/auth/bootstrap/verifyee/apps/den-api/src/routes/auth/index.ts它校验邮箱 code 并返回短期 grant。该端点还带基于邮箱的限流超出阈值会返回429与Retry-After头。轮换与恢复边界条件第一个用户创建之前轮换 生成新 code 并替换DEN_INITIAL_ADMIN_BOOTSTRAP_CODE或 code 文件然后重启或滚动更新 Den API Pod使其读取新的 secret。第一个用户创建之后轮换 setup code 无法重新启用引导。此后只能走常规的管理员账号恢复流程、数据库备份或经过明确评审的运维恢复流程。Setup code 丢失如果 setup code 缺失引导会fail-closed/setup报告setup 不可用。修复 secret 并重启 API 即可。不要通过删除用户或组织来恢复一个配置错误的引导——这是明确禁止的危险操作。一个实现细节引导可用性是用对 Better Authuser表的存在性查询SELECT id ... LIMIT 1判定的而不是全表计数见 ee/apps/den-api/src/initial-admin-bootstrap.ts。因此一旦存在任意用户setup 就永久不可用除非操作员在 OpenWork 之外刻意修改数据库。安全警告清单不要把真实 setup code 放进源码控制、已提交的 Helm values、ConfigMap、日志、截图、issue 描述、PR 正文、聊天记录示例中一律使用占位符如REPLACE_BOOTSTRAP_CODE初始管理员引导不要求 SMTP也不要求邮箱验证但如果你的部署为常规认证开启了邮箱验证注册机制与保护措施仍由 Better Auth 全权负责——引导流程不会绕过 Better Auth 的注册通道。源码佐证关键实现一览环境解析ee/apps/den-api/src/env.ts 声明四个相关变量ee/apps/den-api/src/env.ts 实现环境变量优先、文件回退的读取ee/apps/den-api/src/env.ts 的文件读取函数在文件不可读时抛错引导核心ee/apps/den-api/src/initial-admin-bootstrap.ts 的verifyInitialAdminBootstrap完成邮箱名单校验、恒定时间 code 比对与 10 分钟 grant 签发ee/apps/den-api/src/initial-admin-bootstrap.ts 的completeInitialAdminBootstrapSignup完成组织复用、owner 强置与白名单写入HTTP 层ee/apps/den-api/src/routes/auth/index.ts 定义GET /v1/auth/bootstrap/status与POST /v1/auth/bootstrap/verify包括限流与 403/409/429 错误语义管理员白名单ee/apps/den-api/src/admin-allowlist.ts 展示DEN_BOOTSTRAP_ADMIN_EMAILS在启动期的播种逻辑note 为Seeded bootstrap admin与引导成功后的Initial administrator bootstrap写入互补环境示例ee/apps/den-api/.env.example 对DEN_BOOTSTRAP_ADMIN_EMAILS的注释明确说明留空即禁用自托管安装的引导管理员播种。适用前提与限制本文所有配置以当前仓库 docs/initial-admin-bootstrap.md 及其对应实现为准引导流程面向single_org私有部署且要求部署处于零 Better Auth 用户的初始状态引导是一次性流程第一个用户落库后即永久关闭请将 setup code 的生成与分发视为部署前的一次性操作并妥善归档到密码管理器或 break-glass 密钥库中。【免费下载链接】openworkThe open-source alternative to Claude Cowork (powered by opencode)项目地址: https://gitcode.com/GitHub_Trending/ope/openwork创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考