diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 32d8ff6..67a1b6a 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -431,6 +431,24 @@ docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --build fro --- +## 16. 备选:IP:端口模式(无域名 / 无 SSL) + +若不用域名 / 证书(域名被占用、或临时测试),可直接用 `http://:8088` 访问。**容器配置完全不变**(仍绑定 127.0.0.1),只需让宿主机 Nginx 在一个公开端口上做 HTTP 反代,并**跳过 certbot**。配置见 [deploy/nginx-ipport.conf](deploy/nginx-ipport.conf)(监听 8088、`server_name _`、反代到 127.0.0.1:8080/8000;与域名模式的 `deploy/nginx.conf` 用了不同端口与不同 upstream 名,互不冲突,可共存)。 + +部署命令(在 `/opt/qingye/chat`): + +```bash +sudo cp deploy/nginx-ipport.conf /etc/nginx/sites-available/qingye-ipport.conf && sudo ln -sf /etc/nginx/sites-available/qingye-ipport.conf /etc/nginx/sites-enabled/ && sudo nginx -t && sudo systemctl reload nginx && sudo ufw allow 8088/tcp +``` + +随后浏览器打开 `http://103.170.72.162:8088`。前端域名无关(同源 `/api/v1`、按页面协议推导 `ws://`),HTTP 下照常工作;浏览器提示「不安全」属正常。 + +> **换端口**:把 `nginx-ipport.conf` 里唯一的 `listen 8088` 与 `ufw allow 8088/tcp` 中的 `8088` 一并改掉即可。 +> **CORS**:同源访问不触发 CORS,`.env.prod` 的 `CORS_ORIGINS` 无需改也能用;想精确匹配可设为 `http://103.170.72.162:8088` 再 `docker compose -f docker-compose.prod.yml restart backend`。 +> **以后拿到域名**:启用第 7、8 节的 `deploy/nginx.conf` + certbot,IP:端口配置可保留或删除。 + +--- + ## 附:开发环境(本机) 开发环境与本指南的生产环境**完全独立**,命令不变: diff --git a/deploy.md b/deploy.md index e609ee1..f92bd48 100644 --- a/deploy.md +++ b/deploy.md @@ -1,3 +1,5 @@ 计划将这个项目部署到生产环境,域名为www.e4s.world,使用Nginx作为反向代理,使用Docker Compose作为容器编排。VPS的IP为:103.170.72.162。请修改相关代码,以便项目能区分生产环境和开发环境。 -之后,生成一个md文件,告知如何在VPS中执行部署命令。VPS的OS是Ubuntu 20.04。安装了nginx,但其他必要的软件包未安装。 \ No newline at end of file +之后,生成一个md文件,告知如何在VPS中执行部署命令。VPS的OS是Ubuntu 20.04。安装了nginx,但其他必要的软件包未安装。 + +本地自测通过了。但这个VPS之前申请过证书,并且域名www.e4s.world可能被占用了。所以我计划直接用IP地址和端口的形式部署这个qingye的服务。请修改相关设置,并给出后续部署的命令。 \ No newline at end of file diff --git a/deploy/nginx-ipport.conf b/deploy/nginx-ipport.conf new file mode 100644 index 0000000..97ba365 --- /dev/null +++ b/deploy/nginx-ipport.conf @@ -0,0 +1,93 @@ +# ============================================================ +# 青叶 (QingYe) —— 宿主机 Nginx 反向代理(IP:端口 模式,无 SSL) +# ------------------------------------------------------------ +# 适用:无域名 / 不用证书,直接用 http://:8088 访问。 +# 访问地址:http://103.170.72.162:8088 +# +# 与域名模式的 deploy/nginx.conf 互不冲突(端口不同、upstream 名不同), +# 二者可同时存在;以后拿到域名时改用 deploy/nginx.conf + certbot 即可。 +# +# 部署: +# sudo cp deploy/nginx-ipport.conf /etc/nginx/sites-available/qingye-ipport.conf +# sudo ln -sf /etc/nginx/sites-available/qingye-ipport.conf /etc/nginx/sites-enabled/ +# sudo nginx -t && sudo systemctl reload nginx +# sudo ufw allow 8088/tcp +# +# 想换端口:把下面唯一的 listen 8088 与上面的 ufw allow 8088/tcp 改掉即可。 +# +# 流量走向: +# http://:8088/ → 127.0.0.1:8080 (前端容器, SPA) +# http://:8088/api/... → 127.0.0.1:8000 (后端容器) +# http://:8088/uploads/ → 127.0.0.1:8000 (后端 StaticFiles) +# ws://:8088/ws → 127.0.0.1:8000 (后端 WebSocket) +# ============================================================ + +upstream qingye_frontend_ipport { + server 127.0.0.1:8080; +} + +upstream qingye_backend_ipport { + server 127.0.0.1:8000; +} + +server { + listen 8088; # ← 公开端口,可改 + server_name _; # 接受任意 Host(含 IP) + + # 上传体积上限:须 >= 后端 MAX_UPLOAD_SIZE_MB(默认 10MB),此处留余量 + client_max_body_size 12M; + + # 基础安全响应头(无 HTTPS,故不加 HSTS) + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + + # ---- 前端 SPA(默认路由,最低优先级)---- + location / { + proxy_pass http://qingye_frontend_ipport; + 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; + } + + # ---- API 接口(proxy_pass 不带尾部斜杠,保留 /api/ 前缀)---- + location /api/ { + proxy_pass http://qingye_backend_ipport; + 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; + } + + # ---- 上传文件(后端 StaticFiles 挂载于 /uploads)---- + location /uploads/ { + proxy_pass http://qingye_backend_ipport; + 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; + add_header X-Content-Type-Options "nosniff" always; + expires 7d; + access_log off; + } + + # ---- WebSocket(精确匹配 /ws,优先级高于 location /)---- + location = /ws { + proxy_pass http://qingye_backend_ipport; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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_read_timeout 86400s; + proxy_send_timeout 86400s; + # 不记录含 token 的查询串 + access_log off; + } +}