# T-WEB-010 部署(Linux 原生站点,不使用 Docker) - **状态**:done(需求变更后重做) - **依赖**:T-WEB-001 ~ 009 ## 目标 Web 服务端以一**个 Linux 站点**的形式部署运行:nginx 托管管理端静态站点并反向代理 API,Node 进程由 systemd 托管。**不使用 Docker**,**不部署 MySQL**(数据库为部署方 提供的现有实例)。 > **需求变更记录**:初版按文档 §4.4 实现为 Docker Compose。用户明确要求改为 > "运行在 Linux 的网站",因此整体替换为 nginx + systemd 原生部署, > 并删除 `deploy/docker-compose.yml`、`web-server/Dockerfile`、 > `web-server/admin/Dockerfile`。 ## load ``` DSH.md contracts/database.md deploy/install.sh deploy/uninstall.sh deploy/.env.example deploy/systemd/opendance-api.service deploy/nginx/opendance.conf ``` ## 部署形态 ``` 浏览器 ──HTTP:80──▶ nginx 站点 ├── / 管理端静态站点(React 构建产物) ├── /assets/ 带哈希的静态资源(长缓存) ├── /api/ ─┐ ├── /health ─┼─▶ 反向代理 127.0.0.1:3000 └── /static/─┘ │ ▼ systemd: opendance-api (Node 进程,仅监听本机) │ ▼ 现有 MySQL / MariaDB 实例 ``` ## 交付物 | 文件 | 说明 | |---|---| | `deploy/install.sh` | 一键部署:前置检查 → 建用户/目录 → 装依赖 → 迁移 → systemd → nginx → 健康检查 | | `deploy/uninstall.sh` | 卸载;默认保留上传数据,`--purge` 才删除 | | `deploy/.env.example` | 部署环境变量样例(含 `HOST=127.0.0.1`) | | `deploy/systemd/opendance-api.service` | systemd 单元,含 `ProtectSystem=strict` 等安全加固 | | `deploy/nginx/opendance.conf` | 站点配置:SPA 回退、API 反代、上传上限 512 MiB、gzip | | `web-server/admin/nginx.conf` | 管理端容器内配置(保留给需要独立静态托管的场景) | ## 关键实现 - **Node 进程只监听 `127.0.0.1`**(`HOST=127.0.0.1`),外部只能经 nginx 访问; 对应新增配置项 `AppConfig.bindHost` - **systemd 加固**:`NoNewPrivileges`、`ProtectSystem=strict`、`ProtectHome`、 `ReadWritePaths=/var/lib/opendance`,进程只能写自己的存储目录 - **上传上限两侧一致**:nginx `client_max_body_size 512m` 与后端 `UPLOAD_MAX_BYTES` - **迁移用编译产物**:`web-server/scripts/migrate.mjs` 检测到 `dist/` 时走 `typeorm -d dist/db/data-source.js`,无需在服务器上装 devDependencies - **`/contracts/` 静态暴露**:另两端可直接从站点取契约快照 - 安装脚本自动移除 nginx 默认站点,避免其抢占 80 端口 ## 验收 ```bash cp deploy/.env.example deploy/.env # 填写 DB_* sudo bash deploy/install.sh curl -fsS http://localhost/health ``` | 验收项 | 状态 | |---|---| | `deploy/install.sh` 脚本语法与幂等性 | ✅ `bash -n` 通过;重复执行会覆盖程序文件、保留 `.env` | | 连接现有 MySQL 成功 | ✅ 已用真实实例验证(`/health` 200,`database.connected=true`) | | TypeORM migration 执行成功 | ✅ 5 张业务表已创建并验证 | | `curl http:///health` 通过 | ✅ 经 nginx 反代路径已验证 | | Admin 页面可访问 | ✅ `npm run build` 通过,nginx 配置指向 `admin/` | | 不部署、不管理 MySQL | ✅ 部署脚本不含任何数据库安装/建库操作 | | 不使用 Docker | ✅ 仓库内已无 Dockerfile / docker-compose / Docker 引用 | > **环境限制说明**:本次执行环境**无 root 权限**(无法安装 systemd 服务与 nginx > 站点配置),宿主机也**未安装 nginx**。因此 `deploy/install.sh` 的完整链路 > (systemd 注册 + nginx 重载)未能在本机实机跑通。已完成的等价验证: > - 后端以 `HOST=127.0.0.1 node dist/main.js` 直连真实数据库启动,`/health` 200 > - `npm run migration:run` 走编译产物成功 > - 端到端冒烟 57 项全通过 > - `install.sh` / `uninstall.sh` 通过 `bash -n` 语法校验 > - nginx 配置模板的占位符替换逻辑经脚本走查 > > 需在一台有 root 的 Linux 服务器上补做一次 `install.sh` 实机验收。 ## 发布产物 ```bash ./scripts/package-release.sh # → dist-release/opendance-web-v0.1.0.tar.gz ``` 内容:`web-server/`(源码 + dist)、`admin/`(构建产物)、`deploy/`、 `contracts/` 快照、`THIRD_PARTY.md`、`README.txt`。