Files
2026-05-25 13:47:34 +08:00

294 lines
11 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.
# 云服务器部署说明
本文说明在 **云服务器(VPS** 上部署 `crypto_monitor` 中控与四实例的推荐配置:硬件、软件、防火墙、宝塔反代、环境变量、PM2 启动与验收。
云上标准做法:**域名 + 宝塔/Nginx 反代 + HTTPS**;业务端口(5100、50005004、1520015203**不对公网直连**。
相关文档:
- **[本地数据迁移到云端.md](./本地数据迁移到云端.md)** — 备份 `crypto.db`、图片、`hub_settings` 与恢复步骤
- [局域网与反代部署说明.md](./局域网与反代部署说明.md) — 局域网 IP:端口 与反代域名对照、SSO 行为
- [部署文档.md](./部署文档.md) — PM2、依赖安装、日常运维
- [使用说明.md](./使用说明.md) — 中控功能说明
- [常见问题.md](./常见问题.md) — 故障排查
- 环境变量模板:[.env.example](./.env.example)
---
## 一、服务器硬件与系统
| 项目 | 建议 |
|------|------|
| 配置 | **2 核 4G** 起步;四实例 + 中控 + PM2 同时运行,**4G8G 更稳** |
| 系统 | **Ubuntu 22.04 / 24.04**(项目文档按 Linux 编写) |
| 磁盘 | **20G+**;日志、SQLite、上传图片会占空间 |
| 网络 | 需能访问各交易所 API;若走代理,在对应 `crypto_monitor_*/.env` 配置 `OKX_SOCKS_PROXY``BINANCE_SOCKS_PROXY` 等 |
---
## 二、软件环境
```bash
sudo apt update
sudo apt install -y python3 python3-venv python3-pip git curl
# 进程守护(推荐)
sudo npm i -g pm2
```
**宝塔面板(可选但推荐)**:安装 **Nginx**,用于反向代理与 **SSL**Lets Encrypt)。
Python 虚拟环境(分开安装,互不替代):
| 目录 | 用途 |
|------|------|
| `manual_trading_hub/.venv` | 中控 `hub.py` + 子代理 `agent.py` |
| `crypto_monitor_binance/.venv` | 币安 Flask |
| `crypto_monitor_okx/.venv` | OKX Flask |
| `crypto_monitor_gate/.venv` | Gate 训练 Flask |
| `crypto_monitor_gate_bot/.venv` | Gate 趋势 Flask |
各实例 `ecosystem.config.cjs` 一般已设置 **`PYTHONPATH=..`**(仓库根),以便加载 `hub_bridge.py``hub_auth.py` 等。
---
## 三、网络与端口(云上最重要)
**原则:公网只暴露 Nginx 的 80/443Flask 与 agent 只监听本机。**
| 服务 | 本机端口(示例) | 是否对公网开放 |
|------|------------------|----------------|
| 中控 hub | 5100 | **否** → 仅 `https://hub.你的域名` 反代 |
| 币安 Flask | 5001 | **否**`https://binance.你的域名` |
| OKX Flask | 5004 | **否**`https://okx.你的域名` |
| Gate 训练 Flask | 5000 | **否**`https://gate.你的域名` |
| Gate 趋势 Flask | 5002 | **否**`https://gate-bot.你的域名` |
| 子代理 agent | 1520015203 | **否**,必须 **127.0.0.1** |
### 云厂商安全组 / 系统防火墙
- **放行**`80``443`(给宝塔/Nginx
- **不要放行**`5100``5000``5004``15200``15203`(除非临时本机调试,用完即关)
---
## 四、域名与宝塔反代
**中控 + 每个要对外打开的实例** 各建一个站点(子域名示例):
| 站点(浏览器访问) | 反代目标 |
|--------------------|----------|
| `https://hub.example.com` | `http://127.0.0.1:5100` |
| `https://okx.example.com` | `http://127.0.0.1:5004` |
| `https://binance.example.com` | `http://127.0.0.1:5001` |
| `https://gate.example.com` | `http://127.0.0.1:5000` |
| `https://gate-bot.example.com` | `http://127.0.0.1:5002` |
### 宝塔操作要点
1. 每个域名 → **网站****反向代理** → 目标 `http://127.0.0.1:对应端口`
2. 申请 **SSL**Lets Encrypt),强制 HTTPS。
3. **不要**再给实例站加一层宝塔「访问密码」(会与 Flask `/login` 重复);直链鉴权用下文 **`APP_USERNAME` / `APP_PASSWORD`**。
4. Nginx 建议保留常见代理头(宝塔默认通常已带):
```nginx
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;
```
中控请求实例 `/api/hub/*` 时会带 **`X-Hub-Token`**,一般无需额外配置。
---
## 五、环境变量(必配)
### 5.1 中控 `manual_trading_hub/.env`
```env
HUB_HOST=0.0.0.0
HUB_PORT=5100
# 与四实例 .env 完全相同(API + SSO 签名)
HUB_BRIDGE_TOKEN=请填一长串随机字符
# 中控网页登录(公网务必设置)
HUB_USERNAME=admin
HUB_PASSWORD=强密码
HUB_SESSION_SECRET=另一串随机字符
# 中控为 HTTPS 时建议 true
HUB_COOKIE_SECURE=true
# 公网用域名访问中控(宝塔反代)时必设其一:
# HUB_ALLOW_PUBLIC=true (推荐:反代 + 中控密码)
# 或反代目标必须是 http://127.0.0.1:5100 且可保持 HUB_TRUST_LAN=false
HUB_ALLOW_PUBLIC=true
HUB_TRUST_LAN=false
# 从中控打开实例的 SSO 链接有效期(秒),默认 7200 = 2 小时
HUB_SSO_TTL_SEC=7200
# 各实例 hub_settings 里 flask_url 已写 https 域名时,一般可不设
# HUB_PUBLIC_ORIGIN=https://hub.example.com
```
完整项见 [`.env.example`](./.env.example)。
### 5.2 四个实例 `crypto_monitor_*/.env`
每个目录都要有(**直链** `https://okx.域名` 时用这套登录网页):
```env
# 各所 API 密钥(按交易所填写)
# APP_PORT=5004
# 与中控 manual_trading_hub/.env 中 HUB_BRIDGE_TOKEN 完全一致
HUB_BRIDGE_TOKEN=与中控相同
# 四实例建议统一(直链登录用)
APP_USERNAME=统一用户名
APP_PASSWORD=统一强密码
# 云服务器切勿开启(会跳过网页登录):
# APP_AUTH_DISABLED=true
```
### 5.3 子代理
- `CONTROL_TOKEN` 可与 `HUB_BRIDGE_TOKEN` 相同。
- 由 PM2 在对应 `crypto_monitor_*` 目录启动,`run_agent.sh` 加载该目录 `.env`
- 只监听 **127.0.0.1:1520x**,不映射到公网。
---
## 六、中控「系统设置」`hub_settings.json`
在网页 **系统设置** 保存,或编辑 `manual_trading_hub/hub_settings.json`
云上 **`flask_url` 必须写浏览器能打开的 HTTPS 域名**(不要写 `127.0.0.1`,除非配合 `HUB_PUBLIC_ORIGIN` 做替换):
| 字段 | 云上填法 | 说明 |
|------|----------|------|
| `flask_url` | `https://okx.example.com` | 用户浏览器、SSO 打开实例 |
| `agent_url` | `http://127.0.0.1:15201` | 仅中控本机访问子代理 |
| `enabled` | 按需 | 不参与监控的户可关 |
| `capabilities` | 按需 | `key` / `trend` 等 |
**同机部署的两种写法(二选一):**
1. **推荐**:每个实例 `flask_url` 直接写该实例的 `https://子域名`
2. **备选**`flask_url``http://127.0.0.1:5004`,中控 `.env``HUB_PUBLIC_ORIGIN=https://okx.example.com`(适合共用一个 IP、靠端口区分时)。
`agent_url` 始终用 **`http://127.0.0.1:1520x`**。
---
## 七、PM2 启动顺序
代码路径示例:`/opt/crypto_monitor/`(按实际替换)。
```bash
cd /opt/crypto_monitor
# 1)四个实例 Flask(各目录 ecosystem.config.cjs,进程名以你机器为准)
cd crypto_monitor_okx && pm2 start ecosystem.config.cjs
cd ../crypto_monitor_binance && pm2 start ecosystem.config.cjs
cd ../crypto_monitor_gate && pm2 start ecosystem.config.cjs
cd ../crypto_monitor_gate_bot && pm2 start ecosystem.config.cjs
# 2)中控 + 四个子代理(一条拉起 5 个进程)
cd ../manual_trading_hub
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # 编辑填入真实值
chmod +x scripts/run_hub.sh scripts/run_agent.sh
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup # 按提示执行 sudo 命令后再 pm2 save
```
或:
```bash
cd /opt/crypto_monitor/manual_trading_hub
bash scripts/pm2_hub.sh start
```
### PM2 进程一览
| 进程名 | 说明 |
|--------|------|
| `manual-trading-hub` | 中控 :5100 |
| `manual-agent-binance` | :15200 |
| `manual-agent-okx` | :15201 |
| `manual-agent-gate` | :15202 |
| `manual-agent-gate-bot` | :15203 |
| `crypto_*`(各目录自定) | 各 Flask `APP_PORT` |
不用 OKX 时可在 `.env``HUB_DISABLED_IDS=1`,或 `pm2 stop manual-agent-okx`
---
## 八、访问与登录(云上行为)
| 访问方式 | 地址示例 | 需要什么 |
|----------|----------|----------|
| 中控监控 | `https://hub.example.com/monitor` | **中控** `HUB_USERNAME` / `HUB_PASSWORD` |
| 中控点「实例 / 策略交易 / 复盘」 | 自动打开 `https://okx.example.com/hub-sso?...` | 已登中控即可;**2 小时内、单次** SSO,**免输**实例密码 |
| 浏览器直链实例 | `https://okx.example.com` | 实例 **`APP_USERNAME` / `APP_PASSWORD`**`/login` |
SSO 复用 **`HUB_BRIDGE_TOKEN`** 签名,详见 [局域网与反代部署说明.md §五](./局域网与反代部署说明.md)。
---
## 九、安全建议(云服务器必看)
1. **SSH**:密钥登录,关闭密码登录;必要时改 SSH 端口。
2. **`HUB_BRIDGE_TOKEN`**:足够长、随机;勿提交 Git、勿写进前端页面。
3. **交易所 API Key**:仅放在各实例 `.env`;权限尽量最小化(勿随意开提币)。
4. **中控**:公网必须设 `HUB_PASSWORD``HUB_TRUST_LAN=false`
5. **实例**:云上 **`APP_AUTH_DISABLED` 必须为 false**(或未设置)。
6. **备份**:定期备份各实例数据库 / SQLite 与 `hub_settings.json`
7. **`.env` 换行**Linux 上勿用 Windows CRLF;可用 `bash scripts/fix_env_crlf.sh`
---
## 十、部署后验收清单
- [ ] `https://hub.你的域名` 能打开并登录中控
- [ ] 监控卡片有持仓/余额(子代理在线)
- [ ] 已登录中控 → 点「实例」→ **无**实例登录页,直接进入
- [ ] 隐身窗口直开 `https://okx.你的域名` → 出现 **`/login`**,统一账号密码可进
- [ ] `pm2 status`hub、4×agent、用到的 `crypto_*` 均为 online
- [ ] 云安全组 **未** 对公网开放 5100、50005004、1520015203
- [ ] 四实例 `.env` 与中控 `HUB_BRIDGE_TOKEN` 一致
- [ ] 实例启动日志无长期 `[hub_bridge] ImportError`
---
## 十一、常见问题速查
| 现象 | 处理 |
|------|------|
| 从中控打开仍要实例密码 | 见 [常见问题.md §4.3](./常见问题.md);检查 token、重启 Flask、`hub_settings``key` |
| 监控无持仓 / 子代理不可用 | `curl http://127.0.0.1:15201/status`;查 `.env` CRLF、API 密钥 |
| 复盘/实例链接是 127.0.0.1 | `flask_url` 改为 https 域名,或设 `HUB_PUBLIC_ORIGIN` |
| 仅 Gate 子代理反复重启 | `.env` CRLF`bash manual_trading_hub/scripts/fix_env_crlf.sh` |
---
## 十二、与局域网部署的区别(简要)
| 项目 | 云服务器 | 局域网 |
|------|----------|--------|
| 对外地址 | `https://子域名` | `http://内网IP:端口` |
| `flask_url` | 写 **域名** | 写 **内网 IP:端口** |
| 防火墙 | 只开 80/443 | 内网可开 5100、500x |
| SSL | 必须(宝塔证书) | 通常 HTTP 即可 |
| `HUB_COOKIE_SECURE` | 建议 `true` | HTTP 时用 `false` |
局域网详细步骤见 [局域网与反代部署说明.md §三](./局域网与反代部署说明.md)。