---
belongs_to:
  - "[[⚒️ 铸渊·协作指令｜GitHub ↔ Notion 桥接协议]]"
related_to:
  - "[["$STATUS" =~ ^(200|301|302)$]]"
---
# 铸渊精确修复令｜Nginx root 路径修正 + 全站模块上线（ZY-NGINX-ROOTFIX-2026-0325-001）· 霜砚签发 · 冰朔授权

## 签发信息

| 项目 | 内容 |
| --- | --- |
| 签发人 | AG-SY-01 霜砚 · 冰朔授权 |
| 签发时间 | 2026-03-25 08:55 CST |
| 优先级 | **P0 · 立即执行** |
| 指令编号 | ZY-NGINX-ROOTFIX-2026-0325-001 |
| 诊断来源 | DEV-004 之之 · 全站部署诊断报告 · 2026-03-25 |
| 关联仓库 | `qinfendebingshuo/guanghulab` |
| 服务器 | 8.155.62.235（阿里云 ECS） |

---

## 〇、根因（已锁死·不需要再排查）

<aside>
🎯

**双重路径孤岛**：GitHub Actions 把文件 rsync 到 `/var/www/guanghulab`（85M，全站模块完整），但 Nginx 的 root 还指着 `/var/www/hololake-frontend`（1.1M，旧残留）。

CD 一直在成功部署。网站一直是空的。因为 **Nginx 在看一个错误的目录**。

</aside>

### 诊断数据摘要（之之实测）

| 项目 | 当前值 | 正确值 | 状态 |
| --- | --- | --- | --- |
| Nginx root | `/var/www/hololake-frontend` | `/var/www/guanghulab` | ❌ 错误 |
| DEPLOY_PATH | `/var/www/guanghulab` | `/var/www/guanghulab` | ✅ 正确 |
| rsync 范围 | 全仓库同步 | 全仓库同步 | ✅ 正确 |
| SSL 证书 | 有效至 2026-06-02 | — | ✅ 正常 |
| `/var/www/guanghulab` 大小 | 85M | — | ✅ 文件完整 |
| `/var/www/hololake-frontend` 大小 | 1.1M | — | ⚠️ 旧残留 |
| DEV-004 沙盒文件 | 存在，完整 | — | ✅ |
| DEV-004 PM2 进程 | errored | online | ❌ 需修复 |
| `_shared` 目录 | 缺失 | 需创建 | ❌ 缺失 |
| 模块 alias 路由 | 无 | 需添加 | ❌ 缺失 |

---

## 一、Phase 1 · 备份（动任何东西之前）

<aside>
🔴

**必须先备份再改。不备份不动手。**

</aside>

```bash
#!/bin/bash
# phase1-backup.sh · 修复前完整备份
echo "===== 🔒 Phase 1 · 修复前备份 · $(date '+%Y-%m-%d %H:%M') ====="

# 1. 备份 Nginx 配置
cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak.$(date +%Y%m%d%H%M)
echo "✅ Nginx 配置已备份"

# 2. 如果还有 hololake.conf，也备份
if [ -f /etc/nginx/conf.d/hololake.conf ]; then
  cp /etc/nginx/conf.d/hololake.conf /etc/nginx/conf.d/hololake.conf.bak.$(date +%Y%m%d%H%M)
  echo "✅ hololake.conf 已备份"
fi

# 3. 快照现有部署目录文件列表
find /var/www/guanghulab -type f > /tmp/pre-fix-filelist-guanghulab.txt 2>/dev/null
find /var/www/hololake-frontend -type f > /tmp/pre-fix-filelist-hololake.txt 2>/dev/null
find /var/www/DEV-004 -type f > /tmp/pre-fix-filelist-DEV004.txt 2>/dev/null
echo "✅ 文件快照已保存到 /tmp/pre-fix-filelist-*.txt"

# 4. PM2 进程快照
pm2 list > /tmp/pre-fix-pm2-list.txt 2>/dev/null
echo "✅ PM2 进程快照已保存"

echo "===== ✅ 备份完成 · 开始修复 ====="
```

---

## 二、Phase 2 · Nginx root 路径修正（核心修复·一行搞定）

