从主题到上线:8cat.life 的建站记录
这不是一份万能部署教程,而是 8cat.life 从“想换一个博客主题”到实际可访问站点的一次真实记录。保留走过的弯路,是为了以后重建、迁移或排障时能知道当时为什么这样选。
想做什么
最初的目标很简单:使用 Yohaku 主题和 Mix Space Core 搭一个可以长期写作的个人站点。
内容不预先限定为某一个技术方向。这里会写代码、AI、历史、哲学,以及仍在形成中的问题和想法。
最终方案
目前的结构如下:
图片里省略了两件刻意分开的事:内容始终在 Mix Space 后台维护,基础设施与源码则通过 Git 和 CI 管理。这样写文章不需要重新构建镜像,改前端才会触发发布流程。
目前的结构如下:
8cat.life:Yohaku 前端,运行在腾讯云轻量服务器的 Docker 容器中。api.8cat.life:Mix Space Core,由 Caddy 反向代理到 Core 服务。- Core 依赖:PostgreSQL、Redis、对象存储 COS。
- 前端镜像:CNB 构建 Docker 镜像,推送到腾讯云个人镜像仓库 TCR。
- 自动部署:CNB 通过腾讯云 TAT 调用轻量服务器中的自动化 Agent,拉取指定镜像并重建前端容器。
这样做的关键是把“构建镜像”和“运行镜像”分开:CNB 负责构建,服务器只负责拉取并运行已经构建好的版本。
走过的路
1. 原本想直接部署到 EdgeOne Pages
Yohaku 是 Next.js SSR 项目。EdgeOne Pages 能识别 Next.js,但实际构建时 Next.js 16 的 Turbopack/webpack 进程被平台的内存限制强制终止:日志中可以看到 SIGKILL 和大约 6 GiB 的内存上限。
即使把构建从 Turbopack 切换到 webpack,构建仍然会被终止;同时 EdgeOne 运行时对该项目的 middleware/proxy 兼容也出现过异常。于是没有继续在生产分支上硬改路由来迁就平台。
取舍: EdgeOne 很适合静态站点和轻量框架,但当前 Yohaku 的 SSR 构建体量不适合这条路径。保留测试分支即可,生产环境改为 Docker。
2. GitHub Actions 能构建,但不适合作为最终发布链路
GitHub Actions 成功构建过 Yohaku,说明源码、子模块与 Next.js 构建本身没有根本问题。
但把镜像放在 GHCR 后,腾讯云服务器拉取跨境镜像偏慢;如果再让 GitHub Runner 直接 SSH 登录服务器发布,还会带来陌生 IP 告警与长期凭据管理问题。
取舍: GitHub 保留为源码主仓库;镜像构建与服务器发布改在腾讯云生态内完成。
3. CNB、TCR 与 TAT 打通自动部署
最终采用 CNB 进行 Docker 构建,产物推送到私有 TCR。镜像同时使用不可变的提交 SHA 标签和 latest,服务器实际部署 SHA 标签,便于追踪“网站运行的是哪一次提交”。发布并不是“让服务器重新编译代码”,而是让它拿到已经验证过的成品镜像。
这一步也踩了几个坑:
- CNB 使用 npm 国内镜像时,个别包在镜像站尚未同步,出现 404;需要让这类包回退到官方 npm registry。
- Docker 构建中的
git: not found来自安装阶段的 hooks;容器构建没有.git目录,属于无害噪声,不是构建失败原因。 - TAT 最初用了错误的 CVM 风格实例 ID,轻量服务器实际需要
lhins-...的实例 ID。 - TAT CAM 权限除了
RunCommand,还需要查询 invocation 与任务状态的权限;缺其中一个会“命令已发出但流水线仍失败”。
最终,CNB 构建完成后会调用 TAT,让服务器执行:拉取指定 SHA 的镜像、更新 compose 服务、重建 yohaku 容器。
内容与主题配置
Mix Space 里的“页面”是普通 CMS 内容,不是 Yohaku 主题文件。因此页脚中 /about、/about-site 与 /message 三个链接最初 404 的原因很直接:相应页面尚未创建。
目前已创建:
- 关于我:
/about - 关于本站:
/about-site - 留言:
/message
而 Yohaku 的首页与页脚视觉配置位于后台“代码片段”中的 theme/shiro JSON,不在项目根目录的 theme.json。这里配置首页标题、简介、一言、favicon 与页脚链接。
图片、favicon 与邮件
- 图片使用腾讯云 COS。Core 当前使用一套 S3 连接配置,博客正文图片与评论图片通过不同的对象路径前缀隔离;访问密钥只授予该存储桶所需的最小权限。
- favicon 从旧站迁移,前端提供 512px 原图供浏览器缩放;主题中保留旧路径时,前端会兼容地回退到这份高分辨率资源。
- 邮件订阅使用 Resend。发送域名使用
updates.8cat.life,例如发件地址newsletter@updates.8cat.life。API Key 只保存于 Core 后台配置,不进入前端或代码仓库。
仍需记住的限制
Google 评论登录
Google OAuth 的浏览器授权可以完成,但服务器还需要访问 oauth2.googleapis.com 以授权码换取 token。腾讯云服务器内的 Core 容器到该地址的 443 端口连接超时,因此最终显示 invalid_code。
这不是 Google 回调地址缺失。若要启用 Google 登录,需要为 Core 配置可稳定访问 Google 的 HTTPS 代理;当前保留已可用的 GitHub 登录更合适。
RSS
RSS 的后端聚合接口可正常返回数据,但 Yohaku 前端的 /feed 路由曾把可选的 RSS 主题配置当成必填项,在新主题配置没有 module.rss 时抛出异常。修复方式是为缺省值提供兜底,并补上一条回归测试;不要把它误认为 Core、DNS 或订阅服务的问题。
还在继续的优化
生产发布链路已经稳定,但还有两类不影响写作的后续工作:
- COS 图片可接入 CDN 自定义域名,以获得更稳定的跨地区访问与更长的静态缓存;当前先使用 COS 官方 HTTPS 域名保证正确性。
- 主站未来也可以接入 EdgeOne,只缓存
/_next/static/、字体与图片等静态路径;文章正文、后台、登录和 API 仍应动态回源,不能用“整站缓存”换取表面速度。
这次建站留下的原则
- 不为了适应部署平台而把生产源码改得难以维护。
- 构建在 CI 完成,服务器只运行不可变镜像。
- 密钥只放在后台或 CI 私密变量中,不写入 Git 仓库与前端镜像层。
- 每次自动部署使用提交 SHA 标签,出现问题时可以准确回溯。
- 后台内容、主题配置与基础设施配置是三层不同的东西;排错前先明确问题属于哪一层。
写代码赖以生存,读闲书文明精神,想问题认识世界。