编辑
2026-10-25
项目分享
00

目录

简介
部署
有服务器、域名
1. 前置条件
2. 先把域名解析好
3. docker-compose 配置
4. 启动与初始化
5. Nginx 反向代理
6. HTTPS
7. 备份与升级
8. 本方案检查清单
面板部署(1Panel)
单容器试跑(仅测试)
常见故障对照
个人博客配置
站点信息与外观
菜单与页面
评论
SEO
多用户
多端写作实现
核心流程
手机端
桌面端
自动化的入口
写作纪律

简介

Halo 是一个用 Java(Spring Boot)写的开源建站 / 博客系统,自带管理后台、主题市场和插件市场。它和 Hugo、Hexo 最大的区别是「动态」:文章存在数据库里,页面由服务端实时渲染,写文章、传图片、换主题都在浏览器后台完成。

核心特点与优势:

  • 有后台:文章管理、附件库、页面、评论、用户权限都在可视化界面里,不用碰 Git 和命令行,手机浏览器也能写。

  • 主题 / 插件市场:控制台里直接搜索安装主题和插件,评论、搜索、对象存储一类的功能靠插件补齐,不用改代码。

  • 数据在数据库:支持 PostgreSQL、MySQL、MariaDB,也可以用内置 H2(生产环境不建议);备份是「数据库 + 附件目录」两件事。

  • 开箱即用的博客结构:文章、分类、标签、独立页面、友链(插件)、归档都有现成实现。

  • 部署方式多:Docker Compose、1Panel / 宝塔应用商店、单容器试跑都可以,官方镜像支持国内镜像源。

  • 多用户与权限:可以给协作者分配角色,适合多人维护的站点。

代价也要说清楚:

  • 需要一台服务器常驻运行,不能像静态站那样丢到 GitHub Pages。
  • 资源占用比静态站高(JVM + 数据库),1 核 1G 勉强能跑,建议 2G 内存。
  • 升级要跟着版本走,主题和插件偶尔有兼容问题,升级前必须备份。
维度HaloHugo / Hexo
形态动态,数据库 + 服务端渲染静态,构建出 HTML
写作方式浏览器后台本地 Markdown + Git
部署服务器 + Docker任意静态托管,含 GitHub Pages
运维数据库备份、版本升级几乎为零
适合想可视化运营、多人协作、要评论想零成本、零运维、纯写作

部署

Halo 只能部署在有公网 IP 的服务器上。最省事的是 Docker Compose + PostgreSQL,一条命令起站,再用 Nginx 做反向代理和 HTTPS。

有服务器、域名

1. 前置条件

  • 云服务器:建议 2 核 2G 起,1 核 1G 能跑但写文章、装插件时会紧。
  • 域名一个。国内服务器必须先完成 ICP 备案,否则 80 / 443 会被拦。
  • 系统 Ubuntu 22.04 / 24.04,已装 Docker 和 Docker Compose 插件。
  • 安全组放行 22 / 80 / 443;8090 不要对公网开放,只给本机 Nginx 访问。

安装 Docker(官方脚本):

bash
curl -fsSL https://get.docker.com | sudo sh sudo systemctl enable --now docker docker compose version

2. 先把域名解析好

Halo 的 external-url 决定后台生成的绝对链接、附件地址、邮件里的跳转,初始化前就要定下来。

  • 测试阶段:先用 http://服务器IP:8090,能跑通再换域名。
  • 正式上线:先加 DNS 记录 A blog → 服务器IP,等 dig +short blog.example.com 返回正确 IP 再继续。

DNS 服务商配置方式:

服务商入口记录
CloudflareDNS → RecordsA blog → IP,橙云/灰云按需,签证书期间用灰云
阿里云 / 腾讯云云解析 DNS → 解析设置A blog → IP,TTL 600
DNSPod域名解析 → 添加记录A blog → IP,TTL 600

3. docker-compose 配置

新建目录并写文件:

bash
mkdir -p ~/halo && cd ~/halo

docker-compose.yaml:

yaml
services: halo: image: halohub/halo:2.27.1 container_name: halo restart: on-failure:3 depends_on: halodb: condition: service_healthy volumes: - ./halo2:/root/.halo2 ports: - "127.0.0.1:8090:8090" environment: TZ: Asia/Shanghai command: - --spring.r2dbc.url=r2dbc:pool:postgresql://halodb:5432/halo - --spring.r2dbc.username=halo - --spring.r2dbc.password=CHANGE_ME - --spring.sql.init.platform=postgresql - --halo.external-url=http://blog.example.com/ halodb: image: postgres:15.4 container_name: halodb restart: always environment: POSTGRES_DB: halo POSTGRES_USER: halo POSTGRES_PASSWORD: CHANGE_ME TZ: Asia/Shanghai volumes: - ./postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U halo -d halo"] interval: 10s timeout: 5s retries: 5

