摘要:
本文档详细介绍了使用Hugo搭建Markdown博客的过程,包括本地编辑环境搭建、主题样式修改、远程部署及图床搭建等步骤。通过本地编辑Markdown文档并预览,成功后可推送至GitHub私有仓库。Hugo将Markdown文档渲染为HTML文件,可利用GitHub Pages服务或VPS中的容器对外暴露。同时,文档还介绍了如何配置SSH Key、克隆主题仓库、修改主题样式,以及通过GitHub Pages或自建服务器进行远程部署,并提供了基于GitHub的图床搭建方法。
Powered by 百度Comate
基本思路:
使用在本地编辑Markdown文档,并测试预览。成功后推送到github私有仓库。hugo可以将markdown文档渲染为html文件。可以使用github的pages服务对外暴漏,也可在vps中启动一个容器来对外暴漏。
1. 本地编辑环境搭建
1.1 二进制安装hugo
直接安装二进制文件,可参考:https://github.com/gohugoio/hugo/releases 下载对应版本并安装
以mac客户端为例,下载对应版本后解压到指定目录。
1
2
3
4
5
6
7
|
# 文件解压
tar -zxvf hugo_0.143.0_darwin-universal.tar.gz
cd hugo_0.143.0_darwin-universal
chmod +x hugo
mv hugo /usr/local/bin
# 验证测试
hugo version
|
1.2 源码安装hugo(可选)
如需源码安装,以mac客户端为例,需要安装git、hugo。
安装git
mac自带git,无需安装。如需安装或更新,可参考:https://git-scm.com/downloads/mac
安装go
可参考链接:https://go.dev/dl/选择对应版本的hugo,下载后解压到指定目录。
安装hugo
go install github.com/gohugoio/hugo@latest
2. 修改主题样式
2.1 配置ssh key
此处为本地开发环境需要,方便免密提交文件到git仓库。这里以提交到github仓库为例。如果主要在国内访问,且有备案域名,建议使用gitee或自有git仓库。
可参考链接:
ssh本地秘钥生成
1
2
3
4
5
6
7
|
ssh-keygen -t ed25519 -C "your_email@example.com" # 邮箱为github注册邮箱,一路输入enter即可
# 如果你使用的是不支持 Ed25519 算法的旧系统,请使用以下命令:
# ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 将 SSH 私钥添加到 ssh-agent。
ssh-add ~/.ssh/id_ed25519
# 查看公钥内容,将其复制
cat ~/.ssh/id_ed25519.pub
|
访问自己的github账号,在账号设置中添加ssh公钥

2.2 克隆主题仓库到本地
将自己喜欢的主题克隆到本地,和hugo一起使用。因涉及到对主题的更改和维护,建议使用git 子模块来维护。可以将该主题fork到自己的空间,然后将自己fork的主题作为子模块添加。这里以stack主题为例。
1
2
3
4
5
6
7
8
9
10
|
# 创建第一个站点
hugo new site pages # pages 为站点文件夹名字
cd pages
git init # 注意初始化的相对位置
# 添加主题,以stack为例。注意github仓库地址不要使用https协议的,否则会出现子模块的更改无法提交的情况
git submodule add --name stack git@github.com:Williamyzd/hugo-theme-stack.git themes/stack
# 添加一个测试页面
hugo new content content/posts/my-first-post.md
echo "hello,word!" >> content/posts/my-first-post.md
hugo server -D -p 8000 # 可查看处于草稿状态下的文档内容 -p 制定可对外暴漏端口,默认是1314
|
浏览器访问页面:http://localhost:8000/posts/my-first-post/,可看到发布内容

