Hugo建站日记

旧时代的船,想要载新世界的梦

前言

2024年底,突然对游戏没了兴趣,在家里装了一台Homelab的机器后,开始广泛的对各种技术重新开始产生兴趣。在网上搜资料看到众多大佬自己的网站,找到了很多宝藏,心血来潮的有了自己建一个博客的想法。于是,拿出了被丢掉很多年的建站技能,和废弃很多年的域名,搭建了一个个人博客站,也就有了经典的博客第一篇文章就是搭建博客,meta-blog!

PS: 按以下教程无需域名也能搭建

阅读前请审视整体方案,需要会使用Github和命令行

  • 建站工具: hugo
  • 建站工具皮肤: PaperMod
  • 源代码(原文档)托管平台: Github
  • 站点部署: Github Pages
  • CI/CD(持续集成/持续部署): Github Actions

hugo-build-site

整体思路为,在Github中创建两个代码仓,一个用于管理源代码(博主的工作台,建议设置为Private),另一个用于部署静态站点(需要特殊命名,利用Github Pages托管),再利用Github Actions监听源代码仓变动后,自动更新Github Pages页面。

Hugo安装及配置

以下命令均由GitBash终端执行,如使用CMD或PowerShell可以自行替换对应命令

Hugo安装

Hugo的安装比较简单,go的编译产物基本都是一个二进制的可执行文件。从Github的Release页面下载对应操作系统的可执行文件即可。

我常用的工作、开发机操作系统均为Windows,则以Windows为例,下载 hugo的windows版本文件,将.exe文件解压到任意位置,如D:\sdk\hugo。打开环境变量配置,在PATH变量中新增D:\sdk\hugo 目录,使得命令行可以直接使用hugo.exe而不需要CD到指定目录(不会新增环境变量的,请自行百度)。

下载及配置完之后,打开命令行,输入hugo versionhugo.exe version进行验证,如输出版本号则代表安装成功。例如我的输出为:

[ bash ]
1$ hugo version
2hugo v0.139.3-2f6864387cd31b975914e8373d4bf38bddbd47bc+extended+withdeploy windows/amd64 BuildDate=2024-11-29T15:36:56Z VendorInfo=gohugoio

创建站点

使用hugo命令 hugo new site $YOUR_SITE_NAME 来创建站点。该站点后续会被作为原文档仓库托管到Github进行管理

[ bash ]
 1$ hugo new site zanks-blog
 2Congratulations! Your new Hugo site was created in D:\03_code\personal\zanks-blog.
 3
 4Just a few more steps...
 5
 61. Change the current directory to D:\03_code\personal\zanks-blog.
 72. Create or install a theme:
 8   - Create a new theme with the command "hugo new theme <THEMENAME>"
 9   - Or, install a theme from https://themes.gohugo.io/
103. Edit hugo.toml, setting the "theme" property to the theme name.
114. Create new content with the command "hugo new content <SECTIONNAME>\<FILENAME>.<FORMAT>".
125. Start the embedded web server with the command "hugo server --buildDrafts".
13
14See documentation at https://gohugo.io/.

命令输入完成后,会在当前目录下创建zanks-blog文件夹,这个文件夹会作为原文档仓库。使用tree命令(没有的也可以直接用ll)看一下hugo生成的目录,内容不多。

[ bash ]
 1$ tree .
 2.
 3|-- archetypes
 4|   `-- default.md
 5|-- assets
 6|-- content
 7|-- data
 8|-- hugo.toml
 9|-- i18n
10|-- layouts
11|-- static
12`-- themes
13
148 directories, 2 files

配置皮肤

在正式启动前,可以给站点安装一个自己喜欢的皮肤(如果不安装,直接进行下一步本地调试,会出现Page Not Found的错误,我已经试过了,不必再试)

我使用的皮肤是PaperMode

首先,使用git init将这个站点目录变为Git仓库,然后使用submodule命令获取皮肤,这边会从Github上下载东西,如果遇到网络问题,需要使用魔法手段解决。

