From f0c4134edd051972128800a731586ca815b44bde Mon Sep 17 00:00:00 2001 From: ln0422 Date: Tue, 21 Apr 2026 13:11:14 +0800 Subject: [PATCH] Document dual-domain deployment (trunk + branch1) - DESIGN.md: add branching strategy table, update online addresses with both trunk (career.ityb.me) and branch1 (www.ityb.me) URLs - OPS_MANUAL.md: update service architecture diagram, ports table (add :8001), file structure (add CareerBot-branch1), systemd services (add careerbot-branch1.service with env-based DB sharing), nginx config (three server blocks + certbot HTTPS) Co-Authored-By: Claude Opus 4.6 --- DESIGN.md | 20 ++++-- OPS_MANUAL.md | 179 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 144 insertions(+), 55 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 3da5ce1..ed85fe7 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -9,11 +9,21 @@ CareerBot 是一个个人职业展示网站,集成了 AI 智能对话助手。 ### 线上地址 -| 用途 | 地址 | -|------|------| -| 主页 | `http://www.ityb.me/careerbot/` | -| 管理后台 | `http://www.ityb.me/careerbot/admin/login` | -| Gitea 代码仓库 | `https://git.ityb.me` | +| 用途 | 地址 | 分支 | 特性 | +|------|------|------|------| +| 展示版主页(无聊天) | `https://www.ityb.me/` | branch1 | 隐藏对话按钮,纯展示 | +| 完整版主页(含聊天) | `https://career.ityb.me/careerbot/` | main (trunk) | 含 AI 对话、JD 匹配、简历生成 | +| 管理后台 | `https://career.ityb.me/careerbot/admin/login` | main (trunk) | 管理员入口 | +| Gitea 代码仓库 | `https://git.ityb.me` | - | 自托管 Git | + +### 分支策略 + +| 分支 | 部署域名 | BASE_PATH | 用途 | +|------|---------|-----------|------| +| `main`(trunk) | `career.ityb.me` | `/careerbot` | 主线开发,保留全部功能 | +| `branch1` | `www.ityb.me` / `ityb.me` | `""`(根路径) | 展示变体,隐藏 AI 对话按钮,共享 trunk 的数据库和上传目录 | + +数据层面两分支共用同一 SQLite 数据库和上传目录,后端资料同步,仅前端展示差异。 ### 技术栈 diff --git a/OPS_MANUAL.md b/OPS_MANUAL.md index 28b37a1..67c1897 100644 --- a/OPS_MANUAL.md +++ b/OPS_MANUAL.md @@ -37,8 +37,9 @@ ssh root@39.106.14.107 # root 直连 | 系统 | 地址 | 账号 | 密码 | |------|------|------|------| -| CareerBot 主页 | `http://www.ityb.me/careerbot/` | (访问令牌或匿名) | - | -| CareerBot 管理后台 | `http://www.ityb.me/careerbot/admin/login` | `ln0422@gmail.com` | `qshs123456` | +| CareerBot 展示版(branch1) | `https://www.ityb.me/` | (访问令牌或匿名) | - | +| CareerBot 完整版(trunk) | `https://career.ityb.me/careerbot/` | (访问令牌或匿名) | - | +| CareerBot 管理后台 | `https://career.ityb.me/careerbot/admin/login` | `ln0422@gmail.com` | `qshs123456` | | Gitea 代码管理 | `https://git.ityb.me` | `ln0422` | `Qshs123456_` | ### 2.3 ECS 用户密码 @@ -54,28 +55,38 @@ ssh root@39.106.14.107 # root 直连 ## 3. 服务架构 ``` -外部访问 (www.ityb.me) +外部访问 │ ▼ -┌──────────────────────────────────────────────────────┐ -│ Nginx (:80) │ -│ 配置: /etc/nginx/sites-enabled/ │ -│ 日志: /var/log/nginx/ │ -├──────────────────────────────────────────────────────┤ -│ http://www.ityb.me/ │ -│ → 302 重定向到 /careerbot/ │ -│ │ -│ http://www.ityb.me/careerbot/ │ -│ → proxy_pass http://127.0.0.1:8000/careerbot/ │ -│ → CareerBot (uvicorn, FastAPI prefix=/careerbot) │ -├──────────────────────────────────────────────────────┤ -│ https://git.ityb.me │ -│ → proxy_pass http://127.0.0.1:3000 │ -│ → Gitea │ -│ │ -│ http://39.106.14.107:3000 (向后兼容) │ -│ → Gitea (直接监听端口) │ -└──────────────────────────────────────────────────────┘ +┌────────────────────────────────────────────────────────────────┐ +│ Nginx (:80 / :443) │ +│ 配置: /etc/nginx/sites-enabled/ │ +│ 日志: /var/log/nginx/ │ +├────────────────────────────────────────────────────────────────┤ +│ https://www.ityb.me/ (主域,展示版 branch1) │ +│ https://ityb.me/ ┤ │ +│ → proxy_pass http://127.0.0.1:8001/ │ +│ → CareerBot branch1 (uvicorn, BASE_PATH="", FAB 隐藏) │ +│ │ +│ https://www.ityb.me/careerbot/* (向后兼容) │ +│ → 301 redirect https://career.ityb.me/careerbot/... │ +├────────────────────────────────────────────────────────────────┤ +│ https://career.ityb.me/careerbot/ (完整版 trunk) │ +│ → proxy_pass http://127.0.0.1:8000/careerbot/ │ +│ → CareerBot main (uvicorn, BASE_PATH="/careerbot", 完整功能) │ +├────────────────────────────────────────────────────────────────┤ +│ https://git.ityb.me │ +│ → proxy_pass http://127.0.0.1:3000 │ +│ → Gitea │ +│ │ +│ http://39.106.14.107/careerbot/ (IP 直连兼容 trunk) │ +│ http://39.106.14.107:3000 (IP 直连兼容 Gitea) │ +└────────────────────────────────────────────────────────────────┘ + +两个 CareerBot 实例共享同一 DB + uploads: + /home/deploy/apps/CareerBot/careerbot.db ← 权威数据源 + /home/deploy/apps/CareerBot/uploads/ ← 权威上传目录 + branch1 通过 systemd 环境变量 DATABASE_URL / UPLOAD_DIR 指向这里 ``` ### 端口使用 @@ -83,30 +94,37 @@ ssh root@39.106.14.107 # root 直连 | 端口 | 服务 | 监听地址 | 防火墙 | 安全组 | |------|------|---------|--------|--------| | 22 | SSH | 0.0.0.0 | 已放行 | 已放行 | -| 80 | Nginx → CareerBot | 0.0.0.0 | 已放行 | 已放行 | -| 443 | HTTPS (预留) | - | 已放行 | 已放行 | +| 80 | Nginx (HTTP → HTTPS) | 0.0.0.0 | 已放行 | 已放行 | +| 443 | Nginx (HTTPS) | 0.0.0.0 | 已放行 | 已放行 | | 3000 | Gitea | 0.0.0.0 | 已放行 | 已放行 | -| 8000 | CareerBot (uvicorn) | 127.0.0.1 | 内部 | 无需 | +| 8000 | CareerBot trunk (uvicorn) | 127.0.0.1 | 内部 | 无需 | +| 8001 | CareerBot branch1 (uvicorn) | 127.0.0.1 | 内部 | 无需 | --- ## 4. 文件目录结构 ``` -/home/deploy/apps/CareerBot/ ← 项目根目录 +/home/deploy/apps/CareerBot/ ← Trunk 项目根目录(main 分支,:8000) ├── venv/ ← Python 虚拟环境 ├── app/ ← 应用代码 ├── templates/ ← 页面模板 -├── careerbot.db ← SQLite 数据库(重要数据!) -├── uploads/ ← 用户上传文件 +├── careerbot.db ← SQLite 数据库(主数据源,branch1 也读写这里) +├── uploads/ ← 用户上传文件(主目录,branch1 也访问这里) ├── requirements.txt ├── init_data.py -├── start.bat / stop.bat ← Windows 本地启动脚本(线上不用) ├── DESIGN.md ← 设计文档 └── OPS_MANUAL.md ← 本文档 +/home/deploy/apps/CareerBot-branch1/ ← Branch1 项目根目录(branch1 分支,:8001) +├── venv/ ← 独立虚拟环境 +├── app/ ← BASE_PATH="" 的代码 +├── templates/ ← 隐藏 FAB 的 index.html +└── (无独立 careerbot.db,通过环境变量指向 trunk 的) + /etc/systemd/system/ -├── careerbot.service ← CareerBot systemd 服务 +├── careerbot.service ← CareerBot trunk systemd 服务 +├── careerbot-branch1.service ← CareerBot branch1 systemd 服务 └── gitea.service ← Gitea systemd 服务 /etc/nginx/ @@ -207,7 +225,7 @@ ssh ecs "ss -tlnp" ### 6.1 CareerBot systemd 服务 -文件:`/etc/systemd/system/careerbot.service` +**Trunk(main 分支)**:`/etc/systemd/system/careerbot.service` ```ini [Unit] Description=CareerBot Web Application @@ -226,19 +244,42 @@ Environment=PATH=/home/deploy/apps/CareerBot/venv/bin:/usr/bin WantedBy=multi-user.target ``` -关键参数: -- `--host 127.0.0.1`:只监听本地,由 Nginx 代理外部访问 +**Branch1(branch1 分支,共享 trunk 数据)**:`/etc/systemd/system/careerbot-branch1.service` +```ini +[Unit] +Description=CareerBot branch1 (display-only, shared DB with trunk) +After=network.target + +[Service] +Type=simple +User=deploy +WorkingDirectory=/home/deploy/apps/CareerBot-branch1 +ExecStart=/home/deploy/apps/CareerBot-branch1/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8001 +Restart=always +Environment=PATH=/home/deploy/apps/CareerBot-branch1/venv/bin:/usr/bin +Environment=DATABASE_URL=sqlite:////home/deploy/apps/CareerBot/careerbot.db +Environment=UPLOAD_DIR=/home/deploy/apps/CareerBot/uploads +Environment=BASE_PATH= + +[Install] +WantedBy=multi-user.target +``` + +关键差异: +- **端口**:trunk 用 8000,branch1 用 8001 +- **数据共享**:branch1 通过 `DATABASE_URL` 和 `UPLOAD_DIR` 环境变量指向 trunk 的数据库和上传目录 +- **BASE_PATH**:branch1 设置为空串,应用部署在根路径 +- **FAB 显示**:branch1 的 `templates/index.html` 已修改,对话按钮 `style="display:none;"` - `Restart=always`:崩溃后自动重启 -- `RestartSec=5`:重启间隔 5 秒 ### 6.2 Nginx 站点配置 -文件:`/etc/nginx/sites-available/careerbot.conf` -```nginx -server { - listen 80; - server_name www.ityb.me ityb.me 39.106.14.107; +文件:`/etc/nginx/sites-available/careerbot.conf`(含三段 server block + certbot 自动追加的 HTTPS 块) +```nginx +# ===== TRUNK: career.ityb.me (完整版,/careerbot/ 子路径) ===== +server { + server_name career.ityb.me; client_max_body_size 10M; location /careerbot/ { @@ -247,26 +288,64 @@ server { 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; - # SSE 流式响应支持(关键!关闭缓冲) - proxy_buffering off; - proxy_cache off; - proxy_read_timeout 300s; + proxy_buffering off; proxy_cache off; proxy_read_timeout 300s; + } + location = / { return 302 /careerbot/; } + + listen 443 ssl; # by certbot + ssl_certificate /etc/letsencrypt/live/career.ityb.me/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/career.ityb.me/privkey.pem; +} + +# ===== BRANCH1: www.ityb.me + ityb.me (展示版,根路径) ===== +server { + listen 80; + server_name www.ityb.me ityb.me; + return 301 https://$host$request_uri; +} +server { + listen 443 ssl; + server_name www.ityb.me ityb.me; + client_max_body_size 10M; + + ssl_certificate /etc/letsencrypt/live/www.ityb.me/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.ityb.me/privkey.pem; + + # 向后兼容:旧的 /careerbot/ URL 跳转到 career 子域名 + location /careerbot/ { + return 301 https://career.ityb.me$request_uri; } - # 根路径重定向到 CareerBot - location = / { - return 302 /careerbot/; + location / { + proxy_pass http://127.0.0.1:8001/; # branch1 + 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_buffering off; proxy_cache off; proxy_read_timeout 300s; } } + +# ===== IP 直连(向后兼容,HTTP only) ===== +server { + listen 80 default_server; + server_name 39.106.14.107; + client_max_body_size 10M; + + location /careerbot/ { + proxy_pass http://127.0.0.1:8000/careerbot/; + # ... 同 trunk ... + } + location = / { return 302 /careerbot/; } +} ``` 关键配置说明: -- **子路径部署**:CareerBot 部署在 `/careerbot/` 子路径下,后续其他项目可使用其他路径 -- `proxy_pass` 尾部带 `/careerbot/`:将完整路径透传给 FastAPI(FastAPI 通过 `prefix="/careerbot"` 匹配路由) +- **双域双实例**:career 子域名走 trunk(:8000),主域名走 branch1(:8001) +- **SSL 证书**:`career.ityb.me` 和 `www.ityb.me+ityb.me` 分别独立证书(均由 certbot 自动申请续期) +- **向后兼容**:`www.ityb.me/careerbot/*` 自动 301 到 `career.ityb.me/careerbot/*`,老链接不会失效 - `proxy_buffering off` + `proxy_cache off`:**必须关闭**,否则 SSE 流式对话无法实时返回 - `proxy_read_timeout 300s`:LLM 长回复可能需要较长时间 -- `client_max_body_size 10M`:允许上传最大 10MB 文件 -- 静态文件和上传文件通过 FastAPI StaticFiles 挂载在 `/careerbot/static/` 和 `/careerbot/uploads/`,无需单独 Nginx location ### 6.3 Gitea 站点配置