From 4ae8c6919342e4cf7e70010c8457a70a521eba08 Mon Sep 17 00:00:00 2001 From: v6ole Date: Fri, 26 Jun 2026 08:27:31 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20qiji=20=E9=83=A8=E7=BD=B2=E4=BA=A4?= =?UTF-8?q?=E6=8E=A5=E6=96=87=E6=A1=A3=20=E2=80=94=20FRP=20+=20OpenResty?= =?UTF-8?q?=20+=20Docker=20=E9=83=A8=E7=BD=B2=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 基于 H3ConuMS2 部署模式,适配 qiji 项目: - 新增 qiji-backend FRP 隧道 (8002→18061) - 前端容器化部署 (qiji-frontend:18063) - OpenResty 站点配置 (qj.dhdx.fun) - 复用已有 Casdoor / PostgreSQL / MinIO - 含部署检查清单和故障排查指南 - 所有敏感凭据已替换为占位符 Co-Authored-By: Claude --- qiji部署交接文档.md | 602 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 602 insertions(+) create mode 100644 qiji部署交接文档.md diff --git a/qiji部署交接文档.md b/qiji部署交接文档.md new file mode 100644 index 0000000..43adf6b --- /dev/null +++ b/qiji部署交接文档.md @@ -0,0 +1,602 @@ +# 企迹 (qiji) 部署交接文档 + +## 1. 部署架构总览 + +``` +用户浏览器 → qj.dhdx.fun → 远程服务器(175.178.19.237) + │ + OpenResty (80/443) + │ + ┌──────────────┴──────────────┐ + ▼ ▼ + 前端容器 frp 隧道(18061) + qiji-frontend │ + (18063→80) frps 服务端 + (175.178.19.237) + │ + frp 隧道 + │ + frpc 客户端 + (本机服务器) + │ + ┌──────────┴──────────┐ + ▼ ▼ + FastAPI 后端 Casdoor 认证 + (8002端口) (18000端口, 共享) + │ + ▼ + PostgreSQL (5432, 共享) + MinIO (10.10.10.13:17051) +``` + +**一句话概括:** 用户访问 `http://qj.dhdx.fun`,OpenResty 将前端 `/` 路由到前端容器(18063),将 `/api/` 路由到 FRP 隧道(18061),frp 将流量转发到本机服务器的 qiji 后端(8002)。Casdoor 和 PostgreSQL 复用已有基础设施。 + +> **与 H3ConuMS2 的关系:** qiji 和 H3ConuMS2 共享同一套基础设施(远程服务器、FRP 隧道网格、OpenResty、Casdoor、PostgreSQL),只是各自占用不同的端口和域名。互不干扰。 + +--- + +## 2. 服务器信息 + +### 远程服务器(部署 frps 服务端 + 前端容器 + OpenResty) + +| 项目 | 值 | +|------|-----| +| IP 地址 | 175.178.19.237 | +| SSH 端口 | 7072 | +| SSH 用户 | root | +| SSH 密码 | (见实际交接信息) | +| SSH 密钥 | 已安装(本机 → 远程),可直接免密登录 | +| 系统 | Ubuntu 22.04 | +| 管理面板 | 1Panel (端口 7071) | +| 配置 | 2 vCPU, 3.6GB RAM | + +### 本机服务器(部署 frpc + 后端 + 数据库) + +| 项目 | 值 | +|------|-----| +| 角色 | 本地开发/服务机 | +| FRP 类型 | frpc 原生进程(非 Docker) | +| frpc 配置文件 | `/etc/frp/frpc.toml` | +| frpc 管理地址 | http://localhost:7000 (admin / your-frp-password) | +| 操作系统 | Ubuntu (带 Docker) | + +--- + +## 3. FRP 配置(新增 qiji 隧道) + +### 当前 FRP 状态 + +frpc 已在本机以原生进程运行(`/usr/bin/frpc -c /etc/frp/frpc.toml`),所有 7 条隧道正常运行。 + +**现有隧道列表(勿动):** + +| 隧道名称 | 本地端口 | 远程端口 | 用途 | +|----------|---------|---------|------| +| mysql | 3306 | 13306 | MySQL 远程访问 | +| postgresql | 5432 | 15432 | PostgreSQL 远程访问 | +| redis | 6379 | 16379 | Redis 远程访问 | +| gitea-web | 18003 | 18009 | Gitea | +| h3conums-v2-backend | 8000 | 18060 | H3ConuMS2 后端 | +| casdoor | 18000 | 18010 | Casdoor 认证 | +| gx-gp-notify | 18001 | 18011 | 通知服务 | + +### 新增 qiji 后端隧道 + +编辑 `/etc/frp/frpc.toml`,在文件末尾添加: + +```toml +[[proxies]] +name = "qiji-backend" +type = "tcp" +localIP = "127.0.0.1" +localPort = 8002 +remotePort = 18061 +transport.useEncryption = true +``` + +然后重启 frpc: + +```bash +# frpc 是原生进程,需要 kill 后重启 +# 查看当前进程 +ps aux | grep frpc + +# 重启(二选一) +# 方式一:如果通过 systemd 管理 +sudo systemctl restart frpc + +# 方式二:如果通过 entrypoint 脚本启动 +sudo kill $(pgrep frpc) && sudo /usr/local/bin/entrypoint.d/20-frpc-start.sh & +``` + +重启后验证隧道状态: + +```bash +curl -s http://localhost:7000/api/status -u admin:your-frp-password | python3 -m json.tool | grep -A5 qiji +``` + +应显示 `"status": "running"`。 + +> ⚠️ **注意:** frpc 使用 host 网络模式(原生进程监听 0.0.0.0),所以 `localIP = "127.0.0.1"` 是安全的——frpc 只连接本机回环地址。 + +### frps 服务端(远程,无需修改) + +frps 配置文件在远程 `/opt/1panel/apps/frps/frps/data/frps.toml`,**无需修改**。只要 frpc 请求的 `remotePort` (18061) 没被远程服务器其他服务占用,隧道即可自动建立。 + +--- + +## 4. 前端部署(远程服务器 Docker 容器) + +### 4.1 构建前端镜像(本机操作) + +前端使用 Vue 3 + Vite 构建,产物由 nginx 托管在 Docker 容器中。 + +**项目中的关键文件:** +- `frontend/Dockerfile` — 多阶段构建(node:20-alpine 构建 → nginx:alpine 运行) +- `frontend/nginx.conf` — nginx 配置(SPA try_files + `/api/` 反向代理) + +**构建前置:** 确保 `frontend/.env.production`(或构建时环境变量)中 Casdoor 配置正确。Casdoor 回调地址应为 `https://qj.dhdx.fun`(或实际域名)。如果没有 `.env.production` 文件,Vite 会使用 `.env` 中的值。 + +```bash +# 1. 进入前端目录 +cd /home/v6ole/pyproject/qiji/frontend + +# 2. (可选)创建生产环境变量文件 +cat > .env.production << 'EOF' +VITE_CASDOOR_ENDPOINT=https://casdoor.dhdx.fun +VITE_CASDOOR_CLIENT_ID=your-client-id +EOF + +# 3. 构建 Docker 镜像 +docker build -t qiji-frontend:latest . + +# 4. 验证镜像 +docker images | grep qiji-frontend +``` + +### 4.2 推送镜像到远程服务器 + +```bash +# 保存镜像并远程加载 +docker save qiji-frontend:latest | ssh -p 7072 root@175.178.19.237 "docker load" + +# 验证远程镜像已加载 +ssh -p 7072 root@175.178.19.237 "docker images | grep qiji-frontend" +``` + +### 4.3 在远程服务器启动前端容器 + +```bash +ssh -p 7072 root@175.178.19.237 " + # 停止并删除旧容器(如果存在) + docker stop qiji-frontend 2>/dev/null + docker rm qiji-frontend 2>/dev/null + + # 启动新容器 + # 容器内部 nginx 监听 80,映射到宿主机 18063 + docker run -d \ + --name qiji-frontend \ + --restart always \ + -p 18063:80 \ + qiji-frontend:latest +" +``` + +### 4.4 前端更新流程(日常使用) + +```bash +cd /home/v6ole/pyproject/qiji/frontend + +# 1. 修改代码后重新构建镜像 +docker build -t qiji-frontend:latest . + +# 2. 推送并重启(一键脚本) +docker save qiji-frontend:latest | ssh -p 7072 root@175.178.19.237 "docker load && docker stop qiji-frontend && docker rm qiji-frontend && docker run -d --name qiji-frontend --restart always -p 18063:80 qiji-frontend:latest" + +# 3. 验证 +curl -s http://175.178.19.237:18063/ | head -20 +``` + +### 4.5 查看前端容器日志 + +```bash +ssh -p 7072 root@175.178.19.237 "docker logs --tail 50 qiji-frontend" +``` + +--- + +## 5. OpenResty / Nginx 配置(远程服务器) + +### 5.1 新建站点配置 + +在远程服务器创建 `/opt/1panel/apps/openresty/openresty/conf/conf.d/qj.dhdx.fun.conf`: + +```nginx +server { + listen 80; + listen 443 ssl http2; + server_name qj.dhdx.fun; + index index.html; + + # 基础代理头 + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + + access_log /www/sites/qj.dhdx.fun/log/access.log main; + error_log /www/sites/qj.dhdx.fun/log/error.log; + + # ACME 验证 + location ^~ /.well-known/acme-challenge { + allow all; + root /usr/share/nginx/html; + } + + # 安全头 + add_header Strict-Transport-Security "max-age=31536000"; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # 前端(qiji-frontend 容器,端口 18063) + location / { + proxy_pass http://127.0.0.1:18063; + } + + # 后端 API(frp 隧道 → 本机后端 8002) + location /api/ { + proxy_pass http://127.0.0.1:18061; + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + proxy_connect_timeout 60s; + } + + # HTTP → HTTPS 重定向 + if ($scheme = http) { + return 301 https://$host$request_uri; + } + + # SSL 证书(通过 1Panel 申请 Let's Encrypt 或手动上传) + ssl_certificate /www/sites/qj.dhdx.fun/ssl/fullchain.pem; + ssl_certificate_key /www/sites/qj.dhdx.fun/ssl/privkey.pem; + ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + error_page 497 https://$host$request_uri; + proxy_set_header X-Forwarded-Proto https; +} +``` + +### 5.2 应用配置 + +```bash +# 方式一:通过 SSH 直接创建配置文件 +cat << 'EOF' | ssh -p 7072 root@175.178.19.237 "cat > /opt/1panel/apps/openresty/openresty/conf/conf.d/qj.dhdx.fun.conf" +# (粘贴上面的完整 nginx 配置) +EOF + +# 创建日志目录 +ssh -p 7072 root@175.178.19.237 "mkdir -p /www/sites/qj.dhdx.fun/log /www/sites/qj.dhdx.fun/ssl" + +# 重载 OpenResty 配置(在 1Panel 面板 → OpenResty → 重载配置) +# 或通过命令行 +ssh -p 7072 root@175.178.19.237 "docker restart openresty" +``` + +> ⚠️ **注意:** 建议通过 1Panel 面板(http://175.178.19.237:7071)管理 OpenResty 站点配置和 SSL 证书。直接修改配置文件后需要在面板中**重载配置**才能生效。 + +### 5.3 DNS 配置 + +在域名 DNS 管理后台添加 A 记录: + +| 类型 | 主机记录 | 记录值 | +|------|---------|--------| +| A | qj | 175.178.19.237 | + +> 域名根据实际情况选择,如 `qj.dhdx.fun`、`qiji.dhdx.fun` 或 `weekly.dhdx.fun`。 + +### 5.4 SSL 证书 + +**方式一(推荐):** 通过 1Panel 面板为 `qj.dhdx.fun` 申请 Let's Encrypt 免费证书,自动续期。 + +**方式二:** 自签名证书(仅测试用,浏览器会报警告)。 + +**方式三:** 暂时只使用 HTTP(注释掉 ssl 相关配置行)。 + +--- + +## 6. 后端服务(本机服务器) + +### 6.1 启动方式 + +后端以原生进程运行(不容器化),与 H3ConuMS2 后端部署方式一致。 + +```bash +cd /home/v6ole/pyproject/qiji/backend + +# 确保 .env 文件配置正确 +cp .env.example .env +# 编辑 .env,填入实际值 + +# 启动后端(端口 8002,监听所有网卡) +uvicorn app.main:app --host 0.0.0.0 --port 8002 --reload +# 生产环境去掉 --reload: +# uvicorn app.main:app --host 0.0.0.0 --port 8002 +``` + +### 6.2 环境变量关键配置 + +| 配置项 | 说明 | 当前值 | +|--------|------|--------| +| `DATABASE_URL` | PostgreSQL 连接 | `postgresql+asyncpg://postgres:your-db-password@localhost:5432/qiji` | +| `CASDOOR_ENDPOINT` | Casdoor 地址 | `http://localhost:18000`(本机直连) | +| `CASDOOR_CLIENT_ID` | Casdoor 应用 ID | 与前端一致 | +| `CASDOOR_CLIENT_SECRET` | Casdoor 应用 Secret | 保密 | +| `MINIO_ENDPOINT` | MinIO 地址 | `10.10.10.13:17051` | +| `SECRET_KEY` | JWT 密钥 | 生产环境务必修改 | +| `CORS_ORIGINS` | 允许的前端域名 | 添加 `https://qj.dhdx.fun` | + +### 6.3 生产环境 CORS 配置 + +确保 `.env` 中 `CORS_ORIGINS` 包含生产域名: + +```env +CORS_ORIGINS=["http://localhost:5173","http://localhost:3000","https://qj.dhdx.fun","http://qj.dhdx.fun"] +``` + +### 6.4 后端更新流程 + +```bash +cd /home/v6ole/pyproject/qiji/backend + +# 1. 拉取最新代码 +git pull + +# 2. (如有新增依赖) +pip install -r requirements.txt + +# 3. 重启后端进程 +# 找到并杀掉旧进程 +pkill -f "uvicorn app.main:app" +# 重新启动 +uvicorn app.main:app --host 0.0.0.0 --port 8002 & +``` + +> 建议使用 `systemd` 管理后端进程(见第 10 节)。 + +--- + +## 7. MinIO 文件存储(已共享) + +### 7.1 当前状况 + +MinIO 部署在 `10.10.10.13:17051`(内网地址),qiji 使用 bucket `qiji-photos`。 + +**问题:** 前端通过预签名 URL 直传 MinIO。如果用户从公网(`qj.dhdx.fun`)访问,浏览器收到的预签名 URL 指向 `10.10.10.13:17051`,公网用户无法访问内网地址。 + +### 7.2 解决方案(三选一) + +**方案一(推荐):新增 MinIO FRP 隧道** + +在 `/etc/frp/frpc.toml` 中添加: + +```toml +[[proxies]] +name = "minio" +type = "tcp" +localIP = "10.10.10.13" +localPort = 17051 +remotePort = 18064 +transport.useEncryption = true +``` + +然后在 MinIO 端配置公网地址(或通过环境变量 `MINIO_ENDPOINT=175.178.19.237:18064`),使生成的预签名 URL 指向公网。 + +**方案二:后端代理 MinIO 流量** + +在 qiji 后端添加文件代理路由(如 `/api/files/{bucket}/{object}`),前端不直传 MinIO,而是通过后端中转。简单但增加后端带宽压力。 + +**方案三:仅限内网使用** + +如果 qiji 用户都在内网(通过 VPN 或内网 IP 访问),当前配置无需修改。 + +> **当前建议:** 如果公网用户需要上传/查看照片,选择方案一。如果只在内网使用,暂不处理。 + +--- + +## 8. Casdoor 认证(共享,已运行) + +qiji 与 H3ConuMS2 共用同一个 Casdoor 实例。 + +| 项目 | 值 | +|------|-----| +| 本机端口 | 18000 | +| FRP 远程端口 | 18010 | +| 外部访问 | `https://casdoor.dhdx.fun`(已有 Nginx 配置) | +| Casdoor 应用名 | `qiji-weekly-report` | + +### 配置要点 + +1. **Casdoor 回调地址** 必须添加 `https://qj.dhdx.fun/callback`(或实际域名) +2. 前端 `.env.production` 中 `VITE_CASDOOR_ENDPOINT` 指向 `https://casdoor.dhdx.fun` +3. 后端 `.env` 中 `CASDOOR_ENDPOINT` 指向 `http://localhost:18000`(本机直连,不经 FRP) + +--- + +## 9. 数据库(共享,已运行) + +qiji 使用已有的 PostgreSQL 实例,database 名为 `qiji`(与 H3ConuMS2 的 database 分开)。 + +| 项目 | 值 | +|------|-----| +| 本机端口 | 5432 | +| FRP 远程端口 | 15432 | +| Database | `qiji` | +| 远程连接 | `postgresql://postgres:your-db-password@175.178.19.237:15432/qiji` | + +--- + +## 10. 常见操作速查 + +### 查看 FRP 隧道状态 + +```bash +# 本机 frpc 管理 API +curl -s http://localhost:7000/api/status -u admin:your-frp-password | python3 -m json.tool + +# 只看 qiji 隧道 +curl -s http://localhost:7000/api/status -u admin:your-frp-password | python3 -c "import sys,json; d=json.load(sys.stdin); [print(p['name'],p['status'],p['local_addr'],'→',p['remote_addr']) for p in d.get('tcp',[])]" + +# 远程 frps 管理 API +curl -s http://175.178.19.237:18001/api/status -u admin:your-frp-password | python3 -m json.tool +``` + +### 重启 FRP + +```bash +# 本机 frpc(原生进程) +sudo kill $(pgrep frpc) && sudo /usr/local/bin/entrypoint.d/20-frpc-start.sh & + +# 远程 frps(Docker 容器) +ssh -p 7072 root@175.178.19.237 "docker restart Frps" +``` + +### 查看前端容器状态 + +```bash +ssh -p 7072 root@175.178.19.237 "docker ps --filter name=qiji-frontend" +ssh -p 7072 root@175.178.19.237 "docker logs --tail 30 qiji-frontend" +``` + +### 查看后端运行状态 + +```bash +# 检查后端进程 +ps aux | grep uvicorn | grep 8002 + +# 测试 API 健康 +curl http://localhost:8002/api/health +``` + +### 通过 FRP 隧道测试后端 + +```bash +# 从远程服务器测试 FRP 隧道是否通 +ssh -p 7072 root@175.178.19.237 "curl -s http://127.0.0.1:18061/api/health" + +# 从公网测试(如果 OpenResty 已配置) +curl -s https://qj.dhdx.fun/api/health +``` + +### 通过 1Panel 管理远程服务器 + +- 浏览器访问 `http://175.178.19.237:7071` +- 可视化管理:OpenResty 站点配置、SSL 证书申请、Docker 容器启停 + +--- + +## 11. 端口总览 + +### 远程服务器 (175.178.19.237) 端口 + +| 端口 | 用途 | 所属项目 | +|------|------|---------| +| 22 | SSH(通过 7072 映射) | 基础设施 | +| 7071 | 1Panel 管理面板 | 基础设施 | +| 7072 | SSH(外部访问端口) | 基础设施 | +| 80 | HTTP(OpenResty) | 基础设施 | +| 443 | HTTPS(OpenResty) | 基础设施 | +| 18000 | frps 控制端口 | 基础设施 | +| 18001 | frps 管理面板 | 基础设施 | +| 18002 | Halo 博客 | 其他 | +| 18003 | Speedtest | 其他 | +| 18004-18005 | OpenList | 其他 | +| 18006 | IP 监测 | 其他 | +| 18009 | ← Gitea (frp) | 共享 | +| 18010 | ← Casdoor (frp) | 共享 | +| 18011 | ← 通知服务 (frp) | 共享 | +| 13306 | ← MySQL (frp) | 共享 | +| 15432 | ← PostgreSQL (frp) | 共享 | +| 16379 | ← Redis (frp) | 共享 | +| 18020 | Sun-Panel | 其他 | +| 18051 | Bitwarden | 其他 | +| 18052 | CookieCloud | 其他 | +| 18054 | Bark Server | 其他 | +| 18055 | WeChat API | 其他 | +| 18060 | ← H3ConuMS2 后端 (frp) | H3ConuMS2 | +| **18061** | **← qiji 后端 (frp)** | **qiji (新增)** | +| 18062 | H3ConuMS2 前端容器 | H3ConuMS2 | +| **18063** | **qiji 前端容器** | **qiji (新增)** | +| ~~18064~~ | ~~MinIO (frp)~~ | **qiji (待定)** | + +### 本机服务器端口 + +| 端口 | 用途 | 所属项目 | +|------|------|---------| +| 3306 | MySQL | 共享 | +| 5432 | PostgreSQL | 共享 | +| 6379 | Redis | 共享 | +| 7000 | frpc 管理面板 | 基础设施 | +| 8000 | H3ConuMS2 后端 | H3ConuMS2 | +| **8002** | **qiji 后端** | **qiji** | +| 18000 | Casdoor | 共享 | +| 18001 | 通知服务 | 共享 | +| 18003 | Gitea | 共享 | + +--- + +## 12. 相关项目路径 + +| 路径 | 说明 | 所在服务器 | +|------|------|-----------| +| `/home/v6ole/pyproject/qiji/` | qiji 项目源码 | 本机 | +| `/home/v6ole/pyproject/qiji/backend/` | 后端源码 | 本机 | +| `/home/v6ole/pyproject/qiji/frontend/` | 前端源码 | 本机 | +| `/home/v6ole/pyproject/qiji/frontend/Dockerfile` | 前端镜像构建文件 | 本机 | +| `/home/v6ole/pyproject/qiji/frontend/nginx.conf` | 前端 nginx 配置 | 本机 | +| `/home/v6ole/pyproject/qiji/backend/.env` | 后端环境变量(不提交 git) | 本机 | +| `/etc/frp/frpc.toml` | frpc 配置(含 qiji 隧道) | 本机 | +| `/opt/1panel/apps/frps/frps/data/frps.toml` | frps 配置 | 远程 | +| `/opt/1panel/apps/openresty/openresty/conf/conf.d/qj.dhdx.fun.conf` | qiji 站点 Nginx 配置 | 远程 | +| `/opt/1panel/apps/openresty/openresty/www/sites/qj.dhdx.fun/ssl/` | qiji SSL 证书 | 远程 | +| `/home/v6ole/pyproject/qiji/qiji部署交接文档.md` | 本文档 | 本机 | + +--- + +## 13. 部署检查清单 + +初次部署时,按以下顺序逐项确认: + +- [ ] **后端**:`.env` 配置正确,`uvicorn` 启动在 8002 端口,`curl localhost:8002/api/health` 正常 +- [ ] **FRP 隧道**:`/etc/frp/frpc.toml` 添加 `qiji-backend` 隧道,重启 frpc 后状态为 `running` +- [ ] **FRP 验证**:从远程 `curl 127.0.0.1:18061/api/health` 能访问后端 +- [ ] **前端镜像**:`docker build -t qiji-frontend:latest .` 构建成功 +- [ ] **前端部署**:推送镜像到远程,容器运行在 18063 端口,`curl 175.178.19.237:18063/` 返回 HTML +- [ ] **OpenResty**:创建 `qj.dhdx.fun.conf`,重载配置 +- [ ] **DNS**:添加 A 记录 `qj → 175.178.19.237` +- [ ] **SSL**:通过 1Panel 申请 Let's Encrypt 证书(或自签名测试) +- [ ] **Casdoor**:确认回调地址添加 `https://qj.dhdx.fun/callback` +- [ ] **端到端**:浏览器访问 `https://qj.dhdx.fun`,登录→填报→查看周报全流程通过 +- [ ] **MinIO**:确认照片上传/查看功能正常(如果公网用户需要,配置 MinIO 隧道) + +--- + +## 14. 故障排查 + +| 现象 | 检查项 | +|------|--------| +| 页面打不开 | 远程前端容器是否运行:`docker ps \| grep qiji-frontend` | +| 页面打开但 API 报错 | FRP 隧道是否正常:`curl localhost:7000/api/status -u admin:your-frp-password` | +| API 返回 500 | 后端进程是否存活:`ps aux \| grep uvicorn \| grep 8002` | +| 登录回调失败 | Casdoor 回调地址是否包含生产域名;前端 `.env.production` 中 Casdoor 地址是否正确 | +| 照片上传失败 | MinIO 是否可达;预签名 URL 域名是否为公网可访问地址 | +| FRP 隧道状态不是 running | frpc 日志:`journalctl -u frpc -f` 或 `dmesg \| grep frpc` | + +> 文档创建日期:2026年6月26日