2.3 修改主题样式
修改主题样式,主要在hugo.toml(yaml)文件中,或者在主题文件夹中修改。可将themes/stack/exampleSite/hugo.yaml 复制到站点根目录,并修改为自己的配置。
- params-sidebar-avatar修改logo
- params-mainSections 指定主页默认获取的最新文章
- menu-main 指定导航模块
- menu-social 指定社交模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
|
baseurl: https://example.com/
languageCode: en-us
# 主题名称,注意要和子模块的文件夹名一致
theme: stack
# 网站标题
title: Example Site
# 版权信息
copyright: Example Person
# 多语言支持相关
# Theme i18n support
# Available values: ar, bn, ca, de, el, en, es, fr, hu, id, it, ja, ko, nl, pt-br, th, uk, zh-cn, zh-hk, zh-tw
DefaultContentLanguage: en
# Set hasCJKLanguage to true if DefaultContentLanguage is in [zh-cn ja ko]
# This will make .Summary and .WordCount behave correctly for CJK languages.
hasCJKLanguage: false
languages:
en:
languageName: English
title: Example Site
weight: 1
params:
sidebar:
subtitle: Example description
zh-cn:
languageName: 中文
title: 演示站点
weight: 2
params:
sidebar:
subtitle: 演示说明
pagination:
pagerSize: 3
permalinks:
post: /p/:slug/
page: /:slug/
params:
# 这个参数比较关键,决定主页回去哪些目录下去取最新的文章来显示
mainSections:
- ai
- cs
- ops
- tools
featuredImageField: image
rssFullContent: true
favicon: # e.g.: favicon placed in `static/favicon.ico` of your site folder, then set this field to `/favicon.ico` (`/` is necessary)
footer:
since: 2020
customText:
dateFormat:
published: Jan 02, 2006
lastUpdated: Jan 02, 2006 15:04 MST
sidebar:
emoji: 🍥
subtitle: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
avatar:
enabled: true
local: true
src: img/avatar.png # logo存放的位置,在`static/img/`下
article:
math: false
toc: true
readingTime: true
license:
enabled: true
default: Licensed under CC BY-NC-SA 4.0
# 是否开启评论,建议不开
comments:
enabled: false
provider: disqus
# 默认会开启的几个组件:搜索、归档、分类、标签云
widgets:
homepage:
- type: search
- type: archives
params:
limit: 5
- type: categories
params:
limit: 10
- type: tag-cloud
params:
limit: 10
page:
- type: toc
opengraph:
twitter:
# Your Twitter username
site:
# Available values: summary, summary_large_image
card: summary_large_image
defaultImage:
opengraph:
enabled: false
local: false
src:
colorScheme:
# Display toggle
toggle: true
# Available values: auto, light, dark
default: auto
imageProcessing:
cover:
enabled: true
content:
enabled: true
### Custom menu
### See https://stack.jimmycai.com/config/menu
### To remove about, archive and search page menu item, remove `menu` field from their FrontMatter
# 自定义的菜单项
menu:
main:
- identifier: ai #标识符,唯一值
name: AI # 显示的名称
url: /ai # 文件路径,相对于content文件夹
weight: -90 #权重 #权重越小,越靠前显示
params:
### For demonstration purpose, the home link will be open in a new tab
newTab: false #是否新开标签页
icon: ai # 图标信息,查看和自定义图标,可修改 themes/stack/assets/icons 下的文件,将文件名写在这里
- identifier: ops
name: 运维&工具
url: /ops
weight: -90 #权重
params:
### For demonstration purpose, the home link will be open in a new tab
newTab: false
icon: ops #更多的图标信息见后
- identifier: cs
name: CS基础
url: /cs
weight: -90 #权重
params:
### For demonstration purpose, the home link will be open in a new tab
newTab: true
icon: cs #更多的图标信息见后
social:
- identifier: github
name: GitHub
url: https://github.com/CaiJimmy/hugo-theme-stack
params:
icon: brand-github
- identifier: twitter
name: Twitter
url: https://twitter.com
params:
icon: brand-twitter
related:
includeNewer: true
threshold: 60
toLower: false
indices:
- name: tags
weight: 100
- name: categories
weight: 200
markup:
goldmark:
extensions:
passthrough:
enable: true
delimiters:
block:
- - \[
- \]
- - $$
- $$
inline:
- - \(
- \)
renderer:
## Set to true if you have HTML content inside Markdown
unsafe: true
tableOfContents:
endLevel: 4
ordered: true
startLevel: 2
highlight:
noClasses: false
codeFences: true
guessSyntax: true
lineNoStart: 1
lineNos: true
lineNumbersInTable: true
tabWidth: 4
|
现在可以在content目录下创建文档了。
最终效果如下:

