- 将所有环境变量前缀从NANO_改为BEAVER_ - 更新README.md文档内容,包括项目介绍、组件说明和快速开始指南 - 修改.gitignore文件,添加auth-portal运行时路径排除规则 - 更新app-instance镜像标签从nano/app-instance改为beaver/app-instance - 增强技能安全检查器,支持工具前缀白名单功能 - 添加技能草稿重新检查安全性API端点 - 扩展证据选择器,收集工具调用名称用于技能学习 - 改进技能合成器,基于实际调用的工具生成工具提示 - 优化路由超时处理机制,增加重试逻辑 - 更新后端架构文档,添加可视化入口和基础概念说明 - 实现在WebSocket消息中传递工具迭代次数信息
11 KiB
Beaver Project 本机部署指南
这份文档用于在一台 Linux 或 WSL2 Ubuntu 机器上跑完整链路:
auth-portalauthz-servicedeploy-controlrouter-proxy- 自动创建出来的
app-instance
目标结果:
- 浏览器能打开
http://127.0.0.1:3081/register - 注册账号后自动创建专属实例
- 浏览器跳转到
http://<slug>.127.0.0.1.nip.io:8088
如果你只单独启动某个前端页面,页面可以打开,但注册、登录、创建实例这些动作不一定能通。
0. 前提
推荐环境:
- Linux
- WSL2 Ubuntu
需要工具:
dockergitcurlopensslpython3
检查:
docker --version
docker ps
python3 --version
openssl version
curl --version
如果 docker ps 报错,先启动 Docker。
1. 进入项目根目录
cd /home/ivan/xuan/beaver_project
pwd
预期目录:
/home/ivan/xuan/beaver_project
2. 准备本机测试变量
本机测试推荐用 127.0.0.1.nip.io。例如:
alice.127.0.0.1.nip.io -> 127.0.0.1
这样 router-proxy 可以按子域名区分不同实例。
直接执行:
export PROJECT_ROOT=/home/ivan/xuan/beaver_project
export BEAVER_NET=beaver-instance-edge
export BEAVER_DEPLOY_TOKEN="$(openssl rand -hex 32)"
export BEAVER_AUTHZ_INTERNAL_TOKEN="$(openssl rand -hex 32)"
export BEAVER_BASE_DOMAIN=127.0.0.1.nip.io
export BEAVER_AUTHZ_URL='http://beaver-authz-service:19090'
export BEAVER_DEPLOY_URL='http://beaver-deploy-control:8090'
export BEAVER_OUTLOOK_MCP_URL=''
export BEAVER_OUTLOOK_MCP_SERVER_ID='outlook_mcp'
变量说明:
| 变量 | 作用 |
|---|---|
PROJECT_ROOT |
仓库根目录 |
BEAVER_NET |
所有容器共用的 Docker network |
BEAVER_DEPLOY_TOKEN |
auth-portal / authz-service 调 deploy-control 的 token |
BEAVER_AUTHZ_INTERNAL_TOKEN |
AuthZ 内部接口 token |
BEAVER_BASE_DOMAIN |
新实例的基域名 |
BEAVER_AUTHZ_URL |
容器网络内访问 AuthZ 的地址 |
BEAVER_DEPLOY_URL |
容器网络内访问 deploy-control 的地址 |
BEAVER_OUTLOOK_MCP_URL |
可选 Outlook MCP HTTP 地址 |
BEAVER_OUTLOOK_MCP_SERVER_ID |
Outlook MCP server id,默认 outlook_mcp |
BEAVER_AUTHZ_URL 和 BEAVER_DEPLOY_URL 必须带协议头。正确写法:
http://beaver-authz-service:19090
http://beaver-deploy-control:8090
错误写法:
beaver-authz-service:19090
beaver-deploy-control:8090
127.0.0.1:19090
127.0.0.1:8090
如果漏了 http://,注册页可能报:
502: Request URL is missing an 'http://' or 'https://' protocol.
如果你改了 shell 里的变量,已经运行的容器不会自动更新。改完这些变量后,至少要重建:
beaver-authz-servicebeaver-auth-portal
3. 创建运行目录
mkdir -p \
"$PROJECT_ROOT/authz-service/runtime/data" \
"$PROJECT_ROOT/app-instance/runtime/instances" \
"$PROJECT_ROOT/app-instance/runtime/registry" \
"$PROJECT_ROOT/router-proxy/runtime/conf.d"
这些目录保存:
- AuthZ 数据
- 实例注册表
- 每个用户实例的配置和数据
router-proxy生成的路由文件
4. 构建镜像
cd "$PROJECT_ROOT"
docker build -t beaver/app-instance:latest app-instance
docker build -t beaver/authz-service:latest authz-service
docker build -t beaver/deploy-control:latest deploy-control
docker build -t beaver/auth-portal:latest auth-portal/src
如果某个镜像构建失败,先修构建错误,不要继续往下跑。
5. 创建共享 Docker 网络
docker network inspect "$BEAVER_NET" >/dev/null 2>&1 || docker network create "$BEAVER_NET"
docker network ls | grep "$BEAVER_NET"
预期能看到:
beaver-instance-edge
6. 启动 router-proxy
cd "$PROJECT_ROOT"
PROXY_NETWORK_NAME="$BEAVER_NET" \
PROXY_HTTP_PORT=8088 \
./router-proxy/start-proxy.sh --replace
实例统一入口:
http://<slug>.127.0.0.1.nip.io:8088
示例:
http://alice.127.0.0.1.nip.io:8088
7. 启动 authz-service
docker rm -f beaver-authz-service >/dev/null 2>&1 || true
docker run -d \
--name beaver-authz-service \
--restart unless-stopped \
--network "$BEAVER_NET" \
-p 19090:19090 \
-v "$PROJECT_ROOT/authz-service/runtime/data:/var/lib/authz-service/data" \
-e AUTHZ_ISSUER="$BEAVER_AUTHZ_URL" \
-e AUTHZ_INTERNAL_TOKEN="$BEAVER_AUTHZ_INTERNAL_TOKEN" \
-e DEPLOY_API_BASE_URL="$BEAVER_DEPLOY_URL" \
-e DEPLOY_API_TOKEN="$BEAVER_DEPLOY_TOKEN" \
beaver/authz-service:latest
重点:
AUTHZ_ISSUER在当前部署里要写http://beaver-authz-service:19090- 不要写
http://127.0.0.1:19090 - 新创建的
app-instance容器要通过 Docker network 访问 AuthZ
检查关键环境变量:
docker inspect beaver-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' \
| egrep '^(AUTHZ_ISSUER|DEPLOY_API_BASE_URL)='
8. 启动 deploy-control
deploy-control 会挂载 Docker socket,再创建新的 app-instance 容器。这里最容易错的是路径挂载:
- 要把宿主机真实路径按原路径挂进容器。
- 不要把
app-instance挂到容器里的/app-instance这种短路径。 APP_INSTANCE_DIR和ROUTER_PROXY_DIR要和挂载路径一致。
直接执行:
docker rm -f beaver-deploy-control >/dev/null 2>&1 || true
docker run -d \
--name beaver-deploy-control \
--restart unless-stopped \
--network "$BEAVER_NET" \
-p 8090:8090 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PROJECT_ROOT/app-instance:$PROJECT_ROOT/app-instance" \
-v "$PROJECT_ROOT/router-proxy:$PROJECT_ROOT/router-proxy" \
-e APP_INSTANCE_DIR="$PROJECT_ROOT/app-instance" \
-e ROUTER_PROXY_DIR="$PROJECT_ROOT/router-proxy" \
-e DEPLOY_CONTROL_API_TOKEN="$BEAVER_DEPLOY_TOKEN" \
-e APP_INSTANCE_IMAGE="beaver/app-instance:latest" \
-e APP_INSTANCE_NETWORK_NAME="$BEAVER_NET" \
-e DEFAULT_AUTHZ_BASE_URL="$BEAVER_AUTHZ_URL" \
-e DEFAULT_AUTHZ_OUTLOOK_MCP_URL="$BEAVER_OUTLOOK_MCP_URL" \
-e DEFAULT_OUTLOOK_MCP_SERVER_ID="$BEAVER_OUTLOOK_MCP_SERVER_ID" \
-e DEPLOY_PUBLIC_SCHEME="http" \
-e DEPLOY_PUBLIC_BASE_DOMAIN="$BEAVER_BASE_DOMAIN" \
-e DEPLOY_PUBLIC_PORT="8088" \
-e DEPLOY_AUTO_START_PROXY="1" \
beaver/deploy-control:latest
当前版本创建实例时会传 --skip-provider-config,也就是先不写 provider、model 或 API key。注册成功后,auth-portal 会进入模型配置引导页,再调用 deploy-control /api/instances/configure-provider 写入该实例的 config.json 并重启容器。
9. 启动 auth-portal
docker rm -f beaver-auth-portal >/dev/null 2>&1 || true
docker run -d \
--name beaver-auth-portal \
--restart unless-stopped \
--network "$BEAVER_NET" \
-p 3081:3081 \
-e AUTHZ_API_BASE_URL="$BEAVER_AUTHZ_URL" \
-e DEPLOY_API_BASE_URL="$BEAVER_DEPLOY_URL" \
-e DEPLOY_API_TOKEN="$BEAVER_DEPLOY_TOKEN" \
beaver/auth-portal:latest
检查关键环境变量:
docker inspect beaver-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' \
| egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
10. 健康检查
curl http://127.0.0.1:19090/healthz
curl http://127.0.0.1:8090/healthz
curl -I http://127.0.0.1:3081
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker logs --tail=50 beaver-router-proxy
至少应该看到这些容器:
beaver-authz-servicebeaver-deploy-controlbeaver-auth-portalbeaver-router-proxy
11. 浏览器首次测试
打开:
http://127.0.0.1:3081/register
预期流程:
- 注册一个新账号。
- Portal 创建不含模型凭证的实例。
- 页面进入模型配置引导。
- 填 provider、model、API key 后确认,或暂时跳过。
- 浏览器跳到你的实例地址。
跳转目标示例:
http://alice.127.0.0.1.nip.io:8088
12. 确认实例已创建
cd "$PROJECT_ROOT/app-instance"
./list-instances.sh
./list-instances.sh --json
docker ps --format 'table {{.Names}}\t{{.Status}}' | grep app-instance
注册表里应包含:
instance_idinstance_slugcontainer_namepublic_urlinstance_host
13. 只看 auth-portal 页面
如果只想看 Portal 页面,不跑全链路:
cd /home/ivan/xuan/beaver_project/auth-portal/src
npm install
npm run dev
打开:
http://127.0.0.1:3081
注意:这只能看页面。注册、登录、创建实例仍依赖 authz-service 和 deploy-control。
14. 常用排错命令
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker logs --tail=100 beaver-authz-service
docker logs --tail=100 beaver-deploy-control
docker logs --tail=100 beaver-auth-portal
docker logs --tail=100 beaver-router-proxy
curl http://127.0.0.1:19090/healthz
curl http://127.0.0.1:8090/healthz
curl -I http://127.0.0.1:3081
实例创建失败时再看:
cd "$PROJECT_ROOT/app-instance"
./list-instances.sh --json
docker ps --format 'table {{.Names}}\t{{.Status}}' | grep app-instance
排查 URL 变量:
docker inspect beaver-authz-service --format '{{range .Config.Env}}{{println .}}{{end}}' \
| egrep '^(AUTHZ_ISSUER|DEPLOY_API_BASE_URL)='
docker inspect beaver-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' \
| egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
它们都必须是完整 URL,不能是空字符串,也不能是裸 host:port。
15. 常见问题
注册页报 URL 缺少协议
现象:
502: Request URL is missing an 'http://' or 'https://' protocol.
优先检查:
beaver-authz-service里的DEPLOY_API_BASE_URLbeaver-auth-portal里的AUTHZ_API_BASE_URLbeaver-auth-portal里的DEPLOY_API_BASE_URL
如果你只是改了当前 shell 变量,但没有重建容器,旧值还会继续生效。
AUTHZ_ISSUER 写成了 127.0.0.1
错误:
http://127.0.0.1:19090
正确:
http://beaver-authz-service:19090
原因是 app-instance 容器里的 127.0.0.1 指向它自己。
deploy-control 路径挂载写错
错误思路:
宿主机 app-instance -> 容器 /app-instance
正确思路:
$PROJECT_ROOT/app-instance -> $PROJECT_ROOT/app-instance
$PROJECT_ROOT/router-proxy -> $PROJECT_ROOT/router-proxy
因为 deploy-control 会通过宿主机 Docker socket 再创建新容器,传给 Docker 的 bind mount 源路径必须是宿主机真实路径。
nip.io 解析失败
检查:
ping 127.0.0.1.nip.io
如果本地网络屏蔽了 nip.io,子域名测试会失败。可以临时换成本机 hosts 或正式域名。
端口被占用
默认端口:
30818088809019090
检查:
ss -ltnp | grep -E '3081|8088|8090|19090'
16. 重新部署基础容器
只重建基础四个容器:
docker rm -f \
beaver-auth-portal \
beaver-authz-service \
beaver-deploy-control \
beaver-router-proxy 2>/dev/null || true
这不会自动删除实例数据。如果你还需要旧账号、旧实例或模型配置,不要删除 runtime/ 目录。