这是一份面向小白的博客维护手册。你不需要理解 Hugo 的全部原理,只要按顺序操作,就可以发布文章、添加图片、修改首页诗句,并在出错时安全地停下来检查。
先记住最重要的三件事
这个博客没有 WordPress 后台,也不需要数据库。它由三部分组成:
- Markdown:保存文章内容,文件名通常以
.md结尾; - Hugo:读取文章、配置和模板,生成静态网页;
- Nginx:把 Hugo 生成的
public目录发布到https://yuning.wang。
日常维护只有一条主线:
修改 Markdown 或配置文件
↓
在预览站检查效果
↓
运行 Hugo 正式构建
↓
打开 yuning.wang 验收
不要直接修改
public里的 HTML。public是 Hugo 自动生成的结果,下次构建时会被覆盖。
一、登录服务器并进入博客目录
打开 macOS 的“终端”,输入:
ssh ubuntu@yuning.wang
第一次连接时,如果终端询问是否信任主机,输入 yes 并按回车。
登录后进入博客目录:
cd /home/ubuntu/blog
确认位置:
pwd
正确输出应当是:
/home/ubuntu/blog
后文中的 Hugo 命令,除非特别说明,都应在这个目录运行。
二、最快发布一篇新文章
如果你只想尽快发布文章,完成这一章即可。其他章节可以等需要时再看。
2.1 决定文章地址
先为文章取一个简短的英文目录名。例如文章标题是“我的第一篇旅行记录”,可以使用:
my-first-trip
建议:
- 只使用小写英文字母、数字和连字符
-; - 不使用空格、中文或下划线;
- 尽量简短,并能表达文章内容;
- 发布后尽量不要改目录名,否则文章地址也会改变。
最终地址会是:
https://yuning.wang/posts/my-first-trip/
2.2 让 Hugo 创建文章
运行:
hugo new posts/my-first-trip/index.md
Hugo 会创建:
content/posts/my-first-trip/
└── index.md
index.md 是文章正文。以后文章使用的图片也放在这个目录中。
2.3 编辑文章
使用 nano:
nano content/posts/my-first-trip/index.md
新文件大致如下:
---
title: "My First Trip"
date: 2026-07-19T18:00:00+08:00
categories:
- 技术笔记
draft: true
---
在这里写文章摘要。
<!--more-->
在这里开始写正文。
两条 --- 之间叫 Front Matter,保存文章标题、日期、分类和草稿状态。
修改为自己的内容,例如:
---
title: "我的第一篇旅行记录"
date: 2026-07-19T18:00:00+08:00
categories:
- 生活随想
draft: true
---
这是显示在首页文章列表里的简短摘要。
<!--more-->
## 出发之前
这里开始写完整正文。
重要字段:
| 字段 | 作用 |
|---|---|
title | 网页上显示的文章标题 |
date | 发布时间,通常保持 Hugo 自动生成的值 |
categories | 文章分类,例如“技术笔记”或“生活随想” |
draft | true 是草稿,false 才会进入正式网站 |
<!--more--> 之前是首页摘要,之后是完整正文。摘要应当简短,不要把整篇文章都放在它前面。
2.4 保存文件
在 nano 中:
- 按
Control + O保存; - 按回车确认文件名;
- 按
Control + X退出。
注意是 Control,不是 Command。
2.5 预览草稿
服务器上的预览服务会读取草稿,并将结果写入独立的 .preview-public,不会污染正式网站。
修改内容后可以重启预览服务:
systemctl --user restart hugo-preview.service
在自己电脑上另开一个终端窗口,建立安全通道:
ssh -N -L 8888:127.0.0.1:8888 ubuntu@yuning.wang
保持这个终端窗口不要关闭,然后用浏览器访问:
http://localhost:8888/posts/my-first-trip/
如果文章地址不存在,先确认目录名是否正确,并检查预览服务:
systemctl --user status hugo-preview.service
2.6 正式发布
确认预览无误后,再次编辑文章:
nano content/posts/my-first-trip/index.md
把:
draft: true
改为:
draft: false
保存退出,然后执行正式构建:
hugo --gc --minify --cleanDestinationDir --baseURL https://yuning.wang/
看到构建完成且没有 ERROR 后,打开:
https://yuning.wang/posts/my-first-trip/
也可以检查 HTTP 状态:
curl -I https://yuning.wang/posts/my-first-trip/
看到 HTTP/2 200 表示网页存在。
正常发布时不要先执行
rm -rf public。Nginx 通过 Docker 挂载这个目录,删除并重新创建目录可能让它暂时仍指向旧目录。上面的 Hugo 命令会安全地清理旧产物。
三、Markdown 常用写法
3.1 标题
文章主标题已经写在 Front Matter 的 title 中,正文一般从二级标题开始:
## 二级标题
### 三级标题
#### 四级标题
Hugo 会根据这些标题自动生成文章目录和锚点。修改标题后重新构建,目录也会自动更新。
本站默认显示目录。文章可单独设置:
ShowToc: true
TocOpen: false
ShowToc: true:显示目录;ShowToc: false:隐藏目录;TocOpen: true:默认展开;TocOpen: false:默认折叠。
3.2 段落与换行
普通段落之间留一个空行:
这是第一段。
这是第二段。
不要依赖连续空格排版,也不要为了首行缩进手动输入许多空格。
3.3 粗体、斜体和删除线
这是 **粗体**。
这是 *斜体*。
这是 ~~删除线~~。
实际效果:这是 粗体,这是 斜体,这是 删除线。
3.4 链接
[访问 Hugo 官网](https://gohugo.io/)
实际效果:访问 Hugo 官网。
3.5 列表
无序列表:
- 第一项
- 第二项
- 子项目
有序列表:
1. 第一步
2. 第二步
3. 第三步
任务列表:
- [x] 已完成
- [ ] 待完成
3.6 引用
> 小舟从此逝,江海寄余生。
实际效果:
小舟从此逝,江海寄余生。
3.7 分隔线
单独写三个短横线:
---
3.8 表格
| 项目 | 状态 |
|---|---|
| 写文章 | 完成 |
| 上传图片 | 进行中 |
实际效果:
| 项目 | 状态 |
|---|---|
| 写文章 | 完成 |
| 上传图片 | 进行中 |
3.9 行内代码与代码块
行内代码用一对反引号:
运行 `hugo version` 查看版本。
多行代码使用三个反引号,并标注语言:
```python
message = "Hello, Hugo"
print(message)
```
实际效果:
message = "Hello, Hugo"
print(message)
代码很长时会出现横向滚动条,不会撑破页面。
四、给文章添加图片
4.1 图片放在哪里
一篇文章和它的图片放在同一目录:
content/posts/my-first-trip/
├── index.md
├── street.jpg
└── ticket.png
这样移动或备份文章时,不容易遗漏图片。
4.2 从自己的电脑上传图片
这条命令在自己的 Mac 终端运行,而不是在服务器 SSH 窗口运行:
scp ~/Desktop/street.jpg ubuntu@yuning.wang:/home/ubuntu/blog/content/posts/my-first-trip/
如果文件名包含空格,建议先改成简短英文名。
上传后,在服务器确认:
ls -lh /home/ubuntu/blog/content/posts/my-first-trip/
4.3 在文章中显示图片

方括号内是图片说明,圆括号内是文件名。文件名大小写必须与服务器文件完全一致。
本站标识图的真实示例:

实际效果:

图片同时作为链接:
[](site-logo.png)
实际效果:
4.4 图片不显示时
依次检查:
- 图片是否真的位于文章目录;
- Markdown 文件名与真实文件名是否一致;
- 是否误用了自己电脑上的绝对路径;
- 是否重新运行了 Hugo 构建。
正式发布后可检查:
curl -I https://yuning.wang/posts/my-first-trip/street.jpg
五、维护首页随机诗句
首页标题下方的诗句来自:
data/quotes.yaml
它是一个本地配置文件,不请求第三方诗词 API。配置至少两句后,每次打开或刷新首页时,浏览器会随机选一句;如果只有一句,就固定显示这一句。页面停留期间不会轮播。
5.1 打开配置文件
在服务器博客目录运行:
nano data/quotes.yaml
当前结构如下:
- text: "小舟从此逝,江海寄余生。"
author: "苏轼"
source: "临江仙·夜归临皋"
- text: "凤箫声动,玉壶光转,一夜鱼龙舞。"
author: "辛弃疾"
source: "青玉案·元夕"
- text: "夜来幽梦忽还乡,小轩窗,正梳妆。"
author: "苏轼"
source: "江城子·乙卯正月二十日夜记梦"
字段含义:
| 字段 | 作用 |
|---|---|
text | 首页显示的正文 |
author | 作者 |
source | 作品名,网页会自动加书名号 |
第一条诗句同时承担两个职责:
- 正常情况下参与随机;
- 如果浏览器禁用了 JavaScript,作为默认诗句显示。
5.2 增加一句诗
在文件末尾增加一个完整区块:
- text: "小舟从此逝,江海寄余生。"
author: "苏轼"
source: "临江仙·夜归临皋"
- text: "醉后不知天在水,满船清梦压星河。"
author: "唐珙"
source: "题龙阳县青草湖"
注意:
- 每句从
- text:开始; author和source前面有两个空格;- 三个值都建议使用英文双引号包裹;
- 区块之间可以留一个空行;
- 不要使用 Tab 缩进;
- 作品名只写名称,不要自己加
《》,网页会自动添加。
保存后先重启预览服务:
systemctl --user restart hugo-preview.service
刷新 http://localhost:8888/ 数次,应当能看到不同诗句。
确认无误后正式构建:
hugo --gc --minify --cleanDestinationDir --baseURL https://yuning.wang/
再刷新 https://yuning.wang/ 验收。
5.3 修改或删除诗句
修改:直接编辑对应区块的文字。
删除:删除该诗句从 - text: 开始的整个区块,不要只删其中一行。
如果只保留一句,首页会固定显示这一句,不会报错;以后增加第二句后,随机功能会自动生效。
5.4 配置错误怎么办
先运行:
hugo --gc --minify --cleanDestinationDir --baseURL https://yuning.wang/
如果 YAML 缩进或引号有问题,Hugo 会停止构建并显示错误位置。此时:
- 不要继续删除
public; - 不要重启 Nginx;
- 回到
data/quotes.yaml检查最近添加的区块; - 可以先删掉刚添加的区块,再重新构建。
Hugo 构建失败不会自动替换现有线上网页,因此先修配置即可。
六、修改已发布文章
找到对应源文件:
nano content/posts/my-first-trip/index.md
修改并保存后,先预览,再运行:
hugo --gc --minify --cleanDestinationDir --baseURL https://yuning.wang/
只修改 Markdown 而不重新构建,公网页面不会更新。
如果想暂时隐藏文章,把 draft 改回 true,然后重新构建。
如果希望页面显示最后修改时间,可在 Front Matter 中增加或更新:
lastmod: 2026-07-19T18:30:00+08:00
七、常见问题排查
7.1 构建成功,但首页没有新文章
检查文章是否仍是草稿,或者日期是否误写到了未来:
hugo list drafts
hugo list future
7.2 文章页面返回 404
确认目录名和访问地址一致:
find content/posts -maxdepth 2 -name index.md
然后重新构建。不要手动修改 public 中的 HTML。
7.3 Hugo 报 YAML 错误
常见原因:
- 缩进不一致;
- 漏掉双引号;
- 使用了 Tab;
- Front Matter 缺少开头或结尾的
---; - 首页诗句没有从
- text:开始。
优先检查最后一次修改的几行。
7.4 预览页没有更新
重启预览服务:
systemctl --user restart hugo-preview.service
检查状态:
systemctl --user status hugo-preview.service
确认本机 SSH 安全通道仍在运行,再强制刷新浏览器。
7.5 正式页面没有更新
确认运行的是正式构建命令:
hugo --gc --minify --cleanDestinationDir --baseURL https://yuning.wang/
macOS Chrome 可使用 Command + Shift + R 强制刷新。
7.6 首页或文章突然变成 403/404
不要反复删除文件。先确认 /home/ubuntu/blog/public/index.html 存在。
如果你曾手动删除整个 public 后重新创建,Docker 可能仍挂载旧目录。此时才需要:
cd /home/ubuntu/nginx
docker compose up -d --no-deps --force-recreate nginx
docker exec my-nginx nginx -t
正常的文章发布不需要执行这一步。
7.7 发布失败时怎么办
不要立刻重启所有容器,也不要删除整个博客目录。保留终端中的完整错误信息,检查刚修改的 Markdown 或 YAML。
Hugo 构建失败时,线上旧页面通常仍能继续访问。
八、发布前检查清单
新文章
- 英文目录名简短,没有空格和中文;
-
title是最终标题; -
categories分类正确; - 首页摘要位于
<!--more-->之前; - 正文标题一般从
##开始; - 图片已上传,文件名完全一致;
- 代码块标注了语言;
- 预览页排版正常;
-
draft已改为false; - Hugo 正式构建没有
ERROR; - 正式文章地址返回
HTTP 200。
首页诗句
- 每句都从
- text:开始; -
author和source使用两个空格缩进; - 没有手动添加书名号;
- 预览首页刷新多次没有异常;
- 正式构建成功;
- 正式首页能显示诗句和出处。
九、日常维护速查
创建文章:
cd /home/ubuntu/blog
hugo new posts/my-first-trip/index.md
nano content/posts/my-first-trip/index.md
维护首页诗句:
cd /home/ubuntu/blog
nano data/quotes.yaml
重启预览:
systemctl --user restart hugo-preview.service
正式发布:
hugo --gc --minify --cleanDestinationDir --baseURL https://yuning.wang/
最终可以把整个博客维护过程记成一句话:
修改源文件,预览确认,Hugo 构建,浏览器验收。