简介:这份资源是面向自动化流程开发者与运维人员的N8N本地部署可运行源码包,适合希望借助Docker快速搭建开源工作流引擎、并进一步阅读源码进行二次开发的技术爱好者。压缩包共4个文件,约12KB,包含sh部署脚本、inscode配置、html介绍页面与gitignore忽略规则,体积轻量但覆盖了从环境准备到容器启动的关键环节。N8N支持Webhook、CRON作业、数据库操作、邮件与社交媒体等多类节点,可通过拖拽方式编排复杂自动化流程,适用于企业内部流程自动化、IT运维与数据处理等场景。目前已有207人学习下载。读者可借助脚本与配置快速完成本地部署,结合介绍页面理解整体架构,并在此基础上修改源码、扩展自定义节点,为深入学习工作流引擎设计打下基础。
1. N8N本地部署:从一条命令到能跑通工作流的完整路径
很多人第一次接触 n8n,是在别人的演示视频里看到拖几个节点就把数据从 A 系统搬到 B 系统,觉得这东西挺香。但真到自己动手,第一步就卡住了——官方推荐的云版本要按月付费,数据还得放在别人服务器上。于是「N8N本地部署」成了搜索框里的高频词。本地部署的核心价值就两条:数据不出内网,流程完全可控。尤其当你需要把 n8n 和本地部署的大模型(比如 Ollama 拉起来的 DeepSeek)串起来做自动化处理时,云版本根本没法直连你本机的 11434 端口。这篇内容面向的是有基本 Linux 或 Docker 操作经验、想在自己机器或内网服务器上把 n8n 跑起来并接入实际业务的工程师。我会从部署方式选型讲到工作流跑通,再到凭据配置和避坑,每一步都给出可复现的命令和参数说明。
2. 部署方式选型:Docker 还是 npm 直装
2.1 两种方式的真实差异
n8n 官方提供多种安装途径,但落到本地部署场景,真正值得考虑的只有两条路:Docker 容器化部署和 npm 全局安装。网上有些教程会推荐用 npx 直接跑,那只适合临时体验,进程一关数据全丢,生产环境千万别这么干。
Docker 方式的好处是环境隔离彻底,n8n 依赖的 Node.js 版本、系统库都打包在镜像里,不会跟你机器上已有的 Node 环境打架。升级也简单,换个镜像标签重启就行。缺点是容器内访问宿主机服务(比如你本机跑的 Ollama)需要额外处理网络配置,这个后面会细说。
npm 直装的好处是直接跑在宿主机上,访问本机服务就是 localhost,没有网络隔阂。缺点是 n8n 对 Node.js 版本有要求,通常需要 Node 18 或 20,如果你机器上已经有其他项目依赖不同版本,容易出玄学问题。另外 npm 全局安装的包在系统迁移时不好带走,数据目录和安装目录是分开的,备份要手动处理。
我一般会这样选:如果是长期跑在内网服务器上、追求稳定和易维护,用 Docker;如果只是在自己开发机上快速验证、需要频繁调用本机其他服务,用 npm 直装更省事。下面两条路径都给出来,你按自己的场景挑一条走就行。
2.2 Docker 部署的完整命令与参数说明
先确认 Docker 和 Docker Compose 已经装好。没有的话,用系统包管理器装,这里不展开。接下来创建一个工作目录,把数据卷挂出来,这样容器删了数据还在。
# 创建 n8n 数据目录和配置文件目录 mkdir -p /opt/n8n/data /opt/n8n/config # 设置目录权限,n8n 容器内以 node 用户运行,UID 通常是 1000 chown -R 1000:1000 /opt/n8n上面这两步很多人会跳过,结果容器启动时报权限错误。n8n 官方镜像默认用非 root 用户跑,如果你挂载的宿主机目录属主是 root,容器内写不进去,日志里会看到 EACCES 报错。
接下来写 docker-compose.yml:
version: "3.8" services: n8n: image: n8nio/n8n:latest container_name: n8n restart: unless-stopped ports: - "5678:5678" environment: - N8N_HOST=192.168.1.100 # 改成你服务器的实际 IP - N8N_PORT=5678 - N8N_PROTOCOL=http - WEBHOOK_URL=http://192.168.1.100:5678/ - GENERIC_TIMEZONE=Asia/Shanghai - N8N_SECURE_COOKIE=false # 内网 http 访问必须关掉,否则登录不了 - DB_TYPE=sqlite - DB_SQLITE_PATH=/home/node/.n8n/database.sqlite volumes: - /opt/n8n/data:/home/node/.n8n - /opt/n8n/config:/home/node/.n8n/config这里有几个参数是血泪经验换来的。N8N_HOST 和 WEBHOOK_URL 必须填你实际访问用的 IP 或域名,否则生成出来的 webhook 地址是 localhost,外部系统回调根本打不进来。N8N_SECURE_COOKIE 默认是 true,只允许 https 下设置 cookie,内网用 http 访问时登录页面会一直转圈,改成 false 才能正常登录。DB_TYPE 默认就是 sqlite,小规模用没问题,但如果你的工作流执行频率高、数据量大,建议换成 PostgreSQL,后面避坑章节会讲什么时候该换。
启动命令:
cd /opt/n8n docker compose up -d # 查看启动日志,确认没有报错 docker compose logs -f n8n看到日志里出现「Editor is now accessible via: http://192.168.1.100:5678」就说明起来了。浏览器打开这个地址,第一次会让你设置管理员账号,邮箱和密码填好就行,这个账号信息存在你挂载的 data 目录里。
2.3 npm 直装的步骤与 Node 版本管理
npm 方式第一步是确认 Node 版本。n8n 官方要求 Node.js 18.17 以上或 20.x。用 nvm 管理版本最稳妥,不会污染系统自带的 Node。
# 安装 nvm(如果还没装) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # 重新加载 shell 配置 source ~/.bashrc # 安装并使用 Node 20 nvm install 20 nvm use 20 # 确认版本 node -v # 应该输出 v20.x.xNode 版本搞定后,全局安装 n8n:
npm install -g n8n # 确认安装成功 n8n --version安装完成后不要急着直接跑 n8n start,先设置几个环境变量。npm 方式下环境变量直接 export 就行,但每次重启终端都要重设,建议写进 ~/.bashrc 或做成 systemd 服务。
export N8N_PORT=5678 export N8N_HOST=192.168.1.100 export WEBHOOK_URL=http://192.168.1.100:5678/ export GENERIC_TIMEZONE=Asia/Shanghai export N8N_SECURE_COOKIE=false # 启动 n8n startnpm 方式的数据默认存在 ~/.n8n 目录下,包括 sqlite 数据库和加密密钥。这个目录要定期备份,尤其是里面的 config 文件,它存着加密凭据用的 key,丢了的话所有已保存的凭据都解不开。
3. 工作流跑通与本地大模型接入
3.1 第一个可运行工作流:Webhook 触发加 HTTP 响应
部署起来只是第一步,能跑通一个完整工作流才算真正可用。我建议第一个测试工作流用 Webhook 节点做触发器,因为这样能同时验证 n8n 自身的服务是否正常、webhook 地址是否可达、以及响应链路是否通畅。
登录 n8n 界面后,点右上角「Add workflow」,然后点左上角的「+」号添加节点。搜索 Webhook,拖到画布上。双击节点,配置如下:
- HTTP Method:选 POST
- Path:填 test-hook
- Authentication:选 None
- Respond:选「Using Respond to Webhook Node」
保存后,再添加一个 Respond to Webhook 节点,连在 Webhook 后面。在 Respond 节点里,Response Body 填一段 JSON:
{ "status": "ok", "message": "n8n webhook is working", "timestamp": "{{ $now.toISO() }}" }这里的 {{ $now.toISO() }} 是 n8n 的内置表达式,取当前时间。配置好后点右上角激活工作流,然后用 curl 测试:
curl -X POST http://192.168.1.100:5678/webhook/test-hook \ -H "Content-Type: application/json" \ -d '{"test": "hello"}'如果返回了带 timestamp 的 JSON,说明 webhook 链路通了。这一步看着简单,但实际部署中 webhook 打不通是最常见的问题之一,原因通常是 WEBHOOK_URL 环境变量没配对,或者防火墙没放行 5678 端口。
3.2 接入 Ollama 本地大模型:HTTP Request 节点的配置细节
n8n 本身不带大模型能力,但通过 HTTP Request 节点可以调用任何兼容 OpenAI 接口的本地服务。Ollama 默认在 11434 端口提供 API,接口格式和 OpenAI 基本兼容。假设你已经在宿主机上跑起了 Ollama,并且拉了一个模型比如 deepseek-r1:
# 在宿主机上确认 Ollama 在跑 ollama list # 应该能看到已下载的模型现在回到 n8n,新建一个工作流,添加 HTTP Request 节点。配置如下:
- Method:POST
- URL:http://host.docker.internal:11434/v1/chat/completions
- Authentication:None
- Send Headers:打开,添加 Content-Type: application/json
- Send Body:打开,Body Content Type 选 JSON
Body 内容:
{ "model": "deepseek-r1", "messages": [ { "role": "user", "content": "用一句话解释什么是工作流自动化" } ], "stream": false }这里的关键点是 URL 里的 host.docker.internal。如果你用 Docker 部署 n8n,容器内的 localhost 指向容器自己,不是宿主机。Docker Desktop 在 Mac 和 Windows 上会自动解析 host.docker.internal 到宿主机,但 Linux 上默认没有这个域名。Linux 下有两个办法:一是启动容器时加 --add-host=host.docker.internal:host-gateway,二是在 docker-compose.yml 的 extra_hosts 里加一行。
extra_hosts: - "host.docker.internal:host-gateway"如果你用 npm 直装,URL 直接写 http://127.0.0.1:11434/v1/chat/completions 就行,没有这层网络隔阂。
配置好后点「Execute Node」,如果 Ollama 那边模型已经加载好,几秒内就能看到返回结果。第一次调用可能会慢,因为模型要从磁盘加载到显存,后面就快了。如果报连接超时,先在宿主机上 curl 一下 Ollama 的接口确认服务本身正常:
curl http://127.0.0.1:11434/v1/models这个命令会列出 Ollama 当前可用的模型。如果这一步就失败了,那问题在 Ollama 不在 n8n。
3.3 凭据管理:n8n credentials 的存储逻辑与备份
n8n 的凭据系统是它区别于很多自动化工具的地方。你配置的数据库密码、API Key 这些东西不会明文存在工作流 JSON 里,而是单独加密存储。加密用的密钥在 ~/.n8n/config 文件里,这个文件在首次启动时自动生成。
Docker 部署下,这个文件在你挂载的 /opt/n8n/data 目录里。npm 直装则在 ~/.n8n/config。不管哪种方式,这个文件必须备份。丢了它,所有已保存的凭据全部作废,只能重新录入。我见过有人迁移服务器时只备份了 database.sqlite,结果凭据全丢,几十个工作流挨个重配,那滋味不好受。
添加凭据的入口在左侧菜单的 Credentials 里。以添加一个 PostgreSQL 凭据为例:
- Host:填数据库地址
- Database:填库名
- User:填用户名
- Password:填密码
- Port:填 5432
保存后 n8n 会用 config 里的密钥加密这些信息再写入数据库。工作流里引用凭据时只存一个 ID,不存明文。这个设计在多人协作时尤其重要,工作流可以导出分享,但凭据不会跟着泄露。
如果你要把工作流从测试环境导到生产环境,凭据需要在新环境重新创建,因为加密密钥不同。n8n 提供了 n8n export:credentials 命令,但导出的文件在新环境导入时仍然需要相同的加密密钥才能解密。所以跨环境迁移时,要么把 config 文件一起带过去,要么在新环境重建凭据。
4. 避坑与排查:本地部署最容易翻车的五个地方
4.1 容器启动后无法访问 5678 端口
现象:docker compose up -d 显示容器在运行,但浏览器打不开 5678 端口,curl 也连不上。
原因:最常见的是宿主机防火墙没放行端口。CentOS 默认 firewalld 开启,Ubuntu 的 ufw 也可能拦着。另一个可能是 docker-compose.yml 里 ports 映射写错了,比如写成了 5678 但前面没加引号导致 YAML 解析成数字。
解决:先确认容器内部端口在监听,docker exec -it n8n netstat -tlnp | grep 5678。如果容器内正常,检查宿主机防火墙。firewalld 用 firewall-cmd --add-port=5678/tcp --permanent && firewall-cmd --reload。ufw 用 ufw allow 5678/tcp。如果是云服务器,还要检查安全组规则。
4.2 登录页面一直转圈或提示 cookie 错误
现象:打开 n8n 界面,输入账号密码后页面卡住,或者浏览器控制台报 cookie 相关错误。
原因:N8N_SECURE_COOKIE 默认为 true,只允许在 https 连接下设置 cookie。内网用 http 访问时,浏览器拒绝设置 secure cookie,导致登录状态无法保持。
解决:在环境变量里加 N8N_SECURE_COOKIE=false,重启容器。注意这个设置只在内网 http 环境下用,如果 n8n 暴露在公网,应该配 https 证书而不是关掉这个选项。
4.3 Webhook 地址生成的是 localhost 导致外部无法回调
现象:工作流里 Webhook 节点显示的 URL 是 http://localhost:5678/webhook/xxx,外部系统调用这个地址当然打不通。
原因:WEBHOOK_URL 环境变量没设置,或者设置的值不对。n8n 默认用 localhost 拼接 webhook 地址。
解决:设置 WEBHOOK_URL=http://你的实际IP:5678/,注意末尾的斜杠要带上。改完重启容器,重新打开工作流,Webhook 节点显示的地址就会更新。如果用了反向代理,WEBHOOK_URL 要填代理后的公网地址。
4.4 SQLite 数据库锁死导致工作流执行卡住
现象:工作流执行到一半卡住不动,日志里出现 database is locked 错误。
原因:SQLite 在并发写入时会有锁竞争。n8n 默认用 SQLite,当多个工作流同时执行、或者单个工作流里有大量并行节点时,写入冲突概率大增。
解决:短期可以降低并发执行数,在环境变量里设 N8N_CONCURRENCY_PRODUCTION_LIMIT=1。长期方案是换 PostgreSQL。在 docker-compose.yml 里加一个 postgres 服务,然后改 n8n 的环境变量:
environment: - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=postgres - DB_POSTGRESDB_PORT=5432 - DB_POSTGRESDB_DATABASE=n8n - DB_POSTGRESDB_USER=n8n - DB_POSTGRESDB_PASSWORD=yourpassword换数据库后原有 SQLite 里的工作流不会自动迁移,需要先导出再导入。n8n 提供了 n8n export:workflow --all --output=./backup 命令,换库后再用 import 导入。
4.5 容器内访问宿主机 Ollama 连接被拒
现象:HTTP Request 节点调用 host.docker.internal:11434 时报 ECONNREFUSED。
原因:Linux 下 Docker 默认不解析 host.docker.internal,或者 Ollama 只监听了 127.0.0.1 没有监听 0.0.0.0。
解决:先确认 Ollama 监听地址。Ollama 默认监听 127.0.0.1:11434,容器内通过 host.docker.internal 访问时,流量到达宿主机后目标地址是宿主机的 11434,如果 Ollama 只绑了 127.0.0.1 就接不到。设置 OLLAMA_HOST=0.0.0.0:11434 后重启 Ollama。然后在 docker-compose.yml 里加 extra_hosts 映射。两个都配好后再试。
5. 进阶技巧:用 n8n 串起本地大模型做批量文档处理
部署跑通之后,真正体现价值的场景是把 n8n 当调度层,把本地大模型当处理引擎,批量处理文档。我拿一个实际做过的例子来说:把一批 Markdown 文件逐个送给本地 DeepSeek 做摘要,结果写回文件。
工作流结构是这样的:Read Binary Files 节点读取目录下所有 .md 文件,Split In Batches 节点控制每次处理一个,HTTP Request 节点调用 Ollama 接口,最后用 Write Binary File 节点把摘要写回。关键在 HTTP Request 节点的 Body 里要用表达式引用当前批次的文件内容:
{ "model": "deepseek-r1", "messages": [ { "role": "system", "content": "你是一个文档摘要助手,用三句话概括用户提供的文档内容。" }, { "role": "user", "content": "{{ $json.data }}" } ], "stream": false }这里的 {{ $json.data }} 是 n8n 表达式,取当前节点输入数据里的 data 字段。Read Binary Files 节点读出来的文件内容默认在 data 字段里,但如果是二进制文件需要先转成文本,可以加一个 Extract from File 节点。
批量处理时有几个参数要调。Split In Batches 的 Batch Size 设成 1,因为本地大模型推理是串行的,并发发多个请求只会让显存爆掉。HTTP Request 节点的 Timeout 要调大,默认 300 秒可能不够,本地模型处理长文档时单次推理超过五分钟很正常,设成 60000 毫秒比较稳妥。另外在 HTTP Request 节点的高级选项里把「Retry on Fail」打开,重试次数设 2,间隔设 5000 毫秒,这样偶发的连接超时能自动恢复。
处理速度方面,一张 16G 显存的卡跑 7B 量化模型,每篇千字文档摘要大概 10 到 20 秒。一百篇文档就是二十分钟左右。这个速度比调云端 API 慢,但数据不出内网,而且没有按 token 计费的心理负担,适合处理内部敏感文档。
验证方法很简单:先拿三五个文件跑一遍,检查输出文件的内容是否合理。如果摘要质量不行,调整 system prompt 里的指令,比如加上「保留关键数字和结论」这类约束。如果速度太慢,换更小的模型或者用量化版本。n8n 的执行历史里能看到每个节点的耗时,哪个环节慢一目了然。
我自己的习惯是,任何批量工作流上线前先拿一个文件跑通,确认输出格式和内容都对,再放开批量。这个习惯帮我省过很多次后悔药——有一次没检查就跑了三百个文件,结果 prompt 里有个变量名写错了,三百个输出全是空摘要,只能删掉重来。希望这些经验能帮到你。
本文还有配套的精品资源,点击获取