halo+nginx 搭建博客系统
categories: 技术 tags: 软件, NAS静态博客与动态博客对比
静态博客系统(如 Hugo)与动态博客系统(如 Halo)在功能、性能和适用场景上存在差异。
| 场景 | 静态博客(Hugo) | 动态博客(Halo) |
|---|---|---|
| 个人博客/文档站 | ✅ 优先选择(低成本、高性能) | ⚠️ 适合需交互功能的场景 |
| 企业官网/产品展示 | ✅ 快速部署、高安全性 | ✅ 需动态内容管理时适用 |
| 高并发场景 | ✅ 静态资源 CDN 加速优势显著 | ❌ 性能瓶颈明显 |
| 非技术用户运营 | ❌ 依赖技术知识 | ✅ 可视化后台降低操作门槛 |
| 长期维护需求 | ✅ 无需频繁更新环境 | ⚠️ 需定期维护服务器和数据库 |
选择将 Hugo 更换为 Halo 的主要原因是,静态页面难以集成各类 AI 插件,不利于网站的现代化。评论功能并非必需。
迁移思路
Hugo 的文章都放置在 content/post/ 下面,直接备份整个 post 文件夹即可,Halo 可以将 markdown 文章直接导入数据库。
即使更换了博客系统,我们依然可以保留原来的写作方式,即在 post 文件夹中编写文章,然后将文章导入 Halo 中进行发布。这种方式为未来可能的迁移需求提供了便利,避免了大费周章的重复工作。

在 post 文件夹初始化 git,方便文章管理,方法与使用 Hugo 的时候类似。
Halo 搭建并添加 SSL 证书
安装 docker 和 docker-compose
Ubuntu 25.04 安装:
sudo apt install docker.io docker-compose-v2
其他发行版也是类似的。注意,有些发行版的 docker-compose 是 1.29 版本,建议安装 v2 以上版本。
运行 Halo
创建一个文件夹,用于存放 Halo 的所有数据——数据库等,此文档以 ./halo 为例。
Halo 官方提供了多种场景的 Docker Compose 配置文件,主要是数据库的不同,可选:PostgreSQL、MySQL、H2 等。也可以手动配置外部数据库,如果对性能没有特别要求的话,不建议配置外部数据库,管理会麻烦很多。
创建 docker-compose.yml 文件:
version: "3"
services:
halo:
image: registry.fit2cloud.com/halo/halo:2 # 最新版 halo
restart: always # 默认开机自启动
...
volumes:
- ./data:/root/.halo2 # 映射数据目录
ports:
- "8090:8090" # http 端口
...
halodb:
image: postgres:15.4
restart: always # 默认开机自启动
...
networks:
halo_network:
先给出几个相比官方 docker-compose 文件需要修改的关键点,后续还会做一些修改。
运行 Nginx
Nginx 的主要作用是给 Halo 添加反向代理和 SSL 证书,SSL 证书需要自行申请,推荐申请 ZeroSSL,不再详述。

