daemon 部署
把 Vyane daemon 装成开机自启的常驻服务——准备 secrets、装 launchd、健康检查、看日志、重启。
Vyane daemon 是那个在后台一直醒着的进程:接 webhook、管 worker 子进程、跑 scheduler、暴露 /health 和 /api/* 接口。把它装成开机自启(macOS 用 launchd),机器一开机它自己就起来,不用每次手动敲命令。
这一页讲的是「一次装好、以后不用管」的常驻部署,全部依据仓库里 scripts/deploy/ 那套脚本和 docs/daemon-deployment-quickstart.md。命令都能直接照抄。
平台说明
下面所有步骤针对 macOS(launchd)。脚本用相对路径推断 vyane 根目录,可以从任何目录调用——但不要通过 symlink 调用,否则根路径会算错。
先决条件(一次性)
装之前确认三样东西都就位:
- 已经
git clone了 vyane 仓库(下面假设在~/vyane)。 - 装好依赖:
cd ~/vyane
uv sync --extra daemon- 装了 Tailscale(只有需要把 daemon 暴露到公网时才用):
brew install tailscale
# 装完打开 Tailscale.app 登录脚本不会帮你自动装 uv / tailscale / homebrew,也不会自动登录 Tailscale——这些是手动前置动作。
部署五步
整套动作大概 5 分钟。核心就是:填 secrets → 检查 → 装 launchd → 健康检查 →(可选)暴露公网。
第一步:准备 secrets.env
secret 不放在仓库里,统一放在用户级配置目录 ~/.config/vyane/secrets.env,权限收到 600(只有你自己能读)。
mkdir -p ~/.config/vyane
test -f ~/.config/vyane/secrets.env || cp .env.example ~/.config/vyane/secrets.env
chmod 600 ~/.config/vyane/secrets.env然后编辑这个文件。唯一必填的是 VYANE_DAEMON_API_TOKEN——脚本不会自动生成它,得你自己造一个再填进去:
python -c 'import secrets; print(secrets.token_urlsafe(32))'
# 把打印出来的串复制到 secrets.env 里的 VYANE_DAEMON_API_TOKEN=这个 token 是公网 API 唯一的门锁
所有 /api/* 端点(比如 workers/spawn-child、research/start、ideas/promote)在 token 缺失时一律返回 401。一旦你在第五步把 daemon 暴露到公网,任何外网请求都会先撞这道墙——VYANE_DAEMON_API_TOKEN 是这些端点唯一的认证防线。所以务必先填好它,再开公网。
顺手确认几个推荐项(不填也能跑,但建议明确写死):
| 变量 | 作用 | 建议值 |
|---|---|---|
VYANE_DAEMON_API_TOKEN | 公网 /api/* 认证 token(必填) | 上面生成的随机串 |
VYANE_SCHEDULER_MODE | scheduler 开关 | on(允许值:off / shadow / on) |
VYANE_DAEMON_PORT | daemon 监听端口 | 不填默认 41522 |
VYANE_WORKDIR | daemon 工作目录 | 按需 |
此外 .env.example 里还有一些历史兼容的可选变量(如外部通知渠道、桥接入口),新部署只跑 daemon API、scheduler 和看板账本时不需要配,按需再填。
第二步:检查 env 齐全
跑一遍检查脚本,确认必填项到位、权限正确:
./scripts/deploy/prepare-env.sh它是只读的,不会问你要 secret 值,只汇报状态:必填项应该全部显示 ✓。加 --strict 时任一必填项缺失会退出码 1(给 CI 用)。它还会顺手提醒你 env 文件权限是不是 600、VYANE_SCHEDULER_MODE 的值是否合法。
第三步:装 launchd agent(开机自启的核心)
这一步把 daemon 注册成 launchd 后台服务,装完就是开机自启:
./scripts/deploy/install-launchd.sh它做的事:按当前 checkout 渲染 plist 模板(把 uv 路径、vyane 根路径、HOME 填进去),拷到 ~/Library/LaunchAgents/com.vyane.daemon.plist,再 launchctl load。脚本是幂等的——如果之前装过,它会先 unload 再 load,重复跑不会出问题。
装完等 1-2 秒,立刻做健康检查确认起来了:
./scripts/deploy/daemon-health-check.sh --wait--wait 会轮询最多 30 秒等 daemon 就绪。看到 ✓ daemon 健康 (HTTP 200) 就成了。
想先手动验一次能不能起
装 launchd 之前,可以先前台手动跑一次看有没有报错,用 Ctrl+C 停:
uv run python -m vyane.daemon.main --scheduler-mode on
第四步(可选):暴露到公网
只有需要外网访问 daemon(接 webhook、远程调 API)时才做这步。用 Tailscale Funnel 把本地端口暴露出去:
# 开公网之前,务必确认 secrets.env 里 VYANE_DAEMON_API_TOKEN 已填
./scripts/deploy/start-tailscale-funnel.sh脚本会前台跑并打印一个公网地址,长这样:https://<你的-hostname>.ts.net/,daemon 的 health URL 就是它加上 /health。这一步前台运行,另开一个终端做后续验证。
funnel 出口在 daemon 眼里都是本机
Funnel 转发过来的请求,daemon 看到的来源都是 127.0.0.1,所以本机白名单那类保护完全失效——VYANE_DAEMON_API_TOKEN 是 /api/* 唯一的认证。开 funnel 前一定先确认 token 已填。
funnel 常用子命令:
./scripts/deploy/start-tailscale-funnel.sh --status # 只看当前 funnel 状态
./scripts/deploy/start-tailscale-funnel.sh --stop # 关掉所有 funnel第五步:端到端验证
看 daemon 日志,确认它真的在干活:
tail -f ~/.config/vyane/logs/daemon-stdout.log正常应该看到类似这几行:
scheduler gate initialized mode=on
task_board_bridge started mode=on
Webhook server listening on port 41522旧的外部任务系统 webhook 已归档
早期版本接过外部任务系统的 webhook,现在这条入口固定返回 410 archived,任务事实源已经全部走 Beacon 看板。看到旧 webhook 调用返回 410 是正常的。
日常运维
看日志
daemon 的日志固定在 ~/.config/vyane/logs/ 下,分 stdout 和 stderr 两个文件:
# 实时看正常输出
tail -f ~/.config/vyane/logs/daemon-stdout.log
# daemon 起不来先看这个
tail ~/.config/vyane/logs/daemon-stderr.log查状态 / 健康检查
# launchd 里在不在(顺便看退出码是不是非 0)
launchctl list | grep vyane
# 单次探 /health(不加 --wait 就是探一下立刻返回)
./scripts/deploy/daemon-health-check.shhealth-check 会自动从 secrets.env 读端口(默认 41522),curl 本机 http://127.0.0.1:<port>/health。
重启 daemon
改了配置或代码想让 daemon 重新加载,标准做法是「先卸再装」——install-launchd.sh 本身也是 unload-then-load,所以重跑它就相当于重启:
./scripts/deploy/uninstall-launchd.sh
./scripts/deploy/install-launchd.sh改了 secrets.env 里的变量后,一定要重启才生效(launchd 只在启动时读一次环境)。
卸载
./scripts/deploy/uninstall-launchd.sh # 卸载(unload + 删 plist)
./scripts/deploy/uninstall-launchd.sh --purge # 卸载并顺手清掉日志文件卸载脚本是幂等的:即使没装过也不会报错。
排障速查
| 症状 | 先查这里 |
|---|---|
install-launchd.sh 跑完 daemon 没起 | tail ~/.config/vyane/logs/daemon-stderr.log |
/health 连不上 | launchctl list | grep vyane,看退出码是不是非 0 |
| 找不到 uv | 安装脚本用 command -v uv;路径特殊时设 VYANE_UV_BIN=/path/to/uv |
| daemon 起不来(stderr 报错) | 多半是 env 缺 VYANE_DAEMON_API_TOKEN、VYANE_SCHEDULER_MODE 值非法、或没跑 uv sync --extra daemon |
| 外网 API 返回 401 | 请求要带 Authorization: Bearer <VYANE_DAEMON_API_TOKEN> |
| Tailscale Funnel 起不来 | 账号要开 Funnel feature(默认关),ACL 里给 daemon 授权 |
| 旧 webhook 调用返回 410 | 正常,旧的外部 webhook 已归档,不用管 |