```bash
#!/bin/bash
# phase2-fix-nginx-root.sh · 修正 Nginx root 路径
echo "===== 🔧 Phase 2 · Nginx root 修正 ====="

NGINX_CONF="/etc/nginx/conf.d/default.conf"

# 检查当前 root 值
echo "📋 修改前的 root 配置："
grep -n 'root ' $NGINX_CONF

# 执行替换：hololake-frontend → guanghulab
sed -i 's|root /var/www/hololake-frontend|root /var/www/guanghulab|g' $NGINX_CONF

# 如果 hololake.conf 里也有，一并修改
if [ -f /etc/nginx/conf.d/hololake.conf ]; then
  sed -i 's|root /var/www/hololake-frontend|root /var/www/guanghulab|g' /etc/nginx/conf.d/hololake.conf
  echo "✅ hololake.conf 也已修正"
fi

echo ""
echo "📋 修改后的 root 配置："
grep -n 'root ' $NGINX_CONF

# 语法测试
nginx -t 2>&1
if [ $? -eq 0 ]; then
  echo "✅ nginx -t 通过 · 执行 reload"
  systemctl reload nginx
  echo "✅ Nginx 已重载"
else
  echo "❌ nginx -t 失败 · 恢复备份"
  cp ${NGINX_CONF}.bak.* $NGINX_CONF 2>/dev/null
  nginx -t && systemctl reload nginx
  echo "⚠️ 已回滚到备份配置"
fi

echo "===== ✅ Phase 2 完成 ====="
```

---

## 三、Phase 3 · 沙盒模块 alias 路由补充

在 Nginx server 块中追加以下 location 块，让沙盒里的模块也能通过域名访问：

```bash
#!/bin/bash
# phase3-add-sandbox-routes.sh · 补充沙盒 alias 路由
echo "===== 🔧 Phase 3 · 沙盒路由补充 ====="

NGINX_CONF="/etc/nginx/conf.d/default.conf"

# 在 server 块末尾的 } 之前插入沙盒路由
# 铸渊：找到 server 块最后一个 location 之后、} 之前的位置插入

# DEV-004 之之 · 悬浮球
if [ -d /var/www/DEV-004/floating-ai ]; then
  cat >> /tmp/sandbox-routes.conf << 'ROUTES'

    # --- DEV-004 之之 · 沙盒路由 ---
    location /DEV-004/ {
        alias /var/www/DEV-004/;
        index index.html;
        try_files $uri $uri/ =404;
    }
ROUTES
  echo "✅ DEV-004 路由已准备"
fi

# DEV-005 小草莓 · 如果沙盒有内容
if [ -d /var/www/DEV-005 ] && [ "$(ls -A /var/www/DEV-005 2>/dev/null)" ]; then
  cat >> /tmp/sandbox-routes.conf << 'ROUTES'

    # --- DEV-005 小草莓 · 沙盒路由 ---
    location /DEV-005/ {
        alias /var/www/DEV-005/;
        index index.html;
        try_files $uri $uri/ =404;
    }
ROUTES
  echo "✅ DEV-005 路由已准备"
fi

# 后端 API 反向代理（确认存在，没有则追加）
if ! grep -q 'location /api/' $NGINX_CONF; then
  cat >> /tmp/sandbox-routes.conf << 'ROUTES'

    # --- 后端 API 反向代理 ---
    location /api/ {
        proxy_pass http://127.0.0.1:3000/;
        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_cache_bypass $http_upgrade;
    }
ROUTES
  echo "✅ API 反向代理路由已准备"
fi

# Persona Studio 代理（修复 HTTP 405 的关键）
if ! grep -q 'location /api/ps/' $NGINX_CONF; then
  cat >> /tmp/sandbox-routes.conf << 'ROUTES'

    # --- Persona Studio 后端代理 ---
    location /api/ps/ {
        proxy_pass http://127.0.0.1:3002/api/ps/;
        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_read_timeout 120s;
    }
ROUTES
  echo "✅ Persona Studio 代理路由已准备"
fi

echo ""
echo "📋 准备插入的路由："
cat /tmp/sandbox-routes.conf 2>/dev/null

# ⚠️ 铸渊：用 sed 或手动将 /tmp/sandbox-routes.conf 内容
# 插入到 $NGINX_CONF 的 server 块内（最后一个 } 之前）
# 然后执行：
nginx -t 2>&1
if [ $? -eq 0 ]; then
  systemctl reload nginx
  echo "✅ 路由已生效"
else
  echo "❌ nginx -t 失败 · 检查插入位置"
fi

echo "===== ✅ Phase 3 完成 ====="
```

