n8n 自建自动化工作流:把每天重复的搬运动作交给它

admin 开源软件 2026-11-01 18 0

用过 Zapier 这类 SaaS 自动化的人都知道那个拐点:前几十个任务跑得挺舒服,等到每天几百次触发时,账单开始不友好。它们大多按任务数计费,每执行一个动作算一次,表单提交一多、RSS 转推一频繁,月底一看四位数。n8n 就是冲这个来的:开源、可自部署、工作流跑在你自己的机器上,除了服务器成本和你的时间,没有按次收费这回事。

下面按「能干什么 → 怎么部署 → 关键配置 → 跑一个真实例子 → 踩过的坑」走一遍。你只要有一台能装 Docker 的机器,群晖、VPS 或者闲置小主机都行。

它能替你干什么

n8n 的核心是节点拼接。每个节点干一件事:收一个请求、读一次 RSS、写一条数据库记录、发一条消息。连起来之后,数据以 JSON 在节点间流动,就成了自动化流程。

场景触发方式用到的节点
表单收集入库Webhook 或内置表单Webhook、Set、数据库节点
RSS 转公众号草稿定时 + 读 RSSSchedule、RSS Read
定时抓数据入库定时Schedule、HTTP Request、Code
企业微信/钉钉推送定时或无头调用HTTP Request
两个库同步定时Select、循环、Upsert

共同点很清楚:都是有规律但懒得手点的事。以前要么写脚本挂 crontab,要么忍着账单。n8n 补的是中间那块——不写代码能拼出来,需要时又能随时插一段脚本。

用 Docker 跑起来

官方镜像 n8nio/n8n,默认监听 5678,持久化数据都在容器内 /home/node/.n8n,必须挂卷出去,否则容器一删工作流就没了。

mkdir -p /opt/n8n/data
docker run -d \
  --name n8n \
  --restart unless-stopped \
  -p 5678:5678 \
  -e GENERIC_TIMEZONE="Asia/Shanghai" \
  -e TZ="Asia/Shanghai" \
  -e N8N_SECURE_COOKIE=false \
  -v /opt/n8n/data:/home/node/.n8n \
  n8nio/n8n

时区变量一定要设,否则定时任务按 UTC 跑,你以为早上九点,实际是国内下午五点。N8N_SECURE_COOKIE=false 是先用 HTTP 直连时的必需品:默认只在 HTTPS 下写 cookie,你用 IP 加端口打开,登录后会一直提示会话失效、反复跳回登录页。等前面挂了反向代理再改回 true。

长期用建议换成 compose,升级和改配置都方便:

services:
  n8n:
    image: n8nio/n8n
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - GENERIC_TIMEZONE=Asia/Shanghai
      - TZ=Asia/Shanghai
      - N8N_HOST=n8n.example.com
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.example.com/
      - N8N_SECURE_COOKIE=true
      - N8N_ENCRYPTION_KEY=换成你的长随机串
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
    volumes:
      - ./data:/home/node/.n8n
docker compose up -d
docker compose logs -f n8n

日志出现监听 5678 就说明起来了。首次访问会让你填邮箱、密码、名字,这就是实例所有者账号,填完直接进主界面,没有注册和激活流程。邮箱在找回密码时用得上,内网实例随便填个记得住的。

几个必须先搞清楚的配置

加密密钥

N8N_ENCRYPTION_KEY 用来加密凭证里的密码和 API Key。不设的话它自动生成一个存在数据目录里,一旦重装时把目录清了,所有凭证全部解不开,工作流还在但全都报认证失败。自己定一个长随机串,单独记好。

Webhook 地址

实例挂在反向代理后面时,WEBHOOK_URL 必须显式写成对外可访问的完整域名。否则你拿到的 webhook 地址会是 http://localhost:5678/webhook/xxx,外部系统根本调不通。同时把 N8N_HOST 和 N8N_PROTOCOL 对齐。

执行记录清理

每次执行的输入输出都进数据库。一个每五分钟跑一次的工作流一天 288 条,加上响应体,几个月能涨到几个 GB。上面那两个变量就是干这个的:只留最近一周。

反代超时

Nginx 默认 60 秒超时对抓取类工作流太短,代理提前返回报错,而 n8n 那边还在跑。读写超时设到 600 秒。

节点怎么理解

别被几百个节点吓到,实际用起来只有几类,理解这四类能拼出九成工作流:

  • Trigger:入口,一个工作流只有一个。Schedule、Webhook、手动、RSS 触发都算,它决定什么时候开始跑。
  • Action:真正干活的部分,发请求、写库、发消息、改数据结构。
  • IF / Switch:按条件分流。IF 是真假两条,Switch 能分出多条,适合按类型字段分发。
  • 循环:节点返回数组时,后面的节点默认对每项执行一遍;需要控节奏时用分批节点切小,避免打爆对方限流。

