Refactor app instance to Keycloak SSO
This commit is contained in:
198
README.md
198
README.md
@ -1,183 +1,75 @@
|
||||
# Beaver Project
|
||||
# Beaver App Instance
|
||||
|
||||
`Beaver Project` 是一套单机 Docker 部署的多实例运行环境:
|
||||
This branch contains a standalone Beaver app instance for an external orchestrator to deploy.
|
||||
|
||||
- 用户先进入独立的 `auth-portal` 完成注册或登录。
|
||||
- 注册会触发 `authz-service` 调用 `deploy-control`。
|
||||
- `deploy-control` 在同一台机器上创建一个独立的 `app-instance` 容器。
|
||||
- `router-proxy` 按实例域名把流量转发到对应容器。
|
||||
The app instance is a single Docker image that runs:
|
||||
|
||||
当前推荐的最小部署方式是一台 Linux / WSL2 Ubuntu 机器加 Docker。生产域名和 HTTPS 可以放在项目外层的 Nginx、Caddy、Traefik 或云负载均衡上。
|
||||
- Next.js frontend
|
||||
- FastAPI backend
|
||||
- Nginx reverse proxy
|
||||
|
||||
## 组件
|
||||
Authentication is delegated to Keycloak. This repository does not maintain local user registration, passwords, per-user instance routing, or deployment orchestration.
|
||||
|
||||
| 目录 | 职责 | 默认端口 |
|
||||
| --- | --- | --- |
|
||||
| `auth-portal/` | 用户登录、注册、模型配置引导入口 | `3081` |
|
||||
| `authz-service/` | AuthZ 服务,负责账号和 backend 身份编排 | `19090` |
|
||||
| `deploy-control/` | 部署控制面,调用 Docker 创建和管理实例 | `8090` |
|
||||
| `router-proxy/` | 统一实例入口代理,按 Host 分发到实例容器 | `8088` |
|
||||
| `app-instance/` | 单用户运行实例,容器内包含前端、后端和 Nginx | 容器内 `8080` |
|
||||
## Runtime Contract
|
||||
|
||||
公网环境通常只暴露:
|
||||
The external orchestrator is responsible for:
|
||||
|
||||
- `auth-portal`: `3081`,或外层代理后的 `https://portal.example.com`
|
||||
- `router-proxy`: `8088`,或外层代理后的 `https://<slug>.apps.example.com`
|
||||
- Building or pulling the app image
|
||||
- Providing a mounted Beaver home directory
|
||||
- Providing `config.json`
|
||||
- Choosing the public host and port
|
||||
- Registering the public callback URL and post-logout callback URL in Keycloak
|
||||
- Managing lifecycle, routing, TLS, and scaling
|
||||
|
||||
不要直接把 `deploy-control:8090` 和 `authz-service:19090` 暴露到公网。
|
||||
|
||||
## 请求链路
|
||||
|
||||
注册:
|
||||
The app instance exposes container port `8080`:
|
||||
|
||||
```text
|
||||
Browser
|
||||
-> auth-portal
|
||||
-> authz-service POST /portal/register
|
||||
-> deploy-control POST /api/instances/register
|
||||
-> app-instance/create-instance.sh
|
||||
-> app-instance POST /api/auth/register
|
||||
-> authz-service /oauth/register or /backends/register
|
||||
-> auth-portal provider onboarding
|
||||
-> deploy-control POST /api/instances/configure-provider
|
||||
/ frontend
|
||||
/api backend API
|
||||
/ws backend WebSocket
|
||||
```
|
||||
|
||||
登录:
|
||||
## Keycloak
|
||||
|
||||
Default IdP settings:
|
||||
|
||||
```text
|
||||
Browser
|
||||
-> auth-portal
|
||||
-> deploy-control POST /api/instances/resolve
|
||||
-> app-instance POST /api/auth/login
|
||||
-> app-instance frontend URL
|
||||
issuer: https://keycloak.bwgdi.com/realms/beaver
|
||||
client_id: beaver-agnet
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
For the current plain-IP deployment, register these values in Keycloak:
|
||||
|
||||
本机完整流程见:
|
||||
```text
|
||||
web_origin: http://172.19.0.245:18080
|
||||
redirect_uri: http://172.19.0.245:18080/auth/callback
|
||||
post_logout_redirect_uri: http://172.19.0.245:18080/logout/callback
|
||||
```
|
||||
|
||||
- [部署指南.md](./部署指南.md)
|
||||
The app validates Keycloak JWT issuer, signature, expiry, audience/azp, and nonce where applicable. The Keycloak `sub` claim is used as the application user ID.
|
||||
|
||||
域名、HTTPS、公网反向代理说明见:
|
||||
|
||||
- [域名配置指引.md](./域名配置指引.md)
|
||||
|
||||
最小配置变量:
|
||||
## Build
|
||||
|
||||
```bash
|
||||
export PROJECT_ROOT=/home/ivan/xuan/beaver_project
|
||||
export BEAVER_NET=beaver-instance-edge
|
||||
export BEAVER_PROXY_CONTAINER_NAME=beaver-router-proxy
|
||||
|
||||
export BEAVER_DEPLOY_TOKEN="$(openssl rand -hex 32)"
|
||||
export BEAVER_AUTHZ_INTERNAL_TOKEN="$(openssl rand -hex 32)"
|
||||
|
||||
export BEAVER_BASE_DOMAIN=localhost
|
||||
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'
|
||||
cd app-instance
|
||||
docker build -t beaver/app-instance:keycloak-login .
|
||||
```
|
||||
|
||||
启动顺序:
|
||||
|
||||
1. 创建运行目录。
|
||||
2. 构建四个镜像。
|
||||
3. 创建共享 Docker network。
|
||||
4. 启动 `router-proxy`。
|
||||
5. 启动 `authz-service`。
|
||||
6. 启动 `deploy-control`。
|
||||
7. 启动 `auth-portal`。
|
||||
8. 打开 `http://127.0.0.1:3081/register` 测试注册。
|
||||
|
||||
## 关键配置关系
|
||||
|
||||
`DEPLOY_API_TOKEN` 和 `DEPLOY_CONTROL_API_TOKEN` 必须相等:
|
||||
|
||||
- `auth-portal` / `authz-service` 用 `DEPLOY_API_TOKEN` 请求 `deploy-control`。
|
||||
- `deploy-control` 用 `DEPLOY_CONTROL_API_TOKEN` 校验请求。
|
||||
|
||||
`AUTHZ_ISSUER` 在这套单机部署里要写容器网络地址:
|
||||
|
||||
```text
|
||||
http://beaver-authz-service:19090
|
||||
```
|
||||
|
||||
不要写成 `http://127.0.0.1:19090`,因为新创建的 `app-instance` 容器里的 `127.0.0.1` 指向它自己,不是 AuthZ 容器。
|
||||
|
||||
`DEPLOY_PUBLIC_*` 决定新实例展示给用户的 URL:
|
||||
## Run Locally
|
||||
|
||||
```bash
|
||||
DEPLOY_PUBLIC_SCHEME=http
|
||||
DEPLOY_PUBLIC_BASE_DOMAIN=localhost
|
||||
DEPLOY_PUBLIC_PORT=8088
|
||||
cd app-instance
|
||||
./run-standalone.sh --build --replace
|
||||
```
|
||||
|
||||
本机测试时实例 URL 形如:
|
||||
The script prints the `web_origin`, `redirect_uri`, and `post_logout_redirect_uri` values that must be configured in Keycloak.
|
||||
|
||||
```text
|
||||
http://alice.localhost:8088
|
||||
```
|
||||
## Useful Paths
|
||||
|
||||
正式 HTTPS 域名通常改成:
|
||||
- `app-instance/` - app image, frontend, backend, runtime helper script, app tests
|
||||
- `skills/` - reusable skill content retained for product/runtime packaging
|
||||
- `agents/` - agent registry retained for runtime packaging
|
||||
- `docs/` - product and architecture documentation
|
||||
- `AGENTS.md` - local coding-agent instructions
|
||||
|
||||
```bash
|
||||
DEPLOY_PUBLIC_SCHEME=https
|
||||
DEPLOY_PUBLIC_BASE_DOMAIN=apps.example.com
|
||||
DEPLOY_PUBLIC_PORT=443
|
||||
```
|
||||
|
||||
实例 URL 形如:
|
||||
|
||||
```text
|
||||
https://alice.apps.example.com
|
||||
```
|
||||
|
||||
前提是你已经在项目外层把 `*.apps.example.com` 的 `80/443` 流量转发到 `router-proxy:8088`。
|
||||
|
||||
## 模型配置方式
|
||||
|
||||
当前版本不会在注册创建实例时写入模型 provider、model 或 API key。
|
||||
|
||||
流程是:
|
||||
|
||||
1. 注册先创建一个不含模型凭证的实例。
|
||||
2. `auth-portal` 进入模型配置引导页。
|
||||
3. 用户确认后,Portal 调用 `deploy-control /api/instances/configure-provider`。
|
||||
4. `deploy-control` 写入该实例的 `config.json` 并重启对应容器。
|
||||
|
||||
如果用户跳过引导,实例仍会创建成功,但后续需要在实例内补齐 provider 配置后才能正常调用模型。
|
||||
|
||||
## 持久化目录
|
||||
|
||||
至少保留:
|
||||
|
||||
```text
|
||||
authz-service/runtime/data
|
||||
app-instance/runtime/instances
|
||||
app-instance/runtime/registry
|
||||
router-proxy/runtime/conf.d
|
||||
```
|
||||
|
||||
不要在需要保留账号、实例或配置时删除这些目录。
|
||||
|
||||
## 模板文件
|
||||
|
||||
可参考这些环境变量模板:
|
||||
|
||||
- [`.env.example`](./.env.example)
|
||||
- [`auth-portal/src/.env.example`](./auth-portal/src/.env.example)
|
||||
- [`authz-service/.env.example`](./authz-service/.env.example)
|
||||
- [`deploy-control/.env.example`](./deploy-control/.env.example)
|
||||
- [`router-proxy/.env.example`](./router-proxy/.env.example)
|
||||
|
||||
这些模板不会被脚本自动加载。你可以手动 `export`,也可以在 `docker run` 时使用 `--env-file`。
|
||||
|
||||
## 子项目文档
|
||||
|
||||
- [`app-instance/README.md`](./app-instance/README.md)
|
||||
- [`auth-portal/src/README.md`](./auth-portal/src/README.md)
|
||||
- [`authz-service/README.md`](./authz-service/README.md)
|
||||
- [`deploy-control/README.md`](./deploy-control/README.md)
|
||||
- [`router-proxy/README.md`](./router-proxy/README.md)
|
||||
See `app-instance/README.md` for the app-specific contract and environment variables.
|
||||
|
||||
Reference in New Issue
Block a user