Files
plane-agentd/docs/deploy-lxc.md
T
jj.wang 20e4e4ed73 Docs: LXC deployment guide, remote POSIX transport in the executor contract
deploy-lxc.md: Debian 12 packages, vault client + identity, Warpgate host key
(pinned by the identity), helper scripts and protocol file, all-remote config,
cron under exec --secret-env, logs/heartbeat, adding a terminal.
design.md 9: P1-6 done for Linux/macOS; Windows still on the helper scripts (TODO unify).
2026-10-21 08:25:14 +00:00

98 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 在精简 LXC 上部署 agentd(design §9 阶段 3)
目标:调度器跑在一台**不装任何 agent CLI** 的 Debian 12 LXC(`agentd-01`)上;所有终端(win10、oregon、mac…)都经 Warpgate SSH 远程启动(`transport: warpgate-ssh`)。LXC 只做调度、回帖、通知。
## 1. 系统包
```bash
apt-get update
apt-get install -y python3 python3-yaml openssh-client git cron ca-certificates curl
# win10 的 helper 脚本另需(Debian 12 默认已有):bash coreutils(base64/sha256sum) gzip libc-bin(iconv)
adduser --disabled-password --gecos '' agentd # 普通用户运行 agentd,不用 root
```
Python ≥ 3.10(Debian 12 是 3.11)。`jsonschema` 可选,没有就用内置子集校验器。
## 2. 网络
| 去向 | 用途 |
|---|---|
| `nas.tail9531b.ts.net:8443`(tailnet) | Agent Vault 身份配置 `identity/agent.json`(含 vault token 与 Warpgate 主机公钥)→ LXC 必须加入 tailnet(`tailscale up`,LXC 需 `/dev/net/tun`) |
| Vault(身份配置里的地址) | 取 Plane token、Warpgate 密码 |
| Warpgate SSH `115.28.210.101:2222` | 所有终端的中继 |
| `https://plane.kappiee.com` | Plane API |
## 3. Agent Vault 客户端与身份
```bash
sudo -u agentd mkdir -p ~agentd/.local/share/server-access-client
# 从 oregon 复制(权限 700,只给 agentd 用户):
scp oregon:~/.local/share/server-access-client/{agent-access.py,agent-access-askpass.py} \
agentd-01:~agentd/.local/share/server-access-client/
chmod 700 ~agentd/.local/share/server-access-client/*
cd ~agentd/.local/share/server-access-client && sudo -u agentd python3 -I agent-access.py \
--config https://nas.tail9531b.ts.net:8443/identity/agent.json list # authenticated: true,能看到 win10 / oregon 等 target
```
- 身份是 tailnet 上的 URL(`--config https://…/identity/agent.json`),不落盘;也可以换成本地私有 JSON 文件(`chmod 600`),把 `vault.config` 指过去。
- **Warpgate known_hosts 不用配**:客户端每次用身份配置里的 `warpgate.host_key` 生成临时 known_hosts(`StrictHostKeyChecking=yes`),不读 `~/.ssh/known_hosts`。只要求有 `ssh` 可执行文件。
- `askpass` 必须与 `agent-access.py` 同目录且可执行。
- Warpgate 侧:该身份(`agent` 用户)要有每个终端 target 的权限(现有:`win10`、`oregon`)。
## 4. 代码与配置
```bash
sudo -u agentd git clone https://git.kappiee.com/kappiee/plane-agentd.git ~agentd/plane-agentd
# win10 仍用 helper 脚本(见 design §9 TODO),复制这两个:
sudo -u agentd mkdir -p ~agentd/helpers
scp oregon:/home/ubuntu/Documents/wjj/project/gwent-design/tools/{win10-ps.sh,win10-put.sh} agentd-01:~agentd/helpers/
# 看板协作协议(拼进每轮 prompt,由 agentd 在本机读取):
scp oregon:/home/ubuntu/Documents/wjj/project/gwent/design/board-protocol.md agentd-01:~agentd/board-protocol.md
cp ~agentd/plane-agentd/config/agentd.yaml ~agentd/plane-agentd/config/agentd.local.yaml # git-ignored,优先于 agentd.yaml
```
`config/agentd.local.yaml` 里改:
- `vault.client: ~/.local/share/server-access-client/agent-access.py`(`~` 在本机展开)
- `agentd.state_dir: ~/state`(JSON 状态、日志、心跳);`agentd.helpers_dir: ~/helpers`
- `projects.GWENT.protocol_file: ~/board-protocol.md`(**它不在终端上读,是 LXC 本机路径**;协议更新时重新复制)
- 所有终端都是 `transport: warpgate-ssh`:
- win10:`target: win10, os: windows, launch: schtasks`(不变)
- oregon:`target: oregon, os: linux, launch: nohup, repo: /home/ubuntu/Documents/wjj/project/gwent, run_root: /home/ubuntu/.gwent-board/agentd-runs, bins: {claude: /home/ubuntu/.local/bin/claude}`
- 远程 POSIX 终端的 `repo`、`run_root` 必须是绝对路径(在远程展开,`~` 不行);`bins` 写远程的绝对路径(SSH 非登录 shell 只有系统 PATH)。
```bash
cd ~agentd/plane-agentd && python3 -m unittest && python3 cli/agentd check-config
```
## 5. cron
`cron/agentd-tick.sh` 里写死了 oregon 的路径;在 LXC 上用同样的形状(单行 crontab 或复制脚本改路径):
```
*/2 * * * * flock -n $HOME/state/cron.lock timeout 900 python3 -I $HOME/.local/share/server-access-client/agent-access.py --config https://nas.tail9531b.ts.net:8443/identity/agent.json exec --secret-env PLANE_OREGON_API_TOKEN=PLANE_OREGON_API_TOKEN --secret-env PLANE_WINDOW10_API_TOKEN=PLANE_WINDOW10_API_TOKEN --timeout 850 -- python3 $HOME/plane-agentd/cli/agentd tick --once >> $HOME/state/agentd-cron.log 2>&1
```
- token 只经 `exec --secret-env` 进 agentd 进程内存;agentd 起的中继子进程环境里去掉了所有 `token_key`(`Config.scrubbed_env()`),远程执行器在终端上由 sshd 起,本来就拿不到 LXC 的环境。
- `--secret-env` 的完整列表:`cli/agentd check-config` 最后一行。
- **切换时先停 oregon 上的 cron**(`crontab -e` 注释掉 `agentd-tick.sh`),再在 LXC 上启用;两个调度器同时跑会重复派单。状态文件 `~/.gwent-board/agentd/agentd-state.json` 从 oregon 复制到 LXC 的 `state_dir`,在途运行(handle 里是终端上的绝对路径)照常被新调度器 poll/collect。
## 6. 日志与心跳
| 路径(LXC) | 内容 |
|---|---|
| `~/state/agentd.log` | 每 tick 的动作、错误 |
| `~/state/heartbeat.json` | `at` 超过 10 分钟不更新 = 调度器没在跑 |
| `~/state/agentd-state.json` | 全部工作项状态 |
| `~/state/agentd-cron.log` | cron 输出(空闲时为空;`skip: another tick holds …` 无害) |
| 终端上 `<run_root>/<run_id>/` | 每轮的 `prompt.md run.sh/run.ps1 pid.txt launch.pid exit.txt stderr.txt` + 执行器输出 |
## 7. 加一个终端(例:mac)
1. Warpgate 加 SSH target(如 `mac`),给 `agent` 身份授权;`agent-access.py … run --target mac --timeout 30 -- bash -c 'echo ok; uname'` 能通。
2. 在终端上装好 agent CLI 并登录(Claude Code / Codex),clone 工作仓库;记下二进制绝对路径。
3. 配置:
```yaml
mac:
transport: warpgate-ssh
target: mac
os: darwin # linux | darwin;darwin 用 perl POSIX::setsid 脱离会话(无 setsid 命令)
launch: nohup
repo: /Users/me/src/gwent
run_root: /Users/me/.agentd-runs
bins: {claude: /Users/me/.local/bin/claude}
plane_user: mac
token_key: PLANE_MAC_API_TOKEN
concurrency: 1
executors: [claude-code]
```
远程 shell 是目标账户的登录 shell(bash/zsh 均可,agentd 发的是 `bash -c '<script>'`);终端需有 `bash base64 nohup pgrep pkill`(Linux 另需 `setsid`,macOS 需 `perl`)。
4. Plane:建用户 `mac`,token 存 Vault 键 `PLANE_MAC_API_TOKEN`;项目 `routing.by_assignee` 加 `mac: mac`,`default_executor` 加 `mac: claude-code`;cron 加 `--secret-env PLANE_MAC_API_TOKEN=PLANE_MAC_API_TOKEN`。
5. `cli/agentd check-config`,然后 `cli/agentd smoke GWENT mac`。