<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hugo on BINGBlog</title><link>https://xbzhang.xyz/tags/hugo/</link><description>Recent content in Hugo on BINGBlog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 16 Sep 2026 21:10:00 +0800</lastBuildDate><atom:link href="https://xbzhang.xyz/tags/hugo/index.xml" rel="self" type="application/rss+xml"/><item><title>我是怎么搭这个博客的</title><link>https://xbzhang.xyz/posts/how-i-built-this-blog/</link><pubDate>Wed, 16 Sep 2026 21:10:00 +0800</pubDate><guid>https://xbzhang.xyz/posts/how-i-built-this-blog/</guid><description>&lt;img src="https://xbzhang.xyz/images/uploads/Default.jpg" alt="Featured image of post 我是怎么搭这个博客的" /&gt;&lt;p&gt;这台博客跑在一台只有 &lt;strong&gt;892MB 内存&lt;/strong&gt;的 Azure 小机器上，同时兼着代理服务。整套方案的第一原则是：&lt;strong&gt;轻&lt;/strong&gt;。以下只讲思路和取舍，代码只放关键几段。&lt;/p&gt;&#10;&lt;h2 id="全貌写作--存储--展示"&gt;&lt;a href="#%e5%85%a8%e8%b2%8c%e5%86%99%e4%bd%9c--%e5%ad%98%e5%82%a8--%e5%b1%95%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;全貌：写作 → 存储 → 展示&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 你在浏览器里写作&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌─────────────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ Sveltia CMS │ 写作后台（/admin/）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 文章 + 图片 │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────────┬────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 保存时直接提交&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌─────────────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ GitHub 私有仓库 │ ← 唯一的“真相来源”，也是备份&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────────┬────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 每 1 分钟自动拉取&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌─────────────────┐&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 小机器 (VM) │ git pull → Hugo 构建 → nginx 托管&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └────────┬────────┘&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 访客访问博客&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一句话：&lt;strong&gt;GitHub 是内容的家，小机器只负责渲染和展示。&lt;/strong&gt; 好处很直接：内容永远有一份私有仓库备份；机器只负责构建，压力小；换设备也能写。&lt;/p&gt;&#10;&lt;h2 id="选型"&gt;&lt;a href="#%e9%80%89%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;选型&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Hugo&lt;/strong&gt;：单文件二进制，整站构建几十毫秒，内存占用几乎可以忽略——在 1GB 小机器上是决定性优势。对比过 Hexo（依赖多）、WordPress（太重）、Ghost（官方建议 1GB 起步）。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Stack 主题&lt;/strong&gt;：卡片式、自带暗色模式、搜索、归档、目录，社区里最成熟的 Hugo 主题之一。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Sveltia CMS&lt;/strong&gt;：最初自己写了个网页后台，能用但很土：图片手动传、预览自己写、格式容易出错。换成 Sveltia 后：富文本 + 实时预览、图片拖拽上传、用表单生成 front matter（不会再因格式写错导致文章不显示）、支持草稿和修订历史。它是纯前端（一个 JS 文件从 CDN 加载），不占服务器内存；支持&lt;strong&gt;用 GitHub Token 登录&lt;/strong&gt;，省掉了自建 OAuth 的麻烦。&lt;/p&gt;&#10;&lt;h2 id="为什么不直接用-github-pages"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e7%9b%b4%e6%8e%a5%e7%94%a8-github-pages" class="header-anchor"&gt;&lt;/a&gt;为什么不直接用 GitHub Pages？&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;内容都在 GitHub 了，为什么不直接用 GitHub Pages 托管？&lt;/strong&gt; 有三个现实约束：&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;1. 仓库是私有的，Pages 用不了。&lt;/strong&gt; 免费账号只能从&lt;strong&gt;公开&lt;/strong&gt;仓库发布 Pages，私有仓库发布需要 Pro/Team 付费计划。想省掉这台机器，就得把整个仓库转公开。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;2. github.io 在国内基本不可达。&lt;/strong&gt; 实测：直连 &lt;code&gt;https://xxxx.github.io/&lt;/code&gt; 超时，而自己的 Azure IP 是通的。GitHub Pages 走 Fastly CDN，国内访问不可靠；换一个「更省事」的方案，结果自己和读者都打不开，没有意义。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;3. 那台小机器本来 24 小时开着。&lt;/strong&gt; 它同时兼着代理服务，博客只是「蹭」在上面：nginx + 构建，平时内存占用不到 20MB，边际成本约等于零。&lt;/p&gt;&#10;&lt;p&gt;这个架构也没有绑死：内容全在 Git 里，换机器 &lt;code&gt;git clone&lt;/code&gt; + 构建就能恢复。哪天仓库转公开、或者 GitHub 访问不再是问题，迁到 Pages 也就十分钟。&lt;/p&gt;&#10;&lt;h2 id="没有域名怎么上-https"&gt;&lt;a href="#%e6%b2%a1%e6%9c%89%e5%9f%9f%e5%90%8d%e6%80%8e%e4%b9%88%e4%b8%8a-https" class="header-anchor"&gt;&lt;/a&gt;没有域名，怎么上 HTTPS？&#10;&lt;/h2&gt;&lt;p&gt;没有域名就签不了证书，而写作后台的密码不能明文传输。取巧的办法是 &lt;strong&gt;sslip.io&lt;/strong&gt;——一个公共通配 DNS 服务，把 IP 写进域名就能用：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;20.48.50.55.sslip.io → 自动解析到 20.48.50.55&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有了它，就能走标准 HTTP 验证，用 certbot 签一张浏览器信任的真证书，并自动续期。代价是依赖 sslip.io 这个第三方服务——对个人博客够用。&lt;/p&gt;&#10;&lt;h2 id="核心github-私有仓库--双向同步"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83github-%e7%a7%81%e6%9c%89%e4%bb%93%e5%ba%93--%e5%8f%8c%e5%90%91%e5%90%8c%e6%ad%a5" class="header-anchor"&gt;&lt;/a&gt;核心：GitHub 私有仓库 + 双向同步&#10;&lt;/h2&gt;&lt;p&gt;写作后台直接往 GitHub 提交，小机器上也可能有本地改动，所以需要&lt;strong&gt;双向同步&lt;/strong&gt;：GitHub → 机器（拉新文章），机器 → GitHub（推本地改动），两个方向处理不好容易冲突。&lt;/p&gt;&#10;&lt;p&gt;做法是一个每分钟跑一次的脚本，逻辑四步：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;先拉取&lt;/strong&gt;：&lt;code&gt;git pull --rebase --autostash&lt;/code&gt;，把远端新文章合并进来&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;判断要不要重建&lt;/strong&gt;：只有「有新提交」或「本地有改动」才构建，避免空转&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;重新构建&lt;/strong&gt;：Hugo 生成静态页&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;再推送&lt;/strong&gt;：本地有改动就提交并推回 GitHub&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;两个细节：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;加锁&lt;/strong&gt;：定时任务和手动触发可能撞车，用 &lt;code&gt;flock&lt;/code&gt; 保证同一时间只有一个同步在跑&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;记住上次构建的版本&lt;/strong&gt;：用标记文件记录上次构建的 commit，精确判断站点是否最新&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这正是备份：&lt;strong&gt;所有会变化的东西——文章、图片、站点配置——都在 Git 里&lt;/strong&gt;。换机器 &lt;code&gt;git clone&lt;/code&gt; 几分钟复原整站；误删文章 &lt;code&gt;git revert&lt;/code&gt; 就能回来；每次改动有完整历史。&lt;strong&gt;版本控制本身就是最好的备份。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h2 id="顺带搭的几件小事"&gt;&lt;a href="#%e9%a1%ba%e5%b8%a6%e6%90%ad%e7%9a%84%e5%87%a0%e4%bb%b6%e5%b0%8f%e4%ba%8b" class="header-anchor"&gt;&lt;/a&gt;顺带搭的几件小事&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;HTTPS 自动续期&lt;/strong&gt;：certbot 定时器自动检查、自动续&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;缓存策略&lt;/strong&gt;：HTML 每次校验（刷新即最新），带哈希指纹的 CSS/JS 长期缓存&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;安全加固&lt;/strong&gt;：后台路径随机化、Basic Auth、登录限速、响应头加固&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="踩过的坑"&gt;&lt;a href="#%e8%b8%a9%e8%bf%87%e7%9a%84%e5%9d%91" class="header-anchor"&gt;&lt;/a&gt;踩过的坑&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;坑&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;现象&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;解法&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;未来日期&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;文章发了但不显示&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hugo 默认不构建未来文章，开 &lt;code&gt;buildFuture&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;缺少 front matter&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;随手记的笔记泄漏到公开页面&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Hugo 会把它当页面处理，后加了自动告警&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;并发推送&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;git 报 &lt;code&gt;remote rejected&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;同步脚本加 &lt;code&gt;flock&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中文文件名&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;后台打不开&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;校验规则放宽到支持中文&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="成本"&gt;&lt;a href="#%e6%88%90%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;成本&#10;&lt;/h2&gt;&lt;p&gt;机器是 Azure 最低配（2 vCPU / 892MB），本来就在跑代理，博客算是「蹭」的；域名 0 元（sslip.io）；证书 0 元（Let&amp;rsquo;s Encrypt）；仓库 0 元（GitHub 私有仓库免费）。平时内存占用不到 20MB。&lt;/p&gt;&#10;&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结&#10;&lt;/h2&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;用静态站点保证「轻」，用 Git 仓库保证「稳」，用成熟的 CMS 保证「好写」，用自动化把三者串起来。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;它不是最省事的方案（想省事直接用 Ghost 或 WordPress），但在&lt;strong&gt;一台很小的机器上、不花钱、有完整掌控权&lt;/strong&gt;的前提下，这是我能找到的最好平衡。&lt;/p&gt;&#10;</description></item></channel></rss>