docs: improve deployment and agent guides

This commit is contained in:
JetSprow
2026-04-29 19:55:09 +10:00
parent 843753bed6
commit 7269afa9bb
4 changed files with 916 additions and 278 deletions

525
README.md
View File

@@ -1,176 +1,156 @@
# J-Board
J-Board也称 JB面板是一个面向代理订阅售卖与流媒体共享的全栈应用。节点运行、入站和客户端配置由 3x-ui 面板维护J-Board 负责售卖、订单、订阅、用户、支付、工单和探测展示;自带 Go 程序只做延迟与线路探测上报
J-Board也称 JB 面板)是一个面向代理订阅售卖与流媒体共享的全栈管理面板。它负责用户、套餐、订单、支付、订阅、工单、邮件、公告、审计、探测展示与订阅风控节点实际运行、入站协议、Xray 客户端配置由 3x-ui 维护
## 架构
J-Board 的定位很明确:它不是新的节点控制面,也不替代 3x-ui。它把售卖、开通、订阅交付、售后和风险审查做成一个完整面板并通过只读 Agent 从节点侧采集延迟、路由和 Xray access log 证据。
## 快速认识
```text
用户浏览器
用户浏览器 / 客户端订阅
Next.js App Router 面板
├─ PostgreSQL / Redis
├─ 3x-ui API同步入站、开通/暂停/删除客户端
Probe API接收 jboard-agent 的延迟与路由上报
├─ PostgreSQL:用户、订单、套餐、订阅、审计、风控事件
├─ Redis限流、后台任务与缓存辅助
3x-ui API同步入站、开通/暂停/删除代理客户端
└─ Agent API接收 jboard-agent 上报的延迟、路由、节点真实连接日志
节点 VPS
├─ 3x-ui / Xray真实入站、客户端、流量限制与代理运行
└─ jboard-agent旁路只读探测与日志聚合不修改 3x-ui 配置
```
J-Board 只保存售卖和展示需的节点、入站、客户端镜像数据,不下发 Xray/Hy2 配置,也不维护自建节点控制面
J-Board 只保存售卖和展示需的节点镜像数据。入站协议、端口、Reality/TLS、Xray 运行状态和客户端真实配置仍以 3x-ui 为准
## 功能
## 功能概览
用户端:
- 注册、登录、Cloudflare Turnstile 人机验证
- 代理套餐与流媒体套餐购买、续费、增流量
- 线路体验:三网延迟、延迟历史、三网路由追踪详情
- 代理订阅查看、订阅链接下载、订阅访问重置
- 流媒体订阅查看与凭据展示
- 通知中心、工单售后、账号资料、邀请码
- 响应式移动端适配
- 注册、登录、邮箱验证、忘记密码、邮箱变更验证
- 支持 Cloudflare Turnstile 人机验证。
- 代理套餐和流媒体套餐购买、续费、增流量。
- 购物车、订单、支付状态查询和支付方式切换。
- 代理订阅查看、订阅链接下载、订阅访问重置。
- 线路体验展示:三网延迟、延迟历史、三网路由追踪。
- 流媒体订阅凭据展示。
- 通知中心、工单售后、账号资料、邀请码。
- 暗色/夜间模式和移动端适配。
管理端:
- 3x-ui 节点管理:保存面板地址、账号、密码,测试连接并同步入站
- 本地入站展示名维护,套餐绑定同步后的入站线路
- 探测 Token 管理:用于 `/api/agent/latency``/api/agent/trace`
- 用户、订单、套餐、订阅、流媒体服务、支付配置
- 公告、工单、系统设置、审计日志、任务中心、备份恢复
- 流量视图:基于本地订阅与 3x-ui 同步结果展示客户端用量
- 3x-ui 节点管理:保存面板地址、账号、密码,测试连接并同步入站
- 本地入站展示名维护,套餐绑定同步后的入站线路
- 探测 Token 管理:用于 Agent 上报延迟、路由和节点日志。
- 用户、订单、套餐、订阅、流媒体服务、支付配置
- SMTP 邮件服务设置、注册邮箱验证开关、邮件模板发送。
- 公告、工单、系统设置、审计日志、任务中心、备份恢复。
- 支持工单上限配置,默认每个用户最多开启 2 个未关闭工单。
- 流量视图:基于本地订阅与 3x-ui 同步结果展示客户端用量。
- 订阅访问风控IP、城市、省/地区、国家变化审查。
- 节点日志风控:基于 Xray access log 分析真实来源 IP、连接数、不同目标数。
- 风控人工处理查看用户、订阅、地图、IP、分析日志生成风险报告选择解除限制或保持封禁/暂停。
节点侧:
- 3x-ui 负责入站、客户端、协议配置和节点运行
- J-Board 通过 3x-ui API 同步入站并执行客户端增删改
- `agent/jboard-agent` 负责三网 TCP 延迟三网路由追踪
- 3x-ui 负责入站、客户端、协议配置和节点运行
- J-Board 通过 3x-ui API 同步入站并执行客户端增删改
- `agent/jboard-agent` 负责三网 TCP 延迟三网路由追踪和可选 Xray access log 风控上报。
- Agent 只读日志文件,不重启 Xray不修改 3x-ui 配置。
## 核心流程
## 版本与发布规则
节点接入:
J-Board 面板和 Agent 使用相对独立的版本节奏。
1. 管理员在 3x-ui 中创建真实入站
2. 管理员在 J-Board 添加节点并填写 3x-ui 面板地址、用户名、密码
3. J-Board 登录 3x-ui读取入站列表并写入 `NodeInbound`
4. 管理员将套餐绑定到已同步入站
5. 用户购买代理套餐后J-Board 调用 3x-ui API 创建客户端,并保存 `NodeClient`
6. 订阅暂停、恢复、删除、重置访问时,同步调用 3x-ui API 更新客户端。
- 面板代码变更可以只提交到 `main`,不一定创建 GitHub Release
- Agent 二进制发生变化时,才需要升级 Agent 版本、打 tag、创建 Release并上传 `jboard-agent-linux-amd64``jboard-agent-linux-arm64``SHA256SUMS`
- Agent 安装/升级脚本默认下载 GitHub 最新 Release 中的 Agent 产物
- 不要为了普通网站页面或后台文案改动强行更新 Agent tag
支付开通:
1. 用户选择套餐、入站和流量规格并创建订单。
2. 支付平台回调后,`src/services/payment/process.ts` 标记订单已支付。
3. `src/services/provision.ts` 创建或更新 `UserSubscription`
4. 代理订阅通过 `src/services/node-panel` 调用 3x-ui 创建或更新客户端。
5. 流媒体订阅分配 `StreamingSlot`
探测上报:
1. 管理员为节点生成探测 Token。
2. 节点运行 `agent/jboard-agent`,配置 `SERVER_URL``AUTH_TOKEN`
3. 探测程序定时调用 `POST /api/agent/latency``POST /api/agent/trace`
4. J-Board 按 Token 匹配节点并更新延迟、历史和路由数据。
当前项目版本写在 `package.json`Agent 运行时版本写在 `agent/jboard-agent/cmd/agent/main.go`Agent 构建版本写在 `agent/jboard-agent/Makefile`
## 技术栈
- Next.js 16 App Router + React 19
- Prisma 7 + PostgreSQL 16
- NextAuth 4 Credentials + Cloudflare Turnstile
- NextAuth 4 Credentials
- Redis 7
- Tailwind CSS 4 + Base UI + Sonner + Recharts
- Go probe agent
- Nodemailer SMTP 邮件
- MaxMind MMDB GeoIP
- Go jboard-agent
- Docker / Docker Compose
## 目录
注意:本项目使用的 Next.js 版本包含和旧版本不同的约定。开发前请阅读 `AGENTS.md`,并按 `node_modules/next/dist/docs/` 中的当前文档实现。
- `src/app`页面、布局、Route Handlers
- `src/actions`Server Actions负责写操作、权限校验、审计和缓存刷新
- `src/services`:领域服务与第三方适配
- `src/services/node-panel`3x-ui 面板适配层
- `src/services/provision.ts`:支付成功后的订阅开通与 3x-ui 客户端同步
- `src/services/subscription.ts`:订阅内容生成
- `src/lib`Prisma、鉴权、加密、Turnstile、通用工具
- `prisma/schema.prisma`:数据模型事实源
- `agent/jboard-agent`:延迟与线路探测程序
- `docs/API.md`HTTP 接口与 Server Actions 参考
- `docs/openapi.yaml`:对外 HTTP 接口的 OpenAPI 描述
## 目录结构
| 路径 | 说明 |
| --- | --- |
| `src/app` | 页面、布局、Route Handlers。 |
| `src/actions` | Server Actions负责写操作、权限校验、审计和缓存刷新。 |
| `src/services` | 领域服务与第三方适配。 |
| `src/services/node-panel` | 3x-ui 面板适配层。 |
| `src/services/provision.ts` | 支付成功后的订阅开通与 3x-ui 客户端同步。 |
| `src/services/subscription-risk.ts` | 订阅访问与节点日志风控判定。 |
| `src/services/subscription-risk-review.ts` | 风控事件证据整理、报告生成辅助。 |
| `src/lib` | Prisma、鉴权、加密、Turnstile、GeoIP、工具函数。 |
| `prisma/schema.prisma` | 数据模型事实源。 |
| `data/GeoLite2-City.mmdb` | 默认 GeoIP 城市库。 |
| `agent/jboard-agent` | Go Agent 源码、构建脚本和 Agent 文档。 |
| `scripts/install-jboard-panel.sh` | 面板一键安装向导。 |
| `scripts/upgrade-jboard-panel.sh` | 面板升级脚本。 |
| `scripts/install-jboard-agent.sh` | Agent 安装脚本。 |
| `scripts/upgrade-jboard-agent.sh` | Agent 升级脚本。 |
| `docs/API.md` | HTTP 接口与 Server Actions 参考。 |
| `docs/openapi.yaml` | 对外 HTTP 接口 OpenAPI 描述。 |
## 环境变量
`.env.example` 为准。生产部署推荐直接使用一键脚本生成 `.env`,手动配置时重点确认这些值:
`.env.example` 为准。生产部署推荐使用一键脚本生成 `.env`,手动配置时重点确认下列变量。
| 变量 | 用途 | 说明 |
| --- | --- | --- |
| `APP_PORT` | 面板监听端口 | 默认 `3000`。反向代理应转发到 `http://127.0.0.1:APP_PORT`。 |
| `SITE_NAME` | 站点名称 | 初始化系统设置和邮件模板会使用。 |
| `NEXTAUTH_URL` | 网站访问地址 | 必须填写准备反代到面板的正式域名,例如 `https://panel.example.com`。不要填容器内地址。 |
| `SUBSCRIPTION_URL` | 订阅访问地址 | 可选。用于生成客户端订阅链接,例如 `https://sub.example.com`;留空时复用 `NEXTAUTH_URL`如果使用独立订阅域名,也要反代到同一个面板服务。 |
| `NEXTAUTH_URL` | 网站访问地址 | 必须填写准备反代到面板的正式域名,例如 `https://panel.example.com`。不要填 `localhost`、容器名或内网地址。 |
| `SUBSCRIPTION_URL` | 订阅访问地址 | 可选。用于生成客户端订阅链接,例如 `https://sub.example.com`;留空时复用 `NEXTAUTH_URL`。 |
| `NEXTAUTH_SECRET` | 登录会话密钥 | 生产环境必须使用随机长字符串。 |
| `ENCRYPTION_KEY` | 敏感信息加密密钥 | 至少 32 字节。生产使用后不要更换,否则 3x-ui 密码、探测 Token、流媒体凭据等已加密数据会无法解密。 |
| `ENCRYPTION_KEY` | 敏感信息加密密钥 | 至少 32 字节。生产使用后不要更换,否则 3x-ui 密码、探测 Token、SMTP 密码、流媒体凭据等已加密数据会无法解密。 |
| `DATABASE_URL` | PostgreSQL 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内数据库地址。 |
| `POSTGRES_PASSWORD` | Docker PostgreSQL 密码 | 一键脚本会自动生成。 |
| `REDIS_URL` | Redis 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内 Redis 地址。 |
| `GEOIP_MMDB_PATH` | GeoIP 城市库 | 默认 `data/GeoLite2-City.mmdb`。可换成自己的 MaxMind City MMDB。 |
| `ADMIN_EMAIL` / `ADMIN_PASSWORD` / `ADMIN_NAME` | 初始管理员 | 首次 `db:seed` 创建管理员账号。已有数据库不会强制重置旧管理员密码。 |
SMTP 邮件服务、注册邮箱验证开关、支付方式、3x-ui 节点等业务配置在管理后台填写,不建议写进 `.env`
SMTP 邮件服务、注册邮箱验证开关、支付方式、3x-ui 节点等业务配置在管理后台填写,不建议写进 `.env`
## 本地开发
## 一键部署
适合全新 Linux 服务器。脚本会安装基础依赖、安装 Docker 与 Compose 插件、拉取代码、生成 `.env`、初始化数据库并启动面板。
```bash
npm install
cp .env.example .env
npm run db:push
npm run db:seed
npm run dev
bash <(curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-panel.sh)
```
默认管理员账号
脚本会交互询问
- 邮箱:`admin@jboard.local`
- 密码:`admin123`
常用检查:
```bash
npx prisma generate
npx tsc --noEmit
npm run lint
npm run build
```
数据库变更:
- 修改 `prisma/schema.prisma` 后运行 `npx prisma generate`
- 使用 `npm run db:push` 同步 schema 到数据库
- 不维护 Prisma migrations不提交迁移脚本
- 删除字段或模型时同步清理引用、文档和导出逻辑
## 部署
### 一键部署(推荐)
适合全新的 Linux 服务器。脚本会自动安装 Docker 与 Compose 插件,拉取代码,询问并生成 `.env`,初始化数据库,启动面板,最后输出访问地址、反代目标和管理员账号。
```bash
curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-panel.sh | bash
```
脚本会询问这些信息;直接回车即可使用默认值或自动生成值:
| 提示项 | 含义 |
| 问题 | 如何填写 |
| --- | --- |
| 安装目录 | 默认 `/opt/jboard`;如果在仓库内运行脚本则默认当前仓库。 |
| 站点名称 | 面板标题、邮件模板和初始化系统设置会使用。 |
| 网站访问地址 | 你准备反向代理到本机 `3000` 端口的面板域名,例如 `https://panel.example.com`。没有域名时可先用 `http://服务器IP:3000` 测试。 |
| 订阅访问地址 | 用于生成 Clash/V2rayN/Shadowrocket 等客户端订阅链接。可与网站访问地址相同,也可填独立订阅域名,例如 `https://sub.example.com`。 |
| 本机监听端口 | 默认 `3000`Nginx/Caddy/宝塔反代目标就是 `http://127.0.0.1:3000`。 |
| 订阅访问地址 | 用于生成 Clash/V2rayN/Shadowrocket 等客户端订阅链接。可以和网站地址相同,也可填独立订阅域名,例如 `https://sub.example.com`。 |
| 本机监听端口 | 默认 `3000`NginxCaddy宝塔或 1Panel 的反代目标就是 `http://127.0.0.1:3000`。 |
| 管理员邮箱和密码 | 首次初始化会创建该管理员,脚本完成后会再次打印。 |
| PostgreSQL 密码、`NEXTAUTH_SECRET``ENCRYPTION_KEY` | 可手动输入;回车会自动生成安全值。 |
也可以环境变量覆盖默认行为:
也可以通过环境变量覆盖默认行为:
```bash
APP_DIR=/opt/jboard GH_REPO=JetSprow/J-Board BRANCH=main bash <(curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/install-jboard-panel.sh)
```
脚本完成后,你会看到类似信息
脚本完成后会输出
```text
访问地址https://panel.example.com
@@ -180,39 +160,9 @@ APP_DIR=/opt/jboard GH_REPO=JetSprow/J-Board BRANCH=main bash <(curl -fsSL https
管理员密码:自动生成或你输入的密码
```
### 反向代理
请把管理员密码保存到密码管理器。已有数据库重复部署时,脚本会尽量沿用现有配置,不会随意重置管理员。
`NEXTAUTH_URL` 和后台“系统设置 -> 网站 URL”都应该填写面板公网域名也就是你准备给用户访问、并反向代理到 J-Board 的域名。不要填写 `localhost`、容器名或内网地址。
`SUBSCRIPTION_URL` 和后台“系统设置 -> 订阅 URL”只用于生成客户端订阅链接。它可以和网站 URL 相同;如果你想单独做 Cloudflare/WAF/访问风控,建议使用 `https://sub.example.com` 这类独立域名,并把它也反向代理到同一个 J-Board 服务。独立订阅域名只需要承载 `/api/subscription/*`,后续可以在反代或 WAF 层对其他路径返回 404。
Nginx 示例:
```nginx
server {
listen 80;
server_name panel.example.com sub.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
正式上线建议再用 Certbot、宝塔、1Panel、Caddy 或 CDN 申请 HTTPS 证书,然后把 `NEXTAUTH_URL` 改为 `https://panel.example.com`。如果单独使用订阅域名,把 `SUBSCRIPTION_URL` 或后台订阅 URL 改为 `https://sub.example.com`
订阅域名套 Cloudflare 时,源站应只允许 Cloudflare 回源或通过 Cloudflare Tunnel 暴露服务,并正确传递 `CF-Connecting-IP` / `X-Forwarded-For`。否则后续订阅访问风控中的真实 IP 可能被直连源站请求伪造。
J-Board 会记录订阅 API 的真实 IP、User-Agent 和可用的地理位置头,并按后台“系统设置 -> 订阅访问风控”配置执行限流、跨城市/省份告警与自动暂停。默认规则保持为24 小时内 4 个城市警告、5 个城市暂停2 个省/地区警告、3 个省/地区暂停2 个国家/地区警告、3 个国家/地区暂停IP 180 次/小时、订阅 60 次/小时。管理员可以关闭风控总控或关闭自动暂停改为只记录警告也可以在后台“订阅风控”查看关联用户、订阅、IP、地区统计并将事件标记为待处理、已确认或已解决必要时可人工恢复被暂停的订阅。项目内置 `data/GeoLite2-City.mmdb` 作为本地 GeoIP 城市库,默认通过 `GEOIP_MMDB_PATH=data/GeoLite2-City.mmdb` 读取;如果反代或 CDN 已传地理位置头,系统优先使用请求头,并用 MMDB 补齐缺失字段。Cloudflare 场景建议在 Rules -> Settings -> Managed Transforms 开启 Add visitor location headers让回源请求带上 `cf-ipcity``cf-region``cf-region-code` 等字段;未提供城市/省份字段且 MMDB 不可用时,系统只记录 IP不会触发地区变化规则。
### 手动 Docker 部署
## 手动 Docker 部署
首次启动:
@@ -241,21 +191,53 @@ docker compose up -d app
常用排障:
- 查看状态:`docker compose ps`
- 查看日志:`docker compose logs -f app`
- 页面仍是旧版本:确认已执行 `docker compose build init app``docker compose up -d app`
- Schema 没有生效:单独运行 `docker compose --profile setup run --rm init sh -lc 'npm run db:push'`
- 登录回调、邮件链接或支付回跳出现 `localhost`:检查 `.env` 里的 `NEXTAUTH_URL` 和后台系统设置里的网站 URL。
- 订阅链接仍然使用主站域名:检查 `.env` 里的 `SUBSCRIPTION_URL` 或后台系统设置里的订阅 URL后台配置优先于环境变量。
```bash
docker compose ps
docker compose logs -f app
docker compose --profile setup run --rm init sh -lc 'npm run db:push'
```
### 部署后检查清单
如果页面仍是旧版本,确认已执行 `docker compose build init app``docker compose up -d app`。如果 schema 没生效,单独运行 `npm run db:push` 对应的 setup 命令。
1. 登录 `/admin`,进入“系统设置”,确认网站 URL 是面板反代域名,订阅 URL 是你准备给客户端拉取订阅的域名。
2. 配置 SMTP 邮件服务并点击“测试”,再按需要开启注册邮箱验证。
3. 进入“支付配置”,填写并启用至少一种支付方式
4. 添加 3x-ui 节点,测试连接并同步入站。
5. 创建套餐,绑定入站或流媒体服务。
6. 用普通用户注册、下单、支付、查看订阅,走一遍完整流程。
## 反向代理与域名
`NEXTAUTH_URL` 和后台“系统设置 -> 网站 URL”都应该填写面板公网域名也就是给用户访问、并反向代理到 J-Board 的域名。不要填写 `localhost`、容器名或内网地址,否则登录回调、邮件链接、支付回跳和退出登录提示可能出现错误地址
`SUBSCRIPTION_URL` 和后台“系统设置 -> 订阅 URL”只用于生成客户端订阅链接。它可以和网站 URL 相同;如果希望单独做 Cloudflare/WAF/访问风控,建议使用独立订阅域名,例如 `https://sub.example.com`,并把它也反向代理到同一个 J-Board 服务。
Nginx 示例:
```nginx
server {
listen 80;
server_name panel.example.com sub.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
正式上线建议使用 Certbot、宝塔、1Panel、Caddy 或 CDN 配置 HTTPS。订阅域名套 Cloudflare 时,源站建议只允许 Cloudflare 回源或通过 Cloudflare Tunnel 暴露,并正确传递 `CF-Connecting-IP` / `X-Forwarded-For`。如果源站允许绕过 Cloudflare 直连,订阅访问风控中的真实 IP 可能被伪造。
## 后台初始化清单
1. 登录 `/admin`,进入“系统设置”,确认网站 URL 和订阅 URL。
2. 配置 SMTP 邮件服务并点击“测试发信”。
3. 按需要开启注册邮箱验证。忘记密码和邮箱变更也会使用 SMTP。
4. 进入“支付配置”,填写并启用至少一种支付方式。
5. 添加 3x-ui 节点,测试连接并同步入站。
6. 创建代理套餐,绑定入站;或创建流媒体服务和套餐。
7. 在节点页生成探测 Token安装 Agent。
8. 用普通用户注册、下单、支付、查看订阅,走一遍完整流程。
9. 进入“订阅风控”确认地图、IP、分析日志、人工操作按钮都能正常展示。
可以展示给用户的常用入口:
@@ -264,10 +246,23 @@ docker compose up -d app
- 套餐商店:`https://你的域名/store`
- 用户中心:`https://你的域名/dashboard`
- 订阅列表:`https://你的域名/subscriptions`
- 工单中心:`https://你的域名/support`
## 邮件与邮箱验证
SMTP 配置在后台“系统设置”中完成,密码会加密保存在数据库中。支持的邮件场景包括:
- 注册邮箱验证,可由管理员开启或关闭。
- 忘记密码重置链接。
- 修改邮箱验证。
- 管理员测试发信。
- 风控报告发送和通知辅助。
建议使用专用发信邮箱或应用专用密码。Gmail、企业邮箱和大多数 SMTP 服务都可以使用 `host + port + user + password + from` 的方式接入。生产环境请优先使用 587 STARTTLS 或服务商推荐端口。
## 支付配置
支付配置在后台 `/admin/payments` 完成,密钥会保存在数据库中,不写入 `.env`,也不要提交到仓库或截图外传。创建订单时,系统会根据用户选择的支付方式生成支付链接、二维码或链上收款信息;支付成功后进入 `src/services/payment/process.ts` 完成订单确认和订阅开通。
支付配置在后台 `/admin/payments` 完成,密钥会加密保存在数据库中,不写入 `.env`,也不要提交到仓库或截图外传。创建订单时,系统会根据用户选择的支付方式生成支付链接、二维码或链上收款信息;支付成功后进入 `src/services/payment/process.ts` 完成订单确认和订阅开通。
| 支付方式 | 适用场景 | 必填信息 | 回调 / 查询说明 |
| --- | --- | --- | --- |
@@ -277,21 +272,54 @@ docker compose up -d app
支付上线前建议:
- 在支付平台后台把通知域名、回跳域名、应用网关白名单设置为你的公网域名。
- 在支付平台后台把通知域名、回跳域名、应用网关白名单设置为公网域名。
- 先创建低金额测试套餐,确认“创建订单 -> 支付 -> 回调/查询 -> 自动开通订阅”完整可用。
- 易支付 API 地址不要带尾部路径,例如填 `https://pay.example.com`,系统会自动请求 `/mapi.php``/submit.php``/api.php`
- 易支付 API 地址不要带尾部路径,例如填 `https://pay.example.com`,系统会自动请求 `/mapi.php``/submit.php``/api.php`
- 支付宝密钥可以填写纯 key 内容或 PEM 格式;系统会自动补 PEM 包装。
- USDT TRC20 按金额匹配入账,测试时避免短时间出现多笔完全相同金额。
## 节点与探测
## 节点、3x-ui 与 Agent
节点接入流程:
1. 在 VPS 安装并配置 3x-ui确认面板 API 可访问。
2. 管理后台添加 3x-ui 节点
3. 保存后 J-Board 会登录 3x-ui 并同步入站
4. 在代理套餐中绑定已同步入站
5. 如需前台展示延迟/线路,点击“生成探测 Token”复制弹窗里的一键安装命令到节点执行
2. 3x-ui 中创建真实入站
3. 管理后台添加 3x-ui 节点,填写面板地址、用户名和密码
4. 保存后 J-Board 会登录 3x-ui 并同步入站到 `NodeInbound`
5. 在代理套餐中绑定已同步入站
6. 用户购买代理套餐后J-Board 调用 3x-ui API 创建客户端,并保存 `NodeClient`
7. 订阅暂停、恢复、删除、重置访问时,同步调用 3x-ui API 更新客户端。
8. 如需前台展示延迟、线路和节点日志风控,点击“生成探测 Token”复制一键安装命令到节点执行。
探测程序也可手动运行
Agent 安装脚本会
- 下载 GitHub Release 中对应架构的 Agent 二进制。
- 安装或复用 `nexttrace`
- 自动查找 `/usr/local/x-ui/access.log` 等常见 Xray access log 路径。
- 创建 `/var/lib/jboard-agent``/var/log/jboard`
- 尝试让 Agent 具有 access log 读取权限。
- 写入 `/etc/jboard-agent.env`
- 停用并移除旧的 Agent systemd 服务,避免冲突。
- 写入并启动 `jboard-agent.service`
节点机常用命令:
```bash
systemctl status jboard-agent --no-pager -l
journalctl -u jboard-agent -n 100 --no-pager
journalctl -u jboard-agent -f --no-pager
journalctl -u jboard-agent -f --no-pager | grep --line-buffered xray-log
cat /etc/jboard-agent.env
cat /var/lib/jboard-agent/xray-log-state.json
```
升级 Agent
```bash
curl -fsSL https://raw.githubusercontent.com/JetSprow/J-Board/main/scripts/upgrade-jboard-agent.sh | bash
```
如果只想手动运行 Agent
```bash
SERVER_URL=https://your-domain.com \
@@ -299,14 +327,63 @@ AUTH_TOKEN=后台生成的探测Token \
./jboard-agent
```
可选变量:
更多 Agent 说明见 `agent/jboard-agent/README.md`
- `LATENCY_INTERVAL`:默认 `5m`
- `TRACE_INTERVAL`:默认 `30m`
## 订阅访问风控
路由探测依赖 `nexttrace`。没有该命令时,延迟探测仍可运行,路由探测会记录错误日志
J-Board 的订阅风控分两层
## 备份与安全
第一层是订阅 API 访问风控。用户或客户端拉取 `/api/subscription/*` 时,系统记录真实 IP、User-Agent、国家、省/地区、城市、经纬度,并按后台配置判断:
- 单 IP 每小时访问次数。
- 单订阅 token 每小时访问次数。
- 24 小时窗口内不同城市数量。
- 24 小时窗口内不同省/地区数量。
- 24 小时窗口内不同国家/地区数量。
第二层是节点真实连接风控。Agent 读取 Xray access log将日志里的 `email: user@example.com-xxxx` 匹配到本地 `NodeClient.email`,再归属到用户和订阅。系统记录:
- 真实来源 IP。
- 真实来源 IP 的 GeoIP。
- 入站 tag。
- tcp/udp。
- 样本目标域名或 IP。
- 目标端口。
- 聚合窗口内连接数。
- 聚合窗口内不同目标数。
- 首次和最近连接时间。
管理员可在“系统设置 -> 订阅访问风控”中配置总开关、自动暂停开关、窗口时长、城市/省/国家阈值、IP/订阅访问频率阈值,以及节点日志风控中的连接数和不同目标数阈值。
默认规则保持为:
- 24 小时内 4 个城市警告5 个城市暂停。
- 2 个省/地区警告3 个省/地区暂停。
- 2 个国家/地区警告3 个国家/地区暂停。
- IP 180 次/小时,订阅 60 次/小时。
- 节点日志风控默认开启,连接数和不同目标数按 Agent 单次聚合窗口计算。
风控事件会进入后台“订阅风控”。管理员可以:
- 查看关联用户和订阅详情。
- 查看 IP、国家、省/地区、城市统计。
- 在世界地图上查看可识别坐标点。
- 展开分析日志,看到每条证据的 IP、时间、来源、Xray 解析详情、连接数和不同目标数。
- 生成风险报告。
- 选择是否发送到用户端。
- 解除限制或保持封禁/暂停。
用户收到管理员发送的风险报告后,会看到全屏不可关闭的限制通知,只能新建工单联系客服,不能继续进行其他用户端操作。
## GeoIP 与 Cloudflare
项目内置 `data/GeoLite2-City.mmdb` 作为本地 GeoIP 城市库,默认通过 `GEOIP_MMDB_PATH=data/GeoLite2-City.mmdb` 读取。系统会优先使用反向代理或 CDN 提供的地理位置头,并用 MMDB 补齐缺失字段。
Cloudflare 场景建议在 Rules -> Settings -> Managed Transforms 开启 Add visitor location headers让回源请求带上 `cf-ipcity``cf-region``cf-region-code` 等字段。未提供城市/省份字段且 MMDB 不可用时,系统只记录 IP不会触发地区变化规则。
如果网站域名和订阅域名相同,系统只统计订阅 API 访问,不会把普通网站浏览计入订阅风控。
## 备份与恢复
下载 SQL 备份:
@@ -316,29 +393,113 @@ docker compose exec -T db pg_dump -U jboard jboard > backup_$(date +%Y%m%d_%H%M%
后台也可通过 `/admin/backups` 导出或恢复数据库。恢复前务必先保存当前数据库备份。
安全建议:
建议:
- 不要提交 `.env`、探测 Token、3x-ui 密码、支付密钥
- 数据库备份里包含用户、订单和支付配置,建议加密保存并限制下载权限
- 生产环境不要公开 PostgreSQL 和 Redis 端口
- 3x-ui 面板建议限制来源 IP 或使用反向代理鉴权
- `ENCRYPTION_KEY` 一旦生产使用不要随意更换,否则已加密数据会无法解密
- 定期备份 PostgreSQL volume。
- 将备份加密保存。
- 备份恢复后立即检查管理员登录、支付配置、节点密码、SMTP、订阅 URL 和 Agent 上报。
## 开发原则
## 本地开发
- 节点入站与客户端运行配置以 3x-ui 为准J-Board 只保存售卖镜像
- 后端只保留探测上报接口,不再新增节点控制面接口
- Server Actions 负责权限、校验、审计和缓存刷新
- Route Handlers 仅用于外部 HTTP 接口或文件下载
- 重要副作用必须记录审计日志或任务记录
```bash
npm install
cp .env.example .env
npm run db:push
npm run db:seed
npm run dev
```
默认管理员账号:
- 邮箱:`admin@jboard.local`
- 密码:`admin123`
常用检查:
```bash
npx prisma generate
npx tsc --noEmit
npm run lint
npm run build
```
数据库变更:
- 修改 `prisma/schema.prisma` 后运行 `npm run db:push`
- 生产 Docker 部署更新后,运行 `docker compose --profile setup run --rm init sh -lc 'npm run db:push'`
- 当前项目使用 `prisma db push --accept-data-loss`,上线前请确认 schema 变更不会误删重要数据。
Agent 开发:
```bash
cd agent/jboard-agent
go test ./...
make build-linux
shasum -a 256 jboard-agent-linux-amd64 jboard-agent-linux-arm64 > SHA256SUMS
```
## 安全建议
- 不要提交 `.env`、探测 Token、3x-ui 密码、SMTP 密码、支付密钥。
- 数据库备份包含用户、订单、支付配置、节点凭据和邮件配置,建议加密保存并限制下载权限。
- 生产环境不要公开 PostgreSQL 和 Redis 端口。
- 3x-ui 面板建议限制来源 IP 或使用反向代理鉴权。
- `ENCRYPTION_KEY` 一旦生产使用不要随意更换。
- 管理后台账号建议使用强密码和专用邮箱。
- 订阅域名套 CDN 时应避免源站裸露,否则真实 IP 风控可信度会下降。
- Agent 只读 Xray access log但日志中包含用户 IP、访问目标和 client email应按敏感数据处理。
## 常见问题
### 登录、退出或邮件链接出现 localhost
检查 `.env` 中的 `NEXTAUTH_URL` 和后台系统设置中的网站 URL。后台配置优先于环境变量。生产环境必须填写公网域名。
### 订阅链接使用了错误域名
检查 `.env` 中的 `SUBSCRIPTION_URL` 和后台系统设置中的订阅 URL。后台配置优先于环境变量。
### 点击测试发信报错
先确认 SMTP 是否启用、Host/Port/User/Password/From 是否正确。Gmail 等服务通常需要应用专用密码。生产环境隐藏原始异常时,可查看 `docker compose logs -f app`
### 用户不验证邮箱也能注册
确认后台“注册邮箱验证”已经开启,并检查 SMTP 是否启用。邮箱验证开启后,新用户会进入待验证状态,必须通过邮件链接激活。
### Agent 没有 xray-log 输出
先看 Agent 是否运行:
```bash
systemctl status jboard-agent --no-pager -l
journalctl -u jboard-agent -n 100 --no-pager
```
再确认 access log 状态:
```bash
cat /etc/jboard-agent.env | grep XRAY
cat /var/lib/jboard-agent/xray-log-state.json
tail -n 50 /usr/local/x-ui/access.log
grep "email:" /usr/local/x-ui/access.log | tail -n 20
```
Agent 默认 `XRAY_LOG_START_AT_END=1`,首次启动会从文件末尾开始,只分析启动后的新连接。需要真实客户端连接节点并产生带 `email:` 的 access log后台才会出现节点真实连接分析。
### Xray client email 带后缀是否有影响
没有影响。J-Board 用户邮箱可能是 `user@example.com`Xray client email 可能是 `user@example.com-cmojtnp3`。节点日志风控用 Xray access log 里的 client email 匹配本地 `NodeClient.email`,再找到真实用户和订阅。不要手动在 3x-ui 改 client email否则会导致日志无法归属。
## 文档
- `docs/API.md`HTTP 接口与 Server Actions 参考
- `docs/openapi.yaml`:对外 HTTP 接口 OpenAPI 3.1 描述
- `agent/jboard-agent/README.md`探测程序说明
- `docs/API.md`HTTP 接口与 Server Actions 参考
- `docs/openapi.yaml`:对外 HTTP 接口 OpenAPI 3.1 描述
- `agent/jboard-agent/README.md`Agent 安装、升级、日志与排障说明
- `AGENTS.md`:给代码协作 Agent 的仓库规则。
## 请我喝杯咖啡
![JsPYre9xe7W1Ad6mwPgrfuXBYJ8iy6oC.webp](https://cdn.nodeimage.com/i/XuxZ7NoLsc51fS99S6AtMB9K9ekTTQcD.webp)
USDT-TRC20: TQfaGEBdnB89V4y6R6bypZXx7Za5QfXBCi