适合谁:在写个人博客时喜欢插入大量高清插图,但发现服务器硬盘空间日渐缩水、图片加载缓慢、备份越来越庞大臃肿的 Halo 博客博主。

支持环境:Halo 2.x 全系列版本(Docker / 1Panel 部署均可)、搭配免费 Cloudflare 账号。

耗时预期:约 15 ~ 20 分钟(跟着一步步配好,一劳永逸搞定个人图床)。

做完你将得到:彻底实现博客**“动静分离”**;在 Halo 后台写文章时随意拖拽图片,图片自动异步上传至 Cloudflare R2 云端,走全球 CDN 加速直出,服务器磁盘 0 占用、外网下载流量 0 费用!

⚠️ 全程唯一保命铁律:
创建 R2 API 令牌时,权限必须选择「对象读和写 (Object Read & Write)」! 权限选错或选为只读,Halo 上传图片时会报绝望的 403 Forbidden。


🧭 核心概念:为什么必须做“动静分离”?(大白话解密)

很多新手刚开始建站,喜欢把图片直接上传到服务器本地,半年后就会遭遇三大灾难:

TEXT
┌─────────────────────────────────────────────────────────────┐
│ 🔴 传统本地图床的死穴                                        │
│    - 磁盘撑爆:几百张单反原图塞满小 VPS,博客卡死;         │
│    - 备份庞大:每次备份数据库,动辄被十几 GB 图片拖死;      │
│    - 带宽瓶颈:小机器 1M~3M 带宽,访客打开带大图的文章要等10秒。│
├─────────────────────────────────────────────────────────────┤
│ 🟢 Cloudflare R2 动静分离架构                                │
│    - 宿主机 0 占用:文字与数据库留在服务器,所有图片直奔云端; │
│    - 💰 0 出口流量费:AWS S3 下载流量收天价,而 R2 外网流量 0 元;│
│    - 🎁 10GB 免费空间:个人博客插图几年都用不完;              │
│    - ⚡ 全球 CDN 加速:绑定自己的图片二级域名,全球毫秒秒开!    │
└─────────────────────────────────────────────────────────────┘

📋 开始前的准备清单(缺一项都别往下走)

  • 一个正常运行的 Halo 博客:能够正常登录 /console 管理后台;
  • 一个免费 Cloudflare 账号:官网注册即可;
  • 一个托管在 Cloudflare 的域名:准备给图床单独分配一个二级域名(例如 img.0000996.xyz)。

第 1 步:在 Cloudflare 免费开通 R2 并创建存储桶

💻 【你本地的浏览器】 打开 Cloudflare 仪表盘:

  1. 在左侧主菜单中点击 「R2 对象存储」;
  2. 第一次使用会提示开启 R2 服务(完全免费,未超出 10GB 不产生任何费用);
  3. 点击 「创建存储桶 (Create Bucket)」:
    • 存储桶名称:起一个英文名字(例如 blog-images);
    • 位置:选择 「自动 (Automatic)」 或 「亚太 (APAC)」;
    • 点击 「创建存储桶」!
  • ✅ 成功标志:页面跳转进入该存储桶的概览页,状态显示正常。

第 2 步:绑定属于你的个性图片域名(开启公开访问)

默认创建的存储桶是完全私密的,外界无法直接通过链接看图。我们给它绑上专属域名:

💻 【你本地的浏览器】 在当前存储桶管理页:

  1. 点击顶部的 「设置 (Settings)」 标签;
  2. 找到 「公共访问权限 (Public Access)」 区域;
  3. 找到 「自定义网域 (Custom Domains)」,点击 「连接网域」;
  4. 输入你想给图床用的二级域名(例如 img.yourdomain.com);
  5. 点击继续,Cloudflare 会全自动在你的 DNS 里补上一条解析记录;
  6. 点击 「连接网域」 确认。
  • ✅ 成功标志:自定义网域列表中显示你的图片域名,状态显示为绿色的 有效 (Active)。

第 3 步:生成 S3 兼容 API 凭据(最关键的防坑步)

Halo 插件是通过标准的 AWS S3 协议向 R2 推送图片的,需要一对公私密钥。

💻 【你本地的浏览器】:

  1. 回到 Cloudflare 左侧菜单的 「R2 对象存储」 首页;
  2. 在右侧上方找到并点击 「管理 R2 API 令牌 (Manage R2 API Tokens)」;
  3. 点击 「创建 API 令牌 (Create API Token)」:
    • 令牌名称:随便填,如 halo-pic-token;
    • 权限:⚠️ 极其关键!必须勾选「对象读和写 (Object Read & Write)」;
    • 应用到特定存储桶:可以选择刚才创建的 blog-images,或者所有存储桶;
    • TTL 有效期:选择 「永久有效」;
  4. 点击页面最底部的 「创建 API 令牌」。

屏幕上将展示仅出现一次的凭据密匙(如下图):

TEXT
=====================================================
凭据保护区(请立刻复制保存进便签!)
访问密钥 ID (Access Key ID):        xxxx...xxxx
机密访问密钥 (Secret Access Key):    yyyy...yyyy
终结点 (Endpoint):                  https://<账户ID>.r2.cloudflarestorage.com
=====================================================

