Files
frontend-miniapp/docs/deployment/guide-test-server-nginx-ssl.md
lyf 337446f33c
Some checks failed
CI / verify (push) Has been cancelled
停用 stop/info 旧接口,统一详情入参为 stopId
- 详情页路由入参统一为 stopId,废弃 targetType/targetId
- ExplainDetailEntryRequest 与 GlobalAudioSource 移除 targetType/targetId 字段
- 播放器源匹配仅按 stopId 判定,移除 targetType 兜底
- 删除 explainDetailTarget 死代码
- 清理 guideStopInfoAdapter 中 stop/info、play-info、text-info 旧契约类型与转换函数
- 补充测试服务器 Nginx SSL 部署手册
- 同步更新单测与 e2e 用例

Made-with: Proma
2026-09-17 11:30:32 +08:00

614 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 测试服务器导览 H5 部署手册
最后更新2026-09-15
## 1. 部署目标
- 站点:`guide.whaoyue.com`
- 服务器公网 IP`124.220.83.186`
- SSH 用户:`root`
- 操作系统Ubuntu 22.04.5 LTS
- HTTPS 入口:`https://guide.whaoyue.com:4433/`
- HTTP/IP 测试入口:`http://124.220.83.186:8888/`
- 部署对象:`frontend-miniapp` H5 构建产物
- Nginx 容器:`sgs-nature-nginx`
`8888` 直接提供明文 HTTP不再跳转到 HTTPS并接受域名、公网 IP 和其他 Host。HTTP 仅用于测试;请求内容、登录凭据和 Token 均不会被加密,不得作为生产入口。
Nginx 源站也支持 `http://guide.whaoyue.com:8888/`,但截至 2026-09-15腾讯侧会在请求到达 Nginx 前将该域名 HTTP 请求重定向到 DNSPod `webblock` 页面。因此公网 HTTP 验收应使用 IP 入口;该外部拦截不能通过本机 Nginx 配置消除。
域名 DNS A 记录应指向:
```text
guide.whaoyue.com -> 124.220.83.186
```
## 2. 当前部署拓扑
```text
公网用户
-> 124.220.83.186:8888HTTP/ guide.whaoyue.com:4433HTTPS
-> sgs-nature-nginx Docker 容器
-> 容器使用 host 网络
-> /usr/share/nginx/html/guide
-> 宿主机 /data/sgs-nature/web/guide
```
`sgs-nature-nginx` 当前不是 Docker Compose、Docker Stack、systemd 或 1Panel 项目管理的容器,而是手动创建并启动的 Docker 容器。
容器实际参数:
```text
镜像nginx:latest
Nginx1.31.3
网络host
重启策略unless-stopped
启动命令nginx -g 'daemon off;'
```
当前容器挂载:
| 宿主机路径 | 容器路径 | 权限 | 用途 |
| --- | --- | --- | --- |
| `/data/sgs-nature/deploy/nginx.conf` | `/etc/nginx/conf.d/default.conf` | 只读 | Nginx 配置 |
| `/data/sgs-nature/web` | `/usr/share/nginx/html` | 只读 | 静态站点和资源 |
由于容器使用 `host` 网络Docker 没有 `-p` 端口映射。Nginx 配置中的 `listen 8888``listen 4433` 就是宿主机的监听端口。`8888` 直接提供 HTTP`4433` 提供 HTTPS。
不要操作或重启服务器上另一个名为 `nginx` 的容器。该容器占用公网标准端口 `80/443`,与本导览容器职责不同。因此导览 HTTP 入口必须显式携带 `:8888`,不能使用无端口的 `http://124.220.83.186/`
## 3. 服务器目录
导览站点目录:
```text
/data/sgs-nature/web/guide/
```
容器内对应目录:
```text
/usr/share/nginx/html/guide/
```
证书目录按当前部署方案放在已有 Web 挂载目录内:
```text
/data/sgs-nature/web/ssl/guide.whaoyue.com/fullchain.pem
/data/sgs-nature/web/ssl/guide.whaoyue.com/privkey.pem
```
容器内证书路径:
```text
/usr/share/nginx/html/ssl/guide.whaoyue.com/fullchain.pem
/usr/share/nginx/html/ssl/guide.whaoyue.com/privkey.pem
```
证书目录位于 Web 挂载目录下,因此 Nginx 配置必须拒绝公网访问:
```nginx
location ^~ /ssl/ {
deny all;
return 404;
}
```
证书权限建议:
```text
fullchain.pem0644
privkey.pem0600
```
相关部署和备份文件:
```text
/data/sgs-nature/deploy/nginx.conf
/data/sgs-nature/backup/
```
## 4. 本地构建
项目根目录:
```text
E:\MyWork\深圳国际艺术馆\museum-guide\museum-guide-v4.0\frontend-miniapp
```
环境要求:
- Node.js `>=20 <25`
- pnpm 9
安装依赖:
```powershell
pnpm install
```
测试环境默认配置文件为 `.env.test`,关键配置如下:
```dotenv
VITE_APP_PUBLIC_BASE=/
VITE_GUIDE_DATA_SOURCE_MODE=sdk
VITE_EXPLAIN_CONTENT_SOURCE_MODE=remote
VITE_DATA_SOURCE_MODE=sdk
VITE_GUIDE_CONTENT_SOURCE_MODE=remote
VITE_GUIDE_STATIC_DATA_BASE_URL=/static/guide-data
VITE_API_BASE_URL=/app-api
VITE_AUDIO_API_BASE_URL=/app-api
VITE_SGS_API_BASE_URL=/app-api
VITE_SGS_MAP_ID=1
VITE_SGS_SDK_SCRIPT_URL=/static/sgs-map-sdk/index.global.js?v=2.5.0
VITE_SGS_H5_ENGINE_URL=/engine/index.html
VITE_SGS_SDK_ORIGIN=
```
由于站点通过域名根路径提供服务,`VITE_APP_PUBLIC_BASE` 必须为 `/`,不能设置为 `/guide/``guide` 是服务器上的目录名,不是 URL 路径。
执行质量检查和测试构建:
```powershell
pnpm type-check
pnpm lint
pnpm build:test:h5
```
`pnpm build:test:h5` 会生成 H5 产物,并复制以下资源:
- `static/nav-assets`
- `static/guide-data`
- `static/sgs-map-sdk`
- `static/three`
- `static/icons`
- `static/explain`
- `static/Fonts`
- `engine`
- 讲解图片、占位图片等补充资源
构建目录:
```text
dist/build/h5/
```
生产发布需要真实腾讯地图 Web Key 时,使用生产构建:
```powershell
$env:VITE_TENCENT_MAP_KEY = '<真实腾讯地图 Web Key>'
pnpm build:h5
Remove-Item Env:VITE_TENCENT_MAP_KEY
```
不要将真实 Key、密码、Token 或其他密钥提交到仓库。
构建后建议检查:
```powershell
Test-Path dist\build\h5\index.html
Get-ChildItem dist\build\h5 -Recurse -File | Measure-Object Length -Sum
rg -n -S --glob '!*.map' '1\.92\.206\.90|guide\.whaoyue\.com|http://124\.220\.83\.186:9000' dist\build\h5
```
最后一个命令不应出现旧服务器地址或不应使用的绝对 HTTP 资源地址。
## 5. 打包和上传
在项目根目录执行:
```powershell
New-Item -ItemType Directory -Force -Path '.tmp' | Out-Null
$archive = '.tmp\museum-guide-h5.tar.gz'
if (Test-Path -LiteralPath $archive) {
Remove-Item -LiteralPath $archive -Force
}
tar -C 'dist\build\h5' -czf $archive .
```
SSH 主机别名为:
```text
museum-guide-test
```
该别名位于本机:
```text
C:\Users\Administrator\.ssh\config
```
上传构建包:
```powershell
scp '.tmp\museum-guide-h5.tar.gz' 'museum-guide-test:/tmp/museum-guide-h5.tar.gz'
```
不要把密码写入 SSH 配置、命令脚本或部署文档。
## 6. 证书
当前使用的证书为 `guide.whaoyue.com` 的 Lets Encrypt 证书,记录的有效期为:
```text
Not Before: 2026-06-07 15:33:10 GMT
Not After: 2026-09-05 15:33:09 GMT
```
截至 2026-09-15该证书已经过期。`4433` 仍能建立忽略证书校验的 HTTPS 连接,但浏览器会显示安全警告;应尽快完成证书续期。开放 `8888` HTTP 仅用于测试,不替代证书续期。
查看证书:
```bash
openssl x509 \
-in /data/sgs-nature/web/ssl/guide.whaoyue.com/fullchain.pem \
-noout -subject -issuer -dates
```
证书续期注意事项:
- 新服务器目前没有发现已配置的 `acme.sh``certbot` 续期任务。
- Lets Encrypt HTTP-01 验证固定使用公网 `80`,不会访问 `8888`
- 公网 `80/443` 已被服务器上另一个 `nginx` 容器占用。
- 证书到期前必须配置 DNS-01或者制定临时借用公网 `80` 完成验证的方案。
- 续期后需要把新证书复制到上述目录,并执行 Nginx 配置检查和 reload。
续期后的最低操作:
```bash
docker exec sgs-nature-nginx nginx -t
docker exec sgs-nature-nginx nginx -s reload
openssl x509 \
-in /data/sgs-nature/web/ssl/guide.whaoyue.com/fullchain.pem \
-noout -subject -issuer -dates
```
## 7. Nginx 配置
配置文件:
```text
/data/sgs-nature/deploy/nginx.conf
```
当前已有 `18101` server服务 `/dp/``/gl/``/map/` 及自然馆测试环境 API。新增导览站点时不得删除或覆盖该 server。
导览 HTTP 与 HTTPS 由同一个 server 块提供,以避免两套静态资源和反向代理规则发生漂移。核心配置:
```nginx
server {
# 测试环境明文 HTTP公网 80 仍由另一 nginx 容器占用。
listen 8888 default_server;
listen 4433 ssl;
server_name guide.whaoyue.com 124.220.83.186 _;
root /usr/share/nginx/html/guide;
index index.html;
ssl_certificate /usr/share/nginx/html/ssl/guide.whaoyue.com/fullchain.pem;
ssl_certificate_key /usr/share/nginx/html/ssl/guide.whaoyue.com/privkey.pem;
location ^~ /ssl/ {
deny all;
return 404;
}
location ^~ /static/nav-assets/ {
try_files $uri =404;
}
location ^~ /assets/ {
try_files $uri =404;
}
location ^~ /engine/ {
try_files $uri =404;
}
location ^~ /static/ {
try_files $uri =404;
}
location ^~ /app-api/ {
proxy_pass http://127.0.0.1:48100;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location ^~ /minio/ {
proxy_pass http://127.0.0.1:9000/;
proxy_http_version 1.1;
proxy_set_header Host 127.0.0.1:9000;
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 300s;
}
location ^~ /museum-assets/ {
proxy_pass http://127.0.0.1:9000/museum-assets/;
proxy_http_version 1.1;
proxy_set_header Host 127.0.0.1:9000;
expires 30d;
add_header Cache-Control "public";
proxy_read_timeout 300s;
}
location / {
try_files $uri $uri/ /index.html;
}
}
```
`/static/nav-assets/` 必须使用 `try_files $uri =404`,避免缺失 JSON、GLB 或其他模型资源时错误返回 SPA 的 `index.html`
修改配置前备份:
```bash
TS=$(date +%Y%m%d%H%M%S)
cp -p /data/sgs-nature/deploy/nginx.conf \
"/data/sgs-nature/backup/nginx-before-guide-$TS.conf"
```
配置文件以单文件 bind mount 方式挂载。修改时必须保留宿主机文件 inode例如原地编辑或使用 `cat candidate.conf > "$CONFIG"`;不要使用 `mv``install` 或其他原子替换方式覆盖路径。替换 inode 后,容器会继续看到旧文件,普通 reload 不会载入新配置。
修改后先确认宿主机和容器内文件一致,再检查并 reload
```bash
CONFIG=/data/sgs-nature/deploy/nginx.conf
sha256sum "$CONFIG"
docker exec sgs-nature-nginx \
sha256sum /etc/nginx/conf.d/default.conf
docker exec sgs-nature-nginx nginx -t
docker exec sgs-nature-nginx nginx -s reload
```
配置检查失败时不得 reload。应使用备份原地恢复配置重新执行 `nginx -t`,确认通过后再 reload。如果已经替换了 inode应先用独立临时容器对宿主机新配置执行 `nginx -t`,然后只重启 `sgs-nature-nginx` 使其重新建立挂载;仍然不要操作另一个名为 `nginx` 的容器。
本部署方式不需要:
- 新增 Docker Compose 文件
- 新增 Nginx systemd 服务
- 新增 Docker 端口映射
- 重启服务器原有 `nginx` 容器
## 8. 发布站点文件
上传压缩包后,在服务器上执行。发布前先备份当前 `guide` 目录:
```bash
set -e
SITE=/data/sgs-nature/web/guide
ARCHIVE=/tmp/museum-guide-h5.tar.gz
TS=$(date +%Y%m%d%H%M%S)
BACKUP=/data/sgs-nature/backup
mkdir -p "$SITE" "$BACKUP"
if [ -f "$SITE/index.html" ]; then
tar -C "$SITE" -czf "$BACKUP/guide-before-deploy-$TS.tar.gz" .
fi
test -f "$ARCHIVE"
find "$SITE" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
tar -C "$SITE" -xzf "$ARCHIVE"
mkdir -p /data/sgs-nature/web/ssl/guide.whaoyue.com
printf 'backup=%s\n' "$BACKUP/guide-before-deploy-$TS.tar.gz"
printf 'files=%s\n' "$(find "$SITE" -type f | wc -l)"
```
证书目录不属于 H5 构建包,不能在清理站点目录时误删。证书位于同级的 `/data/sgs-nature/web/ssl/`,不在 `/data/sgs-nature/web/guide/` 内。
如果证书需要更新:
```bash
install -o root -g root -m 0644 fullchain.pem \
/data/sgs-nature/web/ssl/guide.whaoyue.com/fullchain.pem
install -o root -g root -m 0600 privkey.pem \
/data/sgs-nature/web/ssl/guide.whaoyue.com/privkey.pem
```
## 9. 部署后验证
### 9.1 DNS 和端口
在 Windows PowerShell 中:
```powershell
Resolve-DnsName guide.whaoyue.com -Type A
Test-NetConnection 124.220.83.186 -Port 8888
Test-NetConnection guide.whaoyue.com -Port 4433
```
DNS A 记录应为 `124.220.83.186`
### 9.2 HTTP/IP 和 HTTPS
```powershell
curl.exe -I --max-time 30 http://124.220.83.186:8888/
curl.exe -k -I --max-time 30 https://guide.whaoyue.com:4433/
```
期望:
```text
124.220.83.186:8888200 OK不跳转
guide.whaoyue.com:4433200 OK
```
公网直接访问 `http://guide.whaoyue.com:8888/` 可能收到腾讯 DNSPod `webblock``302`,这不代表源站 Nginx 未启用 HTTP。可在服务器本机携带域名 Host 验证源站:
```bash
curl -I -H 'Host: guide.whaoyue.com' http://127.0.0.1:8888/
```
源站期望返回 `200 OK`
检查证书:
```powershell
cmd /c "echo.| openssl s_client -connect guide.whaoyue.com:4433 -servername guide.whaoyue.com 2>NUL | openssl x509 -noout -subject -issuer -dates"
```
### 9.3 关键静态资源
不要固定使用旧版本的导航资源目录名。先从构建产物或服务器目录查找当前 Manifest
```bash
find /data/sgs-nature/web/guide/static/nav-assets \
-name app_nav_manifest.json -print
```
假设当前资源包目录为:
```text
/static/nav-assets/<当前资源包目录>/
```
验证 Manifest、楼层数据和 GLB
```powershell
curl.exe -k -I --max-time 30 https://guide.whaoyue.com:4433/static/guide-data/manifest.json
curl.exe -k -I --max-time 30 https://guide.whaoyue.com:4433/static/sgs-map-sdk/index.global.js
curl.exe -k -I --max-time 30 https://guide.whaoyue.com:4433/engine/index.html
curl.exe -k -I --max-time 30 https://guide.whaoyue.com:4433/static/icons/marker-exhibit.svg
```
导航资源应至少验证:
- `app_nav_manifest.json``200`JSON
- 一个实际楼层 JSON`200`JSON
- 一个实际 GLB`200``model/gltf-binary`
- 不存在的 GLB`404`
缺失的导航资源不能返回 `index.html`
### 9.4 API 和原有服务
```powershell
curl.exe -I --max-time 30 http://124.220.83.186:8888/app-api/gis/sdk/maps/1/manifest
curl.exe -k -I --max-time 30 https://guide.whaoyue.com:4433/app-api/gis/sdk/maps/1/manifest
curl.exe -I --max-time 30 http://124.220.83.186:18101/dp/
```
期望:
```text
HTTP 与 HTTPS /app-api/gis/sdk/maps/1/manifest200 application/json
18101 /dp/200
```
### 9.5 私钥保护
```powershell
curl.exe -sS -o NUL -w "%{http_code}\n" `
http://124.220.83.186:8888/ssl/guide.whaoyue.com/privkey.pem
curl.exe -k -sS -o NUL -w "%{http_code}\n" `
https://guide.whaoyue.com:4433/ssl/guide.whaoyue.com/privkey.pem
```
两个入口都应返回:
```text
404
```
### 9.6 浏览器验收
分别打开:
```text
http://124.220.83.186:8888/
https://guide.whaoyue.com:4433/
```
证书续期前,第二个地址会显示证书过期警告。
至少检查:
- 首页正常加载
- 馆外 2D 地图和馆内 3D 入口显示正常
- 进入馆内 3D 后,实际楼层模型可以加载
- 楼层切换和 POI 数据正常
- 讲解列表、展厅、讲解点和详情页正常
- 图片、模型、音频没有 Mixed Content
- 浏览器控制台没有关键资源 404
- 不存在的模型资源不会返回 HTML
- `/dp/``/gl/``/map/` 原有服务未受影响
## 10. 回滚
### 10.1 回滚前端文件
部署时会在以下目录生成备份:
```text
/data/sgs-nature/backup/guide-before-deploy-YYYYMMDDHHMMSS.tar.gz
```
回滚:
```bash
set -e
SITE=/data/sgs-nature/web/guide
BACKUP=/data/sgs-nature/backup/guide-before-deploy-YYYYMMDDHHMMSS.tar.gz
test -f "$BACKUP"
find "$SITE" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
tar -C "$SITE" -xzf "$BACKUP"
docker exec sgs-nature-nginx nginx -t
docker exec sgs-nature-nginx nginx -s reload
```
### 10.2 回滚 Nginx 配置
```bash
set -e
CONFIG=/data/sgs-nature/deploy/nginx.conf
BACKUP=/data/sgs-nature/backup/nginx-before-guide-YYYYMMDDHHMMSS.conf
test -f "$BACKUP"
cat "$BACKUP" > "$CONFIG"
chown root:root "$CONFIG"
chmod 0644 "$CONFIG"
docker exec sgs-nature-nginx nginx -t
docker exec sgs-nature-nginx nginx -s reload
```
回滚时只恢复对应的 `guide` 文件或 Nginx 配置,不要删除整个 `/data/sgs-nature/web`,以免影响 `/dp``/gl` 等现有站点。
## 11. 当前部署记录
2026-09-15
-`8888` 从 HTTP→HTTPS 跳转改为直接提供导览 H5公网 IP 入口为 `http://124.220.83.186:8888/`
- `8888` HTTP 与 `4433` HTTPS 共用同一 server 块,支持域名、公网 IP 和其他 Host
- 配置备份:`/data/sgs-nature/backup/nginx-before-ip-http-20260915114641.conf`
- 候选配置和运行容器的 `nginx -t` 均通过;因单文件 bind mount 的 inode 被替换,仅重启了 `sgs-nature-nginx` 以重新挂载配置
- 公网验证IP HTTP 首页、Manifest、`/app-api/` 均返回 `200`HTTP/HTTPS 私钥路径均返回 `404``4433` HTTPS 与原有 `18101 /dp/` 均返回 `200`
- 域名 HTTP 请求仍被腾讯 DNSPod `webblock` 在源站前重定向;服务器本机以域名 Host 访问 `8888` 返回 `200`
- `guide.whaoyue.com` 当前证书已于 2026-09-05 过期,待单独续期
2026-08-27
- 使用 `pnpm build:test:h5` 构建测试 H5
- 类型检查通过
- Lint 无错误,有 1 个既有未使用变量 warning
- 构建产物 229 个文件,约 204 MB
- 发布到 `/data/sgs-nature/web/guide`
- 复用 `/data/sgs-nature/web` 现有挂载存放证书
- 更新 `/data/sgs-nature/deploy/nginx.conf`
- `sgs-nature-nginx` 执行 `nginx -t` 和 reload
- `8888` 跳转、`4433` HTTPS、API、讲解数据、SDK、Engine、GLB 和私钥保护验证通过
- 原有 `18101 /dp/` 验证通过
本次构建使用测试环境腾讯地图 Key 占位符,不代表正式生产地图 Key 已配置。正式发布前需要注入真实 Key 后重新构建并验证。