本文将详细介绍在 Windows 环境下使用 Hugo 与 Blowfish 主题搭建个人博客,并借助 GitHub Actions 自动推送静态网站到 GitHub Pages 的方法。
在搭建这个博客的过程中,我遭遇了各种各样的问题。然而,部分问题在官方文档和其他网络教程里都语焉不详,只能靠我自己慢慢摸索解决办法。现在,我把这些踩过的坑记录下来,一来是提醒自己,二来也希望能对后来者有所帮助。
准备工作#
创建 GitHub 仓库#
我们需要创建两个 GitHub 仓库。其中一个是私有仓库,用于存放网页的源代码;另一个是公共仓库,作为我们接下来要用到的 GitHub Pages 仓库,用于存放静态网页文件。
首先创建一个新的私有仓库,稍后将会用它来存放 Hugo 生成的源代码。你可以为它取任何你喜欢的名字。例如,我将它命名为 BlogSource。
然后创建一个公共仓库作为 GitHub Pages 的存放位置。需要注意的是,这个仓库的名称必须是 <username>.github.io,其中,<username> 是你的 GitHub 用户名。例如,我将它命名为 derec30240.github.io。
关于 GitHub Pages 的更多信息参见 GitHub Pages 官方文档。
本地安装#
安装 Hugo#
前往 Hugo 官方 GitHub 仓库,进入 Release 界面下载对应版本。我这里选择下载
hugo_0.148.1_windows-amd64.zip。将下载的文件解压后,放在合适的位置,例如
D:\Hugo。将
hugo.exe所在的文件夹路径 (不是hugo.exe的路径!!!) 添加到系统环境变量中。例如,如果
hugo.exe的路径是D:\Hugo\hugo.exe,那么将D:\Hugo添加到系统环境变量中。在终端执行以下命令,验证安装是否成功:
hugo version如果安装成功,会显示 Hugo 的版本信息。否则会报错。
> hugo version hugo v0.148.1-98ba786f2f5dca0866f47ab79f394370bcb77d2f windows/amd64 BuildDate=2025-07-11T12:56:21Z VendorInfo=gohugoio
创建本地站点#
在终端执行以下命令,创建一个新的 Hugo 站点:
hugo new site <mysite>其中
<mysite>是站点的名称,下文将以BlogSource为例进行说明。当然你也可以将其替换为自己喜欢的名称。这个命令将在当前位置创建一个名为
<mysite>的文件夹,站点根目录即位于该文件夹内。进入站点根目录:
cd BlogSource到这一步,不出意外的话,你已经成功创建了一个站点。你可以直接跳转到这里继续下一步操作。当然,如果你已经迫不及待地想要尝试运行这个站点,也可以接着按下面的步骤操作。
新建一篇文章:
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,启动服务后这篇文章是默认不可见的。如果要在预览中显示这些文章,需要给命令添加参数。详见下文。你可以在文件中随意编辑,之后点击保存。
进行预览
在站点根目录下,执行以下命令启动服务:
hugo server # 显示草稿状态的文章 hugo server -D此时在浏览器中访问
http://localhost:1313即可看到你的站点。但是此时你会发现页面显示404 Page Not Found。不用担心,这是正常的,因为我们还没有安装主题。先按 Ctrl + C 停止服务。接下来开始安装主题。
安装 Blowfish 主题#
在站点根目录依次执行以下命令:
git init -b main git submodule add -b main https://github.com/nunocoracao/blowfish.git themes/blowfish这些命令将把你的站点目录初始化为一个新的 git 仓库,并把 Blowfish 作为其子模块导入。
等待 Blowfish 下载完成后进行下一步操作。
删除站点根目录中的
hugo.toml文件。将
/themes/blowfish/archetypes和/themes/blowfish/config两个文件夹分别复制到站点根目录的/archetypes和/config中,替换原有文件。进入
/config/_default目录,将其中的language.en.toml和menus.en.toml两个文件名中的en替换为默认语言代码。例如,在中文环境下,将其分别重命名为language.zh-cn.toml和menus.zh-cn.toml。打开同一目录下的
hugo.toml文件,按照以下步骤修改:- 取消第 5 行的注释。
- 取消第6 行的注释,并将其中的域名替换为你的域名,也就是之前创建的 GitHub Pages 域名:
https://<userename>.github.io,其中<username>是你的 GitHub 用户名。 - 将第 7 行的
en替换为zh-cn。 - 在第 8 行插入
hasCJKLanguage = true,以启用汉字计数。
以我的文件为例,修改后的
hugo.toml开头应该是这样的:5 6 7 8theme = "blowfish" baseURL = "https://derec30240.github.io/" defaultContentLanguage = "zh-cn" hasCJKLanguage = true现在回到站点根目录,执行以下命令启动服务:
hugo server可以看到你的站点已经成功运行了。