另一个容易忽略的是错误处理。单节点能设「出错时继续」或走另一条分支,工作流级别还能挂一个错误触发器统一推告警。别等某个静默失败的工作流跑了两个月才发现数据一直是空的。

完整实例:每天九点推 RSS 到企业微信

建触发器

新建工作流,加定时触发器,间隔选天,小时填 9。点手动执行一次,确认下一轮触发时间显示的是本地时间。

读 RSS 并去重

接 RSS 读取节点填订阅地址,输出是 items 数组。去重是整条链路的关键,否则每天重复推同样几篇。稳妥做法是用一张表记录已推送的链接,Code 节点里做差集:

const seen = new Set($('读取已推送记录').all().map(i => i.json.link));
return $input.all()
  .filter(i => !seen.has(i.json.link))
  .map(i => ({ json: i.json }));

图省事可以用内置去重节点,比较字段选链接,但历史记在内存里,重启就丢,长期用还是落库靠谱。

判断有没有新内容

接 IF 节点,条件写 {{ $items().length }} 大于 0。真分支往下推送,假分支结束,这样没新文章那天不会发空消息。

推送到群机器人

群机器人不用登录授权,就是一个 webhook 地址。HTTP 请求节点,方法 POST,Body 选 JSON:

{
  "msgtype": "markdown",
  "markdown": {
    "content": "{{ $json.items.map(i => '- [' + i.title + '](' + i.link + ')').join('\n') }}"
  }
}

注意单条消息有长度上限,条目多时用 Code 节点每批切 5 到 8 条分次发。钉钉结构类似,改类型字段即可。最后把链接写回记录表,链路闭环,设为启用就会自己跑。

Webhook 与外部系统对接

另一条主线是「被调用」。加一个 Webhook 节点会得到一个 URL,支持多种方法和认证方式,外部往这个地址发请求,工作流立刻开跑。典型用法:表单提交后过来做校验写库发通知;告警时按级别分派到不同群;把多个内部接口聚合后返回统一格式。

响应有两种模式:立即返回确认,或等跑完再返回。后者能让调用方拿到结果,但要设超时。走反向代理时确认 WEBHOOK_URL 配好,并让代理透传 /webhook/ 子路径,很多反代只写了根路径,正好漏掉这里。

这几个坑我先替你踩了

登录一直打转

输入密码后页面刷新一下回到登录页,没有任何报错。原因就是 cookie 的 Secure 标志:软件认为你该用 HTTPS,浏览器看到的是 HTTP,直接把 cookie 丢了。要么把反代协议头补齐并真用 HTTPS,要么临时关掉这个开关,切到 HTTPS 后再打开。

定时跑偏

容器默认 UTC,比北京时间晚八小时。两个变量都要设:GENERIC_TIMEZONE 决定调度器怎么理解时间,TZ 决定容器内取到的当前时间。只设一个时,你在 Code 节点里打印时间会发现还是错的。

内存不足执行超时

处理大数组、抓几十页数据、解析大 JSON 都很吃内存。默认配额下可能跑到一半被 OOM 杀掉,表现是执行历史里失败或卡在运行中。给容器提上限,必要时调到 1 到 2 GB,同时用分批节点切小,既省内存也不容易触发对方限流。

默认 SQLite 并发差

单机小规模够用,但几个工作流同时跑、或者一次写入大量执行记录时,会遇到数据库锁错误,症状是随机失败和界面卡顿。上生产建议换 Postgres,加一个数据库服务,用环境变量传连接信息即可。切换前先导出工作流备份,两个库的数据不会自动迁移。

社区版和企业版的边界

自部署的是社区版,节点数、工作流数、执行次数都不限,个人和中小团队够用。但细粒度权限与团队协作、多环境切换、单点登录、执行审计这几样是企业版才有。另外别把 API Key 直接写在节点头里,一导出分享密钥就跟着走了,用凭证管理,导出时也别勾选带凭证。

什么时候该用,什么时候别硬上

适合:几个自建服务想串起来、有周期性数据搬运、需要「表单进来就通知某人」这类轻量业务流、想把重复操作沉淀成可视化流程便于维护。流程稍微变一下拖两个节点就连上了,这是它最舒服的地方。

不适合:高频率低延迟的实时处理;逻辑复杂、需要严格类型和单元测试的核心业务;涉及强一致性的交易操作,可视化流程很难保证出错回滚的完整性。它是个趁手的胶水工具,但胶水替代不了承重墙。