视频加载失败

备案通过后的图床重生记:把 CloudFlare-ImgBed 从 Telegram 渠道搬回境内服务器的完整复刻手册

2511 字
13 分钟
备案通过后的图床重生记:把 CloudFlare-ImgBed 从 Telegram 渠道搬回境内服务器的完整复刻手册
备案通过后的图床重生记:把 CloudFlare-ImgBed 从 Telegram 渠道搬回境内服务器的完整复刻手册

备案通过后的图床重生记:把 CloudFlare-ImgBed 从 Telegram 渠道搬回境内服务器的完整复刻手册#

2026 年 10 月,本站的 ICP 备案(鲁ICP备2026062086号-1)下证,随后完成了一轮伤筋动骨的迁移:Cloudflare Pages → 腾讯云 EdgeOne Pages,DNS 权威从 Cloudflare 切到 EdgeOne(qeodns),博客三入口归一到 azuma.mstzuomu.space,途中顺手救活了友圈、发布台、Twikoo 评论三个子系统。

但所有变更里最凶险、坑最密的是图床。本文以图床为主线写完整复刻手册——和我处境一样的人(CloudFlare-ImgBed + Telegram 渠道 + 国内备案 + 备案后必须境内访问)照着做就能重建;其他变更在第三节顺带记录。


〇、变更总览(备案下证后都发生了什么)#

项目变更前变更后
博客托管Cloudflare Pages腾讯云 EdgeOne Pages
DNS 权威(NS)CloudflareEdgeOne qeodns(ns1/ns2.qeodns.com)
主入口azuma.mstzuomu.space(CF 301)azuma.mstzuomu.space(页面脚本 302)
页脚备案号无鲁ICP备2026062086号-1(FooterConfig.html)
图床CF-ImgBed(Telegram 渠道,CF Worker)CF-ImgBed Docker 版自托管在轻量服务器(详见下文)
fc / pub / twikooDNS 记录随 NS 迁移丢失在 EO zone 补 CNAME → cname.vercel-dns.com
备案载体—轻量应用服务器 Ubuntu-o66q(140.143.143.178,北京)

一、图床为什么必须搬:四重死因#

原图床是 MarSeventh/CloudFlare-ImgBed(前端为 Sanyue ImgHub),部署在 Cloudflare Worker 上,域名 tu.mstzuomu.space。备案后它在国内的每条活路都被堵死了:

  1. 图片本体存在 Telegram 渠道。CF-ImgBed 是「元数据存 KV/D1、本体分流到外部渠道」的架构,本站全部图片的二进制在 Telegram 频道里,靠 Bot token 经 Worker 中转。国内服务器直连 Telegram 不可能,Worker 又跑在 CF 上;
  2. workers.dev 国内 DNS 污染。实测 114DNS 与 DNSPod 对 *.workers.dev 均返回假 IP(冒充脸书的地址段),国内访客直连必挂;
  3. EO 反代方案实测 522。把 tu 做成 EdgeOne 加速域名、回源 workers.dev:EO 海外节点回源正常,国内节点回源超时(522 Connection Timeout with Origin Server)——跨境链路被卡,等于白搭;
  4. CF 封死子域 zone。想把 tu.mstzuomu.space 单独挂回 Cloudflare(NS 委派子域):新版控制台拒绝子域名,API 报错码 1116(服务器端硬限制)。而整域 NS 迁回 CF 会让博客瘫痪并与备案接入冲突,不可考虑。

结论:数据必须导出,程序必须在境内自己跑。


二、图床重建复刻手册#

2.1 架构定稿#