3. 远程部署
hugo 生成的静态html文件在public目录下,可以考虑单独创建一个仓库来管理,在主git仓库下再建一个子模块。
3.1 添加静态文件子模块
添加子模块主要使用命令如下:
- 新建远程仓库:git@github.com:Williamyzd/blogs-html.git
- 在主仓库下添加子模块:
1
|
git submodule add -n pub-html git@github.com:Williamyzd/blogs-html.git blog/public
|
如果 子模块添加错误,可用如下命令删除:
1
2
3
|
git rm --cached pub-html # pub-html:子模块名称
rm -rf blog/public # 删除本地文件夹
vim .gitmodules # 删除.gitmodules文件中的子模块信息
|
3.2 远程服务器部署(可选)
- 创建Dockerfile文件,参考如下:
如无服务器可用,可以不考虑这一步。
通过vps(服务器)托管一个nginx服务。dockerfile参考:
1
2
3
4
5
6
7
8
9
10
11
12
|
FROM nginx:1.27.3-alpine
WORKDIR /home
COPY blog.conf /etc/nginx/conf.d/default.conf
# 准备证书,如有可打开
# COPY cert /etc/nginx/cert
RUN apk update && apk add git && \
git clone https://github.com/Williamyzd/blogs-html.git /home/public && \
echo "echo \$(date +%Y-%m-%d) \$(date +%H:%M:%S) [info]: \$(cd /home/public && git pull) >> /var/log/blog/\$(date +%Y-%m-%d).log" >> /home/blog.sh && \
chmod +x /home/blog.sh && \
mkdir -p /var/log/blog && \
echo "*/1 * * * * /home/blog.sh" >> /etc/crontabs/root
CMD crond && nginx && tail -f /dev/null
|
- Dockerfile 内容说明:
这里使用了更加轻量版的alpine版本nginx,并安装了git。这个镜像本身具备定时功能,创建了一个定时任务,每天执行一次git pull命令。因仓库是只读且对外公开,所以这里不需要认证。最后的启动命令是先启动定时任务,再启动nginx服务。同时保留一个主进程,保证容器不会退出。
- nginx配置文件参考:
blog.conf参考(未包含https配置):
1
2
3
4
5
6
7
8
|
server {
listen 80;
server_name blog.xxx.com;
location / {
root /home/public;
index index.html index.htm;
}
}
|
ssl配置的例子,需要提前准备下证书,并将dockerfile 中的注释去掉。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# 以下属性中以ssl开头的属性代表与证书配置有关,其他属性请根据自己的需要进行配置。
server {
listen 80;
# 需要调整为您证书绑定的域名。
server_name blog.xxx.com
return 301 https://$host/$request_uri;
}
server {
listen 443 ssl;
server_name blog.xxx.com; # localhost修改为您证书绑定的域名。
ssl_certificate /etc/nginx/cert/domain_ca.crt; # 将domain_ca.crt替换成您证书链的文件名(如下载文件没有domain_ca.crt则使用domain.crt或domain.pem)。
ssl_certificate_key /etc/nginx/cert/domain.key; # 将domain.key替换成您证书的密钥文件名。
ssl_session_timeout 5m; # 指定SSL/TLS会话的超时时间
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #使用此加密套件。
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #使用该协议进行配置。
ssl_prefer_server_ciphers on;
location / {
root /home/public; #站点目录。
index index.html index.htm;
}
}
|
- 创建docker-compose.yml文件,参考如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
version: '3'
services:
blog:
build:
context: .
dockerfile: Dockerfile
image: blog:v1.0
container_name: blog
restart: always
ports:
- "80:80"
- "443:443"
|
- 构建并启动容器:
将ssl证书(可选)、blog.conf、Dockerfile、Dockerfile文件放到同一目录下,执行如下命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 一键构建并启动脚本
docker-compose up -d # 如果镜像版本不存在,会自动构建镜像,然后启动镜像
# 如需在启动时,都重新构建镜像可执行如下命令
docker-compose up -d --build
# 单独构建镜像并启动容器
# 如当前操作环境的架构与目标机器的架构不同,可以构建镜像,并指定操作系统架构,如:
docker build --platform linux/amd64,linux/arm64 -t blog:v1.0 .
docker compose up -d
# 停止脚本
docker-compose down
|
3.3 使用github pages托管
3.2 自建容器的方式部署,需要自备服务器、域名等,成本较高。不具备条件或者想节约成本,可以考虑白嫖github,使用github pages托管静态文件。只需要一些简单的配置即可。
上文我们已经创建了html文件的仓库:https://github.com/Williamyzd/blogs-html.git 我们只需要在仓库的设置中,开启github pages功能即可。
- 进入仓库设置页面,选择pages选项卡
- 在Source中选择main分支,并选择/(根目录)
- 稍等片刻,即可通过域名访问了。

