Halo 是一款基于 Java 体系开发的现代化开源博客系统,拥有非常精致的管理后台、丰富的插件生态与现代主题。

很多新手在初次搭建时,容易在 Docker 端口映射、Nginx 反代配置以及域名 SSL 解析之间被搞晕。

其实理清网络拓扑就很简单:Halo 容器在后台本地端口运行,Nginx 负责对外监听 80/443 并把请求反向代理给容器,域名解析通过 CDN 转发到服务器。

这篇笔记整理了从购买服务器到 Halo 容器拉起、Nginx 反代配置、端口放行与主题安装的完整上手记录。


建站核心逻辑:服务器、Docker 与反向代理

本教程会在几个地方来回切换,每一步开头都会标明操作位置,千万别敲错地方:

标记图标 代表含义 怎么打开 职责与作用
服务器端: 远程连接在你云服务器上的黑色控制台 本地终端输入 ssh root@IP 连入 负责安装 Docker、启动博客程序、配置反代,全程保持开启
💻 【你本地的浏览器】 你自己手机或电脑上的 Chrome/Edge/Safari 平时上网用的浏览器 负责买域名、配置 Cloudflare 解析、登录博客管理后台
☁️ 【Cloudflare 仪表盘】 免费的全球 CDN 与网络大管家 浏览器打开 dash.cloudflare.com 负责把域名指向服务器,并免费送你终身免维护的 HTTPS 绿锁

准备工作

  • [ ] 一台云服务器(VPS):
  • 拥有公网 IP(例如 123.45.67.89)和初始 root 密码;
  • 推荐系统选 Debian 12 或 Ubuntu 22.04/24.04;
  • [ ] 拍个“快照”(存档):
  • 🗣️ 大白话:在云服务商网页控制台点一下「创建快照」。万一中途操作翻车了,点一下「恢复快照」就能瞬间穿越回起点,新手不存档等于裸奔!
  • [ ] 一个属于你的域名:
  • 任何后缀都行(比如 .com、.xyz、.top),建议在 Namesilo、腾讯云、阿里云或 Cloudflare 购买;
  • 本教程以二级域名 blog.example.com 演示,你可以替换为你自己的域名。

服务器连接与基础环境准备

💻 【你本地的电脑】 打开 Windows 的 PowerShell 或 Mac 的「终端」,输入连接命令(将 IP 替换为你的):

  • 第一次连的提示:终端弹出 Are you sure you want to continue connecting (yes/no)?
    👉 敲键盘输入 yes 并按回车;
  • 输密码的提示:接着出现 root@... password:
    👉 粘贴或输入你的初始 root 密码,然后直接按回车;
  • ⚠️ 高频心理障碍预警:在 Linux 终端输密码时,屏幕上不会有任何星号、圆点或光标移动! 屏幕看上去像没反应一样,这不是键盘失灵,只管稳稳敲完密码按回车即可。
  • ✅ 成功标志:终端屏幕出现 root@xxx:~# 样式的绿色或白色命令提示符。

💡 从这一秒开始,这个黑色终端窗口就是 🖥️【服务器窗口】。把它放在屏幕左边。

紧接着,在 服务器端: 粘贴以下整段命令,校准时钟并刷新环境:

# 1. 设置时区为北京时间
timedatectl set-timezone Asia/Shanghai

# 2. 刷新系统仓库并安装必备轻量小工具
export DEBIAN_FRONTEND=noninteractive
apt update && apt install -y curl wget git htop ufw
  • 🗣️ 说明:升级过程屏幕会飞速刷代码,别慌,等它停下来出现命令提示符即可。

安装 Docker 运行环境

Halo 博客作为一个现代化的开源程序,跑在 Docker 容器里是最稳定、最干净的(完全不污染服务器底层,想删随时一键干掉)。

服务器端: 粘贴执行官方全自动 Docker 安装脚本:

curl -fsSL https://get.docker.com | bash

安装完成后,启动 Docker 并检查版本:

systemctl enable --now docker
docker --version
docker compose version
  • ✅ 成功标志:终端清晰输出类似 Docker version 27.x.x 以及 Docker Compose version v2.x.x 的字样。

创建数据目录与 Compose 配置文件

很多老教程最坑的地方,就是让新手用 vim 逐行去建 docker-compose.yaml,新手一旦漏了个空格或者按错了键,就会卡在编辑界面动弹不得,或者报错 yaml parse error。

