# 测试环境裸机部署说明 > 本文档描述测试机 `101.35.245.122` 上的 **web-admin + backend** 裸机部署拓扑与日常操作。 > 代码仓库:`web-admin/`、`backend/`;服务器部署根目录:`/root/zkxw/`。 **说明**:旧 **8112 / 双机拓扑**(前端 `47.121.120.79` + 后端 `47.99.164.66:8112`)已废弃,**以本文件为准**。 --- ## 1. 环境拓扑 | 角色 | 地址 | |------|------| | 入口 | `https://www.chengyantek.cn`(兼容 `http://101.35.245.122:10001`) | | Nginx 静态 | `/root/zkxw/web-admin/dist` | | OA H5 静态 | `/root/zkxw/static/oa-h5`(路径前缀 `/oa-h5/`) | | 后端 | `127.0.0.1:10002`(仅本机) | | 中间件 | 与本机 `backend/.env` 相同(`47.99.164.66`) | | MinIO | 同域 `/minio/zkxw` → `47.99.164.66:20004/zkxw` | | SSL 证书 | 服务器 `/root/zkxw/cert/www.chengyantek.cn.{pem,key}` | 流量路径: ```text 浏览器 → https://www.chengyantek.cn (或 http://IP:10001) ├─ / → Nginx 静态(web-admin/dist) ├─ /oa-h5/ → Nginx 静态(mobile-oa-h5 → /root/zkxw/static/oa-h5) ├─ /api/* → 127.0.0.1:10002(本机后端) └─ /minio/zkxw/ → 47.99.164.66:20004/zkxw/ ``` `mobile-h5` 配置示例:`OA_H5_ORIGIN = 'https://www.chengyantek.cn/oa-h5'`(微信 web-view 业务域名须含 `www.chengyantek.cn`)。 云安全组 / 防火墙仅放行 **TCP 10001**;后端绑定 `127.0.0.1`,不对公网暴露 10002。 --- ## 2. 机装依赖 | 组件 | 状态 | 说明 | |------|------|------| | Python | **已有 3.12.3** | 用于创建 `.venv` | | Nginx | **需安装** | 对外 10001,反代 `/api` | | 中间件 | 远程复用 | MySQL / Redis / MinIO 在 `47.99.164.66` | 探测包管理器后安装 Nginx(示例): ```bash # Debian/Ubuntu sudo apt-get update && sudo apt-get install -y nginx # RHEL/CentOS/Alma(示例) sudo yum install -y nginx # 或 dnf install -y nginx sudo systemctl enable --now nginx ``` --- ## 3. 服务器目录 ```text /root/zkxw/ ├── web-admin/ │ └── dist/ # pnpm build:test 产物 ├── backend/ │ ├── app/ │ ├── requirements.txt │ ├── start-test.sh │ ├── .env.test # 敏感,勿提交 git │ ├── .venv/ # Python 3.12.3 虚拟环境 │ ├── backend-test.pid │ └── logs/ └── (Nginx site 配置见下文) ``` --- ## 4. 首次部署 ### 4.1 后端环境变量 `.env.test` 来源:从**本机开发机** `backend/.env` 复制为服务器 `backend/.env.test`,按测试需要调整(库名、Redis DB、密钥等)。**勿将含密码的文件提交 git**。 ```bash # 在本机执行(示例) scp backend/.env root@101.35.245.122:/root/zkxw/backend/.env.test ``` 或使用模板 `backend/.env.test.example` 手工填写。 ### 4.2 虚拟环境与启动 ```bash cd /root/zkxw/backend python3.12 -m venv .venv ./.venv/bin/pip install -U pip ./.venv/bin/pip install -r requirements.txt chmod +x start-test.sh HOST=127.0.0.1 PORT=10002 ./start-test.sh start ./start-test.sh status curl -s http://127.0.0.1:10002/health ``` `start-test.sh` 子命令:`start` / `stop` / `restart` / `status` / `logs` / `activate` / `help`。 ### 4.3 前端静态资源 在本机构建后上传(见 §6 日常发版)。 ### 4.4 启用 Nginx 配置文件已存在于仓库:`测试环境部署/zkxw-test-10001.conf`。 **Ubuntu / Debian:** ```bash sudo cp 测试环境部署/zkxw-test-10001.conf /etc/nginx/sites-available/zkxw-test-10001.conf sudo ln -sf /etc/nginx/sites-available/zkxw-test-10001.conf /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx ``` **RHEL / CentOS / Alma:** ```bash sudo cp 测试环境部署/zkxw-test-10001.conf /etc/nginx/conf.d/zkxw-test-10001.conf sudo nginx -t && sudo systemctl reload nginx ``` Nginx 关键配置摘要: - `https://www.chengyantek.cn`(443 SSL)+ `http` 80/apex → 301 到 https://www - 兼容 `http://IP:10001` - `root /root/zkxw/web-admin/dist`;`/api`、`/health` → `127.0.0.1:10002` - `/oa-h5/` → `/root/zkxw/static/oa-h5`(`mobile-oa-h5`,Vite `base=/oa-h5/`) - `/minio/zkxw/` → `47.99.164.66:20004/zkxw/`(HTTPS 同域,避免混合内容) - 证书:`/root/zkxw/cert/www.chengyantek.cn.{pem,key}`(来源仓库旁证书包,私钥勿提交 git;`*.pem`/`*.key` 已在 `.gitignore`) **云安全组须放行 TCP 80、443**(10001 已通不代表 443 已开)。 静态目录在 `/root/...` 下时,Nginx 工作用户(如 `www-data`)须能穿越 `/root`,否则首页 500 / Permission denied: ```bash chmod 755 /root chmod -R a+rX /root/zkxw/web-admin ``` (或将静态目录放到 `/var/www/zkxw` 等非 `/root` 路径。) ### 4.5 更新 SSL 证书 ```bash # 本机 scp 26548929_www.chengyantek.cn_nginx/www.chengyantek.cn.pem \ 26548929_www.chengyantek.cn_nginx/www.chengyantek.cn.key \ root@101.35.245.122:/root/zkxw/cert/ ssh root@101.35.245.122 'chmod 600 /root/zkxw/cert/* && nginx -t && systemctl reload nginx' ``` --- ## 5. 脚本与环境对照 | 项 | 测试环境(本拓扑) | 生产环境 | |----|-------------------|----------| | 启动脚本 | `backend/start-test.sh` | `backend/start-prod.sh` | | 环境变量文件 | `.env.test` | `.env.production` | | 监听地址 | `127.0.0.1:10002` | `0.0.0.0:8111` | | 虚拟环境 | `.venv` | `venv` | | PID 文件 | `backend-test.pid` | `backend-prod.pid` | | 运行日志 | `logs/backend-test.log` | `logs/backend-prod.log` | 应用通过 `ENV_FILE` 加载配置(见 `backend/app/core/config.py`),启动脚本会 `export ENV_FILE` 后再拉起 uvicorn。 --- ## 6. 日常发版 ### 6.1 推荐:一键脚本 ```bash # 仓库根目录执行(默认:前端 build:test + rsync、后端 rsync、重启、验收) python3 测试环境部署/deploy_test_env.py python3 测试环境部署/deploy_test_env.py --frontend-only # 仅前端 python3 测试环境部署/deploy_test_env.py --backend-only # 仅后端并重启 python3 测试环境部署/deploy_test_env.py --verify # 仅验收 python3 测试环境部署/deploy_test_env.py --upload-env # 额外上传本机 backend/.env → 远端 .env.test python3 测试环境部署/deploy_test_env.py --pip # 远端重新 pip install -r requirements.txt python3 测试环境部署/deploy_test_env.py --health-timeout 90 # 重启后等待健康检查最长时间(默认 60s) ``` 依赖本机:`python3`、`pnpm`、`rsync`、`ssh`/`scp`;密码登录需 `sshpass`。 SSH 密码默认读仓库根 `测试环境机器的账号密码`,或环境变量 `ZKXW_TEST_SSH_PASS`(**勿提交密码到 git**)。 发版若重启了后端,会先轮询 `127.0.0.1:10002/health`(再确认 Nginx `/health`)通过后再跑验收,避免瞬时 502。 ### 6.2 手工命令(等价) ```bash # 前端 cd web-admin && pnpm build:test rsync -avz --delete dist/ root@101.35.245.122:/root/zkxw/web-admin/dist/ # 后端 rsync -avz --exclude .venv --exclude venv --exclude '__pycache__' --exclude logs \ backend/ root@101.35.245.122:/root/zkxw/backend/ ssh root@101.35.245.122 \ 'cd /root/zkxw/backend && HOST=127.0.0.1 PORT=10002 ./start-test.sh restart' ``` **注意**: - 前端须使用 `pnpm build:test`(读取 `web-admin/.env.test`),勿误用 `pnpm build`。 - rsync 默认不覆盖服务器 `.env.test`;配置变更用脚本 `--upload-env` 或单独 scp。 - rsync 排除 `.venv`,依赖变更时用脚本 `--pip` 或在机器上重新 `pip install -r requirements.txt`。 --- ## 7. 验收 ```bash curl -s -o /dev/null -w '%{http_code}\n' http://101.35.245.122:10001/ curl -s http://101.35.245.122:10001/health curl -s -o /dev/null -w '%{http_code}\n' --connect-timeout 5 http://101.35.245.122:10002/health || echo '10002_closed_ok' curl -s -o /dev/null -w '%{http_code}\n' http://101.35.245.122:10001/api/web/auth/login-rsa-public-key ``` 预期: - 首页与 `/health` 返回 **200** - 外网直连 `10002` **不可达**(输出 `10002_closed_ok` 或超时) - 登录 RSA 公钥接口经 Nginx 反代返回 **200** --- ## 8. 前端环境变量(`web-admin/.env.test`) | 变量 | 说明 | |------|------| | `VITE_BASE_URL` | `/`(部署在 10001 根路径) | | `VITE_API_URL` | `/api`(同域 Nginx 反代至 127.0.0.1:10002) | | `VITE_MINIO_BASE_URL` | `http://47.99.164.66:20004/zkxw`(浏览器直连,不经测试机 Nginx) | | `VITE_API_ENCRYPT_*` | 与 `backend/.env.test` 中 `API_ENCRYPT_*` 一致 | --- ## 9. 常见问题 ### 启动报「环境文件不存在」 ```bash cp .env.test.example .env.test # 或从本机 backend/.env 复制后编辑 ./start-test.sh start ``` ### API 504 / 502 在测试机上排查: ```bash ./start-test.sh status curl -s http://127.0.0.1:10002/health sudo nginx -t sudo tail -f /var/log/nginx/zkxw_admin_10001_error.log ``` ### 脚本语法错误(CRLF) ```bash sed -i 's/\r$//' start-test.sh ``` ### 虚拟环境未找到 ```bash python3.12 -m venv .venv ./.venv/bin/pip install -U pip ./.venv/bin/pip install -r requirements.txt ``` --- ## 10. 仓库内相关文件 | 路径 | 说明 | |------|------| | `backend/start-test.sh` | 测试环境启动脚本 | | `backend/.env.test.example` | 测试环境变量模板 | | `web-admin/.env.test` | 测试环境前端打包变量 | | `web-admin/package.json` | `pnpm build:test` | | `测试环境部署/zkxw-test-10001.conf` | Nginx 10001 site 配置 | | `测试环境部署/deploy_test_env.py` | 日常发版一键脚本(前端打包 + rsync + 重启 + 验收) | | `docs/superpowers/specs/2026-08-06-test-env-bare-metal-deploy-design.md` | 设计说明 | --- ## 11. 修订记录 | 日期 | 说明 | |------|------| | 2026-06-01 | 初版:测试脚本 `start-test.sh`(8112、`.env.test`、`.venv`)、`activate` 命令、与生产对照及部署步骤 | | 2026-06-01 | 补充:`web-admin` 测试打包(`pnpm build:test`)、Nginx 8112、`/root/zkxw/dist`、API 反代 `47.99.164.66:8112` | | 2026-08-06 | 裸机部署 10001/10002 于 101.35.245.122 | | 2026-08-06 | 新增 `deploy_test_env.py` 日常发版脚本 | | 2026-08-10 | 启用 `www.chengyantek.cn` HTTPS(443)+ HTTP→HTTPS;MinIO 同域 `/minio/zkxw` |