Hugo + GitHub Actions:从本地 Markdown 到线上站点的全自动流水线
0. 背景与架构演进:为什么我们需要流水线? Hugo 的运行机制 Hugo 是一个基于 Go 语言的静态网站生成器(Static Site Generator)。它的核心工作流是将我们编写的 Markdown 源文件,结合站点配置和主题模板,在编译阶段直接渲染成纯静态的 HTML、CSS 和 JS 文件(输出到 public/ 目录)。 由于是纯静态站点,线上的服务器不需要运行任何数据库或动态后端(如 PHP/Node.js),只需要一个 Web 服务器来托管这些文件即可对外提供访问。这种架构带来了极高的访问速度和安全性。 自动化构建的必然性 正因为 Hugo 所有的页面都是预先生成的,如果采用手动发布,我们每次更新文章就会陷入一个繁琐的循环:本地写 Markdown -> 本地运行 hugo 构建出 public 目录 -> 手动打包或通过 scp/rsync 把文件传到服务器。 这三步里有两步是枯燥的机械劳动,不仅容易出错(比如忘了构建就上传),而且如果更换电脑写作,还得重新配置 Hugo 环境。因此,搭建一条自动化的 CI/CD 流水线,把编译和部署工作交给云端,是大幅提升博客写作体验的必选项。我们最终期望的体验是:只管写 Markdown,推代码即自动部署。 为什么这样设计部署架构? 基于上述诉求,我们设计了当前的流水线架构: 构建层(GitHub Actions):文章源码天然需要使用 Git 进行版本控制并托管在 GitHub 上。GitHub Actions 提供了与代码仓库深度绑定的免费 CI/CD 环境。它可以监听 git push 事件,自动在云端运行容器,拉取子模块(主题)并执行 hugo build。这样无论我们在哪里写代码,只要能 push,云端就能帮我们完成构建。 传输层(rsync):在云端构建完成后,我们使用 rsync 经由 SSH 将生成的静态文件增量同步到阿里云 ECS。rsync 非常轻量高效,配合 --delete 参数能够确保服务器上的文件状态与最新编译结果完全一致(自动删除已移除的文件),不需要在服务器端部署任何复杂的 Agent。 网关与服务层(从 Nginx 到 Pingap):静态文件传到服务器的指定目录后,需要对外暴露。本站点早期用 Nginx 直接托管静态文件,后来迁移到 Pingap 统一入口。为了让 Hugo 生成的目录页、文章页和标签页都保持稳定的 index.html 行为,当前采用 darkhttpd 在本机监听静态目录,Pingap 负责 HTTPS、SNI、HTTP 跳转和反代。无论入口网关怎么演进,“云端编译静态文件并推送到服务器目录” 始终是整套发布流程的核心。 1. 最终部署架构图 本地写 Markdown ──git push──→ GitHub ──Actions──→ Hugo build ──rsync──→ ECS /var/www/hugo-site/ ↑ SSH deploy key GitHub:源码仓库 + CI 触发器 + 版本历史 GitHub Actions:Ubuntu runner 上跑 hugo build,然后 rsync 阿里云 ECS:实际跑服务的地方,darkhttpd 承载静态文件,Pingap 对外反代 2. 准备:仓库初始化 假设你已经有一个空仓库克隆到本地: ...