几个要点:

  • 镜像版本写具体小版本(2.27.1),不要用 latest,否则某天重启就悄悄升级了。安装前去 Halo 的 Releases 页确认当前最新 2.x。
  • ports 写成 127.0.0.1:8090:8090,避免把 8090 暴露到公网;外部访问统一走 Nginx。
  • external-url 必须以 / 结尾,并且和最终访问地址一致。先用 IP 测试就写 http://IP:8090/,配好域名后再改。
  • 数据库密码两处必须一致,改完记得 docker compose down 再 up -d(改密码不能只重启)。
  • 国内拉镜像慢时,把镜像换成 registry.fit2cloud.com/halo/halo:2.27.1。
  • 想换 MySQL / MariaDB,把 spring.r2dbc.url 和 spring.sql.init.platform 改成对应驱动(mysql 或 mariadb)。

4. 启动与初始化

bash
docker compose up -d docker compose logs -f halo

看到启动完成后访问 http://blog.example.com/console(或 http://IP:8090/console),进入初始化向导:

  1. 填写站点名称、站点地址(与 external-url 一致);
  2. 设置管理员用户名、密码、邮箱;
  3. 完成后自动登录控制台,前台首页此时是默认主题。

初始化只在数据库为空时出现,账号密码务必记牢——Halo 没有默认账号。

5. Nginx 反向代理

/etc/nginx/sites-available/halo.conf:

