等了两年,n8n 2.0 终于来了。

这次升级简单说:很多过去能用的“灵活写法”会被默认关闭,换来的是更稳的生产运行。
这篇文章我按实际迁移过程来分享:哪些变化需要重点理解、升级前要查什么、如何在不影响生产的前提下完成迁移。
我会把经验点穿插在每个环节,帮助你判断适配性与风险。
核心变化
UI 的扁平化改动很直观,但对生产影响不大。
对升级决策更关键的是下面这些底层与行为变化:
代码执行隔离(Task Runners):Code 节点的 JS/Python 不再直接跑在主进程,默认进入独立沙盒。好处是单个任务“炸”了,不会带崩主服务。我的测试感受是:故障半径变小,问题定位更清晰,但需要额外配置 Runner(尤其是 Python)。
环境变量默认禁止访问:在表达式和 Code 节点中直接读系统环境变量,2.0 默认不允许。出于凭证泄露保护。如果要临时放开,需要显式设置 N8N_BLOCK_ENV_ACCESS_IN_NODE=false;长期建议把敏感信息迁到 Credentials。
大文件处理从“内存”改为“持久化”:去掉了默认内存模式,新增三种落盘方案:
- filesystem:文件系统(常规模式默认)
- database:数据库(队列模式默认)
- s3:S3 兼容对象存储
升级后会按你的部署模式自动选择 filesystem 或 database。你需要准备磁盘空间。我的测试下,吞吐速度略慢,但稳定性显著提升。
保存与发布分离(新增 Draft):1.x 的 Save=线上生效在调试时很不友好。2.0 终于把 Save(草稿)与 Publish(发布)分离,并支持版本号与变更说明。Active/Inactive 开关被移除,改为 Published 状态标识。官方计划在 2026年1月提供 Autosave。
子工作流“等待”行为修正:父工作流调用子工作流时,遇到等待节点(例如 Wait>65s、表单提交、Slack 审批),现在会真正等待到子工作流结束并拿到最终输出。不再返回输入数据。这是行为变更,涉及人机协同场景,建议逐个验证。
变化与建议速览
| 变更项 | 默认策略 | 影响范围 | 建议动作 |
|---|---|---|---|
| 代码执行隔离(Task Runners) | 启用沙盒,主进程不直接执行 | 所有 Code 节点(JS/Python) | 评估并部署外部 Runner;为 Python 配置可用环境 |
| 环境变量访问 | 默认禁止 | 表达式、Code 节点 | 迁移到 Credentials;临时放开:N8N_BLOCK_ENV_ACCESS_IN_NODE=false |
| 大文件处理 | 持久化(filesystem/database/S3) | 二进制数据流 | 预留磁盘容量;评估性能与清理策略 |
| 保存/发布 | Save=草稿;Publish=上线 | 所有工作流 | 建立版本与说明规范;使用 Unpublish 管理下线 |
| 子工作流等待 | 父流程拿最终输出 | 有审批/表单/长等待的链路 | 复核依赖旧行为的逻辑,更新数据传递 |
升级前注意事项
危险节点策略调整:例如执行 Shell 的 Execute Command、可读写本地文件的 LocalFileTrigger 等被默认禁用或限制。若必须使用,需审查并调整节点加载策略(黑/白名单),并在团队范围内明确权限。
文件访问路径限制:默认仅允许 ~/.n8n-files 路径(由 N8N_RESTRICT_FILE_ACCESS_TO 控制)。既有工作流若读写其他路径,要么挂载到该目录,要么指定允许访问目录。
元数据数据库不再支持 MySQL/MariaDB:这指 n8n 自身的元数据存储,不是工作流里的 MySQL 节点。自建实例需先迁到 PostgreSQL,再升级。记得完整备份与回滚方案。
安全升级
步骤一:先跑迁移报告(Migration Report)
在 Settings > Migration Report(管理员权限,且版本 ≥ 1.121.0)查看风险清单。报告会标注 Critical/Medium 等级并给出解决文档。
我的测试报告里,最影响的是“移除 Pyodide Python,改用原生 Python Runner”,涉及 51 个工作流。选择 Code 节点的 Language 时会看到 Python(Native),如果系统没有 Python 3 或未配置 Task Runners,会报:
Python runner unavailable: Python 3 is missing from this system
Internal mode is intended only for debugging. For production, deploy in external mode:
https://docs.n8n.io/hosting/configuration/task-runners/#setting-up-external-mode
步骤二:搭好外部 Task Runners(建议)
按照官方建议使用 external mode,将 Runner 独立为容器。关键点是主容器与 runner 容器的 Auth Token 必须一致。
示例(按需调整版本与安全策略):
# n8n 主服务
services:
n8n:
image: n8nio/n8n:2.0.2
environment:
- N8N_RUNNERS_MODE=external
- N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
- N8N_RUNNERS_AUTH_TOKEN=your-secret-here
- N8N_NATIVE_PYTHON_RUNNER=true
# Task Runners 服务
services:
task-runners:
image: n8nio/runners:2.0.2
container_name: n8n-runners
environment:
- N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
- N8N_RUNNERS_AUTH_TOKEN=your-secret-here
depends_on:
- n8n
补坑:Python 标准库被默认拦截
即便 Runner 配好了,你可能仍会遇到 json、datetime、hashlib 等标准库 import 失败。原因是默认的 /etc/n8n-task-runners.json 对 Python stdlib 限制较严,且环境变量可能被覆盖。
我的做法是自定义配置文件并挂载,显式允许需要的模块(测试环境可以先开全量,生产建议白名单):
{
"task-runners": [
{
"runner-type": "javascript",
"workdir": "/home/runner",
"command": "/usr/local/bin/node",
"args": ["--disallow-code-generation-from-strings","--disable-proto=delete","/opt/runners/task-runner-javascript/dist/start.js"],
"health-check-server-port": "5681",
"allowed-env": ["PATH","GENERIC_TIMEZONE","NODE_OPTIONS","N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT","N8N_RUNNERS_TASK_TIMEOUT","N8N_RUNNERS_MAX_CONCURRENCY","N8N_SENTRY_DSN","N8N_VERSION","ENVIRONMENT","DEPLOYMENT_NAME","HOME"],
"env-overrides": {
"NODE_FUNCTION_ALLOW_BUILTIN": "*",
"NODE_FUNCTION_ALLOW_EXTERNAL": "*",
"N8N_RUNNERS_HEALTH_CHECK_SERVER_HOST": "0.0.0.0"
}
},
{
"runner-type": "python",
"workdir": "/home/runner",
"command": "/opt/runners/task-runner-python/.venv/bin/python",
"args": ["-m","src.main"],
"health-check-server-port": "5682",
"allowed-env": ["PATH","N8N_RUNNERS_LAUNCHER_LOG_LEVEL","N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT","N8N_RUNNERS_TASK_TIMEOUT","N8N_RUNNERS_MAX_CONCURRENCY","N8N_SENTRY_DSN","N8N_VERSION","ENVIRONMENT","DEPLOYMENT_NAME","N8N_RUNNERS_STDLIB_ALLOW","N8N_RUNNERS_EXTERNAL_ALLOW"],
"env-overrides": {
"PYTHONPATH": "/opt/runners/task-runner-python"
}
}
]
}
并在 Runner 服务中挂载与设置:
services:
task-runners:
image: n8nio/runners:2.0.2
environment:
- N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
- N8N_RUNNERS_AUTH_TOKEN=your-secret-here
# 测试环境可用 *;生产建议明确库名单
- N8N_RUNNERS_STDLIB_ALLOW=*
- N8N_RUNNERS_EXTERNAL_ALLOW=*
volumes:
- ./n8n-task-runners.json:/etc/n8n-task-runners.json
depends_on:
- n8n
重启后,Python 标准库即可正常导入,且不再依赖主容器是否安装系统级 Python。
步骤三:在独立测试环境完整回归
不要在生产直接升级大版本。
用 Docker 起一套隔离实例,把生产工作流导入,重点回归:
- 包含 Code 节点(JS/Python)的工作流
- 有子工作流调用、且包含长等待/人工审批的链路
- 涉及本地文件读写与环境变量读取的场景
我的测试结论:整体兼容性不错,但总会有少量“边缘写法”在 2.0 下报错或行为不同。迁移报告 + 小规模灰度可以显著降低风险。
适配性评估
适合尽快迁移的场景:
团队协作、多人共享实例,需强化安全隔离与权限边界
生产负载对稳定性有明确要求,曾遇到单任务拖垮主服务的情况
有审批、人机协同链路,依赖子工作流的稳定等待与输出一致性
需要额外准备的场景:
大量使用环境变量、文件系统“任意路径”访问、或执行 Shell
工作流重度依赖 Code 节点,且混用 JS/Python 与第三方包
当前元数据数据库为 MySQL/MariaDB(需先迁 PostgreSQL)
总结
n8n 2.0 的方向很明确:更安全、更可靠、更适合规模化,而不是“更自由”。
对我们这些在生产环境里跑自动化的团队而言,这次升级更像是一次“治理与规范”的落地:把潜在风险点默认关掉,让能力通过明确配置与白名单来释放。
迁移建议很具体:先看迁移报告、搭外部 Runner、在隔离环境回归,再按模块灰度上线。
官方承诺 v1.x 仍会维护约三个月(仅修 Bug),所以没必要赶时间。把稳定放在第一位,按步骤把风险收敛,升级是可控的。
参考文档
n8n v2.0 介绍:https://blog.n8n.io/introducing-n8n-2-0/
n8n v2.0 破坏性变更说明:https://docs.n8n.io/2-0-breaking-changes/
n8n v2.0 迁移报告工具:https://docs.n8n.io/migration-tool-v2/