为什么搬
不是说 Pages 不好。Pages 的问题是它只负责发文件:没有服务端钩子、不能按平台拒客、出不了 RSS 之外的任何东西。
而我想让它变成「我的站」,不是「我在别人地盘上的一个目录」。
现在是什么样
访客 ──► Cloudflare(橙云:缓存 / 防护 / 证书)
└─► 东京 43.133.165.x · 宿主 nginx
├─ / 主页(静态)
├─ /posts/ 博客(构建产物)
├─ /games/ 游戏厅
└─ /api/ ──► 云账号 / 云存档 / 全站榜(转发)
└─ 127.0.0.1:8000 一个 NestJS 容器(游戏后端)
源站只允许 Cloudflare 回源段访问——直连 IP 一律 403。
两个必须一起搬的东西
静态文件谁都会搬,真正麻烦的是藏在 functions/ 里的两块服务端逻辑:
- **
/api/全路径中继*:账号、云存档、全站榜都得从这儿转发出去。以前在 CF Pages 的边缘上跑,现在换成 nginx 的一行proxy_pass。 - macOS 服务端拒绝:要求是「不要客户端软拦截,直接服务端拒绝」,所以判定必须发生在发资源之前。现在由 nginx 的
map判定,命中直接 403,页面的一个字节都不下发。
搬完的验证口径:经 CF 200、直连 IP 403、Mac UA 403、iPad 200。四条全过才算数。
踩到的坑
allow/deny和 realip 会打架:日志里想看到访客真实 IP,就得让 realip 改写$remote_addr;可allow <CF 段>; deny all;恰好用的就是$remote_addr——结果把访客一起拒了,全站 403。正解是用$realip_remote_addr(改写之前的对端地址)做判断。- healthcheck 写成 exec 形式的
||:["CMD","wget",…,"||","exit","1"]里||会被当成 wget 的参数,容器永远unhealthy。要么CMD-SHELL,要么别写。
这两条都已写进部署手册的坑清单里。下一篇写博客这套构建器怎么做到零依赖。