其中的自定义域名(标红的3),需要有自己的域名,并在域名解析中添加一条解析记录,指向github pages提供的域名。如本例中,域名pages.liu-nian.top需要添加的记录是:williamyzd.github.io。其模式为[github用户名].github.io。当前域名在百度智能云托管,其添加记录如下:

至此可以愉快地访问自己的博客了。
4. 图床搭建-基于github
本人主要使用vscode撰写博客,vscode有丰富的插件。关于markdown相关的,当前使用到的如下:

在博客撰写过程中,不免要复制、粘贴图片,如果直接上传到博客中,涉及到图片存储为止的考虑。而huogo中如果想在编写和最终生产环境中能够展示图片,涉及到几处复杂配置。做过几次尝试便放弃了。博主之前使用过picgo等图床工具,可以直接将复制的图片上传到对应的文件服务器,同时生成一个文件的链接,直接插入文档即可。可惜picgo已经停止维护了。常见的图床常见的托管方如七牛、微博、腾讯云、阿里云等是免费的或一定限额的免费。处于不愿受制与人的考量,这里考虑使用github搭建一个自己的图床。
4.1 创建仓库
- 选择创建一个公开的仓库,用于存放图片。
- 进入设置中,创建token,用于插件上传图片时使用。可直接点击链接配置:https://github.com/settings/personal-access-tokens
github的开发者token可用api的方式对git仓库、账号进行控制。token分为两种,一种是账号级权限控制,另外一种是项目级别的控制。建议选用项目级别控制的 fine-grained personal token。
红框部分注意填写,其中过期时间根据自己需要填写。

注意选中repo权限,勾选repo的写入权限。

创建后页面会显示token信息,进行复制保存,在后续插件配置时使用。
4.2 安装vscode插件

这里使用markdown-image插件,安装后配置如下:
- base 配置,主要是选github为默认存储方式、规定图片存储的格式等,其他内容酌情设置

File Name Format 这个选项比较关键,建议使用年月方式创建文件夹,当月的文件放在一起,以防止文件过多,导致github仓库管理麻烦货加载缓慢。

- github配置,主要是填写仓库地址、token等信息。token信息来源于github账号中生成的token。

至此,图片上传配置完成。
参考链接:
- 图标生成:https://www.iconfont.cn/search/index
- 博客搭建:https://gohugo.io/getting-started/quick-start/
- ssh设置:https://docs.github.com/zh/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account
- 博客设置参考:https://yidude.com/html/15.html