Featured image of post 我是怎么搭这个博客的

我是怎么搭这个博客的

Hugo + Stack + Sveltia CMS + GitHub 私有仓库:一台 892MB 小机器的完整搭建思路

这台博客跑在一台只有 892MB 内存的 Azure 小机器上,同时兼着代理服务。整套方案的第一原则是:轻。以下只讲思路和取舍,代码只放关键几段。

全貌:写作 → 存储 → 展示

        你在浏览器里写作
              │
              ▼
     ┌─────────────────┐
     │  Sveltia CMS    │  写作后台(/admin/)
     │  文章 + 图片     │
     └────────┬────────┘
              │  保存时直接提交
              ▼
     ┌─────────────────┐
     │ GitHub 私有仓库  │  ← 唯一的“真相来源”,也是备份
     └────────┬────────┘
              │  每 1 分钟自动拉取
              ▼
     ┌─────────────────┐
     │  小机器 (VM)     │  git pull → Hugo 构建 → nginx 托管
     └────────┬────────┘
              │
              ▼
        访客访问博客

一句话:GitHub 是内容的家,小机器只负责渲染和展示。 好处很直接:内容永远有一份私有仓库备份;机器只负责构建,压力小;换设备也能写。

选型

Hugo:单文件二进制,整站构建几十毫秒,内存占用几乎可以忽略——在 1GB 小机器上是决定性优势。对比过 Hexo(依赖多)、WordPress(太重)、Ghost(官方建议 1GB 起步)。

Stack 主题:卡片式、自带暗色模式、搜索、归档、目录,社区里最成熟的 Hugo 主题之一。

Sveltia CMS:最初自己写了个网页后台,能用但很土:图片手动传、预览自己写、格式容易出错。换成 Sveltia 后:富文本 + 实时预览、图片拖拽上传、用表单生成 front matter(不会再因格式写错导致文章不显示)、支持草稿和修订历史。它是纯前端(一个 JS 文件从 CDN 加载),不占服务器内存;支持用 GitHub Token 登录,省掉了自建 OAuth 的麻烦。

为什么不直接用 GitHub Pages?

内容都在 GitHub 了,为什么不直接用 GitHub Pages 托管? 有三个现实约束:

1. 仓库是私有的,Pages 用不了。 免费账号只能从公开仓库发布 Pages,私有仓库发布需要 Pro/Team 付费计划。想省掉这台机器,就得把整个仓库转公开。

2. github.io 在国内基本不可达。 实测:直连 https://xxxx.github.io/ 超时,而自己的 Azure IP 是通的。GitHub Pages 走 Fastly CDN,国内访问不可靠;换一个「更省事」的方案,结果自己和读者都打不开,没有意义。

3. 那台小机器本来 24 小时开着。 它同时兼着代理服务,博客只是「蹭」在上面:nginx + 构建,平时内存占用不到 20MB,边际成本约等于零。

这个架构也没有绑死:内容全在 Git 里,换机器 git clone + 构建就能恢复。哪天仓库转公开、或者 GitHub 访问不再是问题,迁到 Pages 也就十分钟。

没有域名,怎么上 HTTPS?

没有域名就签不了证书,而写作后台的密码不能明文传输。取巧的办法是 sslip.io——一个公共通配 DNS 服务,把 IP 写进域名就能用:

20.48.50.55.sslip.io  →  自动解析到 20.48.50.55

有了它,就能走标准 HTTP 验证,用 certbot 签一张浏览器信任的真证书,并自动续期。代价是依赖 sslip.io 这个第三方服务——对个人博客够用。

核心:GitHub 私有仓库 + 双向同步

写作后台直接往 GitHub 提交,小机器上也可能有本地改动,所以需要双向同步:GitHub → 机器(拉新文章),机器 → GitHub(推本地改动),两个方向处理不好容易冲突。

做法是一个每分钟跑一次的脚本,逻辑四步:

  1. 先拉取:git pull --rebase --autostash,把远端新文章合并进来
  2. 判断要不要重建:只有「有新提交」或「本地有改动」才构建,避免空转
  3. 重新构建:Hugo 生成静态页
  4. 再推送:本地有改动就提交并推回 GitHub

两个细节:

  • 加锁:定时任务和手动触发可能撞车,用 flock 保证同一时间只有一个同步在跑
  • 记住上次构建的版本:用标记文件记录上次构建的 commit,精确判断站点是否最新

这正是备份:所有会变化的东西——文章、图片、站点配置——都在 Git 里。换机器 git clone 几分钟复原整站;误删文章 git revert 就能回来;每次改动有完整历史。版本控制本身就是最好的备份。

顺带搭的几件小事

  • HTTPS 自动续期:certbot 定时器自动检查、自动续
  • 缓存策略:HTML 每次校验(刷新即最新),带哈希指纹的 CSS/JS 长期缓存
  • 安全加固:后台路径随机化、Basic Auth、登录限速、响应头加固

踩过的坑

坑现象解法
未来日期文章发了但不显示Hugo 默认不构建未来文章,开 buildFuture
缺少 front matter随手记的笔记泄漏到公开页面Hugo 会把它当页面处理,后加了自动告警
并发推送git 报 remote rejected同步脚本加 flock
中文文件名后台打不开校验规则放宽到支持中文

成本

机器是 Azure 最低配(2 vCPU / 892MB),本来就在跑代理,博客算是「蹭」的;域名 0 元(sslip.io);证书 0 元(Let’s Encrypt);仓库 0 元(GitHub 私有仓库免费)。平时内存占用不到 20MB。

小结

用静态站点保证「轻」,用 Git 仓库保证「稳」,用成熟的 CMS 保证「好写」,用自动化把三者串起来。

它不是最省事的方案(想省事直接用 Ghost 或 WordPress),但在一台很小的机器上、不花钱、有完整掌控权的前提下,这是我能找到的最好平衡。