跳过正文

使用 Hugo + GitHub Pages 搭建个人博客

·5841 字·12 分钟·
技术 GitHub Hugo
Dr. Kee
作者
Dr. Kee
Talk less. Smile more.

本文将详细介绍在 Windows 环境下使用 Hugo 与 Blowfish 主题搭建个人博客,并借助 GitHub Actions 自动推送静态网站到 GitHub Pages 的方法。

在搭建这个博客的过程中,我遭遇了各种各样的问题。然而,部分问题在官方文档和其他网络教程里都语焉不详,只能靠我自己慢慢摸索解决办法。现在,我把这些踩过的坑记录下来,一来是提醒自己,二来也希望能对后来者有所帮助。

注意 这篇文章主要面向有一定计算机基础的人群。如果你还不了解什么是命令行、如何添加环境变量以及如何使用 Git 等相关内容,建议先系统性地学习这些知识,再按照本文的步骤进行操作。

准备工作
#

  • 一个 GitHub 账号
  • 安装并配置好 Git
  • 一个文本编辑器(比如 VS Code、Notepad++等,记事本也行)
  • 一个浏览器 (废话)

创建 GitHub 仓库
#

我们需要创建两个 GitHub 仓库。其中一个是私有仓库,用于存放网页的源代码;另一个是公共仓库,作为我们接下来要用到的 GitHub Pages 仓库,用于存放静态网页文件。

首先创建一个新的私有仓库,稍后将会用它来存放 Hugo 生成的源代码。你可以为它取任何你喜欢的名字。例如,我将它命名为 BlogSource

然后创建一个公共仓库作为 GitHub Pages 的存放位置。需要注意的是,这个仓库的名称必须是 <username>.github.io,其中,<username> 是你的 GitHub 用户名。例如,我将它命名为 derec30240.github.io

关于 GitHub Pages 的更多信息参见 GitHub Pages 官方文档

本地安装
#

安装 Hugo
#

  1. 前往 Hugo 官方 GitHub 仓库,进入 Release 界面下载对应版本。我这里选择下载 hugo_0.148.1_windows-amd64.zip

  2. 将下载的文件解压后,放在合适的位置,例如 D:\Hugo

  3. hugo.exe 所在的文件夹路径 (不是 hugo.exe 的路径!!!) 添加到系统环境变量中。

    例如,如果 hugo.exe 的路径是 D:\Hugo\hugo.exe,那么将 D:\Hugo 添加到系统环境变量中。

  4. 在终端执行以下命令,验证安装是否成功:

    hugo version
    

    如果安装成功,会显示 Hugo 的版本信息。否则会报错。

    > hugo version
    hugo v0.148.1-98ba786f2f5dca0866f47ab79f394370bcb77d2f windows/amd64 BuildDate=2025-07-11T12:56:21Z VendorInfo=gohugoio
    

创建本地站点
#

  1. 在终端执行以下命令,创建一个新的 Hugo 站点:

    hugo new site <mysite>
    

    其中 <mysite> 是站点的名称,下文将以 BlogSource 为例进行说明。当然你也可以将其替换为自己喜欢的名称。

    这个命令将在当前位置创建一个名为 <mysite> 的文件夹,站点根目录即位于该文件夹内。

  2. 进入站点根目录:

    cd BlogSource
    

    到这一步,不出意外的话,你已经成功创建了一个站点。你可以直接跳转到这里继续下一步操作。当然,如果你已经迫不及待地想要尝试运行这个站点,也可以接着按下面的步骤操作。

  3. 新建一篇文章:

    hugo new post/my-post.md
    

    这个命令将在 /content/post 文件夹中生成 my-post.md 文件。你可以使用文本编辑器打开这个 .md 文件。

    打开之后,你会看到文件里已经生成了一些内容:

    +++
    title = 'My Post'
    date = 2025-07-17T15:09:01+08:00
    draft = true
    +++
    

    这是文件头区域(Front Matter),在使用 hugo new 创建新的 .md 文件时,会根据 /archetypes 中的模板在文件开头自动生成。其中保存着文件的基本信息,例如 title 是标题,date 是日期,draft 是草稿状态等。

    draft 的值为 true ,启动服务后这篇文章是默认不可见的。如果要在预览中显示这些文章,需要给命令添加参数。详见下文。

    你可以在文件中随意编辑,之后点击保存。

  4. 进行预览

    在站点根目录下,执行以下命令启动服务:

    hugo server
    
    # 显示草稿状态的文章
    hugo server -D
    

    此时在浏览器中访问 http://localhost:1313 即可看到你的站点。但是此时你会发现页面显示 404 Page Not Found。不用担心,这是正常的,因为我们还没有安装主题。

    先按 Ctrl + C 停止服务。接下来开始安装主题。

