首次运行

认领全新的 Warmbly 实例,在不使用浏览器的情况下创建所有者,以及认领链接丢失或数据库已有账户时的处理方法。

全新实例中尚无账户,处于未认领状态。认领是系统唯一允许陌生访问者创建首个账户的阶段。本页说明如何顺利完成这一过程,也介绍常规入口已经关闭时的两种处理方式。

认领实例

curl -fsSL https://warmbly.com/install.sh | sh

安装程序启动整套服务,并在完成后打印认领链接。如果通过克隆仓库安装,则执行以下两步,其中包含构建过程:

git clone https://github.com/warmbly/warmbly && cd warmbly
make up

两种方式都会在完成后打印一次性链接。只要实例仍未认领,随时运行 make claim,或在后端容器内运行 warmblyctl setup-link,都能生成并打印新链接:

  No accounts exist yet. Open this link to claim the instance and
  become its admin. Single use, expires in 24 hours:

    http://localhost:5173/setup?token=...

  Lost it? Print a new one:
    docker compose -p warmbly exec backend warmblyctl setup-link

打开链接并设置密码后,你就成为实例所有者和平台管理员。

如果日志中还没有链接,make claim 会生成一个新链接,而不是不输出任何内容;此前尚未使用的链接也会随之失效。

链接根据 APP_URL 生成。因此,不通过 Compose 部署时,应在首次启动前设置 APP_URL,否则打印出的链接会指向托管服务,而非你的部署。系统只存储令牌的哈希值,读取数据库无法得到可用链接;链接使用后立即失效。

不带令牌打开控制台也可以:实例尚未认领时,所有未登录访问都会跳转到 /setup。该页面会说明如何打印认领链接,而不是显示一个当前无法登录的表单。

以下四种情况会导致你无法再使用原认领链接,处理方式都相同:

  • 日志已轮转,或容器已重新创建。
  • 已过去 24 小时。
  • Redis 已被清空,或在未启用持久化的情况下重启。
  • 使用 Kubernetes 或直接运行二进制程序,从未看到 Compose 日志。

重新打印链接即可。此前的链接如果存在,会停止生效:

docker compose -p warmbly exec backend warmblyctl setup-link   # docker compose
docker exec -it warmbly-backend warmblyctl setup-link          # plain docker
kubectl exec -it deploy/warmbly-backend -- warmblyctl setup-link
warmblyctl setup-link                                          # bare binary

对于 Compose 安装,make claim 执行相同操作并打印结果。

已认领的实例会拒绝这条命令,这是预期行为:系统不会再创建第二位初始所有者。如果看到该拒绝提示,请继续阅读下一节。

实例已有账户时

这种情况经常让人困惑,通常原因如下。

make dev 和 make up 共用同一个数据库

两者固定使用相同的 Compose 项目(-p warmbly)、相同的 warmbly_postgres_data 卷以及相同的 warmbly_dev 数据库。make dev 默认会写入测试账户。一旦这些记录存在,实例便被视为已认领,系统不会再生成设置链接,而 DISABLE_REGISTRATION=invite_only 又会拒绝通过注册表单创建账户。如果先运行了 make dev,再运行 make up,遇到的就是这种情况。

make claim 会说明当前状态,并在最后给出解决问题的命令:

  This instance already has 9 account(s), so no claim link is issued.
  Registration is invite_only (DISABLE_REGISTRATION), so the sign-up form will
  refuse new accounts.

  Make yourself an owner and platform admin:
    docker compose -p warmbly exec backend warmblyctl user create --email [email protected] --admin

  Already have an account?  http://localhost:5173
  Lost the password?        docker compose -p warmbly exec backend warmblyctl user reset-password --email [email protected]
  See everything:           make doctor
  Why:                      https://docs.warmbly.com/development/first-run/

该命令会创建账户、组织和试用记录,并授予全部平台管理员权限位。密码由你输入:在终端中需要输入两次;在非 TTY 环境中,命令会拒绝执行,而不会创建无密码账户。因此,从脚本调用时应传入 --password-stdin。之后即可在 APP_URL 使用该密码登录。参见 user create。

如果已有账户中包含你的账户,只是忘记了密码,请改用 warmblyctl user reset-password。全部恢复命令见恢复访问权限。

另一种具有破坏性的做法是从头开始:

make reset && make up

make reset 会销毁加密卷

此操作会删除存储各组织数据密钥的卷。所有已加密的邮箱凭据和已存储的邮件正文都将永久无法解密,即使之后恢复数据库备份也无济于事。只有在可以接受失去整个实例时才执行此操作。

无人值守初始化

在首次启动前设置所有者信息,系统便不会生成认领链接:

WARMBLY_BOOTSTRAP_EMAIL=[email protected]
WARMBLY_BOOTSTRAP_PASSWORD_HASH=$argon2id$v=19$m=65536,t=3,p=2$...
WARMBLY_BOOTSTRAP_ORG=Acme

可以直接生成哈希,避免将明文密码写入存储位置。在终端中,命令会提示输入;没有终端时则读取管道,因此手动操作和自动配置脚本都可以使用同一命令:

warmblyctl hash-password
printf '%s' 'your password' | warmblyctl hash-password

为哈希值加上引号

Argon2 PHC 字符串包含 $ 字符。Docker Compose 会将其视为变量插值,因此直接在 .env 中写入未加引号的哈希,会悄然丢失部分内容,并导致初始化失败,且没有有用的提示。在 .env 中用单引号包住哈希;如果直接粘贴到 docker-compose.yml 中,则将每个 $ 写成两个。

