适合谁:在写个人博客时喜欢插入大量高清插图,但发现服务器硬盘空间日渐缩水、图片加载缓慢、备份越来越庞大臃肿的 Halo 博客博主。
支持环境:Halo 2.x 全系列版本(Docker / 1Panel 部署均可)、搭配免费 Cloudflare 账号。
耗时预期:约 15 ~ 20 分钟(跟着一步步配好,一劳永逸搞定个人图床)。
做完你将得到:彻底实现博客**“动静分离”**;在 Halo 后台写文章时随意拖拽图片,图片自动异步上传至 Cloudflare R2 云端,走全球 CDN 加速直出,服务器磁盘 0 占用、外网下载流量 0 费用!
⚠️ 全程唯一保命铁律:
创建 R2 API 令牌时,权限必须选择「对象读和写 (Object Read & Write)」! 权限选错或选为只读,Halo 上传图片时会报绝望的403 Forbidden。
🧭 核心概念:为什么必须做“动静分离”?(大白话解密)
很多新手刚开始建站,喜欢把图片直接上传到服务器本地,半年后就会遭遇三大灾难:
┌─────────────────────────────────────────────────────────────┐
│ 🔴 传统本地图床的死穴 │
│ - 磁盘撑爆:几百张单反原图塞满小 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 仪表盘:
- 在左侧主菜单中点击 「R2 对象存储」;
- 第一次使用会提示开启 R2 服务(完全免费,未超出 10GB 不产生任何费用);
- 点击 「创建存储桶 (Create Bucket)」:
- 存储桶名称:起一个英文名字(例如
blog-images); - 位置:选择 「自动 (Automatic)」 或 「亚太 (APAC)」;
- 点击 「创建存储桶」!
- 存储桶名称:起一个英文名字(例如
- ✅ 成功标志:页面跳转进入该存储桶的概览页,状态显示正常。
第 2 步:绑定属于你的个性图片域名(开启公开访问)
默认创建的存储桶是完全私密的,外界无法直接通过链接看图。我们给它绑上专属域名:
💻 【你本地的浏览器】 在当前存储桶管理页:
- 点击顶部的 「设置 (Settings)」 标签;
- 找到 「公共访问权限 (Public Access)」 区域;
- 找到 「自定义网域 (Custom Domains)」,点击 「连接网域」;
- 输入你想给图床用的二级域名(例如
img.yourdomain.com); - 点击继续,Cloudflare 会全自动在你的 DNS 里补上一条解析记录;
- 点击 「连接网域」 确认。
- ✅ 成功标志:自定义网域列表中显示你的图片域名,状态显示为绿色的
有效 (Active)。
第 3 步:生成 S3 兼容 API 凭据(最关键的防坑步)
Halo 插件是通过标准的 AWS S3 协议向 R2 推送图片的,需要一对公私密钥。
💻 【你本地的浏览器】:
- 回到 Cloudflare 左侧菜单的 「R2 对象存储」 首页;
- 在右侧上方找到并点击 「管理 R2 API 令牌 (Manage R2 API Tokens)」;
- 点击 「创建 API 令牌 (Create API Token)」:
- 令牌名称:随便填,如
halo-pic-token; - 权限:⚠️ 极其关键!必须勾选「对象读和写 (Object Read & Write)」;
- 应用到特定存储桶:可以选择刚才创建的
blog-images,或者所有存储桶; - TTL 有效期:选择 「永久有效」;
- 令牌名称:随便填,如
- 点击页面最底部的 「创建 API 令牌」。
屏幕上将展示仅出现一次的凭据密匙(如下图):
=====================================================
凭据保护区(请立刻复制保存进便签!)
访问密钥 ID (Access Key ID): xxxx...xxxx
机密访问密钥 (Secret Access Key): yyyy...yyyy
终结点 (Endpoint): https://<账户ID>.r2.cloudflarestorage.com
=====================================================
⚠️ 关键动作:立刻把这三行内容复制并妥善保存在你本地的记事本中!关闭页面后机密密钥将永远无法再次查看。
第 4 步:在 Halo 后台安装并配置 PictureBed 插件
现在把云端图床无缝装进 Halo 的写作后台。
💻 【你本地的浏览器】 登录你的 Halo 博客后台(https://你的博客域名/console):
- 点击左侧菜单 「应用中心」➔「插件」;
- 点击应用市场,搜索
PictureBed(或对象存储插件),点击安装并启用; - 启用后,点击左侧菜单新出现的 「存储策略」(或在插件配置里点击设置):
- 点击 「添加存储策略」,存储类型选择
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);
- 策略名称:填
- 点击 「保存并设为默认存储策略」!
- ✅ 成功标志:存储策略列表中,R2 图床策略被高亮标记为「默认」。
第 5 步:终极拖拽测试与公网加载验证
我们来验证整套“动静分离”链路是否 100% 跑通。
💻 【你本地的浏览器】 在 Halo 后台:
- 点击左侧 「文章」➔「新建文章」;
- 随手从本地电脑拖拽一张图片扔进 Markdown 编辑器窗口;
- 观察编辑器底部进度条:图片上传完毕后,编辑器会自动生成一行 Markdown 图片代码:MARKDOWN
 - 复制这段图片 URL 在浏览器新标签页打开。
- ✅ 大功告成标志:图片瞬间加载呈现,URL 为你的独立图床域名,且浏览器地址栏显示安全小绿锁!
此时再去服务器敲 df -h 查看磁盘占用,你会发现服务器磁盘空间没有增加半个字节,所有图片全在 Cloudflare 全球节点为你免费待命!🚀
🎁 进阶锦囊:开启 Cloudflare 缓存规则(榨干 CDN 性能)
为了让图片加载更快、进一步降低 R2 的读请求计数,可以在 Cloudflare 开启静态长缓存:
- 打开 Cloudflare 控制台,进入你的域名管理页;
- 点击左侧 「缓存」➔「缓存规则 (Cache Rules)」,点击创建规则;
- 匹配条件:主机名等于你的图片域名(例如
img.yourdomain.com); - 缓存资格:设为 「符合缓存条件」;
- 边缘缓存 TTL:设为 「忽略无缓存标头,覆盖 TTL」➔「1 个月」;
- 保存生效!从此访客看图几乎全部直接从离他最近的 CDN 边缘节点秒开!
🚑 翻车急救站(新手最怕的 4 大图床翻车现场)
| 异常现场 | 真实根因 | 对应一秒救命招式 |
|---|---|---|
拖入图片提示 403 Forbidden | API 令牌权限选错了(只给了读权限,没给写权限) | 回到第 3 步,重新创建一个 API 令牌,务必勾选「对象读和写」,把新密钥更新到 Halo 后台。 |
| 上传成功,但文章里的图片全是破损红叉 | 自定义域名未正确回填,或未配置协议头 | 检查 Halo 存储策略中的「自定义访问域名」,必须带上 https://(如 https://img.xxxx.com)。 |
上传提示 S3 Connection Failed | Endpoint 格式填错(多敲了斜杠或手滑填了 bucket) | 检查 Endpoint 必须是纯净的 https://<账户ID>.r2.cloudflarestorage.com,末尾不能有 /。 |
传稍大一点的照片报 413 Request Too Large | Nginx 反代限制了外部上传体积 | 在你的服务器 Nginx 反代配置的 server 块中加入 client_max_body_size 100M;,执行 nginx -t && systemctl reload nginx。 |
🎓 毕业全维度自检清单
核对以下 5 项指标,全部打钩即代表你的博客动静分离已达到工业级标准:
- 存储桶就位:Cloudflare R2 存储桶状态正常,绑定了自定义专属二级域名;
- 权限读写闭环:API 令牌具备读写权限,无 403 权限被拒问题;
- 拖拽秒传体验:在 Halo 编辑器直接拖入图片能顺畅上传并自动生成外链;
- 宿主机磁盘 0 污染:上传多张大图后,服务器宿主机磁盘存储空间不被消耗;
- CDN 全球加速:通过图片外链公网访问秒开,完全享受 Cloudflare 0 流量费红利!