diff --git a/AGENT.md b/AGENT.md new file mode 100644 index 0000000..4f8ca85 --- /dev/null +++ b/AGENT.md @@ -0,0 +1,86 @@ +# Xboard 仓库 Agent 协作规范 + +本文给自动化代理与协作者使用,目标是提升并行效率,减少回归风险。 + +## 1. 输出与沟通 + +- 默认使用简体中文。 +- 先给结论,再给关键证据与改动点。 +- 复杂任务必须先给执行计划,再落地改动。 + +## 2. 执行原则 + +1. 质量优先:不为速度牺牲正确性与可维护性。 +2. 并行优先:能并行的信息收集与文件操作尽量并行。 +3. 最小改动:仅修改与任务直接相关的文件。 +4. 可追溯:说明改了什么、为什么改、如何验证。 + +## 3. 并行拆分规则 + +1. 先画依赖图,区分可并行和必须串行任务。 +2. 不允许并行写同一文件或同一区域。 +3. 收集阶段可并行,分析和冲突解决阶段串行。 +4. 每轮并行结束后先汇总再进入下一轮。 + +## 4. 仓库事实(执行前必须知道) + +- 技术栈:Laravel 12 + Octane + Horizon + Redis。 +- 安装命令:`php artisan xboard:install`(交互式,强依赖 Redis 可连通)。 +- 前端资产:仓库内为已编译静态资源,不是完整前端源码仓。 +- 任务调度:依赖 `schedule:work` 或 `cron + schedule:run`。 +- 当前仓库默认无 `tests/` 与 `phpunit.xml`,测试基建可能缺失。 + +## 5. 推荐命令基线 + +信息收集: + +```bash +rg --files +rg -n "" app config routes docs +``` + +本地运行(三进程): + +```bash +php artisan octane:start --host=0.0.0.0 --port=7001 --watch +php artisan horizon +php artisan schedule:work +``` + +质量检查: + +```bash +php artisan about +php artisan migrate:status +vendor/bin/phpstan analyse --memory-limit=1G +``` + +测试(若已补齐测试): + +```bash +timeout 60s php artisan test +``` + +## 6. 高风险操作确认 + +以下操作必须先得到明确确认: + +- 删除/批量改写文件 +- `git reset --hard`、`git checkout --`、强制回滚 +- 数据库清库、结构变更、批量数据更新 +- 调用生产环境 API 或发送敏感数据 +- 全局安装/卸载依赖 + +## 7. 仓库特殊风险提醒 + +- `update.sh` 含 `git reset --hard origin/master`,默认禁止直接执行。 +- `xboard:update` / `xboard:install` 可能恢复 `plugins/` 下被跟踪文件,执行前需确认是否会覆盖开发中的插件改动。 +- `compose.sample.yaml` 使用 `network_mode: host`,跨平台可用性有限,必要时改端口映射。 + +## 8. 提交前自检清单 + +1. 变更范围最小且与需求一致。 +2. 关键路径已验证(安装/运行/队列/调度至少一项)。 +3. 质量检查命令执行结果已记录。 +4. 风险与未覆盖项已明确说明。 + diff --git a/README.md b/README.md index 4d6a618..20a6a2c 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ docker compose up -d ### Development Guides - [Plugin Development Guide](./docs/en/development/plugin-development-guide.md) - Complete guide for developing XBoard plugins +- [Developer Guide (ZH-CN)](./docs/development-guide.zh-CN.md) - Local development, testing, running and build guide +- [V2bX Integration Guide (ZH-CN)](./docs/v2bx-integration.zh-CN.md) - Full Xboard ↔ V2bX integration guide ### Deployment Guides - [Deploy with 1Panel](./docs/en/installation/1panel.md) diff --git a/docs/development-guide.zh-CN.md b/docs/development-guide.zh-CN.md new file mode 100644 index 0000000..19a5696 --- /dev/null +++ b/docs/development-guide.zh-CN.md @@ -0,0 +1,236 @@ +# Xboard 开发文档(开发环境 / 本地测试 / 运行 / 编译) + +本文面向仓库维护者与二次开发者,覆盖本项目在本地和容器中的完整开发流程。 + +## 1. 项目现状与边界 + +- 后端框架:Laravel 12(`laravel/framework`)+ Octane(Swoole)+ Horizon。 +- 运行依赖:数据库(SQLite / MySQL / PostgreSQL)+ Redis。 +- 前端资产:当前仓库已包含编译产物,主要位于: + - `theme/Xboard/assets` + - `theme/v2board/assets` + - `public/assets/admin` +- `package.json` 仅含 `chokidar` 依赖,主要用于 Octane `--watch` 开发体验,不是完整前端工程。 + +## 2. 开发环境要求 + +## 2.1 必需依赖 + +- Git +- PHP `8.2+` +- Composer `2.x` +- Redis `7+` +- 数据库三选一: + - SQLite(最快) + - MySQL `5.7+` + - PostgreSQL + +## 2.2 推荐依赖(开发体验) + +- Docker + Docker Compose(推荐) +- Node.js `18+`(仅在使用 `php artisan octane:start --watch` 时需要) + +## 2.3 操作系统建议 + +- 推荐 Linux / WSL2。 +- `compose.sample.yaml` 使用 `network_mode: host`,在非 Linux 环境可能需要改为端口映射(如 `7001:7001`)。 + +## 3. Docker 开发模式(推荐) + +## 3.1 初始化 + +```bash +git clone -b compose --depth 1 https://github.com/cedar2025/Xboard +cd Xboard +cp compose.sample.yaml compose.yaml +``` + +## 3.2 安装(首次) + +推荐使用 SQLite + 内置 Redis 的快速安装: + +```bash +docker compose run -it --rm \ + -e ENABLE_SQLITE=true \ + -e ENABLE_REDIS=true \ + -e ADMIN_ACCOUNT=admin@demo.com \ + web php artisan xboard:install +``` + +安装完成后请记录: + +- 管理员账号/密码(安装命令输出) +- 后台路径(安装命令输出中的 `secure_path`) + +## 3.3 启动与停止 + +```bash +docker compose up -d +docker compose ps +docker compose logs -f web +docker compose logs -f horizon +``` + +停止: + +```bash +docker compose down +``` + +## 3.4 访问地址 + +- 用户前台:`http://:7001/` +- 管理后台:`http://:7001/` + +说明:`secure_path` 默认不是固定字符串,而是安装后生成并可在后台配置修改。 + +## 4. 宿主机本地开发(非 Docker) + +## 4.1 安装依赖 + +```bash +composer install +cp .env.example .env +``` + +如果你计划使用 SQLite,可先准备文件: + +```bash +mkdir -p .docker/.data +touch .docker/.data/database.sqlite +``` + +## 4.2 首次安装 + +```bash +php artisan xboard:install +``` + +安装向导会交互配置: + +- 数据库类型(SQLite / MySQL / PostgreSQL) +- Redis 连接(安装阶段会强校验可连通) +- 管理员账号 + +## 4.3 启动服务(开发三进程) + +建议至少开 3 个终端: + +1. Web 服务(Octane) +```bash +php artisan octane:start --host=0.0.0.0 --port=7001 --watch +``` + +2. 队列消费(Horizon) +```bash +php artisan horizon +``` + +3. 定时任务(开发态) +```bash +php artisan schedule:work +``` + +说明: + +- 生产环境通常由 `cron` 调 `schedule:run`,开发环境直接 `schedule:work` 更直观。 +- 若不使用 `--watch`,可不安装 Node.js。 + +## 4.4 权限问题(Linux) + +```bash +chmod -R 775 storage bootstrap/cache .docker/.data +``` + +## 5. 本地测试与质量检查 + +## 5.1 当前仓库事实 + +- 当前仓库未包含 `tests/` 目录。 +- 当前仓库未包含 `phpunit.xml` / `phpunit.xml.dist`。 + +因此默认没有可执行的项目内单元测试套件,建议先补齐测试基建再启用 CI 强校验。 + +## 5.2 建议的本地检查基线 + +```bash +php artisan about +php artisan migrate:status +php artisan route:list +vendor/bin/phpstan analyse --memory-limit=1G +``` + +如后续补充测试用例后,再执行: + +```bash +timeout 60s php artisan test +``` + +> 约定:自动化执行测试时,单条任务建议设置 60s 超时,避免阻塞流水线。 + +## 6. 运行与调试要点 + +## 6.1 调度与队列健康 + +- 定时任务心跳来源:`App\Console\Kernel::schedule` 中写入缓存键 `SCHEDULE_LAST_CHECK_AT`。 +- Horizon 状态可在后台系统状态页查看。 + +若后台提示异常,先检查: + +```bash +php artisan schedule:list +php artisan horizon:status +``` + +## 6.2 关键日志位置 + +- 应用日志:`storage/logs` +- Docker 运行日志:`docker compose logs -f web|horizon` + +## 7. 编译 / 构建说明 + +## 7.1 应用层“编译”边界 + +- 本仓库不包含完整的后台/前台前端源码工程。 +- 默认是消费已编译好的静态资源,不存在常规 `npm run build` 的全量前端构建链。 + +## 7.2 Docker 镜像构建 + +CI 使用 `.github/workflows/docker-publish.yml` 进行多架构构建并推送镜像。 + +本地可执行: + +```bash +docker build \ + --build-arg CACHEBUST=$(date +%s) \ + --build-arg REPO_URL=https://github.com/cedar2025/Xboard \ + --build-arg BRANCH_NAME=master \ + -t xboard:dev . +``` + +重要说明: + +- 当前 `Dockerfile` 在构建时会 `git clone` 指定仓库分支,不直接打包你本地未提交改动。 +- 若目标是“本地改动实时调试”,优先使用 Docker Compose 挂载源码运行,而非用该 `Dockerfile` 打镜像。 + +## 8. 升级、回滚与危险脚本 + +常用命令: + +```bash +php artisan xboard:update +php artisan xboard:rollback +``` + +注意事项: + +- `update.sh` 包含 `git reset --hard origin/master`,会覆盖本地改动,不建议在开发分支使用。 +- `xboard:update` / `xboard:install` 内部包含插件目录恢复逻辑,可能回退 `plugins/` 下被 Git 跟踪且非新增的修改。 + +## 9. 建议开发流程(最小闭环) + +1. 建立分支并完成代码改动。 +2. 启动 `octane + horizon + schedule:work` 做手工联调。 +3. 运行静态检查(`phpstan`)和基础 smoke 检查(`about` / `migrate:status`)。 +4. 确认后台路径、队列、定时任务均正常后再提交。 + diff --git a/docs/v2bx-integration.zh-CN.md b/docs/v2bx-integration.zh-CN.md new file mode 100644 index 0000000..6e1caeb --- /dev/null +++ b/docs/v2bx-integration.zh-CN.md @@ -0,0 +1,327 @@ +# Xboard 对接 V2bX 完整文档 + +本文基于以下两套源码交叉整理: + +- 面板端:`Xboard-new` +- 节点端:`E:/code/go/V2bX` + +适用目标:让 `V2bX` 节点稳定对接 `Xboard`,完成配置拉取、用户同步、流量上报、在线设备上报。 + +## 1. 对接结论(先看这个) + +1. `V2bX` 当前固定请求 `Xboard` 的 `V1 UniProxy` 路径(不是 `V2` 路径): + - `GET /api/v1/server/UniProxy/config` + - `GET /api/v1/server/UniProxy/user` + - `GET /api/v1/server/UniProxy/alivelist` + - `POST /api/v1/server/UniProxy/push` + - `POST /api/v1/server/UniProxy/alive` +2. 鉴权依赖 URL Query 参数:`token`、`node_id`、`node_type`。 +3. `Xboard` 的 `server_token` 长度需要 >= 16。 +4. `V2bX` 启动时如果拉不到可用用户会直接报错退出:`add users error: not have any user`。 +5. 在线设备数据写入由队列任务处理,面板端必须保证队列消费者(通常 `horizon`)在运行。 + +## 2. 源码级接口对齐 + +## 2.1 V2bX 侧(请求方) + +关键实现: + +- `api/panel/panel.go`:初始化 Query 参数(`node_type/node_id/token`),并限制 `NodeType` 枚举。 +- `api/panel/node.go`:拉取节点配置(`/api/v1/server/UniProxy/config`)。 +- `api/panel/user.go`:拉取用户、在线列表,上报流量和在线 IP。 +- `node/controller.go`:启动时先拉配置和用户,再注册节点。 +- `node/task.go`:按 `pull_interval/push_interval` 定时同步与上报。 + +## 2.2 Xboard 侧(服务方) + +关键实现: + +- `app/Http/Routes/V1/ServerRoute.php`:`/api/v1/server/UniProxy/*` 路由定义。 +- `app/Http/Middleware/Server.php`:校验 `token/node_id/node_type`,并注入 `node_info`。 +- `app/Http/Controllers/V1/Server/UniProxyController.php`:实现 `config/user/push/alive/alivelist/status`。 +- `app/Services/ServerService.php`:按 `node_id`(支持 `code` 或 `id`)和 `node_type` 查节点,按权限组取可用用户。 +- `app/Jobs/UpdateAliveDataJob.php`:异步写在线设备计数。 + +## 3. 类型与协议兼容要点 + +`V2bX` 允许的 `NodeType`(`api/panel/panel.go`): + +- `vmess` +- `vless` +- `trojan` +- `shadowsocks` +- `hysteria` +- `hysteria2` +- `tuic` +- `anytls` +- 兼容别名:`v2ray -> vmess` + +`Xboard` 节点类型(`app/Models/Server.php`)有别名: + +- `v2ray -> vmess` +- `hysteria2 -> hysteria` + +建议: + +1. 绝大多数场景按面板节点真实类型填写 `NodeType`。 +2. Hysteria v2 场景建议仍使用 `NodeType: "hysteria"`,在面板协议设置里把 `version` 设为 `2`,避免类型语义混乱。 +3. `V2bX` 并不对接 `Xboard` 的 `socks/naive/http/mieru` 这几类。 + +## 4. Xboard 面板端配置步骤 + +## 4.1 全局通信参数 + +后台系统配置里设置: + +- `server_token`:与 V2bX 的 `ApiKey` 完全一致,长度建议 32+。 +- `server_pull_interval`:节点拉配置周期(秒)。 +- `server_push_interval`:节点推送流量周期(秒)。 +- `device_limit_mode`:设备限制统计策略(按你的业务选)。 + +源码依据: + +- `app/Http/Controllers/V2/Admin/ConfigController.php` +- `app/Http/Requests/Admin/ConfigSave.php` + +## 4.2 创建节点(每个 NodeID 对应一个节点) + +至少需要正确配置: + +- `type` +- `name` +- `host` +- `port` +- `server_port` +- `group_ids` +- `rate` +- `protocol_settings`(按协议必填项) + +源码依据:`app/Http/Requests/Admin/ServerSave.php` + +## 4.3 用户可用性条件(非常关键) + +节点可拉到的用户必须同时满足(`ServerService::getAvailableUsers`): + +- 用户 `group_id` 在节点 `group_ids` 内 +- `u + d < transfer_enable` +- 未过期 +- 未被禁用 + +否则 `V2bX` 首次启动可能直接失败(无可用用户)。 + +## 4.4 队列进程 + +`/alive` 上报会派发 `UpdateAliveDataJob` 到 `online_sync` 队列。 +若没有队列消费者,在线设备统计会滞后或不更新。 + +建议至少保证: + +- `php artisan horizon` 正常运行 + +## 5. V2bX 配置(可直接改) + +参考 `E:/code/go/V2bX/example/config.json`。 + +## 5.1 单节点最小可用示例 + +```json +{ + "Log": { + "Level": "info", + "Output": "" + }, + "Cores": [ + { + "Type": "sing", + "Log": { + "Level": "info", + "Timestamp": true + }, + "OriginalPath": "/etc/V2bX/sing_origin.json" + } + ], + "Nodes": [ + { + "Core": "sing", + "ApiHost": "https://panel.example.com", + "ApiKey": "请填写与Xboard一致的server_token", + "NodeID": 1, + "NodeType": "vmess", + "Timeout": 30, + "ListenIP": "0.0.0.0", + "SendIP": "0.0.0.0", + "DeviceOnlineMinTraffic": 200, + "MinReportTraffic": 0 + } + ] +} +``` + +## 5.2 字段说明(高频踩坑项) + +- `ApiHost`:必须是面板根地址,不要写成 `.../api/v1`。 +- `ApiKey`:对应 `Xboard server_token`。 +- `NodeID`:对应面板节点 `id`(或数值型 `code`)。 +- `NodeType`:必须是 V2bX 支持的枚举。 +- `Timeout`:HTTP 超时秒数。 +- `ApiSendIP`(可选):多网卡时指定请求源 IP。 + +源码依据:`E:/code/go/V2bX/conf/node.go` + +## 6. 启动与热重载 + +## 6.1 启动命令 + +```bash +V2bX server -c /etc/V2bX/config.json +``` + +默认支持 `--watch`(开启配置监听),配置文件变化后会自动重载核心和节点。 + +源码依据:`E:/code/go/V2bX/cmd/server.go` + +## 6.2 建议运行形态 + +- 使用 `systemd` 托管 `V2bX` +- 配置 `Restart=always` +- 单独落日志文件,便于排错 + +## 7. 联调验证(建议按顺序) + +## 7.1 手工验证面板接口可达 + +在节点机执行(把参数换成你的真实值): + +```bash +curl -sS "https://panel.example.com/api/v1/server/UniProxy/config?node_type=vmess&node_id=1&token=YOUR_TOKEN" +``` + +预期:返回 JSON,包含 `base_config.push_interval` 与 `base_config.pull_interval`。 + +```bash +curl -sS "https://panel.example.com/api/v1/server/UniProxy/user?node_type=vmess&node_id=1&token=YOUR_TOKEN" +``` + +预期:返回 `users` 列表,且非空(至少有一个可用用户)。 + +## 7.2 启动后看 V2bX 日志 + +应出现这类信息: + +- `Core ... started` +- `Nodes started` +- 周期性 `Report N users traffic` +- 周期性在线用户上报日志 + +## 7.3 面板侧确认 + +- 节点状态 `last_check_at`、`last_push_at` 持续刷新 +- 用户流量持续累加 +- `online_count` 有变化(需要队列正常) + +## 8. 常见问题与处理 + +## 8.1 `unsupported Node type` + +原因:`NodeType` 不在 V2bX 白名单。 +处理:改为支持值(如 `vmess/vless/trojan/shadowsocks/hysteria/tuic/anytls`)。 + +## 8.2 `Invalid token` + +原因:`ApiKey != server_token`。 +处理:面板与节点统一同一密钥,并确认没有前后空格。 + +## 8.3 `Server does not exist` + +原因: + +- `NodeID` 错误 +- `NodeType` 与面板节点类型不匹配 + +处理:先在面板确认节点 ID/类型,再校正 V2bX 配置。 + +## 8.4 `add users error: not have any user` + +原因:该节点按权限组筛选后没有可用用户。 +处理: + +1. 确认节点 `group_ids` +2. 确认至少一个用户满足流量/到期/禁用条件 + +## 8.5 在线设备不上报或不更新 + +原因:面板队列消费者未运行。 +处理:启动并确认 `horizon` 正常消费(尤其 `online_sync` 队列)。 + +## 8.6 配置路径重复导致 404 + +原因:`ApiHost` 写成 `https://panel/api/v1`,最终拼接成重复路径。 +处理:`ApiHost` 只保留根域名(如 `https://panel.example.com`)。 + +## 9. 请求/响应数据形状(排错用) + +## 9.1 配置拉取 + +- 请求:`GET /api/v1/server/UniProxy/config?node_type=...&node_id=...&token=...` +- 响应:按协议字段 + `base_config` + +## 9.2 用户拉取 + +- 请求:`GET /api/v1/server/UniProxy/user?...` +- 响应:`{"users":[{"id":1,"uuid":"...","speed_limit":0,"device_limit":0}]}`(也兼容 msgpack) + +## 9.3 流量上报 + +- 请求:`POST /api/v1/server/UniProxy/push?...` +- Body(V2bX 实际发送): + +```json +{ + "1001": [12345, 67890], + "1002": [11111, 22222] +} +``` + +## 9.4 在线上报 + +- 请求:`POST /api/v1/server/UniProxy/alive?...` +- Body: + +```json +{ + "1001": ["1.1.1.1", "2.2.2.2"], + "1002": ["3.3.3.3"] +} +``` + +## 10. 安全建议 + +1. `ApiHost` 必须用 HTTPS。 +2. `server_token` 使用高强度随机值并定期轮换。 +3. 在反向代理/Nginx 层限制节点来源 IP 访问 `server/UniProxy` 接口。 +4. 变更 `server_token` 后,面板与全部节点必须同时切换。 + +## 11. 代码参考索引 + +Xboard: + +- `app/Http/Routes/V1/ServerRoute.php` +- `app/Http/Middleware/Server.php` +- `app/Http/Controllers/V1/Server/UniProxyController.php` +- `app/Services/ServerService.php` +- `app/Jobs/UpdateAliveDataJob.php` +- `app/Http/Requests/Admin/ConfigSave.php` +- `app/Http/Requests/Admin/ServerSave.php` + +V2bX: + +- `api/panel/panel.go` +- `api/panel/node.go` +- `api/panel/user.go` +- `node/controller.go` +- `node/task.go` +- `node/user.go` +- `conf/node.go` +- `cmd/server.go` +- `example/config.json` +