本文主要介绍如何使用 Obsidian + Hugo + Gitea + Cloudflare Pages 搭建博客自动发布系统。

其工作流为:

graph TD
  A[Obsidian/VSCode 写博客] --> B[提交到 Gitea]
  B --> C[Gitea Actions 使用 Hugo 构建静态页]
  C --> D[使用 Wrangler 将静态页推送到 Cloudflare Pages]
  D --> E[通过自定义域名访问]

注: 如果你使用 Github/Gitlab,可以让 Cloudflare Pages 构建而不使用 Actions 和 Wrangler

软件安装#

下载 Obsidian#

下载 Hugo#

需下载带_extended的预编译包

下载 nvm-windows#

然后使用如下命令安装 nodejs:(使用 Cloudflare Pages 从 Github/Gitlab 构建可以跳过此步骤

# 列出目前可用 nodejs 版本
nvm list available

# 安装指定版本 nodejs
nvm install 24.10.0;

# 使用指定版本 nodejs
nvm use 24.10.0;

注: nodejs 版本选用可以参考安装 Wranglernodejs 发布

在手机上安装番茄钟工具 Forest#

防拖延、提高专注度的工具,如无需要可跳过

配置 Obsidian#

创建仓库#

在你的工作目录 workdir 创建一个仓库,如:my-digital-garden

初始化 git 仓库#

cd my-digital-garden
git init

.gitignore 配置#

# 忽略 obsidian 配置目录 必须以 /* 结尾 否则不忽略规则不生效
.obsidian/*

# 追踪以下文件
!.obsidian/app.json
!.obsidian/hotkeys.json
!.obsidian/templates.json

软件设置#

文件与链接#

文件与链接设置

模板#

模板设置

快捷键#

快捷键设置

配置 Hugo#

创建 Hugo site#

在 workdir 执行以下命令,让 Hugo 使用 Obsidian 的仓库路径

hugo new site my-digital-garden --format yaml --force

设置 Hugo 主题 book#

cd my-digital-garden
git submodule add https://git.codehub.cn.eu.org/amos/hugo-book.git themes/book`

# 将 theme: 'book' 添加到 hugo.yaml 文件

.gitignore 配置#

...

# 忽略hugo文件
*.lock
public/
_gen/

完善目录结构#

创建 Obsidian 配置中使用的目录

mkdir content/posts
mkdir assets/images

修改模板文件#

修改 archetypes/default.md 文件内容如下:

---
date: '{{date}}T{{time}}+08:00'
draft: true
title: '{{title}}'
---

图像路径映射#

追加路径映射配置到 hugo 配置文件 hugo.yaml。这样 obsidian 和 hugo 中图像的路径就统一了,如果想在 vscode 的 markdown 预览器中正确显示图片,需要图像链接以 / 开头,即:![](/assets/images/someimage.png)

[module]
  [[module.mounts]]
    source = "assets/images"
    target = "static/assets/images"

本地测试预览#

新建笔记#

修改标题,使用快捷键插入模板,写入内容

在 Hugo 中预览#

Hugo server -D

注: 如果你也使用 book 主题,请注意 hugo.yaml 中的 BookServiceWorker 设置,如果不需要 service worker 缓存页面和资源,建议设置为 false

将静态页发布到 Cloudflare Pages#

注: 如果你选择从导入现有 Git 存储库开始,即源码托管在 Github/Gitlab 上,那么按照 Cloudflare Pages 的步骤做即可,本部分请跳过

本部分内容适用于托管在其他代码托管平台

配置 Cloudflare#

创建 Pages 项目#

graph TD
  A[Cloudflare Dashboard] --> B[展开计算(Workers)]
  B --> C[选择 Workers 和 Pages]
  C --> D[点击创建应用程序]
  D --> E[选择 Pages]
  E --> F[选择拖拽文件]
  F --> G[点击开始使用]
  G --> H[输入项目名称]
  H --> I[点击创建项目]

绑定自定义域名#

graph TD
  A[Workers 和 Pages] --> B[选择刚才创建的项目]
  B --> C[选择自定义域标签页]
  C --> D[点击 设置自定义域]
  D --> E[输入域名]
  E --> F[继续]
  F --> G[激活域]

等待 DNS 更新成功之后,即可通过自定义域名访问

创建账户 API 令牌#

graph TD
  A[Cloudflare Dashboard] --> J[展开管理账户]
  J --> B[选择账户API令牌]
  B --> C[点击创建令牌]
  C --> D[选择自定义令牌]
  D --> E[指定令牌名称]
  D --> F[权限下选择账户、Cloudflare Pages 和编辑]
  E --> G[点击继续以显示摘要]
  F --> G
  G --> H[点击创建令牌]
  H --> I[将令牌添加到 Gitea secrets(参考后续步骤)]

创建账户API令牌

获取账号ID#

graph TD
  A[Cloudflare Dashboard] --> B[点击左侧菜单栏 账户主页]
  B --> C[点击已托管的域名]
  C --> D[滚动内容到最下面]
  D --> E[在右侧 API 部分找到 账户ID]
  E --> F[将账户ID 添加到 Gitea secrets(参考后续步骤)]

配置 Gitea#

graph TD
  A[登录 Gitea] --> B[转到 Gitea 用户设置]
  B --> C[在 Actions 下找到密钥]
  C --> D[添加**CLOUDFLARE_ACCOUNT_ID**,值为账号ID]
  C --> E[添加**CLOUDFLARE_API_TOKEN**,值为账户API令牌]

注: 这两个名称是 Wrangler 默认支持的,参见System environment variables · Cloudflare Workers docs

在这里理论上支持自定义的名称,只要与 workflow 中的 secrets.自定义名称 一致即可,这个没有测试

配置 CI/CD#

安装 Wrangler#

在项目根目录运行命令:

# 本地安装,Cloudflare 推荐方式
npm i -D wrangler@latest
npx wrangler -v

.gitignore 配置#

...

# 忽略nodejs
node_modules/
# package-lock.json 应该追踪,优点如下:版本一致性、确定性安装,快速安装

# 忽略wrangler
.wrangler/

创建 Workflow#

在项目根目录创建 .gitea/workflows/pages-deployment.yaml,内容如下:

name: Cloudflare Pages Deployment Action
run-name: Deploy by ${{ gitea.actor }}

on: [push]

jobs:
  deploy:
    runs-on: [win_x64]
    permissions:
      contents: read
      deployments: write
    name: Deploy to Cloudflare Pages
    steps:
      - name: Checkout
        uses: https://gitea.com/actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.YOUR_TOKEN }} # Replace YOUR_TOKEN
  
      - name: Build
        run: npm install && hugo

      - name: Deploy
        env:
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}        
        run: npx wrangler pages deploy public --project-name=<PROJECT NAME> # Replace PROJECT NAME

总结#

通过搭建博客自动发布系统,简化了发布博客流程,提升了写作效率,我们可以将精力更多的放到博客内容上