diff --git a/DEPLOY.md b/DEPLOY.md index 96857f4..022837f 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -1,10 +1,15 @@ -# openai_node · 生产部署文档 +# openai_node · 生产部署文档(Ubuntu) -本文说明如何在 **VPS** 上部署本网关,并通过 **宝塔面板** 反向代理、**frp** 汇聚多台本地 Ollama 节点。适用于当前推荐拓扑: +本文说明如何在 **Ubuntu VPS** 上以 **root** 用户部署本网关,安装目录 **`/opt/openai_node`**,并通过 **宝塔面板** 反向代理、**frp** 汇聚多台本地 Ollama 节点。 -- 网关监听:**8150** -- 宝塔反代:域名 → `127.0.0.1:8150` -- 各 PC 模型端口:**3313–3318**(frp 映射到 VPS 本机 `127.0.0.1`) +| 项 | 约定 | +|----|------| +| 系统 | Ubuntu 22.04 / 24.04 | +| 用户 | **root** | +| 安装路径 | **`/opt/openai_node`** | +| 网关端口 | **8150** | +| 宝塔反代 | 域名 → `http://127.0.0.1:8150` | +| 模型端口 | **3313–3318**(frp 映射到本机 `127.0.0.1`) | 代码仓库:[https://git.bz121.com/dekun/openai_node.git](https://git.bz121.com/dekun/openai_node.git) @@ -17,11 +22,11 @@ │ ▼ ┌─────────────────┐ - │ VPS │ + │ Ubuntu VPS │ │ 宝塔 Nginx:443 │ │ │ │ │ ▼ │ - │ openai_node │ + │ /opt/openai_node │ :8150 │ │ │ │ │ 127.0.0.1:3313 ├─── frp ─── PC1 Ollama :3313 @@ -32,7 +37,7 @@ 要点: -1. **不要**把 3313 等端口直接暴露到公网,仅 VPS 本机访问。 +1. **不要**把 3313 等端口直接暴露到公网,仅本机 `127.0.0.1` 访问。 2. **不要**让宝塔直接把域名反代到各 PC;应只反代到 **8150**,由网关按 `model` 调度。 3. `nodes.json` 里 `host` 填 **`127.0.0.1`**,`port` 填 frp 映射后的端口。 @@ -40,31 +45,56 @@ ## 2. 前置条件 +以 **root** 登录 VPS 后,安装基础组件: + +```bash +apt update +apt install -y python3 python3-venv python3-pip git curl +``` + | 组件 | 版本建议 | 用途 | |------|----------|------| -| Python | 3.10+ | 运行网关 | +| Python | 3.10+(`python3 -V` 确认) | 运行网关 | | Node.js | LTS | 安装 PM2 | | PM2 | 最新 | 进程守护 | | 宝塔 | 7.x+ | Nginx 反代、SSL | -| frp | 客户端 + 服务端 | 内网穿透(可用其它方案,原理相同) | +| frp | 客户端 + 服务端 | 内网穿透 | -各 PC 已安装 **Ollama** 并监听本地端口(如 3313),且与 VPS 网络可达(通过 frp)。 +安装 Node.js 与 PM2: + +```bash +curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - +apt install -y nodejs +npm install -g pm2 +``` + +各 PC 已安装 **Ollama** 并监听本地端口(如 3313),且通过 frp 与 VPS 连通。 --- -## 3. 在 VPS 上部署网关 +## 3. 部署网关到 /opt/openai_node + +以下命令均在 **root** 下执行。 ### 3.1 克隆代码 ```bash -cd /www/wwwroot # 按宝塔网站目录调整 +cd /opt git clone https://git.bz121.com/dekun/openai_node.git -cd openai_node +cd /opt/openai_node +``` + +若目录已存在,更新代码: + +```bash +cd /opt/openai_node +git pull ``` ### 3.2 虚拟环境与依赖 ```bash +cd /opt/openai_node python3 -m venv venv source venv/bin/activate pip install -r requirements.txt -U @@ -73,14 +103,15 @@ pip install -r requirements.txt -U ### 3.3 配置文件 ```bash +cd /opt/openai_node cp gateway.json.example gateway.json cp nodes.json.example nodes.json chmod 600 gateway.json nodes.json ``` -编辑 **`gateway.json`**:设置 `username`、`password`;`api_key` 可留空自动生成。 +编辑 **`/opt/openai_node/gateway.json`**:设置 `username`、`password`;`api_key` 可留空自动生成。 -编辑 **`nodes.json`**(示例三台): +编辑 **`/opt/openai_node/nodes.json`**(示例): ```json { @@ -102,82 +133,99 @@ chmod 600 gateway.json nodes.json `models[].id` 必须与 Ollama 模型名、API 请求中的 `model` **完全一致**。 -也可部署后浏览器打开 **系统设置** 页面维护(需先登录)。 +也可部署后浏览器打开 **系统设置** 维护(需先登录)。 ### 3.4 环境变量 +在 **`/opt/openai_node/ecosystem.config.cjs`** 的 `env` 中配置(推荐),或导出后启动: + | 变量 | 生产建议 | |------|----------| | `JWT_SECRET` | **必改**,长随机字符串 | -| `GATEWAY_PORT` | `8150`(与 PM2、宝塔一致) | +| `GATEWAY_PORT` | `8150` | 可选: | 变量 | 说明 | |------|------| -| `STATS_DB` | 统计库路径,默认 `gateway_stats.db` | -| `NODES_CONFIG` | 节点配置路径,默认 `nodes.json` | -| `UPSTREAM_URL` | 仅在没有配置 `nodes.json` 节点时作为单机上流 | +| `STATS_DB` | 默认 `/opt/openai_node/gateway_stats.db` | +| `NODES_CONFIG` | 默认 `/opt/openai_node/nodes.json` | +| `GATEWAY_CONFIG` | 默认 `/opt/openai_node/gateway.json` | ### 3.5 手动试跑 ```bash +cd /opt/openai_node +source venv/bin/activate export JWT_SECRET="你的随机密钥" python -m uvicorn main:app --host 0.0.0.0 --port 8150 ``` -确认: +另开终端确认: ```bash curl -s http://127.0.0.1:8150/api/models/cards | head curl -s http://127.0.0.1:3313/v1/models # frp 通了才有返回 ``` -浏览器访问 `http://VPS_IP:8150`,首页应出现模型卡片。 +浏览器访问 `http://VPS公网IP:8150`,首页应出现模型卡片。确认无误后 `Ctrl+C` 停止,改由 PM2 守护。 --- ## 4. PM2 守护 -项目已包含 **`ecosystem.config.cjs`**(端口 **8150**)。 +项目 **`/opt/openai_node/ecosystem.config.cjs`** 已配置端口 **8150** 与 venv 内 Python 路径。 ### 4.1 修改 PM2 配置 -编辑 `ecosystem.config.cjs` 中 `env.JWT_SECRET` 为生产密钥。 +```bash +nano /opt/openai_node/ecosystem.config.cjs +``` + +将 `env.JWT_SECRET` 改为生产密钥。 ### 4.2 启动 ```bash -cd /www/wwwroot/openai_node -source venv/bin/activate +cd /opt/openai_node pm2 start ecosystem.config.cjs pm2 save pm2 status ``` +应看到进程名 **`llm-gateway`** 为 `online`。 + 常用命令: | 命令 | 作用 | |------|------| | `pm2 logs llm-gateway` | 查看日志 | -| `pm2 restart llm-gateway` | 重启(改代码/配置后) | +| `pm2 restart llm-gateway` | 重启 | | `pm2 stop llm-gateway` | 停止 | 更新代码后: ```bash +cd /opt/openai_node git pull source venv/bin/activate pip install -r requirements.txt -U pm2 restart llm-gateway ``` -### 4.3 开机自启 +### 4.3 开机自启(root) ```bash pm2 save pm2 startup -# 按提示执行输出的 sudo 命令 +``` + +**root** 用户下,终端会打印一行命令(通常已含 `systemd` 配置),**直接复制执行**即可,一般无需再加 `sudo`。 + +验证: + +```bash +systemctl status pm2-root # 服务名以 pm2 实际输出为准 ``` --- @@ -186,7 +234,7 @@ pm2 startup ### 5.1 添加站点 -宝塔 → **网站** → 添加站点 → 绑定域名 → 申请 **SSL**(Let’s Encrypt)。 +宝塔 → **网站** → 添加站点 → 绑定域名 → 申请 **SSL**。 ### 5.2 反向代理到 8150 @@ -197,7 +245,7 @@ pm2 startup | 目标 URL | `http://127.0.0.1:8150` | | 发送域名 | `$host` | -在 **配置文件** 或「高级」中建议补充(流式 LLM 必备): +在 **配置文件** 中建议(流式 LLM 必备): ```nginx location / { @@ -213,36 +261,32 @@ location / { } ``` -说明: - -- `X-Forwarded-For` / `X-Real-IP` 用于网关 **流量统计** 记录真实客户端 IP。 -- `proxy_buffering off` 与长超时避免流式输出卡顿或中断。 - ### 5.3 验证 ```bash curl -I https://你的域名/ ``` -应返回 200。登录 Web → 首页查看模型卡片状态。 +登录 Web → 首页查看模型卡片。 --- ## 6. frp 多机穿透(示例) -以下为常见做法,按你实际 frp 版本调整。 +### 6.1 VPS(root)运行 frps -### 6.1 VPS 运行 frps - -`/etc/frp/frps.toml` 示例: +```bash +mkdir -p /etc/frp +nano /etc/frp/frps.toml +``` ```toml bindPort = 7000 ``` -### 6.2 各 PC 运行 frpc +按需配置 systemd 开机启动 frps。 -`/etc/frp/frpc.toml` 示例(书房电脑,本地 Ollama 3313): +### 6.2 各 PC 运行 frpc ```toml serverAddr = "VPS公网IP" @@ -256,7 +300,7 @@ localPort = 3313 remotePort = 3313 ``` -其它电脑分别映射 **3314、3315** … 到 VPS 的 **3314、3315**。 +其它电脑映射 **3314、3315** … ### 6.3 在 VPS 上验证 @@ -265,15 +309,15 @@ curl http://127.0.0.1:3313/v1/models curl http://127.0.0.1:3314/v1/models ``` -均正常后,在 Web **系统设置** 中为对应节点点击 **测试**,或等待首页健康检查(约 30 秒)变为 **空闲**。 +Web **系统设置** 中点击 **测试**,或等待首页健康检查(约 30 秒)。 --- ## 7. Ollama 侧注意 -1. Ollama 需监听 `0.0.0.0` 或 frp 能访问的地址(仅内网/frp,勿公网裸露)。 -2. API 请求中的 `model` 使用 `ollama list` 中的名称,与 `nodes.json` 一致。 -3. 流式统计 Token 依赖响应中的 `usage`;可在请求中加 OpenAI 兼容参数(若上游支持): +1. Ollama 监听地址需能被 frp 访问(勿将模型端口裸露公网)。 +2. API 中 `model` 与 `nodes.json` / `ollama list` 名称一致。 +3. 流式 Token 统计(可选): ```json "stream_options": { "include_usage": true } @@ -286,9 +330,7 @@ curl http://127.0.0.1:3314/v1/models | 项 | 值 | |----|-----| | Base URL | `https://你的域名/v1` | -| API Key | `gateway.json` 的 `api_key` 或用户中心复制 | - -示例: +| API Key | `/opt/openai_node/gateway.json` 或用户中心复制 | ```bash curl https://你的域名/v1/chat/completions \ @@ -303,12 +345,12 @@ curl https://你的域名/v1/chat/completions \ | 路径 | 说明 | 备份 | |------|------|------| -| `gateway.json` | 账号、API Key | 建议 | -| `nodes.json` | 节点与模型 | 建议 | -| `gateway_stats.db` | 访问与 Token 统计 | 可选 | -| `~/.pm2/logs/` | PM2 日志 | 按需 | +| `/opt/openai_node/gateway.json` | 账号、API Key | 建议 | +| `/opt/openai_node/nodes.json` | 节点与模型 | 建议 | +| `/opt/openai_node/gateway_stats.db` | 访问与 Token 统计 | 可选 | +| `/root/.pm2/logs/` | PM2 日志 | 按需 | -修改 `nodes.json` 或 Web 设置后,**PM2 会自动读入**(`save_nodes_config` 热加载);若仅改环境变量需 `pm2 restart`。 +Web 保存节点配置会写入 `nodes.json` 并热加载;仅改 `ecosystem.config.cjs` 环境变量时需 `pm2 restart llm-gateway`。 --- @@ -316,28 +358,29 @@ curl https://你的域名/v1/chat/completions \ | 现象 | 排查 | |------|------| -| 首页卡片 **离线** | VPS 上 `curl 127.0.0.1:端口/v1/models`;检查 frp、Ollama 是否启动 | -| **404 未找到模型** | 请求 `model` 与 `nodes.json` 中 `models[].id` 不一致 | -| **502 上游连接失败** | 端口错、frp 断、防火墙;`pm2 logs llm-gateway` | -| 统计 IP 全是 VPS | 宝塔未传 `X-Forwarded-For`,见 §5.2 | -| Token 始终为 0 | 上游未返回 `usage`;流式需 `include_usage` | -| 改 `JWT_SECRET` 后无法进设置 | 重新登录 Web | +| 首页卡片 **离线** | `curl http://127.0.0.1:端口/v1/models`;frp、Ollama | +| **404 未找到模型** | 请求 `model` 与 `nodes.json` 中 `id` 不一致 | +| **502 上游连接失败** | `pm2 logs llm-gateway`;端口与 frp | +| 统计 IP 不对 | 宝塔是否传递 `X-Forwarded-For`(§5.2) | +| Token 为 0 | 上游 `usage`;流式 `include_usage` | +| PM2 找不到模块 | 确认使用 `/opt/openai_node/venv` 内 Python | --- ## 11. 部署检查清单 -- [ ] `gateway.json`、`nodes.json` 已配置且权限 `600` -- [ ] `JWT_SECRET` 已修改 -- [ ] PM2 进程 `llm-gateway` 在线,端口 **8150** -- [ ] 宝塔 HTTPS 反代到 `127.0.0.1:8150`,流式相关 Nginx 参数已加 -- [ ] frp 映射 3313+ 在 VPS 本机 `curl` 通过 -- [ ] 首页模型卡片状态为 **空闲** 或 **忙碌**(非长期离线) -- [ ] API 试调用成功,`/stats` 有记录 +- [ ] 以 **root** 部署,代码在 **`/opt/openai_node`** +- [ ] `gateway.json`、`nodes.json` 已配置,`chmod 600` +- [ ] `JWT_SECRET` 已在 `ecosystem.config.cjs` 中修改 +- [ ] `pm2 status` 中 **llm-gateway** 在线,监听 **8150** +- [ ] 宝塔 HTTPS 反代到 `127.0.0.1:8150`,Nginx 流式参数已加 +- [ ] frp 映射端口在本机 `curl` 通过 +- [ ] 首页模型卡片非长期 **离线** +- [ ] API 试调用成功 --- ## 12. 相关文档 -- 功能与配置总览:[README.md](./README.md) -- 仓库地址:[https://git.bz121.com/dekun/openai_node.git](https://git.bz121.com/dekun/openai_node.git) +- [README.md](./README.md) +- 仓库:[https://git.bz121.com/dekun/openai_node.git](https://git.bz121.com/dekun/openai_node.git) diff --git a/README.md b/README.md index 3de6a94..d13c286 100644 --- a/README.md +++ b/README.md @@ -43,34 +43,51 @@ ## 环境要求 +- 系统:**Ubuntu** 22.04 / 24.04(生产环境推荐) - Python **3.10+** - 上游服务:**Ollama**(或其它 OpenAI 兼容 HTTP API) -- 生产建议:**PM2** 守护进程;**宝塔** 或 Nginx 做 HTTPS 反代 +- 生产建议:**root** 部署到 **`/opt/openai_node`**,**PM2** 守护;**宝塔** 或 Nginx 做 HTTPS 反代 --- -## 快速开始 +## 快速开始(Ubuntu / root / /opt) -### 1. 克隆仓库 +以下命令在 **root** 下执行,安装目录为 **`/opt/openai_node`**。 + +### 1. 安装系统依赖 ```bash -git clone https://git.bz121.com/dekun/openai_node.git -cd openai_node +apt update +apt install -y python3 python3-venv python3-pip git curl +# PM2 需要 Node.js(若未安装) +curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - +apt install -y nodejs +npm install -g pm2 ``` -### 2. 安装依赖 +### 2. 克隆仓库 + +```bash +cd /opt +git clone https://git.bz121.com/dekun/openai_node.git +cd /opt/openai_node +``` + +### 3. 安装 Python 依赖 ```bash python3 -m venv venv -source venv/bin/activate # Windows: .\venv\Scripts\Activate.ps1 +source venv/bin/activate pip install -r requirements.txt -U ``` -### 3. 配置文件 +### 4. 配置文件 ```bash +cd /opt/openai_node cp gateway.json.example gateway.json cp nodes.json.example nodes.json +chmod 600 gateway.json nodes.json ``` 编辑 **`gateway.json`**: @@ -90,13 +107,17 @@ cp nodes.json.example nodes.json - `models[].id` 必须与调用 API 时 JSON 里的 **`model` 字段完全一致**(Ollama 模型名)。 - `models[].label` 为 Web 卡片上的显示名。 -### 4. 启动 +### 5. 启动(调试) ```bash +cd /opt/openai_node +source venv/bin/activate export JWT_SECRET="请改为长随机字符串" python -m uvicorn main:app --host 0.0.0.0 --port 8150 ``` +生产环境请用 PM2,见 **[DEPLOY.md](./DEPLOY.md)**。 + 浏览器打开 `http://127.0.0.1:8150`: | 路径 | 说明 | @@ -204,7 +225,7 @@ curl https://你的域名/v1/chat/completions \ ## 生产部署 -详见 **[DEPLOY.md](./DEPLOY.md)**(VPS、宝塔反代 8150、frp 多机、PM2)。 +详见 **[DEPLOY.md](./DEPLOY.md)**:**Ubuntu**、**root** 用户、目录 **`/opt/openai_node`**、宝塔反代 **8150**、frp 多机、PM2。 ---