Nginx 有两种安装方法:
- 直接写在该
docker-compose.yml中,仅为 Halo 使用,实现单一功能。 - 利用系统现有的 Nginx,添加配置文件实现反向代理。
这里讲解第 1 种方法实现一键配置及设备迁移,对于熟悉 Nginx 的用户,添加反向代理并非难题。
编写一份 nginx.conf,路径为 ./nginx/nginx.conf
# 定义事件处理模块配置
events {
# 设置每个工作进程的最大连接数
worker_connections 1024;
}
# 定义 HTTP 模块配置
http {
# 将 nginx 代理的所有请求实体的大小限制为 1024m
client_max_body_size 1024m;
# 配置主 HTTPS 服务器
server {
# 监听 IPv4 地址的 8091 端口,启用 SSL
listen 8091 ssl;
# 监听 IPv6 地址的 8091 端口,启用 SSL
listen [::]:8091 ssl;
# 设置服务器名(可以是域名或 IP)
server_name localhost;
# SSL 证书配置
ssl_certificate /etc/nginx/ssl/ssl.crt; # SSL 证书文件路径
ssl_certificate_key /etc/nginx/ssl/ssl.key; # SSL 私钥文件路径
# 启用的 SSL/TLS 协议版本
ssl_protocols TLSv1.2 TLSv1.3;
# 允许的加密套件,HIGH 表示高强度加密,!aNULL 禁用无认证加密,!MD5 禁用弱 MD5
ssl_ciphers HIGH:!aNULL:!MD5;
# 配置反向代理规则
location / {
# 将所有请求转发到 Halo 服务的 8090 端口
proxy_pass http://halo:8090;
# 设置代理请求头,将客户端真实信息传递给后端
proxy_set_header Host $host; # 传递客户端请求的原始 Host 头
proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 添加客户端 IP 到 X-Forwarded-For 头
proxy_set_header X-Forwarded-Proto $scheme; # 传递原始协议(http/https)
}
}
}
核心功能总结:
- HTTPS 加密:通过 SSL/TLS 保护数据传输安全。
- 反向代理:将外部请求无缝转发到内网 Halo 服务。
- 安全优化:限制加密协议版本,禁用弱加密算法。
- 大文件支持:允许上传最大 1GB 的文件,防止博客中的图片传不上去。
- 注意:暂无 HTTP 重定向功能,需要自行添加。
将 Nginx 集成到 docker-compose.yml
最终的 docker-compose.yml 文件内容
version: "3"
services:
halo:
image: registry.fit2cloud.com/halo/halo:2.21.6
restart: always
depends_on:
halodb:
condition: service_healthy
networks:
halo_network:
volumes:
- ./data:/root/.halo2
# 反向代理后无需映射此端口
# ports:
# - "8090:8090"
healthcheck:
test:
[
"CMD",
"curl",
"-f",
"http://localhost:8090/actuator/health/readiness",
]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
environment:
# JVM 参数,默认为 -Xmx256m -Xms256m,可以根据实际情况做调整,置空表示不添加 JVM 参数
- JVM_OPTS=-Xmx256m -Xms256m
command:
- --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo
- --spring.r2dbc.username=halo
# PostgreSQL 的密码,请保证与下方 POSTGRES_PASSWORD 的变量值一致。
- --spring.r2dbc.password=passwd
- --spring.sql.init.platform=postgresql
# 外部访问地址,请根据实际需要修改
- --halo.external-url=https://your_domain:8091
halodb:
image: postgres:15.4
restart: always
networks:
halo_network:
volumes:
- ./db:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
environment:
- POSTGRES_PASSWORD=passwd
- POSTGRES_USER=halo
- POSTGRES_DB=halo
- PGUSER=halo
nginx: # 内置一个反向代理服务器
image: nginx:alpine
ports:
- "8091:8091" # 使用 8091 作为 https 访问端口
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/cert.crt:/etc/nginx/ssl/ssl.crt
- ./nginx/cert.key:/etc/nginx/ssl/ssl.key
depends_on:
- halo
networks:
- halo_network
networks:
halo_network:
需要按需修改的地方:
- PostgreSQL 的密码:一定要使用强密码
- 外部访问地址:实际的访问域名和端口
- https 访问端口:公网 IP 使用 443 即可,家庭宽带由于 443 端口被禁,需要改为别的,实例为 8091
- 证书:申请的证书修改为
cert.crt/cert.key,放置到./nginx目录中
启动 docker-compose 项目
如果操作正确,目前的目录结构应该是这样的:

注意证书的路径一定要正确映射。
使用 docker-compose up -d 启动项目,不出意外的话,等一会就可以通过 https://your_domain:port 来安全访问网站了。
文章迁移
图片管理
图片的名称不要重复,名称重复的图片(哪怕在不同的路径下)在上传后会被自动添加后缀,不利于管理,在迁移之前要先把文章中的图片名称检查一遍,该修改的修改,该调整的调整。

插件:内容助手


只能一篇一篇地迁移,不能批量,迁移一篇文章结束后,一定要把图片和文章都清除,再迁移下一篇文章,否则会导致文章重复上传。如果重复上传了也没关系,可以在
附件中进行删除。
经过研究,可以批量迁移,但必须保证每篇文章的文件名不同,hugo 一般全部用的 index.md,因此需要逐文件重命名文档,推荐使用 AI 完成。确保文档名和图片都无重复后,可以直接上传整个文件夹,就不用一篇篇上传了。
迁移后的文章,“标题”markdown 文件内的 # 标题,别名为 markdown 文件名,发表时间为现在的时间,需要进行修改。

摘要留空即可。
插件:highlight.js 代码高亮
Halo 中的文章原生没有提供代码高亮的支持,因此需要手动添加功能插件,推荐使用 highlight.js。

任何主题都可以使用。
插件:自动备份插件
支持按天/小时进行自动备份、自动删除冗余备份。
总结
本文详细介绍了如何使用 Halo 和 Nginx 搭建一个功能完善的博客系统,并提供了从 Hugo 迁移的思路和具体步骤。通过 docker-compose 一键部署,简化了环境配置的复杂度,同时通过 Nginx 实现了 SSL 证书的添加和反向代理,保障了网站的安全性。文章迁移部分则重点讲解了图片管理和内容助手插件的使用,帮助用户顺利完成博客内容的迁移。