安装 Blowfish 主题
#

  1. 在站点根目录依次执行以下命令:

    git init -b main
    git submodule add -b main https://github.com/nunocoracao/blowfish.git themes/blowfish
    

    这些命令将把你的站点目录初始化为一个新的 git 仓库,并把 Blowfish 作为其子模块导入。

    等待 Blowfish 下载完成后进行下一步操作。

  2. 删除站点根目录中的 hugo.toml 文件。

  3. /themes/blowfish/archetypes/themes/blowfish/config 两个文件夹分别复制到站点根目录的 /archetypes/config 中,替换原有文件。

  4. 进入 /config/_default 目录,将其中的 language.en.tomlmenus.en.toml 两个文件名中的 en 替换为默认语言代码。例如,在中文环境下,将其分别重命名为 language.zh-cn.tomlmenus.zh-cn.toml

  5. 打开同一目录下的 hugo.toml 文件,按照以下步骤修改:

    • 取消第 5 行的注释。
    • 取消第6 行的注释,并将其中的域名替换为你的域名,也就是之前创建的 GitHub Pages 域名:https://<userename>.github.io,其中 <username> 是你的 GitHub 用户名。
    • 将第 7 行的 en 替换为 zh-cn
    • 在第 8 行插入 hasCJKLanguage = true,以启用汉字计数。

    以我的文件为例,修改后的 hugo.toml 开头应该是这样的:

    5
    6
    7
    8
    
    theme = "blowfish"
    baseURL = "https://derec30240.github.io/"
    defaultContentLanguage = "zh-cn"
    hasCJKLanguage = true
    
  6. 现在回到站点根目录,执行以下命令启动服务:

    hugo server
    

    可以看到你的站点已经成功运行了。

    fig1.png

    至此,Blowfish 的基本安装已经完成。接下来我们将进一步完善网站配置。

配置与调试
#

配置站点
#

本节内容仅供参考。请根据 Blowfish 官方文档,结合自己的实际情况进行配置。

配置文件中每一项参数在官方文档中都有详细说明,如有疑问建议优先查阅。在此仅对一些关键步骤与容易出错的地方进行解释。

建议一边运行 hugo server 预览,一边进行修改。

  1. 进入 /config/_default 目录,打开 language.zh-cn.toml 文件进行修改。以下是我文件中的部分内容:

    languageCode = "zh-cn"
    languageName = "Simplified Chinese (China)"
    weight = 1
    title = "Dr. Kee's Blog"
    
    [params]
      displayName = "简体中文"
      isoCode = "cn"
      rtl = false
      dateFormat = "2006 年 1 月 2 日"
      logo = "img/logo.png"
      description = "Dr. Kee's Blog"
      copyright = "© { year } by Dr. Kee. All Rights Reserved."
    
    [params.author]
      name = "Dr. Kee"
      image = "img/profile.png"
      bio = "Talk less. Smile more."
      links = [
        { github = "https://github.com/derec30240" },
        { bilibili = "https://space.bilibili.com/526473701" },
        { steam = "https://steamcommunity.com/profiles/76561199075095514/" },
        { email = "mailto:derec30240@163.com" },
      ]
    
    • params.logo:站点 logo 在 /assets 中的相对位置
    • params.author.image:作者头像在 /assets 中的相对位置,也可以是外部 URL

    这里所说的这两个目录是站点根目录中的 /assets,而非 /themes/blowfish 中的 /assets。事实上,对网站进行的所有编辑均应在站点根目录中进行,一般不要编辑 /themes/blowfish 中的内容。这样可以避免文件结构混乱。

    经过测试,若 /assets/themes/blowfish/assets 中存在同名文件,会优先调用 /assets 中的文件。另外,如果编辑了 /themes/blowfish 中的文件,在后续更新主题时可能会产生冲突。综上,推荐优先在站点根目录中进行编辑。

  2. 打开 menus.zh-cn.toml 进行修改。以下是我文件中的部分内容:

    [[main]]
      name = "Posts"
      pageRef = "/posts"
      weight = 10
    
    [[main]]
      name = "Tags"
      pageRef = "/tags"
      weight = 20
    
    [[main]]
      name = "About"
      pageRef = "/about"
      weight = 30
    

    这段配置将在网站头部菜单栏中创建三个项目:PostsTagsAbout,分别指向各自 pageRef 中的对应路径。这些项目会根据各自的 weight 进行排序,若 weight 相等则根据 name 的字母顺序排序。你可以根据自己的需求进行调整。

  3. 打开 params.toml 进行修改。具体的可调节参数特别多,请参照 Blowfish 官方文档进行配置。你可以逐一尝试调节这些参数,看看会产生什么效果。

