# 动态路由与Nginx自动化配置 Spec ## Why 当前系统为每个项目分配独立端口(9000-9100),存在以下问题: 1. 服务器防火墙需要开放大量端口 2. URL不够友好(需要带端口号) 3. 手动配置Nginx反向代理繁琐 通过动态路由+Nginx自动化配置,可以实现: - 所有项目共用单一端口(80/443) - 友好的URL路径(如 `/project/{id}/`) - 自动化Nginx配置更新,无需手动干预 ## What Changes - **新增** Nginx配置管理服务 - **新增** Nginx配置模板系统 - **修改** 项目访问方式从多端口改为动态路由 - **修改** processManager 启动逻辑,使用固定内部端口 - **新增** Nginx配置自动重载机制 - **新增** 本地开发模式支持(可选安装Nginx) ## Impact - Affected specs: 项目部署流程、URL生成规则、端口管理 - Affected code: - `server/services/processManager.js` - `server/services/projectService.js` - `server/config/index.js` - 新增 `server/services/nginxManager.js` - 新增 `server/templates/nginx/` 配置模板 ## ADDED Requirements ### Requirement: Nginx配置管理服务 系统 SHALL 提供Nginx配置管理服务,支持自动生成和更新Nginx配置。 #### Scenario: 创建项目时生成Nginx配置 - **WHEN** 用户创建新项目 - **THEN** 系统自动为该项目生成Nginx location配置块 - **AND** 配置文件保存到指定目录 - **AND** 自动重载Nginx使配置生效 #### Scenario: 删除项目时清理Nginx配置 - **WHEN** 用户删除项目 - **THEN** 系统自动移除该项目的Nginx配置 - **AND** 自动重载Nginx使配置生效 #### Scenario: 启动项目时更新upstream - **WHEN** 项目启动成功 - **THEN** 系统更新Nginx upstream配置指向正确的内部端口 - **AND** 自动重载Nginx使配置生效 ### Requirement: 动态路由访问 系统 SHALL 通过动态路由路径访问不同项目,而非独立端口。 #### Scenario: 访问项目 - **WHEN** 用户访问 `/project/{projectId}/` - **THEN** Nginx将请求代理到对应项目的内部服务 - **AND** 项目内部服务运行在固定内部端口范围(如127.0.0.1:9000-9100) #### Scenario: 生成项目URL - **WHEN** 项目启动成功 - **THEN** 系统生成格式为 `{BASE_URL}/project/{projectId}/` 的访问地址 - **AND** 不再包含端口号 ### Requirement: 本地开发模式支持 系统 SHALL 支持本地开发环境,可选择是否使用Nginx。 #### Scenario: 本地无Nginx环境 - **WHEN** 系统检测到本地未安装或未配置Nginx - **THEN** 系统回退到原有的多端口模式 - **AND** 在日志中提示可安装Nginx获得更好体验 #### Scenario: 本地有Nginx环境 - **WHEN** 系统检测到本地已安装Nginx - **THEN** 系统使用动态路由模式 - **AND** 自动配置Nginx ### Requirement: Nginx配置模板 系统 SHALL 使用模板化方式管理Nginx配置。 #### Scenario: 主配置模板 - **GIVEN** 系统需要生成Nginx主配置 - **WHEN** 初始化或配置变更 - **THEN** 使用预定义模板生成 `auto-deploy.conf` - **AND** 模板支持变量替换(如端口范围、项目列表) #### Scenario: 项目location模板 - **GIVEN** 需要为项目生成location配置 - **WHEN** 创建或更新项目配置 - **THEN** 使用location模板生成配置片段 - **AND** 支持SPA路由回退处理 ### Requirement: 配置热重载 系统 SHALL 在配置变更后自动重载Nginx。 #### Scenario: 配置变更后重载 - **WHEN** Nginx配置文件被修改 - **THEN** 系统执行 `nginx -s reload` 命令 - **AND** 检查重载结果 - **AND** 失败时回滚配置并记录错误日志 ### Requirement: 环境配置扩展 系统 SHALL 扩展环境配置以支持Nginx相关设置。 #### Scenario: 新增环境变量 - **GIVEN** 用户配置 `.env` 文件 - **WHEN** 系统读取配置 - **THEN** 支持以下新增配置项: - `USE_NGINX` - 是否使用Nginx(true/false/auto) - `NGINX_CONFIG_DIR` - Nginx配置目录路径 - `NGINX_TEMPLATE_PATH` - 配置模板路径 - `NGINX_RELOAD_CMD` - Nginx重载命令 ## MODIFIED Requirements ### Requirement: 项目URL生成 **原需求**: 项目URL格式为 `http://{domain}:{port}/` **修改为**: 项目URL格式为 `{BASE_URL}/project/{projectId}/` ### Requirement: 端口管理 **原需求**: 项目使用外部可访问端口(9000-9100) **修改为**: 项目使用内部端口(127.0.0.1:9000-9100),外部通过Nginx代理访问 ## Technical Design ### 架构设计 ``` ┌─────────────────────────────────────┐ │ Nginx (80/443) │ │ │ │ location /project/xxx/ { │ │ proxy_pass http://127.0.0.1:9000│ │ } │ └──────────────┬──────────────────────┘ │ ┌────────────────────┼────────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 项目1 │ │ 项目2 │ │ 项目N │ │ :9000 │ │ :9001 │ │ :90xx │ │(内部端口) │ │(内部端口) │ │(内部端口) │ └──────────┘ └──────────┘ └──────────┘ ``` ### 文件结构 ``` server/ ├── services/ │ ├── nginxManager.js # 新增:Nginx配置管理 │ ├── processManager.js # 修改:端口绑定127.0.0.1 │ └── projectService.js # 修改:URL生成逻辑 ├── templates/ │ └── nginx/ │ ├── main.conf.tpl # 主配置模板 │ └── location.conf.tpl # location配置模板 └── config/ └── index.js # 修改:新增Nginx配置项 nginx/ └── sites-enabled/ └── auto-deploy.conf # 生成的Nginx配置 ``` ### Nginx配置模板示例 **主配置模板 (main.conf.tpl)**: ```nginx # Auto-generated by auto-deploy-demo # Do not edit manually upstream projects { # 项目upstream配置将由系统自动生成 } server { listen {{PORT}}; server_name {{SERVER_NAME}}; # 管理后台 location / { proxy_pass http://127.0.0.1:{{MANAGER_PORT}}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # API接口 location /api/ { proxy_pass http://127.0.0.1:{{MANAGER_PORT}}/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 项目路由 - 由系统动态生成 {{PROJECT_LOCATIONS}} } ``` **Location配置模板 (location.conf.tpl)**: ```nginx # Project: {{PROJECT_NAME}} ({{PROJECT_ID}}) location /project/{{PROJECT_ID}}/ { proxy_pass http://127.0.0.1:{{PROJECT_PORT}}/; 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; # SPA路由支持 try_files $uri $uri/ /project/{{PROJECT_ID}}/index.html; } ``` ### 核心流程 **项目启动流程**: ``` 1. 查找可用内部端口 2. 启动项目服务(绑定127.0.0.1) 3. 生成/更新Nginx location配置 4. 重载Nginx 5. 返回项目URL: {BASE_URL}/project/{id}/ ``` **项目停止流程**: ``` 1. 停止项目进程 2. 更新Nginx配置(移除upstream或标记为down) 3. 重载Nginx ``` **项目删除流程**: ``` 1. 停止项目(如运行中) 2. 删除项目文件 3. 移除Nginx location配置 4. 重载Nginx ``` ### 本地开发模式 当 `USE_NGINX=auto` 时: 1. 检测系统是否安装Nginx 2. 检测Nginx配置目录是否可写 3. 若检测失败,回退到多端口模式 4. 在控制台输出当前模式信息 ### 安全考虑 1. Nginx配置文件权限控制 2. 配置变更前备份 3. 配置验证(`nginx -t`)后再重载 4. 重载失败时回滚