这里我们采用全自动防呆写入。并且采用 内置 H2 嵌入式文件数据库:
* 🗣️ 大白话:很多教程教小白额外安装一个独立的 MySQL 或 PostgreSQL 容器,那两个大家伙起步就吃 800MB 内存,小机器瞬间卡死爆 OOM!而 Halo 官方原生内置的 H2 数据库是轻量文件库,零额外开销,1.6G 内存的小机器跑起来轻松自如!

服务器端: 复制下面整段代码,粘贴并回车:

# 1. 创建 Halo 专属数据存放目录
mkdir -p /opt/halo && cd /opt/halo

# 2. 全自动生成 docker-compose.yaml 文件(彻底杜绝手动缩进错误)
cat << 'EOF' > /opt/halo/docker-compose.yaml
version: "3"

services:
  halo:
    image: halohub/halo:2.20
    container_name: halo
    restart: unless-stopped
    volumes:
      - ./:/root/.halo2
    ports:
      - "127.0.0.1:8090:8090"
    environment:
      # 限制 JVM 内存,保证小机器绝对不爆内存
      - JVM_OPTS=-Xms256m -Xmx512m
EOF

# 3. 检查文件是否生成成功
ls -lh /opt/halo/docker-compose.yaml
  • ✅ 成功标志:终端输出显示 /opt/halo/docker-compose.yaml 文件存在,大小约几百字节。
  • 💡 安全设计亮点:端口绑定为 127.0.0.1:8090,意味着 8090 端口只对本机内部开放,外网黑客完全扫描不到它,所有外网访问稍后统一由安全网关接入!

启动 Halo 容器并检查日志

配置就位后,让 Docker 在后台把博客拉起。

服务器端: 执行启动指令:

cd /opt/halo
docker compose up -d
  • 🗣️ 说明:Docker 第一次会自动从云端下载 Halo 镜像,屏幕会滚动显示 Pulling... Download complete,喝口水等待 1~2 分钟。

下载完毕后,检查容器运行状态:

docker compose ps
  • ✅ 成功标志:在输出的列表中,halo 容器的状态显示为 Up 或 running(如下图示例):
    text
    NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
    halo halohub/halo:2.20 "sh -c 'java ${JVM_O…" halo 10 seconds ago Up 8 seconds 127.0.0.1:8090->8090/tcp

配置域名解析与 CDN 代理

🗣️ 大白话:传统老教程最折磨新手的一步,就是在服务器里搞 Certbot 申请证书,遇到国内 DNS 污染、80 端口冲突或解析延迟,频繁报超时错误。现在最聪明的现代化做法是把域名托管在 Cloudflare:它不仅免费帮你抵挡黑客攻击、加速全网访问,还默认自带终身有效的 HTTPS 免费小绿锁!

💻 【你本地的浏览器】 打开 Cloudflare 控制台:

  1. 进入你的域名管理页,点击左侧菜单的 「DNS」➔「记录」;
  2. 点击 「添加记录」:
    * 类型:选择 A;
    * 名称:填你想用的前缀(比如 blog);
    * IPv4 地址:填入你的服务器真实公网 IP(例如 123.45.67.89);
    * 代理状态:保持开启(橙色小云朵 ☁️);
  3. 点击 「保存」。
  4. 接着点击左侧菜单的 「SSL/TLS」:
    * 在加密模式里,选择 「完全 (Full)」 或 「灵活 (Flexible)」 模式。
  • ✅ 成功标志:DNS 记录列表里看到 blog 指向你的 IP,且云朵显示为橙色。

配置 Nginx 反向代理与 SSL 证书

服务器内部的 Halo 跑在 8090 端口,现在我们要让官方标准的 Web 网关(Nginx)接管外部请求,把外界访问平滑反向代理给 Halo。

服务器端: 先填写你的域名变量(将第 1 行换成你自己的真实域名):

MY_DOMAIN="blog.example.com"

接着,整段粘贴执行以下自动化网关部署脚本:

# 1. 安装轻量 Nginx 网页服务
apt install -y nginx