另外,如果想要配置站点的 Favicon(即浏览器标签中网站标题旁边的小图标),应当把它们保存在 /static 目录中。它的结构看起来应当是这样的:

static
├─ android-chrome-192x192.png
├─ android-chrome-512x512.png
├─ apple-touch-icon.png
├─ favicon-16x16.png
├─ favicon-32x32.png
├─ favicon.ico
└─ site.webmanifest

能够制作 Favicon 的网站有很多,我使用的是 favicon.io

创建文章页面
#

如果你在之前的步骤中已经创建过文章,推荐把他们全部删除后再创建新的文章,因为 Blowfish 的模板和 Hugo 的默认模板有一些区别。当然如果不嫌麻烦的话你也可以在之前的基础上进行修改。

  1. 新建一篇文章:

    hugo new post/my-new-post.md
    

    这个命令将在 /content/post 文件夹中生成 my-new-post.md 文件。

  2. 打开 my-new-post.md 文件,可以看到文件里已经生成了一些内容:

    ---
    title : 'My New Post'
    date : 2025-07-17T17:10:29+08:00
    draft : true
    description : ""
    ---
    
  3. 你可以在文件中随意编辑,之后点击保存。

    与标准 Markdown 语法和 Hugo 默认简码略有不同的是,Blowfish 有一套额外的语法和简码规则。同时,Blowfish 还允许你对页面内容进行高度自定义。如果你对这些还不是很了解的话,推荐参考以下 Blowfish 官方内容:

  4. 在站点根目录下,输入 hugo server 启动服务。此时在浏览器中访问 http://localhost:1313,进入 Posts 页面,即可看到你的文章。

    如果文章没有显示出来,请确认其 draft 参数是否为 false,并确保 menus.zh-cn.toml 中的 pageRef 配置正确。
    如果想要预览草稿状态的文章,请使用 hugo server -D 命令。

上传站点
#

  1. 在站点根目录下,执行以下命令生成静态文件:

    hugo
    

    这时你会发现,站点根目录下多了一个 /public 文件夹,生成的站点静态文件都存放在这个文件夹里。这也是我们接下来要使用 GitHub Actions 自动推送的目录。

  2. 依次执行以下命令,将站点的所有源文件推送到你的私有仓库中:

    git remote add origin <你的私有仓库地址>
    git pull --rebase origin main
    git add .
    git commit -m '<提交信息>'
    git push -u origin main
    
  3. 之后对站点做出修改并需要提交时,使用以下命令即可:

    git add .
    git commit -m '<提交信息>'
    git push -u origin main
    

到这里,你的站点源文件应该被成功推送到之前创建好的私有仓库中了。接下来,我们将使用 GitHub Actions 实现自动推送并发布到 GitHub Pages。

发布到 GitHub Pages
#