nginx
server { listen 80; listen [::]:80; server_name blog.example.com; client_max_body_size 1024m; 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; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
bash
sudo ln -s /etc/nginx/sites-available/halo.conf /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx

client_max_body_size 决定单次上传上限,1G 是为了传大附件;不设的话默认 1M,传图就会 413。

6. HTTPS

bash
sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d blog.example.com sudo certbot renew --dry-run

certbot 会在同一个 server 块里追加 443 和跳转规则,代理配置不受影响。

证书生效后,把 --halo.external-url 改成 https://blog.example.com/,然后:

bash
docker compose down docker compose up -d

不改这一步的典型症状:后台里文章封面、附件地址还是 http://,浏览器按混合内容拦截。

7. 备份与升级

备份三样东西:

bash
cd ~/halo docker compose exec -T halodb pg_dump -U halo -d halo > backup-$(date +%F).sql tar -czf halo2-$(date +%F).tar.gz halo2/

exec 加 -T 是为了关掉伪终端,否则重定向出来的 SQL 可能混入多余字符。

  • 数据库:pg_dump(或控制台「系统 → 备份」入口,如果当前版本提供);
  • 附件与主题插件:./halo2 目录;
  • 反向代理和证书:Nginx 配置与 /etc/letsencrypt。

升级:

bash
docker compose pull docker compose up -d docker compose logs -f halo

升级前先备份,升级后进后台检查主题和插件是否有兼容提示。

8. 本方案检查清单

  • dig 能解析到服务器 IP
  • 8090 只监听 127.0.0.1,公网直接访问 IP:8090 不通
  • external-url 与最终域名、协议完全一致,且以 / 结尾
  • Nginx 代理后 /console 能正常登录
  • 上传一张大图成功(验证 client_max_body_size)
  • certbot renew --dry-run 通过
  • 数据库和 halo2/ 目录已做一次备份
  • 升级前记录当前镜像版本号,便于回滚

面板部署(1Panel)

不想手敲 Docker 命令时,用 1Panel 的应用商店:

  1. 服务器安装 1Panel(官方安装脚本),登录面板;
  2. 应用商店搜索 Halo,点安装;
  3. 填写名称、端口(默认 8090)、域名、数据库(面板自动创建 PostgreSQL),设置管理员;
  4. 安装完成后,1Panel 的网站 → 反向代理里把域名指向 127.0.0.1:8090;
  5. 在 1Panel 的证书页申请 Let's Encrypt 证书并绑定域名,开启 HTTPS;
  6. 访问 https://域名/console 登录后台。

面板路线的优势和代价:省掉 compose、Nginx、证书的手工步骤;出问题时多一层封装,日志和端口映射要去「容器」页看。

单容器试跑(仅测试)

机器上只有 Docker、想 5 分钟看效果:

bash
docker run -it -d --name halo -p 8090:8090 \ -v ~/.halo2:/root/.halo2 \ -e TZ=Asia/Shanghai \ halohub/halo:2.27.1

默认用内置 H2 数据库,重启后数据在 ~/.halo2 里。官方明确说过 H2 不适合生产环境,只用于试用。

常见故障对照

现象原因处理
8090 打不开容器没起 / 端口只绑了 127.0.0.1docker compose ps、logs halo;外部走 Nginx
初始化后链接跳到 127.0.0.1external-url 没改改 compose 参数后 down + up -d
上传图片 413Nginx 上传上限太小调 client_max_body_size
后台能开、保存失败反向代理缺 X-Forwarded-Proto / Upgrade 头按第 5 步完整配置
容器起不来,日志报数据库连接密码不一致 / 数据库未就绪两处密码对齐,确认 healthcheck 通过
证书申请失败DNS 未生效、80 被占、Cloudflare 橙云先灰云、确认 80 可达
升级后主题报错主题与核心版本不兼容回滚镜像版本,或升级主题
内存不足容器被杀JVM + PostgreSQL 占用加 swap 或升到 2G 内存

个人博客配置

站点信息与外观

后台 → 设置 → 基本设置:站点标题、副标题、站点描述、Logo、favicon、备案号。备案号在国内服务器上是硬要求,填在页脚会显示。

外观:后台 → 主题 → 安装(市场或上传 zip)。装完在「主题设置」里改配色、菜单、首页布局,多数主题支持暗色模式。

菜单与页面

  • 菜单:外观 → 菜单,把「首页」「归档」「分类」「标签」「关于」建好并绑定到具体页面或分类。
  • 独立页面:后台 → 页面 → 新建,适合「关于」「友链」「留言板」。
  • 文章:后台 → 文章 → 新建,支持 Markdown 与富文本切换,右侧设置分类、标签、封面、摘要。

评论

后台有「评论」管理入口,评论组件由主题提供(部分主题需要在主题设置里开启)。国内访客为主时,主题通常支持 Twikoo、Waline、Giscus 等第三方方案,按主题文档填服务地址即可。

SEO

  • 基本设置里的「站点描述」是首页 description 的来源,必填。
  • 文章编辑页有「摘要」,它会用于列表页和分享描述,不要留空。
  • 检查 /sitemap.xml 与 /rss.xml 是否可访问(不同主题 / 插件提供的路径可能不同),有的话提交到搜索引擎。
  • 后台「设置 → 代码注入」可以加统计脚本(GA4、51LA)和站点验证 meta。

多用户

后台 → 用户 → 新建,分配角色(管理员 / 作者 / 访客)。多人维护时,给作者角色即可,不要共用管理员账号。

多端写作实现

Halo 的写作模型和静态站完全不同:内容在数据库,任何浏览器登录后台就能写,不需要 Git、不需要构建。

核心流程

浏览器打开 https://域名/console → 新建文章 → 写 → 发布 → 数据库保存 → 前台立即可见

手机端

  • 控制台是响应式的,手机浏览器可以直接写、传图、改设置;登录后建议加到主屏幕。
  • 图片从相册上传后进附件库,正文插入的是附件地址,换域名或迁移时要同步处理附件 URL。
  • 手机端不适合装主题、装插件、改配置,这些操作放桌面。

桌面端

桌面浏览器体验最好,可以多标签同时开文章、附件库、设置。需要批量导入时,用后台的导入功能(支持 Markdown 压缩包 / 单文件,按当前版本文档为准),导入前把 Markdown 的 front matter 对齐。

自动化的入口

Halo 提供 REST API 和个人令牌(控制台 → 个人中心 → 个人令牌)。需要从本地脚本或其它系统推送文章时,用令牌调用文章创建接口即可,不用模拟登录。注意令牌等同密码,不要提交进仓库。

写作纪律

  • 发布前在「预览」里看一眼手机尺寸效果,主题对图片宽度处理不一定友好。
  • 固定「一篇文章一个分类 + 若干标签」,后台统计和归档才不会乱。
  • 附件按月或按文章分目录,迁移和备份时好定位。
  • 改域名时,external-url、站点地址、附件 URL 三处要一起改。
  • 升级主题或插件前先备份数据库和 halo2/,回滚靠这两份。

本文作者:Weee

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!