Files
J-Board-Lite/README.md

347 lines
16 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.
# J-Board
J-Board也称 JB面板是一个面向代理订阅售卖与流媒体共享的全栈应用。节点运行、入站和客户端配置由 3x-ui 面板维护J-Board 负责售卖、订单、订阅、用户、支付、工单和探测展示;自带 Go 程序只做延迟与线路探测上报。
## 架构
```text
用户浏览器
Next.js App Router 面板
├─ PostgreSQL / Redis
├─ 3x-ui API同步入站、开通/暂停/删除客户端
└─ Probe API接收 jboard-agent 的延迟与路由上报
```
J-Board 只保存售卖和展示所需的节点、入站、客户端镜像数据,不下发 Xray/Hy2 配置,也不维护自建节点控制面。
## 功能
用户端:
- 注册、登录、Cloudflare Turnstile 人机验证
- 代理套餐与流媒体套餐购买、续费、增流量
- 线路体验:三网延迟、延迟历史、三网路由追踪详情
- 代理订阅查看、订阅链接下载、订阅访问重置
- 流媒体订阅查看与凭据展示
- 通知中心、工单售后、账号资料、邀请码
- 响应式移动端适配
管理端:
- 3x-ui 节点管理:保存面板地址、账号、密码,测试连接并同步入站
- 本地入站展示名称维护,套餐绑定同步后的入站线路
- 探测 Token 管理:仅用于 `/api/agent/latency``/api/agent/trace`
- 用户、订单、套餐、订阅、流媒体服务、支付配置
- 公告、工单、系统设置、审计日志、任务中心、备份恢复
- 流量视图:基于本地订阅与 3x-ui 同步结果展示客户端用量
节点侧:
- 3x-ui 负责入站、客户端、协议配置和节点运行
- J-Board 通过 3x-ui API 同步入站并执行客户端增删改
- `agent/jboard-agent` 只负责三网 TCP 延迟和三网路由追踪
## 核心流程
节点接入:
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 更新客户端。
支付开通:
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 匹配节点并更新延迟、历史和路由数据。
## 技术栈
- Next.js 16 App Router + React 19
- Prisma 7 + PostgreSQL 16
- NextAuth 4 Credentials + Cloudflare Turnstile
- Redis 7
- Tailwind CSS 4 + Base UI + Sonner + Recharts
- Go probe agent
- Docker / Docker Compose
## 目录
- `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 描述
## 环境变量
`.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_SECRET` | 登录会话密钥 | 生产环境必须使用随机长字符串。 |
| `ENCRYPTION_KEY` | 敏感信息加密密钥 | 至少 32 字节。生产使用后不要更换,否则 3x-ui 密码、探测 Token、流媒体凭据等已加密数据会无法解密。 |
| `DATABASE_URL` | PostgreSQL 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内数据库地址。 |
| `POSTGRES_PASSWORD` | Docker PostgreSQL 密码 | 一键脚本会自动生成。 |
| `REDIS_URL` | Redis 连接 | 本地工具使用Docker 部署时 Compose 会覆盖为容器内 Redis 地址。 |
| `ADMIN_EMAIL` / `ADMIN_PASSWORD` / `ADMIN_NAME` | 初始管理员 | 首次 `db:seed` 创建管理员账号。已有数据库不会强制重置旧管理员密码。 |
SMTP 邮件服务、注册邮箱验证开关、支付方式、3x-ui 节点等业务配置都在管理后台填写,不建议写进 `.env`
## 本地开发
```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` 后运行 `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`。 |
| 管理员邮箱和密码 | 首次初始化会创建该管理员,脚本完成后会再次打印。 |
| 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
订阅地址https://sub.example.com
反代目标http://127.0.0.1:3000
管理员邮箱admin@example.com
管理员密码:自动生成或你输入的密码
```
### 反向代理
`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 个省/地区暂停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 部署
首次启动:
```bash
cp .env.example .env
# 编辑 .env尤其是 NEXTAUTH_URL、SUBSCRIPTION_URL、NEXTAUTH_SECRET、ENCRYPTION_KEY、POSTGRES_PASSWORD、管理员账号
docker compose build init app
docker compose --profile setup run --rm init
docker compose up -d app
```
更新部署:
```bash
git pull --ff-only
docker compose build init app
docker compose --profile setup run --rm init sh -lc 'npm run db:push'
docker compose up -d app
```
仓库内也提供更新脚本:
```bash
./scripts/upgrade-jboard-panel.sh
```
常用排障:
- 查看状态:`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后台配置优先于环境变量。
### 部署后检查清单
1. 登录 `/admin`,进入“系统设置”,确认网站 URL 是面板反代域名,订阅 URL 是你准备给客户端拉取订阅的域名。
2. 配置 SMTP 邮件服务并点击“测试”,再按需要开启注册邮箱验证。
3. 进入“支付配置”,填写并启用至少一种支付方式。
4. 添加 3x-ui 节点,测试连接并同步入站。
5. 创建套餐,绑定入站或流媒体服务。
6. 用普通用户注册、下单、支付、查看订阅,走一遍完整流程。
可以展示给用户的常用入口:
- 登录:`https://你的域名/login`
- 注册:`https://你的域名/register`
- 套餐商店:`https://你的域名/store`
- 用户中心:`https://你的域名/dashboard`
- 订阅列表:`https://你的域名/subscriptions`
## 支付配置
支付配置在后台 `/admin/payments` 完成,密钥会保存在数据库中,不写入 `.env`,也不要提交到仓库或截图外传。创建订单时,系统会根据用户选择的支付方式生成支付链接、二维码或链上收款信息;支付成功后进入 `src/services/payment/process.ts` 完成订单确认和订阅开通。
| 支付方式 | 适用场景 | 必填信息 | 回调 / 查询说明 |
| --- | --- | --- | --- |
| 易支付 | 第三方聚合支付,常用于支付宝/微信通道 | API 地址、商户 ID、商户密钥、启用渠道 | 通知地址为 `https://你的域名/api/payment/notify/epay`。支持 `alipay``wxpay` 渠道。 |
| 支付宝当面付 | 支付宝官方扫码支付 | App ID、应用私钥、支付宝公钥、网关地址 | 通知地址为 `https://你的域名/api/payment/notify/alipay_f2f`,也支持订单查询兜底。 |
| USDT TRC20 | 加密货币收款 | TRC20 钱包地址、汇率,可选 TronGrid API Key | 没有传统回调,系统按订单金额查询近期 TRC20 入账。建议配置 TronGrid API Key 提高稳定性。 |
支付上线前建议:
- 在支付平台后台把通知域名、回跳域名、应用网关白名单都设置为你的公网域名。
- 先创建低金额测试套餐,确认“创建订单 -> 支付 -> 回调/查询 -> 自动开通订阅”完整可用。
- 易支付的 API 地址不要带尾部路径,例如填 `https://pay.example.com`,系统会自动请求 `/mapi.php``/submit.php``/api.php`
- 支付宝密钥可以填写纯 key 内容或 PEM 格式;系统会自动补 PEM 包装。
- USDT TRC20 按金额匹配入账,测试时避免短时间出现多笔完全相同金额。
## 节点与探测
1. 在 VPS 安装并配置 3x-ui确认面板 API 可访问。
2. 管理后台添加 3x-ui 节点。
3. 保存后 J-Board 会登录 3x-ui 并同步入站。
4. 在代理套餐中绑定已同步入站。
5. 如需前台展示延迟/线路,点击“生成探测 Token”复制弹窗里的一键安装命令到节点执行。
探测程序也可手动运行:
```bash
SERVER_URL=https://your-domain.com \
AUTH_TOKEN=后台生成的探测Token \
./jboard-agent
```
可选变量:
- `LATENCY_INTERVAL`:默认 `5m`
- `TRACE_INTERVAL`:默认 `30m`
路由探测依赖 `nexttrace`。没有该命令时,延迟探测仍可运行,路由探测会记录错误日志。
## 备份与安全
下载 SQL 备份:
```bash
docker compose exec -T db pg_dump -U jboard jboard > backup_$(date +%Y%m%d_%H%M%S).sql
```
后台也可通过 `/admin/backups` 导出或恢复数据库。恢复前务必先保存当前数据库备份。
安全建议:
- 不要提交 `.env`、探测 Token、3x-ui 密码、支付密钥
- 数据库备份里包含用户、订单和支付配置,建议加密保存并限制下载权限
- 生产环境不要公开 PostgreSQL 和 Redis 端口
- 3x-ui 面板建议限制来源 IP 或使用反向代理鉴权
- `ENCRYPTION_KEY` 一旦生产使用不要随意更换,否则已加密数据会无法解密
## 开发原则
- 节点入站与客户端运行配置以 3x-ui 为准J-Board 只保存售卖镜像
- 后端只保留探测上报接口,不再新增节点控制面接口
- Server Actions 负责权限、校验、审计和缓存刷新
- Route Handlers 仅用于外部 HTTP 接口或文件下载
- 重要副作用必须记录审计日志或任务记录
## 文档
- `docs/API.md`HTTP 接口与 Server Actions 参考
- `docs/openapi.yaml`:对外 HTTP 接口的 OpenAPI 3.1 描述
- `agent/jboard-agent/README.md`:探测程序说明
## 请我喝杯咖啡
![JsPYre9xe7W1Ad6mwPgrfuXBYJ8iy6oC.webp](https://cdn.nodeimage.com/i/XuxZ7NoLsc51fS99S6AtMB9K9ekTTQcD.webp)
USDT-TRC20: TQfaGEBdnB89V4y6R6bypZXx7Za5QfXBCi
Telegram[@JetSprow](https://t.me/JetSprow)