🚀 终极指南:在 2核1G 服务器上打造高可用 Halo 2.0 博客
侧边栏壁纸
  • 累计撰写 9 篇文章
  • 累计收到 1 条评论

🚀 终极指南:在 2核1G 服务器上打造高可用 Halo 2.0 博客

坑飞
2025-12-27 / 0 评论 / 12 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2025年12月27日,已超过38天没有更新,若内容或图片失效,请留言反馈。

如果是部署在国外服务器上, 则不推荐使用 Halo

摘要: 本文手把手教你在轻量级服务器(1G 内存)上,利用 Docker 部署 Halo 2.0,配置 15 年有效期的 SSL 证书,并实现 Cloudflare R2 异地自动备份。低成本也能拥有高可用!

大家好!今天分享一下我是如何搭建个人博客的。

基于这些需求,我总结了这套 Halo 2.0 + Docker + Cloudflare (全家桶) 的最佳实践方案。

我的目标很明确:成本要低(服务器配置不高),数据要稳(必须有备份),维护要少(证书自动续期)。

一、 给服务器穿上“防爆服” (配置 Swap)

我的服务器内存只有 1G。Java 应用(Halo)加上数据库,启动时很容易因为内存波动导致 OOM(内存溢出)被系统杀掉。

因此,第一步必须配置 Swap (虚拟内存)。如果你直接按照官方教程部署,很可能会经常遇到博客无故宕机的情况。

操作步骤:

连接到服务器终端,执行以下脚本。这个脚本会自动检测是否存在旧的 Swap,并创建一个新的 2G Swap 文件,同时优化内核参数(让系统尽量优先用物理内存)。

Bash

#!/bin/bash
# 1. 检查并清理旧 Swap
if [ -f /swapfile ]; then
    echo "发现旧 Swap,正在卸载..."
    sudo swapoff /swapfile
    sudo rm /swapfile
fi

# 2. 创建 2G Swap
echo "正在创建 2G Swap..."
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 3. 写入 fstab 实现开机自启 (防止重启失效)
# 先清理旧配置防止重复
sudo sed -i '/\/swapfile/d' /etc/fstab
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 4. 优化 Swappiness (值越低越倾向于使用物理内存)
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

echo "✅ Swap 配置完成!"

执行完毕后,输入 free -h 查看结果:

(👆 图注:如图所示,Swap 一栏显示 2.0Gi,说明服务器有了“备用血条”。)

    • *

二、 使用 Docker Compose 极速部署

相比于手动安装 Java 环境,Docker 更加干净卫生,升级也只需要拉取新镜像即可。

1. 准备目录

Bash

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

2. 编写配置文件

创建 docker-compose.yaml。这里有两个关键点:

  1. 显式限制了 JVM 的最大堆内存 (-Xmx512m),防止 Java 吃光资源。
  2. 使用 PostgreSQL 数据库,比 H2 更稳定。

YAML

services:
  halo:
    image: halohub/halo:2.20 # 建议锁定具体版本号
    container_name: halo
    restart: always
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      - halo_network
    volumes:
      - ./halo-data:/root/.halo2
    ports:
      - "8090:8090"
    command:
      # 数据库配置
      - --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo
      - --spring.r2dbc.username=halo
      - --spring.r2dbc.password=YourStrongPassword! # ⚠️ 改成你的强密码
      - --spring.sql.init.platform=postgresql
      # 外部访问地址 (换成你的域名)
      - --halo.external-url=https://www.diggingfly.com 
      # JVM 内存限制 (关键!)
      - -Xms256m -Xmx512m

  halodb:
    image: postgres:15-alpine
    container_name: halodb
    restart: always
    networks:
      - halo_network
    volumes:
      - ./db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=halo
      - POSTGRES_USER=halo
      - POSTGRES_PASSWORD=YourStrongPassword! # ⚠️ 必须与上方一致
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "halo"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  halo_network:

3. 启动与初始化

执行命令启动:

Bash

docker compose up -d

查看容器状态:

docker compose ps

(👆 图注:当 Status 显示为 (healthy) 时,说明服务启动成功。)

在浏览器访问 http://服务器IP:8090,即可看到初始化界面:

三、 SSL 证书:Let's Encrypt 自动化部署 (acme.sh)

使用 acme.sh 脚本,配合 Cloudflare DNS API 申请证书。 优势: 泛域名支持、不需要关闭 Nginx 即可验证、完全自动续期(无需手动介入)。

1. 获取 Cloudflare API Token

登录 Cloudflare -> 点击管理帐户 -> 帐户 API 令牌 -> 创建令牌

点击 Create Token -> 选择模板 Edit zone DNS

区域资源 选择 包括 -> 特定区域 -> 选择你的域名 (diggingfly.com)。