这里稍微解释一下,submodule 是一个不太常见的Git命令,通常被用于管理Git仓库中的子模块(submodule)。子模块是指一个Git仓库作为另一个Git仓库的子目录。使用子模块,可以将一个项目嵌入到另一个项目中,同时保持两者的独立性。(AI告诉我的,其实我也不懂)

[ bash ]
 1$ git init
 2Initialized empty Git repository in D:/03_code/personal/zanks-blog/.git/
 3
 4$ git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
 5Cloning into 'D:/03_code/personal/zanks-blog/themes/PaperMod'...
 6remote: Enumerating objects: 139, done.
 7remote: Counting objects: 100% (139/139), done.
 8remote: Compressing objects: 100% (98/98), done.
 9remote: Total 139 (delta 36), reused 121 (delta 36), pack-reused 0 (from 0)
10Receiving objects: 100% (139/139), 249.18 KiB | 5.08 MiB/s, done.
11Resolving deltas: 100% (36/36), done.
12warning: in the working copy of '.gitmodules', LF will be replaced by CRLF the next time Git touches it

根据PaperMod的官方建议,使用yaml替换toml作为配置文件。安装主题后,备份hugo.toml文件,新增hugo.yml并添加以下内容,其中title可以随意替换为自己喜欢的。

[ yml ]
1baseUrl: https://example.org/
2languageCode: zh-cn
3title: 乱话三千
4theme: PaperMod

以上配置只能保证站点可以启动,下文中将给出更多高阶配置,需要理解并筛选和更改为适用于自己站点的配置项(当然你直接照抄也是可以的)

[ yaml ]
 1baseUrl: https://example.org/
 2languageCode: zh-cn # en-us
 3title: 乱话三千
 4theme: PaperMod
 5  
 6
 7enableRobotsTXT: true # 允许爬虫协议
 8enableEmoji: true # 允许使用Emoji表情
 9buildDrafts: false
10buildFuture: false
11buildExpired: false
12  
13
14params:
15  profileMode:
16    enabled: true
17    subtitle: "记载着某个人的胡言乱语"
18    imageUrl: "/homepage.jpg" # optional
19    imageWidth: 150 # custom size
20    imageHeight: 150 # custom size
21    buttons:
22      - name: 点击开始
23        url: "/posts"
24  
25menu:
26  main:
27    - identifier: post
28      name: 文章
29      url: /posts/
30      weight: 10
31    - identifier: tags
32      name: 标签
33      url: /tags/
34      weight: 20
35    - identifier: about
36      name: 关于
37      url: /about/
38      weight: 30

这份配置使用了ProfileMode,在首页配置了一个图标和一个按钮,按钮将链接到 /posts 路径。并且在右上角的菜单中添加了三个按钮,分别连接到对应的路径,其中weight表示排序权重,数字越小按钮越靠近左侧。

创建文章

使用 hugo new $YOUR_ARTICAL命令来创建文章

[ bash ]
1$ hugo new posts/test.md
2Content "D:\\03_code\\personal\\zanks-blog\\content\\posts\\test.md" created

该命令在content/posts目录下创建了test.md文件,可以再使用 tree content命令或者 ll content 查看

[ bash ]
1$ tree content/
2content/
3|-- posts
4|   `-- test.md
5`-- posts.md
6
71 directory, 2 files

然后再使用cat命令查看自动生成的文件中有什么内容

[ bash ]
1$ cat content/posts/test.md
2+++
3date = '2024-12-09T09:25:05+08:00'
4draft = true
5title = 'Test'
6+++

其中date、titile很好理解,分别为日期和文章的标题。draft 这个查阅了一下官网的解释,大致的意思为表示当前的文章为草案,在构建时除非人为添加参数指定,否则不会打包到最后的静态文件中。以下是官网的原文解释:

[ text ]
1draft:
2(`bool`) If `true`, the page will not be rendered unless you pass the `--buildDrafts` flag to the `hugo` command. Access this value from a template using the [`Draft`](https://gohugo.io/methods/page/draft/) method on a `Page` object.

然后,给文件中,添加一些内容。这里不需要修改draft,后续在编译中可以通过参数指定查看到草稿内容。但生产环境需要发布时,将draft的值改为false

[ bash ]
1$ cat content/test.md
2+++
3date = '2024-12-09T09:25:05+08:00'
4draft = true
5title = 'Test'
6+++
7  
8这是一篇测试文章

本地调试

本地调试是hugo提供的非常方便的工具,可以让我们在正式发布前看到站点的样子。只需要执行 hugo serverhugo serve 即可在本地启动服务端(在调试时可以添加-D参数看到草稿中的文章)。以下是我进行尝试的输出。

[ bash ]
 1$ hugo serve -D
 2Watching for changes in D:\03_code\personal\zanks-blog\{archetypes,assets,content,data,i18n,layouts,static,themes}
 3Watching for config changes in D:\03_code\personal\zanks-blog\hugo.yml
 4Start building sites …
 5hugo v0.139.3-2f6864387cd31b975914e8373d4bf38bddbd47bc+extended+withdeploy windows/amd64 BuildDate=2024-11-29T15:36:56Z VendorInfo=gohugoio
 6
 7
 8                   | EN
 9-------------------+-----
10  Pages            | 11
11  Paginator pages  |  0
12  Non-page files   |  0
13  Static files     |  1
14  Processed images |  0
15  Aliases          |  0
16  Cleaned          |  0
17
18Built in 64 ms
19Environment: "development"
20Serving pages from disk
21Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
22Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
23Press Ctrl+C to stop

启动后,终端输出了服务器地址,使用浏览器进入就可以预览站点部署后的样子了。不出意外的话,可以看到创建的测文章。

配置文章模板

在archetypes目录下备份并修改default.md文件来修改新增文章的模板,以下是我根据官方模板进行修改的模板

[ yaml ]
 1---
 2title: "{{ replace .File.ContentBaseName "-" " " | title }}"
 3date: 2020-09-15T11:30:03+00:00
 4tags: [""]
 5author: "Zanks"
 6draft: true # 默认为草稿模式
 7  
 8
 9weight:  #可以用于置顶
10showToc: true # 显示目录
11TocOpen: false # 打开目录
12comments: false # 评论
13description: ""
14searchHidden: false # 优化SEO
15ShowReadingTime: true
16ShowWordCount: true
17cover:
18---

添加About页面

前面已经配置了About的链接,但是在访问时会出现404,下文中将会配置这个页面。 依然是使用hugo new 命令来创建md文件

[ bash ]
1$ hugo new about.md
2Content "D:\\03_code\\personal\\zanks-blog\\content\\about.md" created

在其中添加一些介绍自己的内容,然后进入页面,点击关于就可以看到新增加到内容了(在发布时,记得将draft更改为false)

我尝试直接在content目录下创建 about.md 文件,在调试环境中可以看到这个页面,但是实际发布后却没有在public目录找到对应文件,暂时没有找到解决方案。删除并配置了文章模板后,通过命令创建about.md后可以正常工作。

源代码仓管理

本地仓初始化

  1. 执行 git init 命令来初始化目录为git仓
[ bash ]
1$ git init
2Initialized empty Git repository in D:/03_code/personal/zanks-blog/.git/
  1. 添加一个.gitignore文件,将public文件夹取消跟踪,该仓将作为源代码仓进行管理,所以构建产物不需要加入跟踪。并将该文件commit(建议通过VSCode等带有图形化管理的操作)
[ bash ]
1$ cat .gitignore
2/public
  1. 为每个空的目录添加.gitkeep文件,来保证源代码仓的完整目录结构(asset、data、i18n、layouts),提交所有改动文件。

完成以上动作之后,本地仓构建完成。后面将在Github上创建代码仓,与该本地仓进行关联。

Github代码仓创建

在Github上创建一个空代码仓,使用命令进行关联。在Github页面上会有提示如何关联已有仓库,根据给出的命令直接复制到终端执行即可。

[ bash ]
 1$ git remote add origin git@github.com:ZaNksC/zanks-blog.git
 2git branch -M main
 3git push -u origin main
 4Enumerating objects: 165, done.
 5Counting objects: 100% (165/165), done.
 6Delta compression using up to 12 threads
 7Compressing objects: 100% (148/148), done.
 8Writing objects: 100% (165/165), 274.80 KiB | 1.01 MiB/s, done.
 9Total 165 (delta 36), reused 0 (delta 0), pack-reused 0
10remote: Resolving deltas: 100% (36/36), done.
11To github.com:ZaNksC/zanks-blog.git
12 * [new branch]      main -> main
13branch 'main' set up to track 'origin/main'

登录Github就可以看到该代码仓中已经有内容了。

完成这一步后,就可以在任何装有Git和Hugo的机器上对博客进行开发了。

自动化部署

Github Pages托管

使用Github Pages进行静态站点托管,需要在Github中创建一个名为 username.github.io的特殊项目。 创建之后,就可以用 https://username.github.io 作为域名直接访问了,当然现在这里是一个空项目,访问之后会出现404。

Github Action自动化部署

Github的Action是一套标准的CI/CD系统,通过内置在源代码仓中.github/workflow目录下的yaml文件来定义流水线的动作。以下是我从Github Workflow的hugo流水线模板修改来的CICD一体化流水线。

[ bash ]
 1$ cat .github/workflows/hugo.yml
 2# Sample workflow for building and deploying a Hugo site to GitHub Pages
 3name: Deploy Hugo site to Pages
 4
 5on:
 6  # Runs on pushes targeting the default branch
 7  push:
 8    branches: ["main"]
 9
10  # Allows you to run this workflow manually from the Actions tab
11  workflow_dispatch:
12
13# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
14permissions:
15  contents: read
16  pages: write
17  id-token: write
18
19# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
20# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
21concurrency:
22  group: "pages"
23  cancel-in-progress: false
24
25# Default to bash
26defaults:
27  run:
28    shell: bash
29
30jobs:
31  # Build job
32  build:
33    runs-on: ubuntu-latest
34    env:
35      HUGO_VERSION: 0.139.3
36    steps:
37      - name: Install Hugo CLI
38        run: |
39          wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
40          && sudo dpkg -i ${{ runner.temp }}/hugo.deb
41      - name: Install Dart Sass
42        run: sudo snap install dart-sass
43      - name: Checkout
44        uses: actions/checkout@v4
45        with:
46          submodules: recursive
47      - name: Install Node.js dependencies
48        run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
49      - name: Build with Hugo
50        env:
51          HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache
52          HUGO_ENVIRONMENT: production
53        run:
54          hugo --baseURL=https://zanksc.github.io
55      - name: Deploy Pages
56        uses: peaceiris/actions-gh-pages@v3
57        with:
58            PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
59            EXTERNAL_REPOSITORY: ZaNksC/ZaNksC.github.io
60            PUBLISH_BRANCH: main
61            PUBLISH_DIR: ./public
62            commit_message: ${{ github.event.head_commit.message }}

需要自行修改 Build With Hugo 步骤中的构建命令,baseURL替换为自己的博客地址,Deploy Pages步骤中的EXTERNAL_REPOSITORY变量,需要替换为自己的GitPage地址。

需要注意的是,在最后一个步骤Deploy Pages中,有${{ secrets.PERSONAL_TOKEN }}变量,这个变量位于源代码仓-settings-Secrete And variables-Action中。需要在这个目录中创建一个名为PERSONAL_TOKEN的变量。

github-actions-secret
变量的值则需要在Github(点击头像) - settings-Deploy Settings-Personal access tokens中创建,创建一个经典(classic)的Token,赋予 repo 的所有权限保证可以读写仓库。复制该Token的值(只会出现一次),填入上文提到的 PERSONAL_TOKEN的变量中。
github-token

在全部配置完成之后,可以通过 hugo new posts/test.md 输入一些内容并将draft值改为true,输入 git add . && git commit -m "add test.md" 进行提交,然后等待一段时间后,访问 https://name.github.io 查看博客中是否出现该文章来进行全流程验证。

参考资料