也可以使用 WARMBLY_BOOTSTRAP_PASSWORD 接收明文密码,密码须符合与注册时相同的规则。这种方式可以使用,但启动时会出现警告,而且可通过 docker inspect 和 /proc 读取进程环境中的密码。建议使用哈希,并在所有者账户创建后移除所用的密码变量。

这些配置仅在 users 表为空时读取,之后每次重启都不会再生效。因此,它们也无法用于恢复被锁定的访问:只要实例已有账户,就会完全忽略这些配置。

首个账户获得的权限

获得的内容说明
所有者账户成为新组织的所有者;这是一种成员身份状态,而不是角色
组织如果 WARMBLY_BOOTSTRAP_ORG 是有效的工作区名称,则使用该名称;否则根据所有者姓名生成
试用记录自托管默认使用 BILLING_PROVIDER=none,全部功能均已解锁,因此试用记录不影响使用。控制台顶部显示 Self-hosted 标记,而非套餐或试用状态,计费及推荐奖励设置页面会隐藏
全部平台管理员权限位同一账户可以登录 :5173 上的控制台和 :5174 上的管理面板

登录不依赖邮件。自托管安装默认关闭邮件登录验证码,因为尚未配置的邮件中继不应阻止你访问自己的实例。

检查当前状态

docker compose -p warmbly exec backend warmblyctl status

命令会输出四部分内容:实例状态、平台管理员、下一步应执行的操作,以及健康检查。在已有账户的实例上,输出大致如下:

Instance
  Accounts          9
  Claimed           yes, so no setup link is issued
  Platform admins   1
  Registration      invite_only (DISABLE_REGISTRATION is unset, so the deployment default applies)
  Mail transport    log (written to the backend log, never delivered; MAIL_TRANSPORT=log)
  App URL           http://localhost:5173 (APP_URL)

Platform admins
  [email protected] (super, mask 4194303)

How to get in
  Sign in at http://localhost:5173
  Lost the password:       warmblyctl user reset-password --email [email protected]
  Lost the authenticator:  warmblyctl user disable-2fa --email [email protected]
  No account of your own:  warmblyctl user create --email [email protected] --admin
  Who is an admin:         warmblyctl user list --admin

Checks
  ...one line per finding, grouped by severity...

具体文字会随状态变化:未认领的实例会明确说明这一状态,并提示打印设置链接。--json 会以机器可读的文档格式输出相同信息,make claim 读取的就是这一输出。

检查部分与管理面板“设置与健康状态”页面中的结果相同。只要其中任何一项达到错误级别,warmblyctl status 就会以非零状态退出,因此可以将 make doctor 作为部署后的检查关卡。每项检查的说明见实例健康状态。

其他人能够访问之前

Compose 文件为每项密钥提供了可用的默认值,使全新克隆的项目无需配置即可启动。但这五个默认值都已公开在仓库中,无法提供保护:任何人都能伪造会话令牌或解开各组织的密钥。

逐一生成真实密钥,并追加到 .env:

cat >> .env <<EOF
AUTH_SECRET=$(openssl rand -base64 32)
INTERNAL_API_TOKEN=$(openssl rand -hex 24)
SECRET_KEY_BASE=$(openssl rand -base64 64 | tr -d '\n')
KMS_LOCAL_MASTER_KEY=$(openssl rand -base64 32)
CREDENTIALS_ENCRYPTION_KEY=$(openssl rand -hex 32)
APP_ENV=prod
EOF

然后运行 make up 重新创建容器。如果只需要一个新的 KMS_LOCAL_MASTER_KEY,可运行 make gen-key 打印该密钥。

最后再设置 APP_ENV=prod,且必须先确认另外五项已经使用真实密钥。启用生产环境后,已公开的默认值会从日志警告升级为拒绝启动;如果先启用生产环境,后端就无法启动。

Compose 会将空值视为未设置

docker-compose.yml 按 ${VAR:-default} 的方式读取 .env,Compose 会将空赋值与缺少变量同等处理。AUTH_SECRET= 不会把密钥设为空,而是会使用已公开的默认值。需要停用某行配置时,请将其注释掉,而不是清空值。

存储任何邮箱之前,先备份最后两项密钥

KMS_LOCAL_MASTER_KEY 和 CREDENTIALS_ENCRYPTION_KEY 用于加密所有已存储的凭据和邮件正文。密钥丢失后无法恢复,缺少它们的数据库备份也无法解密。

完整说明以及哪些值必须在各服务之间保持一致,见密钥。

演示数据

make seed-demo

加载演示工作区,其中包含邮箱、营销活动、联系人和两周的历史记录。日常演示登录使用 [email protected] / password123。

演示数据会写入公开的超级管理员凭据

make seed-demo 使用 SEED_FULL=true 运行,还会插入账户 [email protected],密码为 Test1234!,授予全部平台管理员权限,并创建一枚拥有完整权限的 API 密钥,其密钥值是仓库中的常量。这三项值均已公开。切勿在他人可以访问的实例上执行;如果已经执行,务必在开放实例访问之前删除该账户并撤销密钥。

写入种子数据也会用掉首次启动的特殊权限,因此之后实例不会再生成认领链接。如果是主动加载演示数据,这符合预期;如果不是,就会遇到实例已有账户一节所述的意外情况。

如果需要完整演示实际邮件收发、回复、打开和点击流程,请参见沙盒环境。

另请参阅

本页目录