在开始之前,我们再来梳理一遍使用 Hugo 生成站点的流程:

  • 安装 Hugo
  • 安装主题
  • 进行编辑
  • 生成静态页面
  • 将静态页面推送到 GitHub Pages

如果你理解了以上流程,那么接下来的操作应该非常好懂。我们使用 GitHub Actions 的目的,就是要将以上所有步骤自动化。之后,当你每次完成编辑并推送到私有仓库时,这些流程都会被自动执行。同样,我们也将按照这个思路来撰写 Workflows 文件。

如果你还不知道什么是 GitHub Actions,推荐阅读这些内容:GitHub Actions 文档5分钟快速入门 GitHub Actions

以子模块形式导入 /public
#

如果你是按照前面的流程一步步进行到这里的,那么只需要将 /public 导入为子模块即可。打开站点根目录下的 .gitmodules 文件,在其中添加下面这一段:

[submodule "public"]
    path = public
    url = <你的 GitHub Pages 仓库地址>

例如,我的 .gitmodules 文件如下:

[submodule "themes/blowfish"]
    path = themes/blowfish
    url = https://github.com/nunocoracao/blowfish.git
    branch = main

[submodule "public"]
    path = public
    url = https://github.com/derec30240/derec30240.github.io

如果你并非按照前面的流程操作到这里,或者你的站点根目录下没有 .gitmodules 文件,或者 .gitmodules 文件中的内容中不包含上面第一项,说明 Blowfish 主题没有被成功添加为子模块。请返回前文,执行这一节中的第一步。

个人访问令牌(PAT)
#

我们在最开始创建了两个仓库,并希望将私有仓库中的内容推送到公共仓库中。但是 GitHub Actions 自身只拥有自己所在仓库的操作权限。所以,为了实现跨仓库推送,我们需要为它添加一个允许跨仓库操作的令牌,即个人访问令牌(personal access token, PAT)。

创建 PAT
#

  1. 前往 GitHub 账号设置中的 Personal access token 界面。
  2. 点击「Generate new token」,选择「Generate new token (classic)」。
    fig2
  3. 按如下方式设置 PAT:
    • Notes 填一个自己喜欢的名称。
    • Expiration 选择 No expiration
    • Select scopes 只需勾选 repoworkflow 即可。
  4. 点击页面最下方的「Generate token」按钮,会显示刚才创建的 PAT。点击右侧的按钮将它复制下来。PAT 只会显示这一次,请务必复制下来保存好,我们马上会用到它。
    fig3

设置私有仓库的 Secret
#

  1. 进入私有仓库界面,打开「Settings」-「Secrets and variables」-「Actions」,点击「New repository secret」。
  2. Name 填一个自己喜欢的名称。将刚才复制的 PAT 粘贴到 SecretValue 字段中。

撰写 Workflows 文件
#

  1. 在私有仓库的根目录中创建目录 /.github/workflows,这个文件夹将用来专门存储 Workflows 文件。

  2. 在其中创建文件 <action>.yml。其中 <action> 可以使用自己喜欢的名称。此时文件结构应当是这样的:

    .
    └─ .github
       └─ workflows
          └─ <action>.yml
    
  3. 打开<action>.yml,开始撰写 workflow。如果你不会写,可以参考我的配置,也可以参考 Hugo 官方配置,或者让 AI 帮你写。当然都要根据你的实际情况进行修改。

    以我的配置为例,第30行的 <Name> 需要替换为你在创建 Secret 时设定的 Name;第32行的 <repo> 需要替换为你自己的 GitHub Pages 仓库地址。

    name: Deploy Hugo site to Pages # Action 的名称
    
    on:
      push:
        branches:
          - main # 在 main 分支发生 push 事件时触发
    
    jobs:
      build:
        runs-on: ubuntu-latest # 使用最新版 Ubuntu 作为虚拟环境
    
        steps:
          - name: Checkout repository
            uses: actions/checkout@v2
            with:
              submodules: true # 使用子模块
    
          - name: Setup Hugo # 在虚拟环境中安装 Hugo
            uses: peaceiris/actions-hugo@v2
            with:
              hugo-version: 'latest'
              extended: true
    
          - name: Build Hugo site # 生成静态文件
            run: hugo --minify
    
          - name: Deploy to GitHub Pages # 部署到 GitHub Pages
            uses: peaceiris/actions-gh-pages@v3
            with:
              personal_token: ${{ secrets.<Name> }} # 拥有相应权限的 PAT
              publish_dir: ./public # 要推送的目录
              external_repository: <repo> # 目标仓库地址
              publish_branch: main # 推送到目标仓库的 main 分支
    