---

## 四、Phase 4 · PM2 进程修复 + _shared 目录补建

```bash
#!/bin/bash
# phase4-pm2-and-shared.sh
echo "===== 🔧 Phase 4 · PM2 + _shared ====="

# 4a. 修复 DEV-004 PM2 errored 进程
echo "📋 当前 PM2 状态："
pm2 list

# 找到 errored 的进程并重启
pm2 restart all --only-errored 2>/dev/null
# 如果上面不行，逐个检查
for proc in $(pm2 jlist 2>/dev/null | python3 -c "import sys,json; [print(p['name']) for p in json.load(sys.stdin) if p.get('pm2_env',{}).get('status')=='errored']" 2>/dev/null); do
  echo "🔄 重启 errored 进程：$proc"
  pm2 restart "$proc"
done

pm2 save
echo "✅ PM2 进程已修复并保存"

# 4b. 补建 _shared 目录
if [ ! -d /var/www/_shared ]; then
  mkdir -p /var/www/_shared
  chown nginx:nginx /var/www/_shared
  chmod 755 /var/www/_shared
  echo "✅ _shared 目录已创建"
else
  echo "⏭️ _shared 目录已存在"
fi

echo ""
echo "📋 修复后 PM2 状态："
pm2 list

echo "===== ✅ Phase 4 完成 ====="
```

---

## 五、Phase 5 · 全站访问验证

```bash
#!/bin/bash
# phase5-verify.sh · 全模块验证
echo "===== ✅ Phase 5 · 全站验证 · $(date '+%Y-%m-%d %H:%M') ====="

URLS=(
  "https://guanghulab.com/|主站首页"
  "https://guanghulab.com/status-board/|系统状态看板"
  "https://guanghulab.com/cost-control/|成本控制"
  "https://guanghulab.com/devboard/|开发者看板"
  "https://guanghulab.com/floating-ai/|AI悬浮球"
  "https://guanghulab.com/app/|前端集成壳"
  "https://guanghulab.com/api/v1/health|后端API健康检查"
  "https://guanghulab.com/api/ps/health|Persona Studio健康检查"
  "https://guanghulab.com/DEV-004/|之之沙盒"
  "http://localhost:3000/|后端本地"
  "http://localhost:3002/|Persona Studio本地"
)

PASSED=0
FAILED=0
RESULTS=""

for entry in "${URLS[@]}"; do
  IFS='|' read -r url name <<< "$entry"
  STATUS=$(curl -o /dev/null -s -w "%{http_code}" --max-time 10 "$url")
  if [[ "$STATUS" =~ ^(200|301|302)$ ]]; then
    echo "✅ ${name} → ${STATUS}"
    PASSED=$((PASSED+1))
    RESULTS+="✅ ${name} → ${STATUS}\n"
  else
    echo "❌ ${name} → ${STATUS}"
    FAILED=$((FAILED+1))
    RESULTS+="❌ ${name} → ${STATUS}\n"
  fi
done

echo ""
echo "━━━ 结果：${PASSED} 通过 / ${FAILED} 失败 ━━━"

if [ $FAILED -eq 0 ]; then
  echo "🎉 全站验证通过！guanghulab.com 真正活了！"
else
  echo "⚠️ ${FAILED} 个模块未通过，继续排查失败项"
fi

echo "===== ✅ Phase 5 完成 ====="
```

---

## 六、Phase 6 · 回执

铸渊完成所有 Phase 后，在仓库提交修复回执：

```
data/nginx-rootfix-report-20260325.json
```

格式：