至此,Blowfish 的基本安装已经完成。接下来我们将进一步完善网站配置。
配置与调试#
配置站点#
配置文件中每一项参数在官方文档中都有详细说明,如有疑问建议优先查阅。在此仅对一些关键步骤与容易出错的地方进行解释。
建议一边运行
hugo server预览,一边进行修改。
进入
/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中的文件,在后续更新主题时可能会产生冲突。综上,推荐优先在站点根目录中进行编辑。打开
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这段配置将在网站头部菜单栏中创建三个项目:
Posts、Tags和About,分别指向各自pageRef中的对应路径。这些项目会根据各自的weight进行排序,若weight相等则根据name的字母顺序排序。你可以根据自己的需求进行调整。打开
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 的默认模板有一些区别。当然如果不嫌麻烦的话你也可以在之前的基础上进行修改。
新建一篇文章:
hugo new post/my-new-post.md这个命令将在
/content/post文件夹中生成my-new-post.md文件。打开
my-new-post.md文件,可以看到文件里已经生成了一些内容:--- title : 'My New Post' date : 2025-07-17T17:10:29+08:00 draft : true description : "" ---你可以在文件中随意编辑,之后点击保存。
与标准 Markdown 语法和 Hugo 默认简码略有不同的是,Blowfish 有一套额外的语法和简码规则。同时,Blowfish 还允许你对页面内容进行高度自定义。如果你对这些还不是很了解的话,推荐参考以下 Blowfish 官方内容:
在站点根目录下,输入
hugo server启动服务。此时在浏览器中访问http://localhost:1313,进入Posts页面,即可看到你的文章。如果文章没有显示出来,请确认其draft参数是否为false,并确保menus.zh-cn.toml中的pageRef配置正确。
如果想要预览草稿状态的文章,请使用hugo server -D命令。
上传站点#
在站点根目录下,执行以下命令生成静态文件:
hugo这时你会发现,站点根目录下多了一个
/public文件夹,生成的站点静态文件都存放在这个文件夹里。这也是我们接下来要使用 GitHub Actions 自动推送的目录。依次执行以下命令,将站点的所有源文件推送到你的私有仓库中:
git remote add origin <你的私有仓库地址> git pull --rebase origin main git add . git commit -m '<提交信息>' git push -u origin main之后对站点做出修改并需要提交时,使用以下命令即可:
git add . git commit -m '<提交信息>' git push -u origin main
到这里,你的站点源文件应该被成功推送到之前创建好的私有仓库中了。接下来,我们将使用 GitHub Actions 实现自动推送并发布到 GitHub Pages。
发布到 GitHub Pages#
在开始之前,我们再来梳理一遍使用 Hugo 生成站点的流程:
- 安装 Hugo
- 安装主题
- 进行编辑
- 生成静态页面
- 将静态页面推送到 GitHub Pages
如果你理解了以上流程,那么接下来的操作应该非常好懂。我们使用 GitHub Actions 的目的,就是要将以上所有步骤自动化。之后,当你每次完成编辑并推送到私有仓库时,这些流程都会被自动执行。同样,我们也将按照这个思路来撰写 Workflows 文件。
以子模块形式导入 /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#
- 前往 GitHub 账号设置中的 Personal access token 界面。
- 点击「Generate new token」,选择「Generate new token (classic)」。

- 按如下方式设置 PAT:
Notes填一个自己喜欢的名称。Expiration选择No expiration。Select scopes只需勾选repo和workflow即可。
- 点击页面最下方的「Generate token」按钮,会显示刚才创建的 PAT。点击右侧的按钮将它复制下来。PAT 只会显示这一次,请务必复制下来保存好,我们马上会用到它。

设置私有仓库的 Secret#
- 进入私有仓库界面,打开「Settings」-「Secrets and variables」-「Actions」,点击「New repository secret」。
Name填一个自己喜欢的名称。将刚才复制的 PAT 粘贴到Secret或Value字段中。
撰写 Workflows 文件#
在私有仓库的根目录中创建目录
/.github/workflows,这个文件夹将用来专门存储 Workflows 文件。在其中创建文件
<action>.yml。其中<action>可以使用自己喜欢的名称。此时文件结构应当是这样的:. └─ .github └─ workflows └─ <action>.yml打开
<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 已经被成功执行。

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

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

🎉恭喜你成功搭建了属于自己的博客!
提示#
修复 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} 即可。例如:
| |
更多操作详见 语法高亮 | Hugo 官方文档。
然而,在默认情况下,如果开启 linenos=table,当代码行过长时无法左右滚动。一种可能的解决方法如下:
在
/config/_default/hugo.toml中添加如下内容:[markup] [markup.highlight] lineNos = true lineNumbersInTable = false # 强制使用非表格模式使用
{linenos=true}。
但是这会导致复制代码时连同行号一起复制。我目前还没有找到更好的解决方法,还请各位提点。
添加自定义图标#
如果想使用主题自带图标之外的图标(例如
),可以去寻找对应的 .svg 矢量图,然后对其重命名,使文件名只包含英文字母和数字,存放在 /assets/icons 目录下。需要使用时,直接通过不带 .svg 扩展名的文件名,在简码中引用即可。
例如,要使用 Bilibili 的图标,在找到合适的文件后将其重命名为 bilibili.svg,使用 {{< icon "bilibili" >}} 即可。主页中的 links 也会自动匹配同名图标。
如果使用后发现图标颜色显示异常,可以用文本编辑器打开对应的 .svg 文件,将 fill="***" 修改为 fill="currentColor",或者将 <path d="***"> 修改为 <path fill="currentColor" d="***">。
在这里推荐一个常用的 svg 图标网站:Simple Icons。但是由于版权原因,有些图标在这个网站中可能找不到 ,就要靠诸位各显神通了。

