这篇教程解决什么问题

n8n 用得越久,里面攒的东西越值钱:几十个工作流、一堆凭据、可回溯的执行历史。换服务器、升配迁移、做灾备,都要把这套东西完整搬到新地方。本文给出两条互补的备份路线——整卷备份适合定时任务与快速恢复,CLI 导出适合把工作流 JSON 放进 Git 做版本管理——再加一套按清单走的完整迁移流程。

环境与版本

旧机:n8n【待补:版本号】,Docker 部署,数据卷 n8n_data
新机:【待补:配置与系统】,已装 Docker 与 Docker Compose
工具:宿主机 crontab(定时备份)、Git 仓库(工作流 JSON 版本管理)

规模参考:几十个工作流的个人实例,1 核 2 GB 的机器跑 n8n 本体足够,数据卷一般也就几十到几百 MB【待补:你的实际卷大小】,备份文件与传输开销都不大。

先搞清楚:n8n 的数据在哪

Docker 部署的 n8n,所有持久化数据都在容器的 /home/node/.n8n 目录(官方镜像的默认用户数据目录),挂载出来就是那个 n8n_data 卷。里面最重要的两样:

  • database.sqlite:默认的内置数据库文件,工作流、凭据引用、执行历史都在里面;
  • 加密密钥:凭据在库里是密文存储,解密密钥来自 N8N_ENCRYPTION_KEY 环境变量;从没设置过这个变量的话,n8n 首次启动会自动生成一把,写进 .n8n 目录下的 config 文件。

一个必须刻进脑子的事实:导出或复制工作流 JSON 不会带走凭据。凭据独立存储、独立加密,所以”导出了所有工作流”不等于”备份完成”——加密密钥和凭据数据必须一起迁移,否则新机器上所有凭据都解不开。

第一步:整卷备份(最简单可靠)

数据集中在一个卷里,把卷打成包:

# 宿主机执行:把 n8n_data 卷打包成 tar.gz
docker run --rm \
  -v n8n_data:/data:ro \
  -v "$(pwd)":/backup \
  alpine tar czf "/backup/n8n_data_$(date +%F).tar.gz" -C /data .

-C /data . 表示打包目录内容而不带绝对路径前缀,恢复时解到新卷结构不变;:ro 只读挂载,备份动作本身不会污染原数据。

严谨性说明:SQLite 文件在容器运行中被复制,存在理论上的不一致风险。小实例影响有限,但定时备份建议选业务空闲时段,或者先 docker stop n8n 再备份再启动(停机十几秒)更稳。把这条命令放进宿主机 crontab 每天凌晨跑一次,再配一条上传到对象存储或另一台机器的命令,异地灾备就有了。恢复是反向操作:

docker volume create n8n_data
docker run --rm \
  -v n8n_data:/data \
  -v "$(pwd)":/backup \
  alpine sh -c "cd /data && tar xzf /backup/n8n_data_2026-08-31.tar.gz"

第二步:CLI 导出(工作流进 Git)

n8n 自带命令行工具,能把工作流和凭据导出成 JSON。在宿主机对容器执行:

# 导出全部工作流到宿主机文件(JSON,可 diff,可进 Git)
docker exec n8n n8n export:workflow --all > workflows_all.json

# 导出全部凭据;不带 --decrypted 时导出的是加密形态
docker exec n8n n8n export:credentials --all --decrypted > credentials_all.json

两条命令用途完全不同。工作流 JSON 干净、可读、可 diff,非常适合进 Git——每个工作流的每次修改都有提交记录,改坏了随时回滚;几十个工作流的导出文件通常不到 1 MB【待补:实测大小】。凭据导出则要当成危险操作对待:--decrypted 导出的是明文密码与 API Key,这个文件等于你所有服务的钥匙串,绝不进 Git、不留共享目录,用完即删或放进加密存储。

对应地,导入用 import:workflow 与 import:credentials 子命令,参数与导出对齐。日常工作里最实用的组合是:Git 管工作流 JSON(免费回滚),整卷备份管凭据与执行历史。

第三步:迁移到新服务器

按顺序走清单:

  1. 旧机备份:整卷 tar 包加导出 JSON 双保险,并拿到加密密钥——要么记下旧机 compose 里的 N8N_ENCRYPTION_KEY,要么从 .n8n/config 文件读出 encryption_key 字段的值,抄进密码管理器;
  2. 新机对齐版本:pull 与旧机相同版本 tag 的 n8n 镜像。版本不一致也能跑(数据库 schema 会由新版启动时自动迁移),但回退就麻烦了——先一致,迁完再走正常升级;
  3. 恢复数据:新机建同名卷并解包(上文的恢复命令),compose 里显式设置 N8N_ENCRYPTION_KEY 为旧机的值;
  4. 启动验证:docker compose up -d,登录实例逐项核对。

验证清单:工作流数量与旧机一致;随便打开一个工作流,节点配置完整;点开任意凭据能正常显示内容——这一步验证加密密钥是否正确,是迁移成败的关键项;手动触发一条工作流跑通;旧数据卷完整搬过来的话,执行历史也在。部署细节(compose 写法、时区变量)见《n8n 本地部署教程:Docker 从零到跑通第一个工作流》。

一个原则:迁移不是升级。先原样搬、验证通过,再升级——两件事分开做,出问题才能定位是搬家搬坏的还是升级升坏的。

常见坑

坑 1:新机起来后凭据全部打不开,编辑凭据时报解密错误【待补:报错原文】。根因是 N8N_ENCRYPTION_KEY 没带上或带错了——数据搬了,钥匙没搬。处理:停容器,把环境变量改成旧机的值再起。这也是为什么密钥要单独抄录在密码管理器里,不能只存在数据卷的 config 文件里。

坑 2:只导出了工作流 JSON,忘了凭据不随 JSON 走。新机上工作流都在,但节点运行时报凭据缺失,只能逐个重建。补救:export:credentials 导出再导入,或者干脆整卷迁移一步到位。

坑 3:新旧版本差距过大。跨了很多个大版本直接启动,schema 迁移可能失败或行为变化【待补:你的版本跨度与现象】。老规矩:先对齐旧版本完成迁移,再小步升级。

坑 4:卷挂载路径写错。照抄了挂到其他路径的教程,容器起来看似正常,数据实际写进容器层,重建容器全部丢失。认准官方镜像的 /home/node/.n8n,这是官方文档明确的默认数据目录。

最终效果

迁移完成后:新服务器上 n8n 正常登录,工作流、凭据、执行历史原样都在,定时任务在下一个触发点准时执行。此后每天凌晨的整卷备份与 Git 里的工作流 JSON 双轨并行,任何一层出问题都有恢复手段。换服务器从心里没底的工程,变成照清单走的操作,小实例全程通常十几分钟【待补:实测耗时】。

n8n 备份与迁移路线示意

【待补:备份产物与新实例工作流列表截图】

相关阅读