# 2. 写入针对 Halo 特化优化的反向代理配置(带长连接保活与大文件上传放行)
cat << EOF > /etc/nginx/sites-available/halo.conf
server {
    listen 80;
    listen [::]:80;
    server_name ${MY_DOMAIN};

    # 允许上传最大 100MB 的插图与附件
    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:8090;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;

        # 支持 WebSocket 与实时后台通知
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";

        # 调优超时时间,防止发布长文时断连
        proxy_connect_timeout 60s;
        proxy_read_timeout 120s;
        proxy_send_timeout 120s;
    }
}
EOF

# 3. 激活站点并自检语法
ln -sf /etc/nginx/sites-available/halo.conf /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default

# 4. 语法体检与优雅重载
if nginx -t; then
    systemctl restart nginx
    echo "[✓] Nginx 自动化网关配置成功并已就绪!"
else
    echo "[✗] 语法体检未通过,请检查域名变量!"
fi
  • ✅ 成功标志:最后终端打印出 [✓] Nginx 自动化网关配置成功并已就绪!,且没有任何报错。

防火墙端口放行

很多新手在服务器里配得天衣无缝,但在浏览器打开网站却死活提示“连接超时”。99% 的原因就是:服务器外面的云服务商防火墙没给通行证!

💻 【你本地的浏览器】 打开购买 VPS 的云服务商后台(腾讯云/阿里云/AWS/华为云等):

  1. 进入当前服务器实例详情,找到 「安全组」 或 「防火墙」;
  2. 点击 「添加入站规则」,放行两个标准网页端口:
    * 放行 80 端口(HTTP)
    * 放行 443 端口(HTTPS)
    * 授权源填 0.0.0.0/0(允许全网所有人访问你的博客);
  3. 保存生效。

首次访问与博客初始化设置

最激动人心的时刻到了!

💻 【你本地的浏览器】 新开一个标签页,在地址栏输入你的域名:

https://blog.example.com

屏幕上将第一次弹出漂亮的 Halo 博客初始化向导:

  1. 站点名称:填入你的博客大名(例如:晚风手记 或 某某的数字花园);
  2. 站点地址:默认自动识别你的域名;
  3. 管理员用户名:想一个你登录后台的专属账号(比如 admin);
  4. 管理员密码:设置一个强密码(务必牢牢记在小本本上);
  5. 管理员邮箱:填你的常用邮箱;
  6. 点击 「初始化」!
  • ✅ 成功标志:页面自动跳转至博客首页,界面清爽现代,地址栏显示安全小绿锁!

进入后台管理:在你的域名后面加上 /console,例如:

https://blog.example.com/console

输入刚才设置的管理员账号密码,即可跃入功能完备的现代化写作后台!🚀✨


更换博客主题与外观设置

Halo 最迷人的地方就是丰富的应用市场。在后台左侧点击 「应用中心」➔「主题」,你可以一键搜索并免费安装这些全网公认的高颜值主题:

  • 🌸 Hao:目前生态中最成熟、最全能的杂志风格主题,图文并茂、动效极其细腻;
  • 🍃 Akari:极简清爽的文艺日系风格,排版呼吸感拉满,专门为沉浸式阅读而生;
  • 💻 Geist / 极客:程序员最爱的代码与 Markdown 极致高亮主题。

点击「安装」➔「启用」,刷新你的前台首页,你的博客瞬间就会蜕变为顶级独立网站的视觉质感!


常见问题排查

异常现象 真实根因 对应一秒救命招式
浏览器打开提示 502 Bad Gateway Halo 容器还在启动中,或端口未连通 等待 30 秒再刷新;若依然 502,在服务器敲 docker logs --tail 50 halo 查看启动日志。
浏览器打开提示 连接超时 (Timed Out) 云厂商控制台外部防火墙未放行 检查【第 7 步】,去云平台控制台核对 80 和 443 端口的安全组入站规则。
Cloudflare 提示重定向循环 (Error 521/522) Cloudflare SSL 加密模式设置过严 登录 Cloudflare 控制台,进入「SSL/TLS」,将模式切为 「Flexible (灵活)」 即可瞬间秒开。
博客发布长文或大图时提示 413 Request Entity Too Large Nginx 默认限制上传 1MB 重新执行【第 6 步】的配置脚本,脚本内已默认放行 100MB 大文件。
万一哪天不小心把后台管理员密码忘了 遗忘管理密码 在服务器窗口输入 docker exec -it halo halo --reset-password,直接生成临时重置链接。