测试效果
#

完成以上所有步骤后,在私有仓库进行 push 操作,即可触发我们编辑好的 workflow。

然后,进入你的 GitHub Pages 仓库界面,可以看到站点的静态文件已经被成功推送。在提交信息旁边的绿色小勾说明我们的 workflow 已经被成功执行。

fig4

进入 Action 界面即可看到全部 workflow 的执行情况。橙色的圈表示正在执行,蓝色的勾表示成功,红色的叉表示失败(不过既然静态文件能够出现在 GitHub Pages 仓库,说明 workflow 肯定运行成功了)。我们可以在私有仓库的 Action 界面查看每次 push 后的执行情况。如果运行失败,GitHub 会通过邮件提醒你。

fig5

点击即可查看详细执行过程和日志。

fig6

🎉恭喜你成功搭建了属于自己的博客!

提示
#

修复 Tags 页面显示问题
#

当你第一次为文章添加了 tags 属性后,进入到「Tags」页面,可能会发现刚才添加的 tags 都没有显示。

如果遇到了这种问题,按照下面的步骤进行配置:

  • 确保 /config/_default/menus.zh-cn.toml 中相关的 pageRef 配置正确。
  • /content 目录下创建 /tags 文件夹。
  • /content/tags 目录下创建 _index.md 文件。

这时再打开「Tags」页面,可以看到 tags 都正常显示在这里了。你可以在这个 _index.md 文件中添加你想要在「Tags」页面显示的内容。

这个方法也适用于首页、「Categories」、「About」等页面。对于首页,_index.md 可直接位于 /content 目录下。

设置代码块行为
#

如果代码块不能复制,按照下面的流程进行配置:

  • /config/_default/params.toml 中的 enableCodeCopy 设置为 true
  • 确保 /config/_default/markup.toml 中的 highlight.noClasses 设置为 false
  • 代码块必须声明使用的语言类型,或者声明为 plaintext 类型。

如果想让代码块显示行号,在语言类型声明后添加 {linenos=table} 即可。例如:

1
2
3
4
5
6
```yml {linenos=table}
name: Deploy Hugo site to Pages
   on:
     push:
       branches:
         - main

更多操作详见 语法高亮 | Hugo 官方文档

然而,在默认情况下,如果开启 linenos=table,当代码行过长时无法左右滚动。一种可能的解决方法如下:

  • /config/_default/hugo.toml 中添加如下内容:

    [markup]
      [markup.highlight]
        lineNos = true
        lineNumbersInTable = false  # 强制使用非表格模式
    
  • 使用 {linenos=true}

但是这会导致复制代码时连同行号一起复制。我目前还没有找到更好的解决方法,还请各位提点。

添加自定义图标
#

如果想使用主题自带图标之外的图标(例如 Bilibili ),可以去寻找对应的 .svg 矢量图,然后对其重命名,使文件名只包含英文字母和数字,存放在 /assets/icons 目录下。需要使用时,直接通过不带 .svg 扩展名的文件名,在简码中引用即可。

例如,要使用 Bilibili 的图标,在找到合适的文件后将其重命名为 bilibili.svg,使用 {{< icon "bilibili" >}} 即可。主页中的 links 也会自动匹配同名图标。

如果使用后发现图标颜色显示异常,可以用文本编辑器打开对应的 .svg 文件,将 fill="***" 修改为 fill="currentColor",或者将 <path d="***"> 修改为 <path fill="currentColor" d="***">

在这里推荐一个常用的 svg 图标网站:Simple Icons。但是由于版权原因,有些图标在这个网站中可能找不到 ,就要靠诸位各显神通了


参考
#