① 事件表「故障」「狼的评论系统」「UptimeRobot:403 Forbidden」不在同一行 根因(实测定位,非推断):四个 td 的 top/height 完全相同(696/72),错位在单元格内部。 .clamp2 为保证行等高固定了 height:2.8em(36px),而「故障」徽标只有 17px; 单元格按 vertical-align:middle 对齐时,两者居中基准不同,徽标比其它三列低约 9px。 修法:事件表单元格改顶部对齐 + clamp2 在事件表内改为 max-height。 实测修复后四列文字顶端错位 0px。 ② 跨域模式隐藏刷新按钮 /api/refresh 在跨域下必然被 refreshLocalOnly 挡下(对端是代理地址而非私网), 给一个必然失败的按钮不如隐藏。setSource 里按 source==='remote' 切换, 同源模式保留(并补断言守住这个行为)。 ③ 新增 docs/DEPLOY-PAGES.md GitHub Pages 面板 + 本地探针的完整部署指南:架构图、先决条件(含混合内容硬限制)、 本地探针启动与 2FA 绑定、Pages 配置三处填法、验证清单、安全要点、 Actions 快照备选方案、六条常见问题排查(Mixed Content / CORS / Failed to fetch 等)。 测试:verify-views 47→49 项(事件行文字顶端对齐 0px、同源保留刷新按钮)。 全项目 8 套 336 项通过。
7.4 KiB
部署指南:GitHub Pages 面板 + 本地探针
面向的场景:面板托管在 GitHub Pages(公开、免运维),探测跑在自己家里/内网的机器上。
┌─────────────────────────────┐ ┌──────────────────────────────────┐
│ GitHub Pages(静态托管) │ HTTPS │ 你自己的机器(内网/家用) │
│ ├─ index.html + assets/ │◄────────┤ ├─ Node 探针:持续探测 │
│ └─ 读 status.json 取配置 │ fetch │ ├─ /admin 管理端(2FA 保护) │
│ │ │ └─ 写 local.monitors.json │
└─────────────────────────────┘ └──────────────────────────────────┘
为什么面板不能直接读本地探针?因为 GitHub Pages 是纯静态的,只能读仓库里的文件。 数据要上去,靠两件事:跨域读接口(本指南的方式)或 Actions 提交快照(下文备选方案)。
一、先决条件
| 条件 | 说明 |
|---|---|
| 本地探针有 HTTPS 地址 | Pages 强制 HTTPS,浏览器禁止 HTTPS 页面请求 HTTP(混合内容)。用你自己的隧道 / 反代给探针套一层 HTTPS |
| Node.js ≥ 18 | 零依赖,只需 Node 自带模块 |
| 一个 GitHub 仓库 | 公开仓库即可(Pages 免费额度对公开仓库无限) |
⚠️ 混合内容是硬限制:即使 CORS 配对了,只要探针是
http://,浏览器仍会直接拦截请求,控制台只留一行Mixed Content ... was blocked。这一条没有绕过办法。
二、本地:跑探针
git clone <你的仓库>
cd shiroko-monitor
# 私有配置(不入库):真实地址、API Key 等放这里
cp local.monitors.json.example local.monitors.json # 或按下面提示自建
node prober/node/index.js
启动后确认:
面板:http://localhost:8787/
管理后台: http://localhost:8787/admin
让探针能被外部访问
默认它只监听 127.0.0.1。要让隧道/反代连进来,在 local.monitors.json 里打开:
{
"settings": {
"admin": { "allowRemote": true } // 监听 0.0.0.0
}
}
打开后同一端口上的公开面板也会对外可达(只读,但目标名称/地址/可用率会暴露)。 如果不希望这样,请在隧道那层按路径只放行
/admin与/api/admin/*。
绑定管理端 2FA(必做)
管理端能改配置、发通知,必须先绑定两步验证:
# 首次绑定需要这个口令(只从环境变量读,不写进任何文件)
export SHIROKO_ADMIN_SETUP_KEY='换成一串足够长的随机口令'
node prober/node/index.js
然后打开 https://你的隧道地址/admin,按提示扫码绑定、保存恢复码。
三、页面:部署到 GitHub Pages
1. 开启 Pages
仓库 Settings → Pages → Build and deployment → Source 选 GitHub Actions。
2. 推送代码
git push
3. 填两处配置(关键)
打开 https://你的隧道地址/admin,在「口径与范围」区块填:
| 字段 | 填什么 |
|---|---|
| 面板上的管理入口链接 | https://你的隧道地址/admin —— Pages 面板页脚会出现「管理」按钮跳过去 |
| 跨域数据源地址 | https://你的隧道地址(不带路径)—— 面板从这里取数据 |
| 允许跨域读取的页面地址 | https://你的用户名.github.io —— 必须是完整来源,含协议 |
填完立刻生效。回本地仓库提交改动:
git add public/monitors.json && git commit -m "chore: 配置跨域数据源" && git push
配置写在
local.monitors.json(私有层)的话,Pages 上的面板读不到 —— 它只能读仓库里的public/monitors.json。所以上面的两步(管理界面填 → 提交仓库)都要做。
4. 验证
打开 https://你的用户名.github.io/<仓库名>/,检查:
- 页脚数据源显示「远程探针(跨域)」—— 说明跨域打通了
- 表格有数据且状态正常
- 页脚有「管理」按钮,点击能跳到管理端
- 页面上没有「刷新」按钮 —— 跨域模式下该接口必然被
refreshLocalOnly挡下,隐藏比给一个失败的按钮好
四、安全要点
| 事项 | 说明 |
|---|---|
| 管理端 2FA 必须绑定 | TOTP(Google Authenticator 等)+ 10 枚一次性恢复码 |
| 恢复码离线保存 | 只在绑定时显示一次,用掉一枚少一枚 |
跨域白名单不要图省事写 * |
代码里不存在 * 分支,写了也不生效。必须写完整来源,如 https://you.github.io |
| 管理端永不放行跨域 | /admin 与 /api/admin/* 不带任何 Access-Control-* 头,外部页面既读不到也改不了 |
| 会话 | 30 分钟无操作失效,最长 2 小时;进程重启全部失效 |
| 登录限流 | 同一 IP 连续 5 次失败后指数退避锁定 |
| API Key | 放 local.monitors.json 或环境变量,绝不要写进 public/monitors.json(会随Pages 公开) |
五、备选:不用跨域,改用 Actions 提交快照
如果不想暴露探针的 HTTPS 地址,可以让数据「流」到 Pages 而不是「拉」:
# .github/workflows/monitor.yml(示意)
on:
schedule: [{ cron: '*/5 * * * *' }]
workflow_dispatch:
jobs:
probe:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: node prober/node/index.js --once --config=public/monitors.json
- run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git add public/status.json
git diff --staged --quiet || git commit -m "chore: status" && git push
面板用 ?source=static 读仓库里的 status.json。
取舍:探测跑在 GitHub Runner 上(不是你的机器),延迟 ≤5 分钟,且没有通知、维护窗口、事件、2FA 管理端。适合纯展示需求。
六、常见问题
面板一直转圈 / 报错 浏览器控制台看具体报错:
Mixed Content ... was blocked→ 探针地址不是 HTTPS,回第一节blocked by CORS policy→ 「允许跨域读取的页面地址」没填对,或与实际访问地址不一致(含www、端口、大小写)Failed to fetch且数据源显示「浏览器直连」 → 面板拿不到数据,退到了兜底模式
页脚没有「管理」按钮 「面板上的管理入口链接」为空(默认就是空的,为了不在公网暴露管理面位置)。
跨域下没有刷新按钮
这是预期行为。跨域模式下 /api/refresh 会被服务端的 refreshLocalOnly 挡下(对端是代理地址而非私网),前端自动隐藏了这个按钮。
改了配置但面板没变
管理端写的是 local.monitors.json(私有层)。如果那部分设置需要 Pages 上的面板看到,得手动同步到 public/monitors.json 并提交。
本机开发时前端跨域被拒
默认白名单放行 localhost / 127.0.0.1且忽略端口,所以 localhost:5173 这类能直接用。若你在局域网 IP 上跑前端,需把那个地址显式加进白名单。