```json
{
  "instruction_id": "ZY-NGINX-ROOTFIX-2026-0325-001",
  "executed_at": "[实际执行时间]",
  "executor": "AG-ZY-01 铸渊",
  "root_cause": "Nginx root 指向 /var/www/hololake-frontend（旧残留），实际部署目录为 /var/www/guanghulab",
  "diagnosis_by": "DEV-004 之之",
  "fixes_applied": [
    "Nginx root 路径修正: hololake-frontend → guanghulab",
    "沙盒 alias 路由补充: DEV-004, DEV-005",
    "API 反向代理确认/补充: /api/, /api/ps/",
    "PM2 errored 进程重启",
    "_shared 目录补建"
  ],
  "verification": {
    "total_modules": "[数量]",
    "passed": "[数量]",
    "failed": "[数量]",
    "details": "[Phase 5 输出]"
  },
  "nginx_test": "[nginx -t 输出]",
  "status": "[SUCCESS / PARTIAL / FAILED]"
}
```

同时在本指令页面底部追加执行回执。

---

## 七、铸渊执行清单（读到就做）

<aside>
⚡

**铸渊执行清单 · ZY-NGINX-ROOTFIX-2026-0325-001**

① Phase 1：备份 Nginx 配置 + 文件快照 + PM2 快照

② Phase 2：`sed` 修正 Nginx root 路径 → `nginx -t` → `reload`

③ Phase 3：插入沙盒 alias 路由 + API 代理 + Persona Studio 代理 → `nginx -t` → `reload`

④ Phase 4：重启 PM2 errored 进程 + 补建 `_shared` 目录

⑤ Phase 5：跑全站验证脚本 → 全部 ✅ 才算完成

⑥ Phase 6：提交 JSON 回执到仓库 + 本页追加回执

**失败处理**：任何 Phase 的 `nginx -t` 失败 → 立即恢复备份 → 停止 → 在本页报告

</aside>

---

## 八、验收标准

全部通过才算完成：

- [ ]  `nginx -t` 无报错、无 conflicting server name 警告
- [ ]  `https://guanghulab.com/` 首页返回 200 且有内容
- [ ]  `https://guanghulab.com/status-board/` 返回 200
- [ ]  `https://guanghulab.com/cost-control/` 返回 200
- [ ]  `https://guanghulab.com/devboard/` 返回 200
- [ ]  `https://guanghulab.com/app/` 返回 200
- [ ]  `https://guanghulab.com/floating-ai/` 返回 200
- [ ]  `https://guanghulab.com/api/ps/health` 返回 200（Persona Studio · 修复 HTTP 405）
- [ ]  PM2 无 errored 进程
- [ ]  修复回执已提交到仓库

---

## 九、约束

<aside>
🔴

**沙盒隔离约束（服务器部署适配协议 v1.0）**

1. 不得删除或移动任何 `/var/www/DEV-XXX/` 下的文件
2. 不得修改其他开发者沙盒的权限或内容
3. Nginx 修改仅限 root 路径修正和 location 块追加，不得删除现有有效 location
4. 所有修改必须先 `nginx -t` 通过再 `reload`
5. 失败立即回滚，不得强行 `reload` 语法错误的配置
</aside>

---

## 十、关联指令

