用飞牛 NAS + 呆呆面板 自动定时备份 Cloudflare D1 数据库
前言
用 Cloudflare Workers + D1 搭博客很方便,但数据安全是个大事。D1 自带的自动备份只保留 24 小时,Time Travel 在 Free 计划下也只能回溯 7 天,都不适合做长期归档。
如果你手头有飞牛 NAS,再配合 呆呆面板,就能实现「每天凌晨自动把 D1 导出成 SQL,存到 NAS 本地」的效果。这篇教程就讲清楚怎么配置。
一、整体思路
Cloudflare D1
↓ (wrangler d1 export)
呆呆面板定时任务(每天 3 点)
↓
飞牛 NAS 本地目录 /vol1/1000/备份/cfblog-backup/
- 呆呆面板负责任务调度和执行脚本
- wrangler 负责连接 Cloudflare、导出 SQL
- 飞牛 NAS 负责保存文件(长期归档)
二、前提条件
动手前,先确认几件事:
| 项目 | 要求 |
|---|---|
| 飞牛 NAS | 已装好,且能通过 SSH 或呆呆面板操作 |
| 呆呆面板 | 已部署在飞牛 NAS 上(Docker 或直装都行) |
| Node.js 环境 | 呆呆面板所在的 NAS 上要能用 npx(呆呆面板自带依赖管理,可以在里面装) |
| Cloudflare API Token | 需要有 D1 导出权限 |
| Cloudflare Account ID | 在 Cloudflare 控制台能查到 |
获取 Cloudflare API Token
- 打开 https://dash.cloudflare.com/profile/api-tokens
- 点 Create Token
- 选 Custom token
- 权限至少加:
- Account → D1 → Edit
- 创建后复制 Token,等下要填到呆呆面板里
获取 Account ID
Cloudflare 控制台右侧栏,随便进一个域名的 Overview,右下角就有 Account ID。
三、在呆呆面板里配置脚本
1. 新建 Shell 脚本
在呆呆面板「脚本管理」里,新建一个脚本,比如叫 backup-d1.sh,内容如下:
#!/bin/bash
# ============ 配置区 ============
# 备份目录(改成你飞牛 NAS 的实际路径)
BACKUP_DIR="/vol1/1000/备份/cfblog-backup"
# D1 数据库名(用你 wrangler.toml 里的 database_name 或 binding 名)
DB_NAME="CFBLOG"
# 保留天数(超过这个天数的备份自动删除)
KEEP_DAYS=30
# ================================
# 创建目录
mkdir -p "$BACKUP_DIR"
cd "$BACKUP_DIR" || exit 1
# 日期
DATE=$(date +%Y-%m-%d_%H-%M-%S)
# 导出 D1
echo "开始导出 D1 数据库:$DB_NAME"
npx wrangler d1 export "$DB_NAME" --remote --output="cfblog-$DATE.sql"
if [ $? -ne 0 ]; then
echo "❌ 导出失败"
exit 1
fi
echo "✅ 导出成功:cfblog-$DATE.sql"
# 清理旧备份
find "$BACKUP_DIR" -name "cfblog-*.sql" -mtime +$KEEP_DAYS -delete
echo "🧹 已清理 $KEEP_DAYS 天前的备份"
几个关键点:
BACKUP_DIR:改成你飞牛 NAS 的实际存储路径,比如/vol1/1000/备份/cfblog-backupDB_NAME:这是最容易踩坑的地方,必须和你wrangler.toml里的一致,或者直接用binding名(你代码里是CFBLOG)KEEP_DAYS:自己定,30 天够用了
2. 配置环境变量
在呆呆面板「环境变量」里添加:
| 变量名 | 值 |
|---|---|
CLOUDFLARE_API_TOKEN |
你刚创建的 API Token |
CLOUDFLARE_ACCOUNT_ID |
你的 Cloudflare Account ID |
这样脚本执行时,wrangler 会自动读取这两个变量,不用每次手动登录。
四、在呆呆面板里新建定时任务
- 进入呆呆面板「定时任务」
- 点 新建任务
- 填写:
| 字段 | 值 |
|---|---|
| 任务名称 | 每日备份 D1 |
| 执行命令 | bash /你的脚本路径/backup-d1.sh |
| Cron 表达式 | 0 3 * * *(每天凌晨 3 点) |
| 通知渠道 | 可选,绑定 Bark / Telegram / 钉钉等 |
- 保存
点击展开▾
Cron 表达式速查
| 表达式 | 含义 |
|---|---|
0 3 * * * |
每天凌晨 3 点 |
0 3 * * 0 |
每周日凌晨 3 点 |
0 */6 * * * |
每 6 小时一次 |
0 3 1 * * |
每月 1 号凌晨 3 点 |
五、手动测试一次
先别等定时触发,手动跑一次看看:
- 在呆呆面板里点「执行一次」
- 看日志输出
- 去飞牛 NAS 的备份目录看一眼,是否出现了
cfblog-2026-10-05_xx-xx-xx.sql
如果看到 .sql 文件,说明配置成功。
六、常见报错和处理
报错 1:Couldn't find a D1 DB with name or binding 'xxx'
原因:DB_NAME 填错了。
解决:
- 打开你的
wrangler.toml,看[[d1_databases]]里的database_name或binding - 或者直接跑
npx wrangler d1 list,看列表里的name
注意:你代码里绑定的名字是 CFBLOG,但数据库实际名字可能是别的(比如 cfblog-prod),要填数据库真实名字。
报错 2:You are not authenticated
原因:环境变量没配好,或 Token 权限不够。
解决:
- 检查
CLOUDFLARE_API_TOKEN和CLOUDFLARE_ACCOUNT_ID是否都填了 - 检查 Token 是否有 D1 Edit 权限
报错 3:npx: command not found
原因:NAS 上没有 Node.js 环境。
解决:
- 在呆呆面板的「依赖管理」里装 Node.js
- 或者用 SSH 进去手动装:
apt install nodejs npm(不同系统命令不同)
报错 4:脚本执行成功但文件是 0 字节
原因:D1 导出时数据库被锁,或账号权限问题。
解决:
- 检查数据库是否在跑大批量写入
- 换到凌晨低峰期执行
七、进阶玩法(可选)
1. 备份文件压缩加密
如果担心备份文件泄露,在脚本里加一步压缩加密:
# 压缩
gzip "cfblog-$DATE.sql"
# 或者加密(需要 openssl)
openssl enc -aes-256-cbc -salt -in "cfblog-$DATE.sql" -out "cfblog-$DATE.sql.enc" -k "你的密码"
rm "cfblog-$DATE.sql"
2. 备份完成发通知
呆呆面板支持 Bark / Telegram 等通知,任务执行失败时会自动推给你。
也可以手动在脚本末尾加:
curl -X POST "https://api.day.app/你的KEY/备份完成/D1 已备份到 NAS"
3. 备份到远程(异地容灾)
如果 NAS 只是中转,可以再同步到另一台机器:
# 用 rsync 同步到另一台 NAS
rsync -avz "$BACKUP_DIR/" user@另一台IP:/path/to/backup/
八、总结
整个流程其实就三步:
- 配好环境变量:
CLOUDFLARE_API_TOKEN+CLOUDFLARE_ACCOUNT_ID - 写好备份脚本:
npx wrangler d1 export+find ... -delete清理旧文件 - 定时任务跑起来:
0 3 * * *每天凌晨 3 点执行
配好之后,你飞牛 NAS 上就会自动积累一堆 .sql 备份,再也不用怕手滑删库、误操作或代码升级翻车了。
核心命令速查:
# 导出(手动)
npx wrangler d1 export CFBLOG --remote --output=backup.sql
# 查看有哪些数据库
npx wrangler d1 list
# 恢复(万不得已时用)
npx wrangler d1 execute CFBLOG --remote --file=backup.sql
备份这件事,跑起来一次之后就再也不用管了。建议今天就配上,别等出事才想起来。

💬 评论区 0