访客 → https://tu.mstzuomu.space
│
Nginx(:80/:443,certbot 证书)
├─ /file/* → 磁盘静态直出(try_files,老图+新图都在这)
│ 查无此文件时回退 @imgbed
└─ 其余路径 → 反代 http://127.0.0.1:7658
│
imgbed 容器(Docker)
上传页 / 管理后台 / API
│ 存储渠道:WebDAV
▼
rclone serve webdav(172.17.0.1:8081)
▼
/var/www/imgbed/file(真身,Nginx 同时静态托管)

要点:新上传经 WebDAV 落到与静态托管同一目录,于是新老图片统一走 Nginx 静态,应用只负责上传/管理;?width= 尺寸参数会被 Nginx 无视并返回原图(博客端本就有回退兜底,显示无碍)。

2.2 数据无损导出(旧站侧)#

CloudFlare-ImgBed 的「备份恢复」只导元数据不含图片二进制,别用它当迁移。可用路径:

  • 管理 API 枚举 + 逐张下载(本文采用):
    1. POST /api/auth/adminLogin,JSON {"username":"...","password":"..."},保存 HttpOnly Cookie;
    2. GET /api/manage/list?start=0&count=1000&recursive=true(或 /api/manage/batch/list?limit=1000&includeValue=true)拿全量 fileId 列表;
    3. 逐个 GET /file/<URL逐段编码的fileId>(不带 width/fallback 参数即为原件),按 fileId 相对路径落盘——fileId 本身含目录(如 文章/1791196825739_19文章.jpg),目录结构天然保留;
  • 也可在后台开启 WebDAV 后用 rclone/Cyberduck 递归下载,效果等同。

本站实测:56 个文件、45.63 MiB、零失败,JPEG/PNG/PDF 魔数头尾全量校验通过。导出目录整包留了一份本地备份(imgbed-export),确认新站稳定后再删。

注意:Windows 下 PowerShell 5.1 读 UTF-8 JSON 会按 ANSI 解码炸掉,用 pwsh 7 或 [IO.File]::ReadAllText(...,[Text.Encoding]::UTF8);curl 提交登录 JSON 建议 -d @文件(BOM 也会让 JSON 解析失败)。

2.3 服务器侧:Nginx#

Ubuntu(备案载体轻量服务器,不要重装系统——备案接入资源绑着它)上:

Terminal window
sudo apt-get install -y nginx
sudo mkdir -p /var/www/imgbed/file # 导出的目录树放进 file/ 下,对齐 /file/ URL 空间

站点配置(/etc/nginx/sites-available/imgbed,核心段):

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name tu.mstzuomu.space _;
root /var/www/imgbed;
charset utf-8;
client_max_body_size 100m;
location /file/ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri @imgbed;
}
location @imgbed {
proxy_pass http://127.0.0.1:7658;
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;
}
location / {
proxy_pass http://127.0.0.1:7658;
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;
}
}

2.4 服务器侧:Docker 部署 CF-ImgBed 本体#

官方提供 Docker 部署(文档 https://cfbed.sanyue.de/ 有专门章节),无需改代码。国内服务器拉 Docker Hub 会超时,必须换镜像源前缀,实测腾讯内网源 mirror.ccs.tencentyun.com 对轻量服务器可用:

/opt/imgbed/docker-compose.yml
services:
imgbed:
image: mirror.ccs.tencentyun.com/marseventh/cloudflare-imgbed:latest
container_name: imgbed
restart: unless-stopped
ports:
- "127.0.0.1:7658:8080" # 注意:应用容器内监听 8080,不是 7658!
environment:
- BASIC_USER=<管理员用户名>
- BASIC_PASS=<管理员密码>
volumes:
- /opt/imgbed/data:/app/data
Terminal window
cd /opt/imgbed && docker compose up -d

两个端口坑:

  • 容器日志会写 Server running at http://0.0.0.0:8080——映射写 宿主机端口:8080,照抄 7658<7658> 会连不上;
  • 首次启动可能报 duplicate column name: tags 迁移警告,无害。

2.5 服务器侧:rclone WebDAV(应用的「本地磁盘」渠道)#

图床程序的存储渠道选 WebDAV,指向宿主机上的 rclone:

Terminal window
sudo apt-get install -y rclone

systemd 单元(/etc/systemd/system/rclone-webdav.service):

[Service]
User=ubuntu
ExecStart=/usr/bin/rclone serve webdav /var/www/imgbed/file --addr 172.17.0.1:8081 --user <dav用户名> --pass <dav密码>
Restart=on-failure
Terminal window
sudo systemctl enable --now rclone-webdav

本方案最大的坑在这里:--addr 绝不能写 127.0.0.1:8081。Docker 容器里的 127.0.0.1 是容器自己,访问宿主机要走 docker0 网桥地址 172.17.0.1。绑定网桥地址后容器可达、公网不可达(配合防火墙),安全与功能兼得。症状是上传接口 500、应用日志 WebDAV upload error: fetch failed。

2.6 后台配置#

浏览器访问 https://tu.mstzuomu.space/dashboard 登录(BASIC_USER/BASIC_PASS):

  1. 系统设置 → 上传设置 → 上传渠道管理:添加渠道,类型 WebDAV,基础地址 http://172.17.0.1:8081,填 dav 账号密码;启用该渠道;
  2. 顺手关掉默认开启的 R2_env 渠道开关(Docker 版会把上传塞进容器内 /app/data/r2,Nginx 静态层看不见,表现为「上传成功但外网 0 字节」);
  3. 安全设置 → 管理端认证可改用户名/密码——注意改密码时除了新密码还有**「确认密码」框**,漏填会静默保存失败(接口表现:旧密码仍可登录)。改完记得同步 docker-compose.yml 的 BASIC_* 环境变量并 docker compose up -d。

2.7 HTTPS 与防火墙#

Terminal window
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d tu.mstzuomu.space -n --redirect --agree-tos --register-unsafely-without-email

轻量应用服务器控制台的防火墙默认只开了 22/80/ICMP,443 需要手动「添加规则」放行 TCP 443,否则证书和 Nginx 都就绪、外网 443 依然不通。certbot 会重排 Nginx 配置,用 IP 直连 <80> 可能从此 404,属正常现象,管理走域名即可。

2.8 DNS 与验收#

EdgeOne zone(NS 已在 EO)里给 tu 加 A 记录 → 服务器公网 IP。验收清单:

  • https://tu.mstzuomu.space/ 出上传页;
  • 老图片原 URL(/file/目录/文件名)200 且字节数与导出一致;
  • http:// 自动 301 到 https;
  • 后台拖图上传 → 返回 /file/ 链接 → 外网可访问 → 服务器磁盘 /var/www/imgbed/file 能看到该文件;
  • /dashboard 用新账号登录成功。

自托管后 Docker、rclone、Nginx 均已 enable 开机自启,certbot 走 systemd timer 自动续签。


三、顺带的其他变更记录#

3.1 备案号页脚#

src/config/FooterConfig.html(Firefly 主题专用页脚注入文件)挂 ICP 号。规则:广东备案挂主体号,非广东挂服务备案号(本站为山东,挂 -1 后缀的服务号),链接到 https://beian.miit.gov.cn/。公安备案号下证后在同文件解注释补挂(去 beian.mps.gov.cn 复制官方 HTML)。

3.2 博客三入口统一到 azuma#

Layout.astro 头部有一段 is:inline 跳转脚本,白名单只匹配 www.mstzuomu.space 与根域 mstzuomu.space,302 到 azuma 并保留路径/查询串。两轮收紧的教训:

  1. 第一版判断「非 azuma 就跳」——localhost 预览也被跳走,改为线上域名匹配;
  2. 第二版用正则匹配所有 *.mstzuomu.space——误伤 tu(若某域名返回了含博客脚本的 HTML)。最终白名单化。

另:siteConfig.ts 的 site_url 已同步为 https://azuma.mstzuomu.space(canonical/sitemap 基址)。

平台侧还埋过一颗雷:曾按「所有域名统一 301」的思路在 EO zone 建过边缘函数规则(匹配全部 Host)。EO 的规则只对 zone 加速域名生效、对 EO Pages 域名(www/azuma/根域)不生效——所以博客没事,但后加的 zone 加速域名 tu 被规则误 301 到博客。已删除该规则。复刻时若只要页面级跳转,别在 zone 上留「匹配全部」的边缘函数。

3.3 fc / pub / twikoo 的复活#

三个子域在 NS 切换时 DNS 记录丢失,均为 Vercel 项目,在 EO zone 各补一条 CNAME → cname.vercel-dns.com 即复活:

子域Vercel 项目用途
fc.mstzuomu.spacefriend-circle-lite友圈数据站(CORS 头在项目 vercel.json)
pub.mstzuomu.spacefireflypriweb-publisher发布台
twikoo.mstzuomu.spacetwikoo-apiTwikoo 评论后端

博客端评论开关在 src/config/commentConfig.ts(type: "twikoo",envId 指向自有域名)。

3.4 服务器与备案的绑定关系#

轻量服务器是 ICP 备案的接入资源(备案单上的云资源 IP),也是本次图床的宿主机。不要释放/退订它——备案接入悬空有被注销风险。网站本体跑在 EdgeOne Pages 上属于常见实践,但服务器必须保持在网。

3.5 DNSPod 控制台的「未生效」提示#

域名 NS 在 EdgeOne 的 qeodns 上,不在 DNSPod。腾讯云「云解析 DNS(DNSPod)」控制台提示「未设置正确的 DNS 服务器」是跨产品的正常现象,无视即可,解析记录都在 EO 站点的「域名服务 → DNS 记录」里管理。


四、写给复刻者的最短路径#

  1. 旧站:后台开 WebDAV 或走管理 API,把图片按 fileId 目录树拉到本地,魔数校验,留备份;
  2. 服务器:装 Nginx(/file/ 静态 + 其余反代 <7658>)→ Docker 拉镜像(记得国内源前缀、容器端口 8080)→ rclone WebDAV 绑 172.17.0.1 → 后台配 WebDAV 渠道、关 R2_env;
  3. certbot 签证书 + 控制台防火墙放行 443;
  4. DNS 加 A 记录,跑第 2.8 节验收清单;
  5. 全绿之后,旧的 Cloudflare Worker 图床留观两周再退役。

数据无价,迁移有路。祝各位同行一次跑通。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

备案通过后的图床重生记:把 CloudFlare-ImgBed 从 Telegram 渠道搬回境内服务器的完整复刻手册
https://azuma.mstzuomu.space/posts/azuma.zuomu-blog-22/
作者
左沐
发布于
2026-10-17
许可协议
CC BY-NC-SA 4.0
相关文章智能推荐
1
从零开始搭建个人图床
技术分享简单搭建属于你的个人图床
2
全站视觉移植复刻:把 Firefly 改造成 animal-island-ui 风格的七期工程(含复刻清单与踩坑全录)
技术分享完整记录如何把一个 Astro + Svelte 博客移植成 animal-island-ui 的治愈系海岛风格:决策依据(为什么不引库、不重写)、规范获取方式、七期改造的逐文件实录与精确色值、Tailwind 层序覆盖等关键机制、Nunito 字体接入、验证三件套,附他人可照做的复刻清单与未尽事项
3
Firefly 博客接入友链朋友圈:从零开始的完整部署教程
技术分享手把手教你为博客搭建自动更新的友链朋友圈,含全部代码改动与实战踩坑排查
4
全站动效补完与 anime.js 数字滚动:五项动效计划的落地、四轮实测踩坑与复刻清单
技术分享完整记录 Firefly 博客一次「按门禁筛出来的动效改造」:五项动效计划(浮层开合/模态进出场/公告折叠/翻页桥接/切标签)的病灶定位、精确参数与四个实测才现形的 bug,以及用 anime.js 给侧栏统计做数字滚动的选型决策、v4 API 与零面积 IntersectionObserver 抢跑坑,附可照做的复刻清单
5
导航栏 UI 改造全记录:卡片边框、悬浮胶囊、三段收拢与 PC 收拢态快捷面板(附完整复现指南)
技术分享一次连续迭代的完整复盘——从卡片边框体系、悬浮胶囊导航,到三段结构拆分、下滑收拢动画,再到 PC 收拢态汉堡的控件快捷面板与"行点击原位弹卡"的两处根因修复,追加 PC 搜索控件图标化与收拢动画卡顿的逐帧诊断修复。每个批次改了哪些文件、为什么这么改、踩了哪些坑(CSS 层序、正圆公式、包含块、Vite 缓存、Playwright headless 动画冻结),附 git 重放与手工重做两条复现路径及验收清单
随机文章随机推荐
Profile Image of the Author
陌殊途左沐
热爱是拯救无趣人生的唯一途径
公告
欢迎来到我的博客!这里是左沐的个人空间,分享我的学习、生活和兴趣爱好。希望你能在这里找到有趣的内容,请不要对我的喜好做出评价哦!请勿使用公网访问本站。
分类
访客信息
加载中...
标签
最新动态
站点统计
文章
30
分类
2
标签
52
总字数
58,096
运行时长
0 天
最后活动
0 天前
总浏览量
-
访客数
-
文章目录