v0.5.5: 应急页 v0.5.4 + 移除IT设备升级 + admin登录修复 + 内容审核架构 + 知识库
This commit is contained in:
+34
-28
@@ -1,6 +1,6 @@
|
||||
# 智能IT支持服务台 — 新服务器部署手册
|
||||
|
||||
> **目标服务器**:`10.80.0.136`(公司内网)
|
||||
> **目标服务器**:`10.90.5.110`(公司内网,**2026-06-15 起替代 10.80.0.136**)
|
||||
> **域名**:`itsupport.servyou.com.cn`
|
||||
> **访问方式**:通过堡垒机 `10.212.189.210:2222`(用户 `sxn`,OTP 动态口令认证)
|
||||
> **Docker**:已安装
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
| 条件 | 状态 | 验证命令 |
|
||||
|------|------|---------|
|
||||
| Linux 服务器 10.80.0.136 | ✅ 已确认 | — |
|
||||
| Linux 服务器 10.90.5.110(替代旧 10.80.0.136) | ✅ 已确认 | 2026-06-15 起使用 |
|
||||
| Docker 已安装 | ✅ 已确认 | `docker --version` |
|
||||
| Docker Compose V2 | 待确认 | `docker compose version` |
|
||||
| 端口 80 未被占用 | 待确认 | `ss -tlnp \| grep :80` |
|
||||
@@ -29,17 +29,22 @@
|
||||
|
||||
### 2.2 连接方式
|
||||
|
||||
```bash
|
||||
# 方式一:ssh -J 一步跳转(推荐)
|
||||
# -J 指定跳板机,ssh 会自动帮你跳转
|
||||
# 堡垒机端口 2222,需要输入 OTP 动态口令
|
||||
ssh -J sxn@10.212.189.210:2222 sxn@10.80.0.136
|
||||
**PuTTY 客户端(用户实际使用)**:
|
||||
- 打开 PuTTY
|
||||
- Host Name(IP 地址):`10.212.189.210`
|
||||
- Port:`2222`
|
||||
- Connection type:SSH
|
||||
- Saved Sessions:起名(如 `wecom-bastion`)→ Save
|
||||
- 点 Open
|
||||
- 用户 `sxn` + 密码
|
||||
- **堡垒机内再跳目标机**:
|
||||
```bash
|
||||
ssh sxn@10.90.5.110
|
||||
```
|
||||
|
||||
# 方式二:先登录堡垒机,再手动跳转
|
||||
ssh -p 2222 sxn@10.212.189.210
|
||||
# 输入 OTP 动态口令
|
||||
> **OpenSSH `ssh -J` 方式不再使用**(用户已确认用 PuTTY,2026-06-15)
|
||||
# 登录成功后:
|
||||
ssh sxn@10.80.0.136
|
||||
ssh sxn@10.90.5.110
|
||||
```
|
||||
|
||||
### 2.3 配置 SSH 快捷方式(推荐)
|
||||
@@ -55,7 +60,7 @@ Host bastion
|
||||
|
||||
# 智能IT支持服务台服务器
|
||||
Host itdesk
|
||||
HostName 10.80.0.136
|
||||
HostName 10.90.5.110
|
||||
User sxn
|
||||
ProxyJump bastion
|
||||
```
|
||||
@@ -78,7 +83,7 @@ scp file itdesk:/opt/ # 文件传输也会自动走堡垒机
|
||||
# 上传单个文件
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
it-smart-desk-server-deploy.zip \
|
||||
sxn@10.80.0.136:/opt/
|
||||
sxn@10.90.5.110:/opt/
|
||||
|
||||
# 如果已配置 ~/.ssh/config:
|
||||
scp it-smart-desk-server-deploy.zip itdesk:/opt/
|
||||
@@ -96,7 +101,7 @@ scp -P 2222 it-smart-desk-server-deploy.zip sxn@10.212.189.210:/tmp/
|
||||
ssh -p 2222 sxn@10.212.189.210
|
||||
|
||||
# 步骤3:从堡垒机传到目标服务器
|
||||
scp /tmp/it-smart-desk-server-deploy.zip sxn@10.80.0.136:/opt/
|
||||
scp /tmp/it-smart-desk-server-deploy.zip sxn@10.90.5.110:/opt/
|
||||
```
|
||||
|
||||
---
|
||||
@@ -133,17 +138,18 @@ npm install && npm run build
|
||||
# 在开发机上执行
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
it-smart-desk-server-deploy.zip \
|
||||
sxn@10.80.0.136:/tmp/
|
||||
sxn@10.90.5.110:/tmp/
|
||||
```
|
||||
|
||||
> 上传到 `/tmp/` 而非 `/opt/`,因为普通用户对 `/opt/` 没有写权限
|
||||
|
||||
### 步骤 3:SSH 登录服务器并解压
|
||||
### 步骤 3:登录服务器并解压
|
||||
|
||||
**PuTTY 登录**(见 §2.2):
|
||||
- Host:`10.212.189.210`,Port:`2222`,SSH
|
||||
- 堡垒机内再 `ssh sxn@10.90.5.110`
|
||||
|
||||
```bash
|
||||
# 登录目标服务器
|
||||
ssh -J sxn@10.212.189.210:2222 sxn@10.80.0.136
|
||||
|
||||
# 切换 root(普通用户对 /opt 无写权限)
|
||||
sudo -i
|
||||
|
||||
@@ -237,7 +243,7 @@ docker compose logs --tail 50 postgres
|
||||
需要联系公司 IT 运维,在公司 DNS 上添加 A 记录:
|
||||
|
||||
```
|
||||
itsupport.servyou.com.cn A 10.80.0.136
|
||||
itsupport.servyou.com.cn A 10.90.5.110
|
||||
```
|
||||
|
||||
**DNS 未生效前**,可以通过本地 hosts 文件测试:
|
||||
@@ -246,7 +252,7 @@ itsupport.servyou.com.cn A 10.80.0.136
|
||||
# Windows: C:\Windows\System32\drivers\etc\hosts
|
||||
# macOS/Linux: /etc/hosts
|
||||
# 添加一行:
|
||||
10.80.0.136 itsupport.servyou.com.cn
|
||||
10.90.5.110 itsupport.servyou.com.cn
|
||||
```
|
||||
|
||||
> 注意:修改 hosts 文件后,浏览器可能有 DNS 缓存。Chrome 可访问 `chrome://net-internals/#dns` 清除缓存,或用无痕窗口测试。
|
||||
@@ -324,11 +330,11 @@ cd frontend-agent && npm run build
|
||||
# 2. 上传到服务器(通过堡垒机)
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r frontend-h5/dist/ \
|
||||
sxn@10.80.0.136:/opt/wecom-it-desk/frontend-h5/dist/
|
||||
sxn@10.90.5.110:/opt/wecom-it-desk/frontend-h5/dist/
|
||||
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r frontend-agent/dist/ \
|
||||
sxn@10.80.0.136:/opt/wecom-it-desk/frontend-agent/dist/
|
||||
sxn@10.90.5.110:/opt/wecom-it-desk/frontend-agent/dist/
|
||||
|
||||
# 3. 重载 Nginx(不需要重启整个服务)
|
||||
ssh itdesk # 如果已配置 SSH 快捷方式
|
||||
@@ -344,7 +350,7 @@ docker exec wecom_it_nginx nginx -s reload
|
||||
# 1. 上传新代码到服务器
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r backend/ \
|
||||
sxn@10.80.0.136:/opt/wecom-it-desk/backend/
|
||||
sxn@10.90.5.110:/opt/wecom-it-desk/backend/
|
||||
|
||||
# 2. 重新构建并启动
|
||||
ssh itdesk
|
||||
@@ -400,8 +406,8 @@ docker exec wecom_it_nginx cat /usr/share/nginx/html/itagent/index.html | grep /
|
||||
nslookup itsupport.servyou.com.cn
|
||||
|
||||
# 如果 DNS 未配置,临时用 IP 直接访问
|
||||
curl http://10.80.0.136/itdesk/
|
||||
curl http://10.80.0.136/api/health
|
||||
curl http://10.90.5.110/itdesk/
|
||||
curl http://10.90.5.110/api/health
|
||||
```
|
||||
|
||||
### Mock 登录返回 401
|
||||
@@ -428,7 +434,7 @@ curl -X POST http://localhost/api/h5/mock-login \
|
||||
### 方式一:公司统一 SSL 终端(推荐)
|
||||
|
||||
```
|
||||
客户端 → HTTPS → 公司SSL终端(F5/网关) → HTTP → 10.80.0.136:80
|
||||
客户端 → HTTPS → 公司SSL终端(F5/网关,公网 115.236.188.3) → HTTP → 10.90.5.110:80
|
||||
```
|
||||
|
||||
不需要在本服务器上配置证书。联系运维配置 SSL 终端即可。
|
||||
@@ -441,7 +447,7 @@ curl -X POST http://localhost/api/h5/mock-login \
|
||||
|
||||
## 十一、与 NAS 部署的差异
|
||||
|
||||
| 维度 | NAS 部署(10.80.0.136 旧) | 新服务器部署(10.80.0.136 新) |
|
||||
| 维度 | NAS 部署(10.80.0.136,已下线) | 新服务器部署(10.90.5.110,2026-06-15 起) |
|
||||
|------|---------------------------|-------------------------------|
|
||||
| 容器数量 | 5个(含 cloudflared) | 4个(无 cloudflared) |
|
||||
| 外网访问 | Cloudflare Tunnel | 公司 DNS 直连 |
|
||||
|
||||
@@ -27,6 +27,21 @@ http {
|
||||
access_log /var/log/nginx/access.log main;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 真实 IP 还原(2026-06-15 v0.5.1 修复)
|
||||
# ------------------------------------------------------------------
|
||||
# 问题:公司有 WAF/堡垒机/反向代理,nginx 看到的 $remote_addr
|
||||
# 是代理 IP(不在白名单),allow/deny 因此误判 403
|
||||
# 修法:信任内网段代理透传的 X-Forwarded-For 头,用真实 IP 做白名单
|
||||
# 注意:set_real_ip_from 是"我信任的代理",不是"我允许的客户端"
|
||||
# 必须精确,否则攻击者可伪造 X-Forwarded-For 绕过白名单
|
||||
set_real_ip_from 10.0.0.0/8; # 内网 A 类(代理/WAF 出口)
|
||||
set_real_ip_from 172.16.0.0/12; # 内网 B 类
|
||||
set_real_ip_from 192.168.0.0/16; # 内网 C 类
|
||||
set_real_ip_from 10.212.0.0/16; # VPN 网段
|
||||
real_ip_header X-Forwarded-For; # 从 X-Forwarded-For 取最后一个非信任 IP
|
||||
real_ip_recursive on; # 递归剥离已信任代理 IP
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 基础配置
|
||||
# ------------------------------------------------------------------
|
||||
@@ -60,29 +75,58 @@ http {
|
||||
# 如果公司有统一 SSL 终端(如 F5/Nginx 反代),此服务器只需监听 80
|
||||
# 如果需要本机 HTTPS,取消下方 server 块注释,并配置证书路径
|
||||
# =================================================================
|
||||
# HTTP — 80 端口强制 301 跳 HTTPS
|
||||
# =================================================================
|
||||
server {
|
||||
listen 80;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# ACME http-01 验证用(如果以后用 Let's Encrypt)
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
# 其他全部 301 跳 https
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTPS — 443 端口(主服务)
|
||||
# =================================================================
|
||||
server {
|
||||
listen 443 ssl;
|
||||
http2 on;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# SSL 证书(通配符 *.servyou.com.cn,fullchain 含 leaf+intermediate+root)
|
||||
ssl_certificate /etc/nginx/ssl/itsupport.servyou.com.cn.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/itsupport.servyou.com.cn.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 1d;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 安全头
|
||||
# ------------------------------------------------------------------
|
||||
# 基础安全头
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
|
||||
# CSP 收紧: 去掉 unsafe-inline(生产不需要,只有 dev HMR 需要)
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval' https://res.wx.qq.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https: http:; connect-src 'self' https://qyapi.weixin.qq.com wss://*; font-src 'self' data:;" always;
|
||||
|
||||
|
||||
# 隐私与跨域控制
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
|
||||
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
||||
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
||||
add_header Cross-Origin-Resource-Policy "same-origin" always;
|
||||
|
||||
|
||||
# 隐藏服务器版本
|
||||
server_tokens off;
|
||||
|
||||
@@ -150,7 +194,7 @@ http {
|
||||
allow 10.212.0.0/16;
|
||||
deny all;
|
||||
|
||||
proxy_pass http://backend_api/;
|
||||
proxy_pass http://backend_api;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
@@ -195,29 +239,10 @@ http {
|
||||
# 此路径已包含在 /api/ 的代理规则中,无需单独配置
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 默认路径 — 重定向到 H5 员工端
|
||||
# 默认路径 — 重定向到统一入口
|
||||
# ------------------------------------------------------------------
|
||||
location = / {
|
||||
return 302 /itdesk/;
|
||||
return 302 /itportal/;
|
||||
}
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTPS 配置(按需启用)
|
||||
# =================================================================
|
||||
# 如果需要本机直接提供 HTTPS(不走公司统一 SSL 终端),
|
||||
# 取消下方注释并配置 SSL 证书路径
|
||||
#
|
||||
# server {
|
||||
# listen 443 ssl;
|
||||
# server_name itsupport.servyou.com.cn;
|
||||
#
|
||||
# ssl_certificate /etc/nginx/ssl/itsupport.servyou.com.cn.crt;
|
||||
# ssl_certificate_key /etc/nginx/ssl/itsupport.servyou.com.cn.key;
|
||||
# ssl_protocols TLSv1.2 TLSv1.3;
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
#
|
||||
# # 其余 location 配置与上方 HTTP server 相同
|
||||
# ...
|
||||
# }
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ INCLUDE_MAP = {
|
||||
"deploy-server/nginx/nginx.conf": f"{PACKAGE_PREFIX}/nginx/nginx.conf",
|
||||
"frontend-h5/dist": f"{PACKAGE_PREFIX}/frontend-h5/dist",
|
||||
"frontend-agent/dist": f"{PACKAGE_PREFIX}/frontend-agent/dist",
|
||||
"frontend-portal/dist": f"{PACKAGE_PREFIX}/frontend-portal/dist",
|
||||
"frontend-admin/dist": f"{PACKAGE_PREFIX}/frontend-admin/dist",
|
||||
"backend": f"{PACKAGE_PREFIX}/backend",
|
||||
}
|
||||
|
||||
@@ -75,6 +77,9 @@ def run_cmd(cmd: str, cwd: Path | None = None) -> bool:
|
||||
|
||||
def should_exclude(path: Path) -> bool:
|
||||
"""判断文件/目录是否应排除"""
|
||||
# 路径中任何一段是 uploads 目录就排除(隐私 P0:真实用户上传文件不进部署包)
|
||||
if "uploads" in path.parts:
|
||||
return True
|
||||
name = path.name
|
||||
if name in {"__pycache__", ".pytest_cache", ".venv", "venv", ".git", ".env", "node_modules"}:
|
||||
return True
|
||||
@@ -121,6 +126,32 @@ def build_frontends():
|
||||
sys.exit(1)
|
||||
print(" ✅ 坐席工作台构建完成")
|
||||
|
||||
# 统一入口 Portal
|
||||
portal_dir = PROJECT_ROOT / "frontend-portal"
|
||||
if (portal_dir / "package.json").exists():
|
||||
print("构建统一入口 Portal...")
|
||||
if not run_cmd("npm install --quiet", cwd=portal_dir):
|
||||
print(" ⚠ npm install 失败,尝试继续...")
|
||||
if not run_cmd("npm run build", cwd=portal_dir):
|
||||
print(" ❌ Portal 端构建失败!")
|
||||
sys.exit(1)
|
||||
print(" ✅ Portal 端构建完成")
|
||||
else:
|
||||
print(" ⏭ Portal 端未实现,跳过")
|
||||
|
||||
# 管理后台 Admin
|
||||
admin_dir = PROJECT_ROOT / "frontend-admin"
|
||||
if (admin_dir / "package.json").exists():
|
||||
print("构建管理后台 Admin...")
|
||||
if not run_cmd("npm install --quiet", cwd=admin_dir):
|
||||
print(" ⚠ npm install 失败,尝试继续...")
|
||||
if not run_cmd("npm run build", cwd=admin_dir):
|
||||
print(" ❌ Admin 端构建失败!")
|
||||
sys.exit(1)
|
||||
print(" ✅ Admin 端构建完成")
|
||||
else:
|
||||
print(" ⏭ Admin 端未实现,跳过")
|
||||
|
||||
|
||||
def create_package():
|
||||
"""创建部署包 zip"""
|
||||
@@ -181,13 +212,13 @@ def main():
|
||||
print(" 后续步骤:")
|
||||
print("=" * 50)
|
||||
print(f"""
|
||||
1. 上传部署包到服务器(通过堡垒机):
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \\
|
||||
{ZIP_FILENAME} \\
|
||||
sxn@10.80.0.136:/tmp/
|
||||
1. 上传部署包到服务器(通过堡垒机 / PuTTY PSCP):
|
||||
pscp -load wecom-bastion {ZIP_FILENAME} sxn@10.90.5.110:/tmp/
|
||||
# 或堡垒机内 scp:
|
||||
# scp {ZIP_FILENAME} sxn@10.90.5.110:/tmp/
|
||||
|
||||
2. SSH 登录服务器(通过堡垒机):
|
||||
ssh -J sxn@10.212.189.210:2222 sxn@10.80.0.136
|
||||
2. PuTTY 登录服务器:
|
||||
- Host 10.212.189.210 Port 2222 → 用户 sxn → 堡垒机内 ssh sxn@10.90.5.110
|
||||
|
||||
3. 在服务器上执行:
|
||||
sudo cp /tmp/{ZIP_FILENAME} /opt/
|
||||
@@ -201,7 +232,7 @@ def main():
|
||||
./deploy.sh
|
||||
|
||||
4. 配置 DNS(联系 IT 运维):
|
||||
itsupport.servyou.com.cn → 10.80.0.136
|
||||
itsupport.servyou.com.cn → 10.90.5.110
|
||||
|
||||
5. 浏览器验证:
|
||||
http://itsupport.servyou.com.cn/itdesk/
|
||||
|
||||
Reference in New Issue
Block a user