Files
2026-05-19 02:16:43 +08:00

391 lines
9.4 KiB
Markdown
Raw Permalink 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.
# openai_node · 生产部署文档(Ubuntu
本文说明如何在 **Ubuntu VPS** 上以 **root** 用户部署本网关,安装目录 **`/opt/openai_node`**,并通过 **宝塔面板** 反向代理、**frp** 汇聚多台本地 Ollama 节点。
| 项 | 约定 |
|----|------|
| 系统 | Ubuntu 22.04 / 24.04 |
| 用户 | **root** |
| 安装路径 | **`/opt/openai_node`** |
| 网关端口 | **8150** |
| 宝塔反代 | 域名 → `http://127.0.0.1:8150` |
| 模型端口 | **33133318**frp 映射到本机 `127.0.0.1` |
代码仓库:[https://git.bz121.com/dekun/openai_node.git](https://git.bz121.com/dekun/openai_node.git)
---
## 1. 部署拓扑
```
Internet
┌─────────────────┐
│ Ubuntu VPS │
│ 宝塔 Nginx:443 │
│ │ │
│ ▼ │
│ /opt/openai_node
│ :8150 │
│ │ │
│ 127.0.0.1:3313 ├─── frp ─── PC1 Ollama :3313
│ 127.0.0.1:3314 ├─── frp ─── PC2 Ollama :3314
│ 127.0.0.1:3315 ├─── frp ─── PC3 Ollama :3315
└─────────────────┘
```
要点:
1. **不要**把 3313 等端口直接暴露到公网,仅本机 `127.0.0.1` 访问。
2. **不要**让宝塔直接把域名反代到各 PC;应只反代到 **8150**,由网关按 `model` 调度。
3. `nodes.json``host`**`127.0.0.1`**`port` 填 frp 映射后的端口。
---
## 2. 前置条件
**root** 登录 VPS 后,安装基础组件:
```bash
apt update
apt install -y python3 python3-venv python3-pip git curl
```
| 组件 | 版本建议 | 用途 |
|------|----------|------|
| Python | **3.8+**(推荐 3.10+`python3 -V` 确认) | 运行网关 |
| Node.js | LTS | 安装 PM2 |
| PM2 | 最新 | 进程守护 |
| 宝塔 | 7.x+ | Nginx 反代、SSL |
| 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. 部署网关到 /opt/openai_node
以下命令均在 **root** 下执行。
### 3.1 克隆代码
```bash
cd /opt
git clone https://git.bz121.com/dekun/openai_node.git
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
# 若曾装过新版 bcrypt 导致 passlib 报错,可强制重装:
# pip install 'bcrypt>=4.0.0,<4.1.0' -U --force-reinstall
```
### 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
```
编辑 **`/opt/openai_node/gateway.json`**:设置 `username``password``api_key` 可留空自动生成。
编辑 **`/opt/openai_node/nodes.json`**(示例):
```json
{
"nodes": [
{
"id": "node-1",
"name": "书房电脑",
"host": "127.0.0.1",
"port": 3313,
"enabled": true,
"max_concurrent": 1,
"models": [
{ "id": "qwen2.5:14b", "label": "千问 14B" }
]
}
]
}
```
`models[].id` 必须与 Ollama 模型名、API 请求中的 `model` **完全一致**
也可部署后浏览器打开 **系统设置** 维护(需先登录)。
### 3.4 环境变量
**`/opt/openai_node/ecosystem.config.cjs`** 的 `env` 中配置(推荐),或导出后启动:
| 变量 | 生产建议 |
|------|----------|
| `JWT_SECRET` | **必改**,长随机字符串 |
| `GATEWAY_PORT` | `8150` |
可选:
| 变量 | 说明 |
|------|------|
| `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`,首页应出现模型卡片。确认无误后 `Ctrl+C` 停止,改由 PM2 守护。
---
## 4. PM2 守护
项目 **`/opt/openai_node/ecosystem.config.cjs`** 已配置端口 **8150** 与 venv 内 Python 路径。
### 4.1 修改 PM2 配置
```bash
nano /opt/openai_node/ecosystem.config.cjs
```
`env.JWT_SECRET` 改为生产密钥。
### 4.2 启动
```bash
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 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 开机自启(root
```bash
pm2 save
pm2 startup
```
**root** 用户下,终端会打印一行命令(通常已含 `systemd` 配置),**直接复制执行**即可,一般无需再加 `sudo`
验证:
```bash
systemctl status pm2-root # 服务名以 pm2 实际输出为准
```
---
## 5. 宝塔反向代理
### 5.1 添加站点
宝塔 → **网站** → 添加站点 → 绑定域名 → 申请 **SSL**
### 5.2 反向代理到 8150
网站 → **设置****反向代理** → 添加:
| 项 | 值 |
|----|-----|
| 目标 URL | `http://127.0.0.1:8150` |
| 发送域名 | `$host` |
**配置文件** 中建议(流式 LLM 必备):
```nginx
location / {
proxy_pass http://127.0.0.1:8150;
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_buffering off;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
```
### 5.3 验证
```bash
curl -I https://你的域名/
```
登录 Web → 首页查看模型卡片。
---
## 6. frp 多机穿透(示例)
### 6.1 VPSroot)运行 frps
```bash
mkdir -p /etc/frp
nano /etc/frp/frps.toml
```
```toml
bindPort = 7000
```
按需配置 systemd 开机启动 frps。
### 6.2 各 PC 运行 frpc
```toml
serverAddr = "VPS公网IP"
serverPort = 7000
[[proxies]]
name = "ollama-pc1"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3313
remotePort = 3313
```
其它电脑映射 **3314、3315**
### 6.3 在 VPS 上验证
```bash
curl http://127.0.0.1:3313/v1/models
curl http://127.0.0.1:3314/v1/models
```
Web **系统设置** 中点击 **测试**,或等待首页健康检查(约 30 秒)。
---
## 7. Ollama 侧注意
1. Ollama 监听地址需能被 frp 访问(勿将模型端口裸露公网)。
2. API 中 `model``nodes.json` / `ollama list` 名称一致。
3. 流式 Token 统计(可选):
```json
"stream_options": { "include_usage": true }
```
---
## 8. 客户端接入
| 项 | 值 |
|----|-----|
| Base URL | `https://你的域名/v1` |
| API Key | `/opt/openai_node/gateway.json` 或用户中心复制 |
```bash
curl https://你的域名/v1/chat/completions \
-H "Authorization: Bearer sk-你的密钥" \
-H "Content-Type: application/json" \
-d '{"model":"qwen2.5:14b","messages":[{"role":"user","content":"hi"}]}'
```
---
## 9. 运维与数据文件
| 路径 | 说明 | 备份 |
|------|------|------|
| `/opt/openai_node/gateway.json` | 账号、API Key | 建议 |
| `/opt/openai_node/nodes.json` | 节点与模型 | 建议 |
| `/opt/openai_node/gateway_stats.db` | 访问与 Token 统计 | 可选 |
| `/root/.pm2/logs/` | PM2 日志 | 按需 |
Web 保存节点配置会写入 `nodes.json` 并热加载;仅改 `ecosystem.config.cjs` 环境变量时需 `pm2 restart llm-gateway`。
---
## 10. 故障排查
| 现象 | 排查 |
|------|------|
| 首页卡片 **离线** | `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 |
| `asyncio` 无 `to_thread` | Python 3.8:拉最新代码(已用 `run_in_thread` 兼容) |
| bcrypt `__about__` 报错 | `pip install 'bcrypt>=4.0.0,<4.1.0' -U --force-reinstall` 后重启 PM2 |
---
## 11. 部署检查清单
- [ ] 以 **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)