Files
beaver_project/部署指南.md
steven_li 9d6cde2d23 feat: 将项目从nano重命名为beaver并更新相关配置
- 将所有环境变量前缀从NANO_改为BEAVER_
- 更新README.md文档内容,包括项目介绍、组件说明和快速开始指南
- 修改.gitignore文件,添加auth-portal运行时路径排除规则
- 更新app-instance镜像标签从nano/app-instance改为beaver/app-instance
- 增强技能安全检查器,支持工具前缀白名单功能
- 添加技能草稿重新检查安全性API端点
- 扩展证据选择器,收集工具调用名称用于技能学习
- 改进技能合成器,基于实际调用的工具生成工具提示
- 优化路由超时处理机制,增加重试逻辑
- 更新后端架构文档,添加可视化入口和基础概念说明
- 实现在WebSocket消息中传递工具迭代次数信息
2026-05-20 18:01:06 +08:00

484 lines
11 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.

# Beaver Project 本机部署指南
这份文档用于在一台 Linux 或 WSL2 Ubuntu 机器上跑完整链路:
- `auth-portal`
- `authz-service`
- `deploy-control`
- `router-proxy`
- 自动创建出来的 `app-instance`
目标结果:
- 浏览器能打开 `http://127.0.0.1:3081/register`
- 注册账号后自动创建专属实例
- 浏览器跳转到 `http://<slug>.127.0.0.1.nip.io:8088`
如果你只单独启动某个前端页面,页面可以打开,但注册、登录、创建实例这些动作不一定能通。
## 0. 前提
推荐环境:
- Linux
- WSL2 Ubuntu
需要工具:
- `docker`
- `git`
- `curl`
- `openssl`
- `python3`
检查:
```bash
docker --version
docker ps
python3 --version
openssl version
curl --version
```
如果 `docker ps` 报错,先启动 Docker。
## 1. 进入项目根目录
```bash
cd /home/ivan/xuan/beaver_project
pwd
```
预期目录:
```text
/home/ivan/xuan/beaver_project
```
## 2. 准备本机测试变量
本机测试推荐用 `127.0.0.1.nip.io`。例如:
```text
alice.127.0.0.1.nip.io -> 127.0.0.1
```
这样 `router-proxy` 可以按子域名区分不同实例。
直接执行:
```bash
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` 必须带协议头。正确写法:
```text
http://beaver-authz-service:19090
http://beaver-deploy-control:8090
```
错误写法:
```text
beaver-authz-service:19090
beaver-deploy-control:8090
127.0.0.1:19090
127.0.0.1:8090
```
如果漏了 `http://`,注册页可能报:
```text
502: Request URL is missing an 'http://' or 'https://' protocol.
```
如果你改了 shell 里的变量,已经运行的容器不会自动更新。改完这些变量后,至少要重建:
- `beaver-authz-service`
- `beaver-auth-portal`
## 3. 创建运行目录
```bash
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. 构建镜像
```bash
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 网络
```bash
docker network inspect "$BEAVER_NET" >/dev/null 2>&1 || docker network create "$BEAVER_NET"
docker network ls | grep "$BEAVER_NET"
```
预期能看到:
```text
beaver-instance-edge
```
## 6. 启动 router-proxy
```bash
cd "$PROJECT_ROOT"
PROXY_NETWORK_NAME="$BEAVER_NET" \
PROXY_HTTP_PORT=8088 \
./router-proxy/start-proxy.sh --replace
```
实例统一入口:
```text
http://<slug>.127.0.0.1.nip.io:8088
```
示例:
```text
http://alice.127.0.0.1.nip.io:8088
```
## 7. 启动 authz-service
```bash
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
检查关键环境变量:
```bash
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` 要和挂载路径一致。
直接执行:
```bash
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
```bash
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
```
检查关键环境变量:
```bash
docker inspect beaver-auth-portal --format '{{range .Config.Env}}{{println .}}{{end}}' \
| egrep '^(AUTHZ_API_BASE_URL|DEPLOY_API_BASE_URL)='
```
## 10. 健康检查
```bash
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-service`
- `beaver-deploy-control`
- `beaver-auth-portal`
- `beaver-router-proxy`
## 11. 浏览器首次测试
打开:
```text
http://127.0.0.1:3081/register
```
预期流程:
1. 注册一个新账号。
2. Portal 创建不含模型凭证的实例。
3. 页面进入模型配置引导。
4. 填 provider、model、API key 后确认,或暂时跳过。
5. 浏览器跳到你的实例地址。
跳转目标示例:
```text
http://alice.127.0.0.1.nip.io:8088
```
## 12. 确认实例已创建
```bash
cd "$PROJECT_ROOT/app-instance"
./list-instances.sh
./list-instances.sh --json
docker ps --format 'table {{.Names}}\t{{.Status}}' | grep app-instance
```
注册表里应包含:
- `instance_id`
- `instance_slug`
- `container_name`
- `public_url`
- `instance_host`
## 13. 只看 auth-portal 页面
如果只想看 Portal 页面,不跑全链路:
```bash
cd /home/ivan/xuan/beaver_project/auth-portal/src
npm install
npm run dev
```
打开:
```text
http://127.0.0.1:3081
```
注意:这只能看页面。注册、登录、创建实例仍依赖 `authz-service``deploy-control`
## 14. 常用排错命令
```bash
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
```
实例创建失败时再看:
```bash
cd "$PROJECT_ROOT/app-instance"
./list-instances.sh --json
docker ps --format 'table {{.Names}}\t{{.Status}}' | grep app-instance
```
排查 URL 变量:
```bash
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 缺少协议
现象:
```text
502: Request URL is missing an 'http://' or 'https://' protocol.
```
优先检查:
- `beaver-authz-service` 里的 `DEPLOY_API_BASE_URL`
- `beaver-auth-portal` 里的 `AUTHZ_API_BASE_URL`
- `beaver-auth-portal` 里的 `DEPLOY_API_BASE_URL`
如果你只是改了当前 shell 变量,但没有重建容器,旧值还会继续生效。
### `AUTHZ_ISSUER` 写成了 `127.0.0.1`
错误:
```text
http://127.0.0.1:19090
```
正确:
```text
http://beaver-authz-service:19090
```
原因是 `app-instance` 容器里的 `127.0.0.1` 指向它自己。
### deploy-control 路径挂载写错
错误思路:
```text
宿主机 app-instance -> 容器 /app-instance
```
正确思路:
```text
$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` 解析失败
检查:
```bash
ping 127.0.0.1.nip.io
```
如果本地网络屏蔽了 `nip.io`,子域名测试会失败。可以临时换成本机 hosts 或正式域名。
### 端口被占用
默认端口:
- `3081`
- `8088`
- `8090`
- `19090`
检查:
```bash
ss -ltnp | grep -E '3081|8088|8090|19090'
```
## 16. 重新部署基础容器
只重建基础四个容器:
```bash
docker rm -f \
beaver-auth-portal \
beaver-authz-service \
beaver-deploy-control \
beaver-router-proxy 2>/dev/null || true
```
这不会自动删除实例数据。如果你还需要旧账号、旧实例或模型配置,不要删除 `runtime/` 目录。