CrabNote螃蟹笔记

n8n 2.0 来了,升级前这几个坑你得知道

n8n 2.0 来了,升级前这几个坑你得知道

n8n 2.0 来了,升级前这几个坑你得知道 n8n 2.0 来了,升级前这几个坑你得知道 Modified December 14, 2025 No access n8n 2.0 UI 变动 00:00 我的建议是分三步走。 1、第一步:先看迁移报告 n8n 官方做了一个 迁移报告工具(Migration Report ) 别盲目升级,在 Settings Migration Report 里(需要管理员权限,且版本 ≥ 1.121.0),它会告诉你: • 哪些工作流用了即将失效的节点 • 哪些配置项在 2.0 会报错 • 甚至会给你标记出 Critical(致命)和 Medium(中等)的风险等级。 看到 Critical,就先别升。修好再说。 每一点都会对应相关的解决文档,如果感到困惑,可以点击查看文档来修复。 拿我自己的报告举例,第一条就是 Remove Pyodide based Python in Code node,影响了 51 个工作流。 这条的意思是:2.0 移除了原来的 Pyodide Python 实现,改用原生 Python Task Runner。 打开 Code 节点,你会发现 Language 选项从原来的 Python 变成了 Python(Native) 如果你的环境里没有 Python 3,或者没配置 Task Runners,选择 Python (Native) 后就会报错: Code block GraphQL Copy 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 怎么解决? 官方推荐用 external mode,单独跑一个 Task Runners 容器。 配置分两步: 第一步:n8n 主容器加环境变量 Code block GraphQL Copy 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 容器(版本号和 n8n 一致): Code block GraphQL Copy 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 可选:N8N RUNNERS LAUNCHER LOG LEVEL=debug 等 depends on: n8n 配置完重启,Python Code 节点就能正常跑了。 💡 主容器和 runner 容器的这个 Token 必须完全一致,否则连不上。 但别高兴太早,还有一个坑:stdlib 模块被拦截 配好 Task Runners 后,你可能还会遇到 json、datetime、hashlib 这些标准库导入失败的问题。 它来自原生 Python Runner 的安全限制:默认不允许导入任何 Python 标准库模块。 这是因为默认的 /etc/n8n task runners.json 配置把 Python 标准库锁得很死。 Code block Bash Copy ➜ docker exec it n8n runners cat /etc/n8n task runners.json { "task runners": [ { "runner type": "javascript", ... }, { "runner type": "python", "workdir": "/home/runner", ... "allowed env": [ "PATH", "N8N RUNNERS LAUNCHER LOG LEVEL", ... ], "env overrides": { "PYTHONPATH": "/opt/runners/task runner python", "N8N RUNNERS STDLIB ALLOW": "", "N8N RUNNERS EXTERNAL ALLOW": "" } } ] } 即使你在 docker compose 里设置了 N8N RUNNERS STDLIB ALLOW= ,也不会生效。 💡 原因有两个: 1. 默认的 allowed env 里根本没有 N8N RUNNERS STDLIB ALLOW 这个变量,所以压根传不进去 2. env overrides 会把这个变量强制覆盖成空字符串 解决办法:自己写配置文件挂载进去。 最直接、可控的做法是自己提供一个 n8n task runners.json 并挂载进去,覆盖默认配置,然后显式允许需要的 stdlib(甚至全部)。 第一步:在宿主机创建 n8n task runners.json Code block JSON Copy { "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" } } ] } 💡 关键改动: • 在 allowed env 里加入 N8N RUNNERS STDLIB ALLOW 和 N8N RUNNERS EXTERNAL ALLOW,这样 Docker 环境变量才能传进 runner。 No access n8n 2.0 UI 变动 00:00 No access n8n 2.0 UI 变动 00:00 我的建议是分三步走。 1、第一步:先看迁移报告 n8n 官方做了一个 迁移报告工具(Migration Report ) 别盲目升级,在 Settings Migration Report 里(需要管理员权限,且版本 ≥ 1.121.0),它会告诉你: • 哪些工作流用了即将失效的节点 • 哪些配置项在 2.0 会报错 • 甚至会给你标记出 Critical(致命)和 Medium(中等)的风险等级。 看到 Critical,就先别升。修好再说。 每一点都会对应相关的解决文档,如果感到困惑,可以点击查看文档来修复。 拿我自己的报告举例,第一条就是 Remove Pyodide based Python in Code node,影响了 51 个工作流。 这条的意思是:2.0 移除了原来的 Pyodide Python 实现,改用原生 Python Task Runner。 打开 Code 节点,你会发现 Language 选项从原来的 Python 变成了 Python(Native) 如果你的环境里没有 Python 3,或者没配置 Task Runners,选择 Python (Native) 后就会报错: 怎么解决? 官方推荐用 external mode,单独跑一个 Task Runners 容器。 配置分两步: 第一步:n8n 主容器加环境变量 第二步:新增 Task Runners 容器(版本号和 n8n 一致): 配置完重启,Python Code 节点就能正常跑了。 💡 主容器和 runner 容器的这个 Token 必须完全一致,否则连不上。 主容器和 runner 容器的这个 Token 必须完全一致,否则连不上。 但别高兴太早,还有一个坑:stdlib 模块被拦截 配好 Task Runners 后,你可能还会遇到 json、datetime、hashlib 这些标准库导入失败的问题。 它来自原生 Python Runner 的安全限制:默认不允许导入任何 Python 标准库模块。 这是因为默认的 /etc/n8n task runners.json 配置把 Python 标准库锁得很死。 即使你在 docker compose 里设置了 N8N RUNNERS STDLIB ALLOW= ,也不会生效。 💡 原因有两个: 1. 默认的 allowed env 里根本没有 N8N RUNNERS STDLIB ALLOW 这个变量,所以压根传不进去 2. env overrides 会把这个变量强制覆盖成空字符串 原因有两个: 1. 默认的 allowed env 里根本没有 N8N RUNNERS STDLIB ALLOW 这个变量,所以压根传不进去 2. env overrides 会把这个变量强制覆盖成空字符串 解决办法:自己写配置文件挂载进去。 最直接、可控的做法是自己提供一个 n8n task runners.json 并挂载进去,覆盖默认配置,然后显式允许需要的 stdlib(甚至全部)。 第一步:在宿主机创建 n8n task runners.json 💡 关键改动: • 在 allowed env 里加入 N8N RUNNERS STDLIB ALLOW 和 N8N RUNNERS EXTERNAL ALLOW,这样 Docker 环境变量才能传进 runner。 关键改动: • 在 allowed env 里加入 N8N RUNNERS STDLIB ALLOW 和 N8N RUNNERS EXTERNAL ALLOW,这样 Docker 环境变量才能传进 runner。 • 删掉 env overrides 里原来的空字符串覆盖,否则会覆盖掉你在 Compose 里设置的值。 第二步:挂载配置文件 在 docker compose.yml 的 task runners 服务里挂载这个文件。同时把需要的模块加到白名单里。因为是测试环境,偷懒下,暴力使用了 重启之后,Python 标准库就能正常导入了,不再依赖主 n8n 容器本身是否安装 Python 3。 配置完成后,回到迁移报告看一下,Python 相关的 Issue 应该已经消失了: 顺便说一个好处: Task Runners 独立出来之后,调试 Code 节点变方便了。 以前代码跑在主进程里,出了问题只能看 n8n 的日志,信息混在一起很难找。现在可以直接看 runner 容器的日志: 代码的执行过程、报错信息都在这里,排查问题清晰多了。 💡 由于篇幅原因,其他 Issue 这里不展开了,如有问题可以在评论区留言。 由于篇幅原因,其他 Issue 这里不展开了,如有问题可以在评论区留言。 2、第二步:在测试环境跑一遍 永远、永远不要在生产环境直接升级大版本。 用 Docker 起一个新实例只要1分钟。把生产工作流导入进去,重点测试: • 用了 Code 节点的工作流 • 有子工作流调用的 • 复杂逻辑的 你会发现,虽然 2.0 兼容性做得不错,但总有那么几个诡异的报错在等着你。 3、第三步:给自己留后路 n8n 官方承诺, v1.x 还会维护 3 个月(只修 Bug 不加功能)。 所以不用慌。你有 90 天时间慢慢适应、去修改、去测试。 记住,自动化工具的最高准则是稳定,而不是求新。 📌 本文重点列出了涉及底层架构和通用安全策略的核心破坏性变更。 当然,2.0 的改动远不止这些。 如果你是重度开发者,或者使用了非常冷门的节点,强烈建议在升级前通读一遍 官方的 Breaking Changes 文档 官方的 Breaking Changes 文档 本文重点列出了涉及底层架构和通用安全策略的核心破坏性变更。 当然,2.0 的改动远不止这些。 如果你是重度开发者,或者使用了非常冷门的节点,强烈建议在升级前通读一遍 官方的 Breaking Changes 文档 官方的 Breaking Changes 文档 写在最后 n8n 2.0 的这次更新,说白了是在"收紧"。 以前能随便访问系统底层、能在代码里干各种骚操作,现在都被限制了。用起来没那么"自由"了,但确实更稳定、更安全。 真正的自动化,不是为了少写几行代码,而是为了更安全、更可控的交付。 如果你准备好了,可以开始迁移;如果还没准备好,那份迁移报告先点开看看。 知道自己要踩哪些坑,比直接踩上去要好。 如果你在升级过程中遇到其他坑,欢迎在评论区留言,我会持续更新这篇文章。 我是林月半子,关注我,带你一起挖掘工作流自动化的无限可能。 References • n8n v2.0 介绍:https://blog.n8n.io/introducing n8n 2 0/ • n8n v2.0 更新说明:https://docs.n8n.io/2 0 breaking changes/ https://docs.n8n.io/2 0 breaking changes/ • n8n v2.0 迁移工具:https://docs.n8n.io/migration tool v2/ 🔗 原文链接:https://mp.weixin.qq.com/s/kQBpC3Gn9nM 77AGzwGNVw ⏰ 发布时间:2025 12 14 19:45:00 (UTC+8) 作者:林月半子的AI笔记 等了两年,n8n 2.0 终于来了。 不知道大家有没有注意到,现在进入 n8n 平台,顶部会有一个小横条,提示让我们准备迎接 v2.0 版本。点击 Learn more,就能看到新版本带来了哪些内容。 事实上 2.0 并不是堆新功能,而是通过引入破坏性变更来增强安全性、可靠性和性能,所以大部分的改动是涉及底层架构的重构。 正如官方所说: “n8n 2.0 标志着平台从一个灵活的工具,转变为一个为安全、可靠和规模而设计的加固的企业级平台。” 但这对我们要干活的人来说,翻译成人话就是:以前很多"野路子"的用法,这次因为安全原因被堵死了。 如果你手里有正在跑的生产环境,先别急着点 Update。 我周末把官方文档啃了一遍,踩了几个坑,今天把我的理解分享出来。 一、2.0 到底改了什么? 打开 2.0 Beta 版本,第一眼你会被扁平化的 UI 吸引。左侧边栏可以拖拽了,设置菜单变得更直接。 我录了个简单的对比,大家感受一下: 但这些是面子工程。真正的变化在底下。 1、代码执行被"关进笼子"了 以前你在 Code 节点里写 JS,代码是在 n8n 主进程里跑的。一旦代码有 bug,比如死循环、内存泄漏,就能把整个服务搞挂。 2.0 它默认启用了一个叫 Task Runners 的东西。简单说,你的代码现在在独立沙盒里跑,就算炸了,主进程也不受影响,安全性更高。 2、环境变量访问被禁 你是不是习惯在 Code 节点和表达式中直接读取系统环境变量? 对不起,2.0 默认禁止。 为了防止凭证泄露,你必须显式地去配置 N8N BLOCK ENV ACCESS IN NODE=false 才能解封。或者,改掉你的坏习惯,用正规的 Credentials 管理敏感信息。 3、大文件处理不吃内存了 以前 n8n 处理大文件是全部加载到内存里。文件一大,内存就爆。 2.0 直接移除了 default 内存模式,改成三种持久化方案: 💡 • filesystem:存到文件系统,常规模式下的默认选项 • database:存到数据库,队列模式下的默认选项 • s3:存到 S3 兼容的对象存储 • filesystem:存到文件系统,常规模式下的默认选项 • database:存到数据库,队列模式下的默认选项 • s3:存到 S3 兼容的对象存储 升级后会根据你的配置自动选择 filesystem 或 database,不用手动改。 但有一点要注意: 确保你的服务器有足够的磁盘空间。以前二进制数据用完就释放内存,现在会实实在在占用磁盘。 速度会慢一点点,但换来的是稳定。不会再因为一个大文件把整个服务搞崩。 4、终于有草稿了 这个功能等了太久。 做自动化的人,最怕什么? 最怕你在调试一个正在运行的工作流,手一抖点了 Save,结果还在测试的半成品逻辑直接生效,线上的数据全乱了。 在 1.x 版本,Save 就是 Publish,这简直是反人类的设计。 2.0 终于把保存和发布分开了! 🎯 • Save:你随便改,随便存,它只是个草稿(Draft),不会影响线上业务 • Publish:你确认没问题了,再点发布 • Save:你随便改,随便存,它只是个草稿(Draft),不会影响线上业务 • Publish:你确认没问题了,再点发布 这才是正常的开发流程。 具体变化: 旧版的 Active/Inactive 开关被移除了,取而代之的是 Publish 按钮。 点击 Publish 时,可以输入版本号和变动说明,方便日后追溯历史。 如果需要下线工作流,点击右上角三个点,选择 Unpublish 即可。 在工作流列表页,原来的 Active 指示器也换成了 Published 状态标识。 另外,我们一直期待的自动保存(Autosave)功能,官方计划在 2026 年 1 月推出。到时候连手动 Save 都省了。 5、子工作流的等待问题修好了 这个改动看起来不起眼,但如果你在做人机协同(Human in the Loop)的业务,这是个大升级。 以前的问题: 当父工作流调用子工作流,而子工作流里有需要"等待"的节点(比如 Wait 节点超过 65 秒、等待表单提交、等待 Slack 审批),父工作流确实会等。 但问题是:等完之后,父工作流拿到的不是子工作流的输出结果,而是子工作流的输入数据。 这就很坑了——你明明在等人工审批,结果父工作流拿到的不是"通过"或"拒绝",而是一堆没用的输入数据。 现在的逻辑: 2.0 修好了。父工作流会老老实实挂起,等子工作流真正跑完,拿到最终结果再继续。 这意味着什么? 你可以放心地把审批、表单、人工确认这些节点放进子工作流里了。哪怕审批人隔了一天才点确认,父工作流也能稳稳接住结果继续跑。 这是行为变更,不是单纯的 Bug 修复。如果你以前的工作流恰好依赖了旧版行为,升级后逻辑可能会变,建议检查一下调用子工作流的地方。 二、升级前必须检查的几件事 为什么我说别急着升? 因为 n8n 2.0 为了安全,它默认关掉了很多你以前用得很爽、但其实很危险的功能。 我第一次升级测试环境的时候,工作流直接挂了一批。后来发现是踩了这些坑: 1、一些危险节点被下架 那个能执行 Shell 命令的 Execute Command 节点?禁用了。 那个能随意读写本地文件的 LocalFileTrigger 节点?限制了。 因为它们允许用户运行任意命令和访问文件系统,存在安全风险。 如果你确实需要用,得去改配置文件的 NODES EXCLUDE。 2、文件访问被限制了 如果你用过 ReadWriteFile 或 ReadBinaryFile 这两个节点,注意了。 以前这俩节点可以读写服务器上的任意路径,很自由,但也很危险。万一工作流被人恶意篡改,理论上可以读取服务器上的任何敏感文件。 2.0 给 N8N RESTRICT FILE ACCESS TO 设了默认值,文件操作只能在 /.n8n files 目录内进行。超出这个范围的读写操作会直接失败。 这个改动我觉得是对的。 n8n 越来越多地被用在团队协作和生产环境里,不再只是个人的玩具。当多人共用一个 n8n 实例时,限制文件访问范围能避免很多安全隐患。 怎么办? 两个选择: • 把原来需要读写的目录挂载到容器的 /.n8n files 目录下 • 或者配置 N8N RESTRICT FILE ACCESS TO=/your/custom/path 指定允许访问的目录 升级前先检查一下你的工作流,看看有没有读写其他路径的操作。 3、后台数据库不再支持 MySQL 注意,这里说的是 n8n 自身的元数据存储,不是你工作流里连接的 MySQL 节点。 如果你自建 n8n 用的是 MySQL 或 MariaDB 存元数据,升级前必须先迁移到 PostgreSQL,否则服务起不来。 如果升级到 2.0 ,务必先备份,然后迁移数据库。 三、如何安全地升级? 前面说了这么多更新项,你可能会想:我怎么知道自己的工作流迁移到 2.0 之后会不会出问题?