CapOwn — 部署指南(手动)¶
首次安装? 请先阅读 快速开始(Master → Worker → token → Agent)。本页侧重进阶部署、Nginx 与故障排查。
提示: 部署脚本(
python3 deploy.py)同时支持交互式部署和配置源驱动部署:首次安装 Master 时会自动创建 starter 用户
chiral和 bundle enrollment token。部署完成后会显示生成的 Worker 和 Client 安装命令。# 从配置源一键部署(本地 TOML、TOML URL 或 bundle enrollment URL) python3 deploy.py install worker https://master.example.com/api/enroll/cown_tmp_xxxxx python3 deploy.py install worker capown-worker.toml python3 deploy.py install worker capown-worker.toml --mirror-cn # 中国镜像 python3 deploy.py install client https://master.example.com/api/enroll/cown_tmp_xxxxx python3 deploy.py install client capown-client.toml # 配合 uv 镜像用于受限网络 python3 deploy.py install worker --uv-mirror https://pypi.example.com/simple CAPOWN_UV_MIRROR_URL=https://pypi.example.com/simple python3 deploy.py install worker # 使用自定义工作空间路径(覆盖配置源 defaults) python3 deploy.py install worker capown-worker.toml --workspace /srv/my-project对于多用户场景,在 Master 主机上生成 bundle enrollment URL:
# 在 Master 主机上 capown-master tokens create alice # 或指定显式 URL(覆盖已配置的 public_url) capown-master tokens create alice --type bundle --master-url https://master.example.com # 在用户 Worker 机器上:一键安装 + 身份配置 python3 deploy.py install worker https://master.example.com/api/enroll/cown_tmp_xxxxx # 或已安装——仅重新配置身份 capown-worker config https://master.example.com/api/enroll/cown_tmp_xxxxx # 在用户 Client/AI Agent 机器上:一键安装 + 身份配置 python3 deploy.py install client https://master.example.com/api/enroll/cown_tmp_xxxxx # 或已安装——仅重新配置身份 capown config https://master.example.com/api/enroll/cown_tmp_xxxxx同一个临时 URL 可用于两种角色;CLI 会向 Master 报告当前角色。
tokens create --type bundle默认还会写入本地 TOML 文件,支持deploy.py install worker <source>和deploy.py install client <source>工作流。每个用户仅允许一个活跃的 bundle URL—— 生成新的 bundle 会自动撤销前一个。重新运行不带 source 参数的 install 命令会更新软件并保留现有本地配置。 运行
deploy.py install worker <source>或deploy.py install client <source>会显式应用该配置源并替换本地身份信息。仅在需要移除配置和数据时使用deploy.py uninstall <component> --purge。部署完成后,
capown和capown-masterCLI 工具会被安装到~/.capown/bin/。 将其加入PATH以便使用:启动配置选项¶
首次安装 Master(尚未存在
~/.capown/master/config.toml或~/.capown/master/data/registry.db)时,会自动创建 starter 用户和 bundle。# 默认情况下自动创建用户 'chiral' python3 deploy.py install master --public-url http://192.168.1.10:9210 # 自定义用户名 python3 deploy.py install master --public-url http://192.168.1.10:9210 --bootstrap-user admin # 跳过自动引导(无需 public URL) python3 deploy.py install master --no-bootstrap也可通过
MASTER_PUBLIC_URL环境变量设置 public URL:选项说明: -
--bootstrap-user <name>:starter 用户的用户名(默认:chiral) ---no-bootstrap:跳过自动创建用户和 bundle ---public-url <url>:Master 的公共 URL(也可使用MASTER_PUBLIC_URL环境变量)启动配置仅在全新安装时执行。重新安装或升级现有 Master 不会创建、 替换或吊销任何用户或 token。starter bundle 的默认 TTL 为 24 小时。 如果启动配置失败,Master 会保持运行状态并显示恢复命令。
本文档涵盖面向高级使用场景的手动配置方法。
前提条件¶
- Master 主机上已安装 Docker 和 Docker Compose
- 所有 Worker 主机到 Master 的出站 HTTPS 访问
- 运行
deploy.py需要 Python 3.10+。无需手动安装 Python 3.12——deploy.py通过uv(安装到~/.capown/tools/uv/)自动管理 Python 运行时。Python 3.12 在首次部署时 由 uv 自动下载和管理。部署前不需要自行安装 Python 包依赖;部署脚本会自动创建 虚拟环境并安装运行时依赖。
使用网络镜像(适用于中国或离线环境):
# 通过环境变量(适用于所有 install 命令)
export CAPOWN_UV_MIRROR_URL=https://pypi.tuna.tsinghua.edu.cn/simple
# 或通过 CLI 标志(逐命令生效)
python deploy.py install worker --uv-mirror https://pypi.tuna.tsinghua.edu.cn/simple
Master 部署(容器)¶
1. 部署 Master¶
使用部署脚本部署 Master。首次安装时会自动创建 starter 用户 chiral
和 bundle enrollment token。
# 交互式部署(提示设置)
python3 deploy.py install master --public-url http://192.168.1.10:9210
# 非交互式部署(使用默认值)
python3 deploy.py install master --public-url http://192.168.1.10:9210 -y
首次安装需要 --public-url。也可以通过 MASTER_PUBLIC_URL 环境变量提供:
使用 --no-bootstrap 跳过自动创建用户和 bundle:
部署完成后会显示生成的 Worker 和 Client 安装命令。starter bundle 的默认有效期为 24 小时。
如需为其他用户创建 enrollment 凭据:
2. 准备数据目录¶
3. 构建并运行¶
cd master/
# 使用默认配置构建(国际镜像)
DOCKER_BUILDKIT=0 docker compose build
# 或使用中国镜像
DOCKER_BUILDKIT=0 \
APT_MIRROR=mirrors.tuna.tsinghua.edu.cn \
PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
docker compose build
# 启动容器
CAPOWN_MASTER_CONFIG="$HOME/.capown/master/config.toml" \
CAPOWN_MASTER_DATA="$HOME/.capown/master/data" \
docker compose up -d
# 检查状态
docker compose logs master
4. 验证¶
端口模式(Docker)。 容器内的 Master 始终监听
0.0.0.0:9210。 Docker 默认将其发布到主机的0.0.0.0:9210,因此同一网络的 Worker 可通过http://<host-ip>:9210访问。请确保主机防火墙允许入站 TCP 9210。 如需使用不同的主机侧端口(例如 9210 已被占用),可在运行deploy.py或docker compose up前设置CAPOWN_HOST_PORT:这会在主机上发布
0.0.0.0:9211,而容器内部仍监听标准的 9210 端口。 如果使用了非默认主机端口,则在运行capown-master health或capown-master start时也需要设置相同的环境变量。如果将 Master 端口保持为仅本地访问(用于 Nginx/反向代理配置),可在部署前设置
CAPOWN_BIND_HOST=127.0.0.1。
5. 管理 CLI¶
部署 Master 后,使用 capown-master 管理服务:
所有可用命令参见用户指南。
Worker 部署¶
Worker 控制进程始终作为原生 OS 服务在宿主机上运行。使用容器执行后端时,
会额外创建一个托管的 Docker 容器用于任务隔离。deploy.py 脚本会自动处理
这两个步骤。
宿主机执行后端(Linux)¶
任务直接在宿主机系统上运行。适用于不需要 Docker 的可信机器。
1. 编写配置文件¶
创建 ~/.capown/worker/config.toml:
[worker]
execution_mode = "host"
worker_name = "<unique-worker-name>"
master_url = "https://your-server.com/v1"
workspace = "/"
max_runtime = 86400
idle_timeout = 600
reconnect_interval = 5
enrollment_token = "cown_enroll_xxx"
2. 安装应用副本¶
mkdir -p ~/.capown/worker/app
cp -r ../shared ~/.capown/worker/app/
cp -r ../worker ~/.capown/worker/app/
cp ../worker/requirements.txt ~/.capown/worker/app/
3. 虚拟环境(由 uv 管理)¶
部署脚本会自动使用 uv 创建虚拟环境:
运行部署脚本时,uv 会先安装到 ~/.capown/tools/uv/(如果 PATH 中尚不存在),
然后 uv 会下载 Python 3.12,并在 ~/.capown/worker/venv/ 中创建包含所有依赖的
虚拟环境。
为 uv 操作使用镜像:
4. 安装 systemd 服务¶
创建 ~/.config/systemd/user/capown-worker.service:
[Unit]
Description=CapOwn Worker
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=%h/.capown/worker/venv/bin/python -m worker.daemon
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.target
然后启用并启动:
systemctl --user daemon-reload
systemctl --user enable --now capown-worker
# 启用 linger 以使服务在开机时自动启动
sudo loginctl enable-linger $USER
宿主机执行后端(Windows)¶
1. 编写配置文件¶
与 Linux 宿主机模式相同,但放在 %USERPROFILE%\.capown\worker\config.toml。
2. 安装应用副本¶
mkdir "$env:USERPROFILE\.capown\worker\app" -Force
Copy-Item ..\shared "$env:USERPROFILE\.capown\worker\app\" -Recurse
Copy-Item ..\worker "$env:USERPROFILE\.capown\worker\app\" -Recurse
Copy-Item ..\worker\requirements.txt "$env:USERPROFILE\.capown\worker\app\"
3. 虚拟环境(由 uv 管理)¶
部署脚本会自动创建虚拟环境:
uv 和 Python 3.12 自动管理。
4. 创建计划任务¶
# 删除已有任务(如有)
schtasks /Delete /TN CapOwnWorker /F
# 创建新任务
schtasks /Create `
/TN CapOwnWorker `
/SC ONLOGON `
/TR "$env:USERPROFILE\.capown\worker\venv\Scripts\python -m worker.daemon" `
/RL LIMITED `
/F
# 启动任务
schtasks /Run /TN CapOwnWorker
同机 Master + Worker¶
当 Master 和 Worker 运行在同一台主机上时,将 Worker 配置为通过 localhost 连接:
# worker/config.toml
[worker]
execution_mode = "container" # 或 "host"
worker_name = "local-worker"
master_url = "http://127.0.0.1:9210"
# ...
配置 Nginx¶
公网 Master 若要同时支持 CLI/skill 与 MCP,需要两条独立入口:
| 用途 | 对外 URL 示例 | 后端路径 | 客户端如何配置 |
|---|---|---|---|
| REST / CLI / skill / Worker SSE / enrollment | https://api.example.net/v1/... |
/api/...、/health 等 |
CLI:master_url = "https://api.example.net/v1" |
| MCP Streamable HTTP | https://api.example.net/mcp |
/mcp |
MCP Host:url = "https://api.example.net/mcp" |
说明:
- Master 进程上 REST 挂在
/api/*,MCP 挂在根路径/mcp(不在/api下)。 - CLI 把路径拼在
master_url后面(例如master_url + "/api/workers"),因此带/v1前缀的master_url很常见。 - 只配置
location /v1/不会自动暴露公网https://.../mcp;MCP 需要单独location(或等价映射)。 - Origin 校验只比较 scheme/host/port,不含 path。
public_url应写成纯 origin,例如https://api.example.net,不要写成https://api.example.net/v1。
将以下内容合并到你的 HTTPS 服务端配置块中:
# CLI / skill / Worker / enrollment:对外前缀 /v1 → 后端根路径
location /v1/ {
proxy_pass http://127.0.0.1:9210/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Worker SSE 需要禁用缓冲
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 可选:健康检查
location = /v1/health {
proxy_pass http://127.0.0.1:9210/health;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
# MCP Streamable HTTP:单独 location,缓冲/超时与 REST 不同
location /mcp {
proxy_pass http://127.0.0.1:9210/mcp;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_cache off;
proxy_set_header Connection '';
chunked_transfer_encoding on;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
然后重新加载:sudo nginx -t && sudo systemctl reload nginx
Master 侧 Origin 相关配置示例:
- 浏览器类 MCP 客户端会带
Origin,须与public_url的 scheme/host/port 一致。 - 非浏览器 MCP 客户端通常省略
Origin,仅用 client bearer token 认证。 - 未配置
public_url时,所有带Origin的 MCP 请求返回 403。
可选:若希望 MCP 也挂在 /v1 下,可增加更具体的 location /v1/mcp,将
proxy_pass 指到后端 /mcp,MCP Host 则填写 https://api.example.net/v1/mcp。
仍建议与 REST 分开写 location,以便单独设置 Streamable HTTP 的缓冲与超时。
工具、认证与客户端示例见 MCP 指南。
安全¶
- 双 Token 机制:Worker Token(Worker 身份)和 Client Token(派遣权限)相互独立
- 全出站网络:Worker 不暴露任何入站端口
- 路径穿越防护:所有文件操作通过 realpath 验证强制遵守 workspace 边界
- 容器隔离:Master 和 Worker 均在 Docker 容器中以非 root 用户运行
- 命令超时:长时间运行的命令会被自动终止
- 无硬编码密钥:Token 从本地配置文件或环境变量覆盖加载
- Master 端口暴露:默认情况下 Docker 将 Master 发布到
0.0.0.0:9210以便局域网快速上手。生产环境中请使用防火墙,或设置CAPOWN_BIND_HOST=127.0.0.1并通过 Nginx/反向代理暴露。 - MCP Origin 校验:带
Origin的 MCP 请求必须与配置的public_url完全匹配;客户端 Token 仍用于每个 MCP 请求的身份验证。
构建系统¶
Docker 构建要求¶
在 Docker 默认桥接网络没有 DNS 解析的机器上(常见于云虚拟机),两个标志必须使用:
| 标志 | 原因 |
|---|---|
DOCKER_BUILDKIT=0 |
BuildKit 的 --network=host 不可靠;旧版构建器可将主机网络透传到中间容器 |
--network=host |
让构建容器使用主机的网络栈,以便 apt-get 和 pip 访问外部仓库 |
ARG 作用域(Dockerfile)¶
在 FROM 之前声明的 ARG 仅在 FROM 指令中可见。要在 RUN 步骤中使用,
需要在 FROM 之后重新声明(不带默认值):
ARG APT_MIRROR=deb.debian.org
FROM ${PYTHON_IMAGE}
ARG APT_MIRROR # 重新声明以引入作用域
RUN sed -i "s|http://deb.debian.org|http://${APT_MIRROR}|g" ...
sudo 和环境变量¶
sudo 默认会剥离大部分环境变量。使用 sudo 运行 docker compose build 时,
APT_MIRROR 等环境变量无法传递到 docker-compose 进程。两种解决办法:
- 显式传递:
sudo -E env APT_MIRROR=... docker compose build - 或直接使用
docker build并通过--build-arg传递
镜像配置¶
| 构建参数 | 默认值(国际) | 中国示例 |
|---|---|---|
PYTHON_IMAGE |
python:3.12-slim |
(保持默认,Docker Hub 可用) |
APT_MIRROR |
deb.debian.org |
mirrors.tuna.tsinghua.edu.cn |
PIP_INDEX_URL |
https://pypi.org/simple |
https://pypi.tuna.tsinghua.edu.cn/simple |
切换为中国镜像,在构建前设置环境变量:
export DOCKER_BUILDKIT=0
export APT_MIRROR=mirrors.tuna.tsinghua.edu.cn
export PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
docker compose build
代码变更后重新构建¶
cd <project-root>
DOCKER_BUILDKIT=0 docker build --no-cache --network=host \
--build-arg APT_MIRROR=mirrors.tuna.tsinghua.edu.cn \
--build-arg PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
-t capown-master -f master/Dockerfile .
cd master/ && docker compose up -d
# Worker 同理
故障排查¶
构建失败:"Undetermined Error"(apt-get)¶
构建容器无法访问 Debian 仓库。三种解决方法:
- 使用
DOCKER_BUILDKIT=0 docker build --network=host(旧版构建器 + 主机网络) - 通过
--build-arg APT_MIRROR=...使用更接近服务器的镜像 - 检查
APT_MIRROR构建参数是否在 Dockerfile 中的FROM之后重新声明(ARG 作用域规则)
构建失败:日志中显示"deb.debian.org"即使已设置镜像¶
--build-arg 的值未传递到 RUN 指令。最常见的原因是 ARG 在 FROM 之前声明,
但未在构建阶段内部重新声明。参见上文构建系统部分中的"ARG 作用域"。
Worker 无法连接到 Master¶
- 验证 Master 可达:
curl <MASTER_URL>/health - 检查 worker token 是否与 Master 配置一致
- 确保出站 HTTPS 未被防火墙阻止
任务已派遣但无结果 / Worker 未显示"executing task"日志¶
- 检查目标 worker 是否在线:
GET /api/workers - 验证 worker SSE 连接是否活跃(Master 日志显示 "broker: node X connected")
- 检查 worker 日志:
- 容器模式:
docker compose logs worker - Linux 宿主机模式:
journalctl --user -u capown-worker -f - Windows 宿主机模式:
schtasks /Query /TN CapOwnWorker - SSE 换行符不匹配:
sse-starlette使用\r\n\r\n(CRLF,符合 SSE 规范)分隔事件。如果 worker 按\n\n(仅 LF)分割流,事件将永远无法被解析。守护进程必须使用\r\n\r\n作为事件分隔符,或先规范化换行符。 - 同机 Worker:建议使用
master_url = "http://127.0.0.1:9210"以避免通过公网 IP / NAT 路径产生 SSE 流问题。 - 阻塞型 HTTP 客户端:
urllib.request.urlopen().read()可能会在 uvicorn 提供的 SSE 流上无限挂起。请使用支持流式的异步 HTTP 客户端(httpx、aiohttp)。