点击 Continue,复制生成的 API Token

(👆 图注:复制这段长长的 Token,这是脚本操作 DNS 的钥匙。)

2. 安装 acme.sh 并配置

在服务器终端执行:

Bash

# 1. 安装 acme.sh (邮箱换成你自己的,用于接收过期提醒)
curl https://get.acme.sh | sh -s [email protected]

# 2. 使命令生效
source ~/.bashrc

# 3. 导入 Cloudflare Token 环境变量
# 注意:export 命令在重启后会失效,但 acme.sh 会把这些凭证自动保存到它的配置文件中,所以只需执行一次
export CF_Token="你刚才复制的API_Token"
export CF_Account_ID="你的Cloudflare_Account_ID" 
# (Account ID 在 Cloudflare 域名概览页右下角可以找到)

3. 申请证书 (DNS 模式)

执行下面这行命令,脚本会自动向 Cloudflare 添加 TXT 记录进行验证,验证完后会自动删除。

Bash

# 申请泛域名证书 (*.diggingfly.com) 和主域名证书
acme.sh --issue --dns dns_cf -d diggingfly.com -d "*.diggingfly.com"

如果看到绿色的 Cert success,说明申请成功!

4. 安装证书到 Nginx 目录

注意: 不要直接引用 .acme.sh 目录下的文件。应该使用 --install-cert 命令把证书“复制”到 Nginx 目录,这样脚本才能记住“续期后要更新这里”。

Bash

# 1. 创建存放目录
sudo mkdir -p /etc/nginx/cert

# 2. 安装证书并指定重载命令
acme.sh --install-cert -d diggingfly.com \
--key-file       /etc/nginx/cert/key.pem  \
--fullchain-file /etc/nginx/cert/cert.pem \
--reloadcmd     "sudo nginx -s reload"

✅ 自动续期机制: acme.sh 安装时已经自动向系统添加了一个 crontab 定时任务。它每天会自动检测证书是否快过期,如果快过期了,它会自动:

  1. 调用 Cloudflare API 重新验证。
  2. 更新 /etc/nginx/cert/ 下的文件。
  3. 执行 nginx -s reload 重启服务。 全程无需你操心。

四、 Nginx 反向代理配置

我们需要 Nginx 监听 80 和 443 端口,并将流量转发给 Halo 的 8090 端口。

同时,这里解决了**“上传大图片失败”**的问题(Nginx 默认只允许 1M)。

编辑 /etc/nginx/conf.d/halo.conf

Nginx

# HTTP -> HTTPS 重定向
server {
    listen 80;
    server_name www.diggingfly.com diggingfly.com;
    # 301 永久重定向
    return 301 https://$host$request_uri;
}

