通知
当有事情需要处理时,Zenavo 会发邮件通知你的团队,这样你就不用一直开着控制台;同样的告警也可以发送到 Slack、Discord、Telegram 或你自己的 Webhook。
事件
| 事件 | 何时发送 |
|---|---|
| 部署失败 | 部署或回滚没有完成。邮件会说明是在构建服务时失败,还是在发布时失败。 |
| 服务器设置失败 | 服务器的初始化或重装没有完成。邮件会给出原因,以及为重试保留 SSH 凭据的截止时间。 |
| 服务已暂停 | 服务重启次数超过了它的崩溃限制,已被停止。 |
| 服务器离线 | 服务器连续 3 次状态检查没有响应(约 3 分钟)。恢复响应时会再发一封邮件。 |
| 磁盘或内存即将用尽 | 服务器磁盘使用率超过 90%,或者内存连续 3 次检查都超过 90%。使用率降到 85% 以下后才会再次告警。 |
| 新的 SSH 登录来源 | 有 IP 地址第一次通过 SSH 登录了团队的某台服务器。如果你刚从新的网络连接过,这是正常的;否则是一个警告信号。 |
| 用量上限 | 团队的镜像传输达到了本账单周期允许额度的 80% 或 100%。达到 100% 时,服务器将停止拉取新镜像。 |
对于同一个项目、服务或服务器,每种告警每小时最多发送一次。偶尔一两次检查没有响应不会发送任何通知。
关于你自己账号的安全邮件(新设备登录、批准的 CLI 登录、新的 API 密钥)见安全。它们只发给你本人,对所有角色默认开启,显示在通知页面的 安全 下。
谁会收到
邮件发给拥有该项目或服务器的团队的成员:
- 所有者和管理员 默认接收所有事件,除非自己关闭。
- 成员 默认不接收,需要自己开启。
- 观察者 永远不会收到通知。
在 账号设置 → 通知 中选择你要接收的事件。这个选择按账号生效,适用于你所在的所有团队。
邮件内容
项目、服务或服务器的名称、时间(UTC),以及控制台中对应页面的链接。邮件中从不包含变量值、机密、命令或日志文本。要查看日志,请打开控制台。
通知渠道
团队管理员还可以把团队的通知发送到聊天工具和 Webhook:账号设置 → 通知 → 团队通知渠道,作用于侧边栏中选中的团队。每个渠道可以选择自己的事件;除了上面的事件,渠道还可以接收 部署成功(从不发邮件)。渠道收到的告警与邮件相同,同样每小时最多一次,并且不受任何人的邮件设置影响。
| 渠道 | 需要什么 |
|---|---|
| Slack | 频道的 Incoming Webhook 地址(https://hooks.slack.com/services/…)。 |
| Discord | 频道 Webhook:频道设置 → 整合 → Webhook(https://discord.com/api/webhooks/…)。 |
| Telegram | 从 @BotFather 获取的机器人令牌,以及聊天 ID(例如 -1001234567890 这样的数字,或公开频道的 @username)。请先把机器人加入聊天。 |
| Webhook | 任意 https:// 地址。Zenavo 会向它 POST 签名后的 JSON(见下文)。 |
测试 会立即发送一条消息,并显示是否送达。每个渠道都会显示最近一次发送的结果或失败原因;发送失败会在大约 13 分钟内重试三次。每个团队最多 20 个渠道。
Webhook 地址和机器人令牌都属于机密:它们加密存储,控制台只显示主机或聊天。Zenavo 只向所有地址都是公网地址的主机发送,并且不跟随重定向。
Webhook 请求内容
{
"type": "deploy_failed",
"team_id": "team_…",
"subject": "Deployment failed: shop",
"text": "The deployment of project \"shop\" failed at 2026-10-19 08:12 UTC.\nIt failed while building service \"web\".\n",
"url": "https://zenavo.app/projects/proj_…/deployments/job_…",
"time": "2026-10-19T08:12:03Z"
}type 是 deploy_failed、deploy_succeeded、service_suspended、server_offline(服务器恢复时也会发送)、server_resources、usage_limit 或 test 之一。任何 2xx 响应都视为已送达。
每个请求都带有 X-Zenavo-Event、X-Zenavo-Timestamp(Unix 秒)和 X-Zenavo-Signature: v1=<hex>,后者是用渠道的签名密钥对 <timestamp>.<原始请求体> 计算的 HMAC-SHA256。密钥(whsec_…)在添加 Webhook 时只显示一次;编辑 不会再次显示它,但可以通过 API 更换。请基于原始字节验证签名,并拒绝过旧的时间戳:
import crypto from 'node:crypto'
function verify(rawBody, headers, secret) {
const ts = headers['x-zenavo-timestamp']
const expected = 'v1=' + crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex')
const given = headers['x-zenavo-signature'] ?? ''
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300
const a = Buffer.from(given), b = Buffer.from(expected)
return fresh && a.length === b.length && crypto.timingSafeEqual(a, b)
}