n8n 自建自动化工作流:把每天重复的搬运动作交给它
用过 Zapier 这类 SaaS 自动化的人都知道那个拐点:前几十个任务跑得挺舒服,等到每天几百次触发时,账单开始不友好。它们大多按任务数计费,每执行一个动作算一次,表单提交一多、RSS 转推一频繁,月底一看四位数。n8n 就是冲这个来的:开源、可自部署、工作流跑在你自己的机器上,除了服务器成本和你的时间,没有按次收费这回事。
下面按「能干什么 → 怎么部署 → 关键配置 → 跑一个真实例子 → 踩过的坑」走一遍。你只要有一台能装 Docker 的机器,群晖、VPS 或者闲置小主机都行。
它能替你干什么
n8n 的核心是节点拼接。每个节点干一件事:收一个请求、读一次 RSS、写一条数据库记录、发一条消息。连起来之后,数据以 JSON 在节点间流动,就成了自动化流程。
| 场景 | 触发方式 | 用到的节点 |
|---|---|---|
| 表单收集入库 | Webhook 或内置表单 | Webhook、Set、数据库节点 |
| RSS 转公众号草稿 | 定时 + 读 RSS | Schedule、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 直接写在节点头里,一导出分享密钥就跟着走了,用凭证管理,导出时也别勾选带凭证。
什么时候该用,什么时候别硬上
适合:几个自建服务想串起来、有周期性数据搬运、需要「表单进来就通知某人」这类轻量业务流、想把重复操作沉淀成可视化流程便于维护。流程稍微变一下拖两个节点就连上了,这是它最舒服的地方。
不适合:高频率低延迟的实时处理;逻辑复杂、需要严格类型和单元测试的核心业务;涉及强一致性的交易操作,可视化流程很难保证出错回滚的完整性。它是个趁手的胶水工具,但胶水替代不了承重墙。