⚠️ 关键动作:立刻把这三行内容复制并妥善保存在你本地的记事本中!关闭页面后机密密钥将永远无法再次查看。


第 4 步:在 Halo 后台安装并配置 PictureBed 插件

现在把云端图床无缝装进 Halo 的写作后台。

💻 【你本地的浏览器】 登录你的 Halo 博客后台(https://你的博客域名/console):

  1. 点击左侧菜单 「应用中心」➔「插件」;
  2. 点击应用市场,搜索 PictureBed(或对象存储插件),点击安装并启用;
  3. 启用后,点击左侧菜单新出现的 「存储策略」(或在插件配置里点击设置):
  4. 点击 「添加存储策略」,存储类型选择 AWS S3(因为 R2 完美兼容 S3 协议):
    • 策略名称:填 Cloudflare R2 图床;
    • Bucket(存储桶名称):填你在第 1 步起的名字(如 blog-images);
    • Access Key ID:粘贴刚才保存的「访问密钥 ID」;
    • Secret Access Key:粘贴刚才保存的「机密访问密钥」;
    • Region(区域):填 auto 或 us-east-1(R2 填 auto 即可);
    • Endpoint(端点地址):⚠️ 防坑核心!填刚才保存的 https://<账户ID>.r2.cloudflarestorage.com,末尾绝不要带斜杠 /,也不要带存储桶名!
    • 自定义访问域名:填入在第 2 步绑定的图片域名(例如 https://img.yourdomain.com);
  5. 点击 「保存并设为默认存储策略」!
  • ✅ 成功标志:存储策略列表中,R2 图床策略被高亮标记为「默认」。

第 5 步:终极拖拽测试与公网加载验证

我们来验证整套“动静分离”链路是否 100% 跑通。

💻 【你本地的浏览器】 在 Halo 后台:

  1. 点击左侧 「文章」➔「新建文章」;
  2. 随手从本地电脑拖拽一张图片扔进 Markdown 编辑器窗口;
  3. 观察编辑器底部进度条:图片上传完毕后,编辑器会自动生成一行 Markdown 图片代码:
    MARKDOWN
    ![测试图片](https://img.yourdomain.com/2026/09/xxxx.jpg)
  4. 复制这段图片 URL 在浏览器新标签页打开。
  • ✅ 大功告成标志:图片瞬间加载呈现,URL 为你的独立图床域名,且浏览器地址栏显示安全小绿锁!

此时再去服务器敲 df -h 查看磁盘占用,你会发现服务器磁盘空间没有增加半个字节,所有图片全在 Cloudflare 全球节点为你免费待命!🚀


🎁 进阶锦囊:开启 Cloudflare 缓存规则(榨干 CDN 性能)

为了让图片加载更快、进一步降低 R2 的读请求计数,可以在 Cloudflare 开启静态长缓存:

  1. 打开 Cloudflare 控制台,进入你的域名管理页;
  2. 点击左侧 「缓存」➔「缓存规则 (Cache Rules)」,点击创建规则;
  3. 匹配条件:主机名等于你的图片域名(例如 img.yourdomain.com);
  4. 缓存资格:设为 「符合缓存条件」;
  5. 边缘缓存 TTL:设为 「忽略无缓存标头,覆盖 TTL」➔「1 个月」;
  6. 保存生效!从此访客看图几乎全部直接从离他最近的 CDN 边缘节点秒开!

🚑 翻车急救站(新手最怕的 4 大图床翻车现场)

异常现场真实根因对应一秒救命招式
拖入图片提示 403 ForbiddenAPI 令牌权限选错了(只给了读权限,没给写权限)回到第 3 步,重新创建一个 API 令牌,务必勾选「对象读和写」,把新密钥更新到 Halo 后台。
上传成功,但文章里的图片全是破损红叉自定义域名未正确回填,或未配置协议头检查 Halo 存储策略中的「自定义访问域名」,必须带上 https://(如 https://img.xxxx.com)。
上传提示 S3 Connection FailedEndpoint 格式填错(多敲了斜杠或手滑填了 bucket)检查 Endpoint 必须是纯净的 https://<账户ID>.r2.cloudflarestorage.com,末尾不能有 /。
传稍大一点的照片报 413 Request Too LargeNginx 反代限制了外部上传体积在你的服务器 Nginx 反代配置的 server 块中加入 client_max_body_size 100M;,执行 nginx -t && systemctl reload nginx。

🎓 毕业全维度自检清单

核对以下 5 项指标,全部打钩即代表你的博客动静分离已达到工业级标准:

  • 存储桶就位:Cloudflare R2 存储桶状态正常,绑定了自定义专属二级域名;
  • 权限读写闭环:API 令牌具备读写权限,无 403 权限被拒问题;
  • 拖拽秒传体验:在 Halo 编辑器直接拖入图片能顺畅上传并自动生成外链;
  • 宿主机磁盘 0 污染:上传多张大图后,服务器宿主机磁盘存储空间不被消耗;
  • CDN 全球加速:通过图片外链公网访问秒开,完全享受 Cloudflare 0 流量费红利!