# HTTPS 主配置
server {
    listen 443 ssl http2;
    server_name www.diggingfly.com diggingfly.com;

    # 1. 证书路径 (指向 acme.sh 安装的位置)
    ssl_certificate /etc/nginx/cert/cert.pem;
    ssl_certificate_key /etc/nginx/cert/key.pem;

    # 2. SSL 安全参数 (推荐配置)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    
    # HSTS (可选,强制浏览器记住 HTTPS,提高安全性)
    add_header Strict-Transport-Security "max-age=63072000" always;

    # 3. 核心优化:解除上传限制
    client_max_body_size 100m;

    # 4. Gzip 压缩
    gzip on;
    gzip_min_length 1k;
    gzip_types text/plain application/javascript text/css application/xml;

    # 5. 反向代理到 Halo
    location / {
        proxy_pass http://127.0.0.1:8090;
        
        # 传递真实 IP
        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;

        # 如果你用了 Cloudflare CDN,建议加上这一行,把 CF 的真实 IP 传给 Halo
        # proxy_set_header X-Real-IP $http_cf_connecting_ip;

        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

配置完成后,重启 Nginx:

Bash

sudo nginx -t
sudo nginx -s reload

现在访问你的域名,你应该能看到那把安全的“小锁”了!🔒

五、 图床配置:Cloudflare R2 免费使用

数据只放在服务器本地是不安全的。我使用了 Cloudflare R2 对象存储,它兼容 AWS S3 协议,且拥有 10GB 的免费存储额度,对于用做博客图床来说绰绰有余。

1. 创建 R2 存储桶

在 Cloudflare 后台 -> R2,创建一个 Bucket,命名为 bolg-img。

进入 Bucket 详情页,复制 Endpoint 地址。

2. 创建 API 令牌

在 R2 页面右侧点击 Manage R2 API Tokens -> Create API Token

权限选择:Object Read & Write, 并指定 Bucket:blog-img (为了安全,只授权这一个), 其它的默认即可

创建后,保存好 Access Key IDSecret Access Key

3. Halo 插件配置

进入 Halo 后台,安装 S3 插件。

进入插件菜单启用 S3 插件

在 设置 -> 存储策略 中添加 S3:

  • Access Key / Secret Key: 填入刚才获取的令牌。
  • Endpoint: 填入 R2 的地址(注意:去掉链接末尾的 bucket 名字,只保留域名)。
  • Region:auto

(👆 图注:这是最容易填错的一步,请仔细核对 Endpoint 格式)

4. 启用文章图片自动上传到 S3

在设置 -> 文章设置 -> 附件存储策略 里选择你刚刚创建的存储策略, 然后保存

这配置在2.22.0中已经废弃了

在设置 -> 附件设置 -> 管理端附件配置 里选择你刚刚创建的存储策略, 然后保存

2.22.0 版本后需要在此配置

六. 自动备份

创建一个自动备份策略,选择每天凌晨 3 点自动备份。

1. 安装备份插件

在应用市场里搜索 “备份” , 安装自动备份插件

2. 启用 备份插件

在插件中启用 “自动备份插件”

3. 自动备份

点击 ‘自动备份插件’ , 进入插件配置页, 点击基本设置配置备份策略

七、换个新皮肤:主题安装与配置 (以 Clarity 为例)

Halo 默认的主题虽然简洁,但可能不够个性。Halo 2.0 拥有强大的应用市场,换主题就像给手机换壁纸一样简单。 这里我们以 Clarity 为例,这是一款非常适合个人开发者的“简历/名片风”主题,简洁且能突出个人介绍。

1. 在应用市场下载主题

  1. 进入 Halo 后台,点击左侧菜单的 应用市场 (App Store)
  2. 在左侧分类选择 主题 (Themes)
  3. 在搜索框输入 Clarity,找到 Clarity
  4. 点击 安装 (Install)

Halo 的生态越来越丰富,一键安装省去了上传文件的麻烦。

Halo 的生态越来越丰富,一键安装省去了上传文件的麻烦。

2. 启用主题

下载完成后,主题并不会自动切换,需要手动启用。

  1. 点击左侧菜单的 外观 (Appearance) -> 主题 (Themes)
  2. 你会看到刚才下载的 vCard4 已经出现在列表里了。
  3. 点击主题卡片下方的 启用 (Enable) 按钮。

点击启用后,进入博客首页查看变化

3. 配置主题 (可选)

主题更精细的配置可以到 主题 菜单下配置

  1. 配置主导航菜单: 这个默认不显示, 你得在 侧边栏头部 -> 主导航菜单,将 主菜单 勾上。

5. 预览效果

现在,打开浏览器访问你的域名 https://www.diggingfly.com 查看预览效果

大功告成!这是属于你在互联网上的第一张名片

八、 开启上帝视角:接入 Google Analytics 4

博客建好了,自然想知道有没有人看。我们来接入业界最标准的统计工具——Google Analytics (GA4)。

1. 获取追踪代码 (Gtag)

访问 analytics.google.com 并登录 Google 账号。

创建媒体资源:

  • 名称:DiggingFly Blog
  • 时区:选择你所在的地区
  • 货币:随意

商家描述:

  • 行业类别:互联网与电信
  • 业务规模:小型- 1 至 10 名员工

业务目标按需选择

选择平台: 点击 "Web (网站)"

设置数据流:

  • 网址:www.diggingfly.com (注意选 https://)
  • 流名称:DiggingFly Website
  • 点击 "创建数据流"

创建成功后,会弹出一个 "安装说明" 窗口。点击 "手动安装" 标签,你会看到一段以 <script> 开头的代码。

复制这段代码,它是你博客连接 Google 的钥匙。

2. 在 Halo 中注入代码

拿到代码后,我们需要把它放入博客的每一个页面中。Halo 2.0 贴心地提供了全局注入功能,不需要修改主题源码。

  1. 登录 Halo 后台,.
  2. 进入 设置 (Settings) -> 代码注入。
  3. 找到 “全局 head 标签 (Head Code)” 输入框。
  4. 把刚才从 Google 复制的那段 <script>...</script> 代码完整粘贴进去。
  5. 点击右下角的 保存

在这里粘贴代码,Halo 会自动把它应用到博客的所有页面

3. 验证是否生效

配置完成后,我们来测试一下。

  1. 打开你的博客首页(建议用手机或者浏览器的无痕模式打开)。
  2. 回到 Google Analytics 后台,点击左侧菜单的 "报告" -> "实时"
  3. 如果你看到地图上出现了一个蓝点,或者“过去 30 分钟的用户数”显示为 1,恭喜你!连接成功!

看到这个数字跳动,说明你的博客已经拥有了“心跳”。

    • *
0

评论 (0)

取消