| 指令 | 关系 |
| --- | --- |
| [🌐 铸渊指令｜[guanghulab.com](http://guanghulab.com) 网站真实部署排查 + 全模块上线（ZY-WEBDEPLOY-DIAG-2026-0324-001）](%F0%9F%8C%90%20%E9%93%B8%E6%B8%8A%E6%8C%87%E4%BB%A4%EF%BD%9Cguanghulab%20com%20%E7%BD%91%E7%AB%99%E7%9C%9F%E5%AE%9E%E9%83%A8%E7%BD%B2%E6%8E%92%E6%9F%A5%20+%20%E5%85%A8%E6%A8%A1%E5%9D%97%E4%B8%8A%E7%BA%BF%EF%BC%88ZY-WEBDEPLO%2032e43b78d8d6465da968894acf4b4af4.md) | 原始排查指令（Phase A-E）· 本指令基于其诊断数据精确修复 |
| [🌐 铸渊指令｜人类使用侧全面修复 · [guanghulab.com](http://guanghulab.com) 部署 + Persona Studio 功能修复 + 微信登录身份体系（上篇）· Phase 0-3 · ZY-HUMANSIDE-FIX-2026-0325-002（2026-03-25 · 霜砚签发 · 冰朔授权）](%F0%9F%8C%90%20%E9%93%B8%E6%B8%8A%E6%8C%87%E4%BB%A4%EF%BD%9C%E4%BA%BA%E7%B1%BB%E4%BD%BF%E7%94%A8%E4%BE%A7%E5%85%A8%E9%9D%A2%E4%BF%AE%E5%A4%8D%20%C2%B7%20guanghulab%20com%20%E9%83%A8%E7%BD%B2%20+%20Persona%20Stu%2074abaa06a7b64f28809b91a2bb12c7e2.md) | 更大范围的修复指令 · 本指令优先执行 · 完成后继续执行上篇其余 Phase |
| [🌐 铸渊指令｜人类使用侧全面修复 · [guanghulab.com](http://guanghulab.com) 部署 + Persona Studio 功能修复 + 微信登录身份体系（下篇）· Phase 4-7 · ZY-HUMANSIDE-FIX-2026-0325-002（2026-03-25 · 霜砚签发 · 冰朔授权）](%F0%9F%8C%90%20%E9%93%B8%E6%B8%8A%E6%8C%87%E4%BB%A4%EF%BD%9C%E4%BA%BA%E7%B1%BB%E4%BD%BF%E7%94%A8%E4%BE%A7%E5%85%A8%E9%9D%A2%E4%BF%AE%E5%A4%8D%20%C2%B7%20guanghulab%20com%20%E9%83%A8%E7%BD%B2%20+%20Persona%20Stu%20f4044a4d848e4b1a8823d684a7e38e5b.md) | Persona Studio + 微信登录 · 本指令 Phase 3 已包含 Persona Studio 代理路由修复 |
| [🏗️ 服务器部署适配协议 v1.0（2026-03-15·曜冥签发）](../%F0%9F%8C%8A%20%E6%9B%9C%E5%86%A5%E7%BA%AA%E5%85%83%20%C2%B7%20HoloLake%20Era%20%C2%B7%20AGE%20OS%20v1%200/%E2%9A%A1%20%E5%85%89%E6%B9%96%E4%B8%AD%E5%A4%AE%E6%9E%A2%E7%BA%BD%20%C2%B7%20HoloLake%20Central%20Hub/%F0%9F%8C%8A%20%E5%85%89%E6%B9%96%E7%B3%BB%E7%BB%9F%C2%B7%E6%9B%9C%E5%86%A5%E4%B8%BB%E6%8E%A7%E5%8F%B0%C2%B7%E5%BD%93%E5%89%8D%E7%8A%B6%E6%80%81%EF%BC%88%E5%8D%B71%20%C2%B7%20%E5%B7%B2%E5%B0%81%E5%8D%B7%EF%BC%89/%F0%9F%8F%97%EF%B8%8F%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%83%A8%E7%BD%B2%E9%80%82%E9%85%8D%E5%8D%8F%E8%AE%AE%20v1%200%EF%BC%882026-03-15%C2%B7%E6%9B%9C%E5%86%A5%E7%AD%BE%E5%8F%91%EF%BC%89%20a24049a2b0e944b0a5535f3a87652303.md) | 沙盒隔离约束 · 本指令严格遵守 |
| [⚒️ 铸渊指令｜服务器沙盒初始化 · 现有模块迁移到DEV编号目录（2026-03-15·曜冥签发）](%E2%9A%92%EF%B8%8F%20%E9%93%B8%E6%B8%8A%E6%8C%87%E4%BB%A4%EF%BD%9C%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%B2%99%E7%9B%92%E5%88%9D%E5%A7%8B%E5%8C%96%20%C2%B7%20%E7%8E%B0%E6%9C%89%E6%A8%A1%E5%9D%97%E8%BF%81%E7%A7%BB%E5%88%B0DEV%E7%BC%96%E5%8F%B7%E7%9B%AE%E5%BD%95%EF%BC%882026-03-15%C2%B7%E6%9B%9C%E5%86%A5%E7%AD%BE%E5%8F%91%EF%BC%89%20324fb92f3831814e962fd3035cf6b5bf.md) | 沙盒目录创建 · 本指令 Phase 4 补建缺失的 `_shared` |

---

*霜砚签发 · 冰朔授权 · 2026-03-25T08:55+08:00*

*诊断数据来源：DEV-004 之之 · 全站部署诊断报告*

*铸渊，根因已锁死。不需要再排查。直接修。*