返回首页

N8N自托管完全指南:从安装到自动化工作流

N8N自托管完全指南:从安装到自动化工作流

TL;DR: n8n是开源的Zapier替代品,支持400+集成,自托管无执行次数限制。本文覆盖一键部署、反向代理配置、以及10个可直接复用的生产级工作流模板。实际测试显示,n8n在4GB内存VPS上可稳定处理日均5万次工作流执行。

为什么选择n8n而不是Zapier/Make

特性 n8n (自托管) Zapier Make
月费 $0 (自托管) $29.99起 $10.59起
执行次数限制 无限制 100次/月(免费) 1000次/月
集成数量 400+ 6000+ 1700+
自定义代码 /Python 仅JS 有限
数据主权 完全控制 第三方托管 第三方托管
可视化编辑器
自定义节点 ✅ 开源

安装:3种部署方式

方式一:Docker Compose(推荐)

创建项目目录:

mkdir -p ~/n8n && cd ~/n8n

创建 docker-compose.yml

version: '3.8'

services:
  n8n:
    : docker.n8n.io/n8nio/n8n:latest
    restart: always
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=n8n.yourdomain.com
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://n8n.yourdomain.com/
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=your-strong-password
      - GENERIC_TIMEZONE=Asia/Shanghai
      - TZ=Asia/Shanghai
      # 使用SQLite(小规模)或PostgreSQL
      - DB_TYPE=sqlite
      - DB_SQLITE_VACUUM_ON_STARTUP=true
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:

启动服务:

docker compose up -d
docker compose logs -f n8n  # 观察启动日志

方式二:Docker + PostgreSQL(生产推荐)

version: '3.8'

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:latest
    restart: always
    ports:
      - "5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=n8n_secure_pw_2026
      - N8N_HOST=n8n.yourdomain.com
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.yourdomain.com/
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started

  postgres:
    image: postgres:16-alpine
    restart: always
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: n8n_secure_pw_2026
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: always
    volumes:
      - redis_data:/data

volumes:
  n8n_data:
  postgres_data:
  redis_data:

方式三:全局安装(开发环境)

# 需要 18+
npm install n8n -g
n8n start

反向代理配置

server {
    listen 443 ssl http2;
    server_name n8n.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://localhost:5678;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket支持(n8n需要)
        proxy_http_version 1.1;
        proxy_set_header  $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # 超时设置(长时间运行的工作流)
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

10个实战工作流模板

工作流1: PR通知到Slack/Discord

触发条件:GitHub Webhook(PR创建/合并)

{
  "nodes": [
    {
      "name": "GitHub Trigger",
      "type": "n8n-nodes-base.githubTrigger",
      "parameters": {
        "events": ["pull_request"],
        "owner": "{{$json.repository.owner.login}}",
        "repository": "{{$json.repository.name}}"
      }
    },
    {
      "name": "判断PR动作",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.action}}",
              "operation": "equal",
              "value2": "opened"
            }
          ]
        }
      }
    },
    {
      "name": "发送通知",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#dev-notifications",
        "text": "新PR: {{$json.pull_request.title}}\n作者: {{$json.pull_request.user.login}}\n链接: {{$json.pull_request.html_url}}"
      }
    }
  ]
}

工作流2:RSS到Newsletter自动同步

每天定时抓取RSS源,生成Newsletter草稿:

// 在Function节点中处理RSS数据
const items = $input.all();
const today =  Date().toISOString().split('T')[0];

const  = `
<h2>今日技术精选 - ${today}</h2>
<ul>
${items.map(item => `
  <li>
    <a href="${item.json.link}">${item.json.title}</a>
    <p>${item.json.contentSnippet?.substring(0, 150)}...</p>
  </li>
`).join('')}
</ul>
`;

return [{ json: { subject: `技术日报 ${today}`, html } }];

工作流3:数据库定时备份到S3

# 通过Execute Command节点
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="/tmp/backup_${DATE}.sql.gz"

# 备份PostgreSQL
PGPASSWORD=$DB_PASS pg_dump -h $DB_HOST -U $DB_USER $DB_NAME | gzip > $BACKUP_FILE

# 上传到S3
aws s3 cp $BACKUP_FILE s3://my-backups/db/$DATE.sql.gz --storage-class GLACIER

# 清理
rm $BACKUP_FILE
echo " completed: $DATE"

工作流4:网站健康监控

{
  "name": "网站健康监控",
  "nodes": [
    {
      "name": "每5分钟触发",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": { "interval": [{ "field": "minutes", "minutesInterval": 5 }] }
      }
    },
    {
      "name": "HTTP请求",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://yourwebsite.com",
        "options": { "timeout": 10000, "redirect": { "redirect": { "followRedirects": true } } }
      }
    },
    {
      "name": "检查状态码",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "number": [{ "value1": "={{$json.statusCode}}", "operation": "notEqual", "value2": 200 }]
        }
      }
    },
    {
      "name": "发送告警",
      "type": "n8n-nodes-base.emailSend",
      "parameters": {
        "toEmail": "[email protected]",
        "subject": "⚠️ 网站异常: {{$json.statusCode}}",
        "text": "网站 yourwebsite.com 返回状态码 {{$json.statusCode}},请立即检查。"
      }
    }
  ]
}

工作流5:表单提交到CRM同步

当Typeform收到新提交时,自动在HubSpot创建联系人:

// Transform节点
const submission = $input.first().json;

return [{
  json: {
    properties: {
      email: submission.answers.find(a => a.field.ref === 'email')?.email,
      firstname: submission.answers.find(a => a.field.ref === 'name')?.text?.split(' ')[0],
      lastname: submission.answers.find(a => a.field.ref === 'name')?.text?.split(' ').slice(1).join(' '),
      company: submission.answers.find(a => a.field.ref === 'company')?.text,
      hs_lead_status: 'NEW'
    }
  }
}];

工作流6:图片自动压缩和水印

# 使用ImageMagick处理上传的图片
convert input.jpg -resize '1920x1920>' -quality 85 -strip resized.jpg

# 添加文字水印
convert resized.jpg \
  -gravity southeast \
  -fill 'rgba(255,255,255,0.5)' \
  -pointsize 24 \
  -annotate +20+20 '© yoursite.com' \
  output.jpg

工作流7:错误日志聚合和告警

// 聚合过去1小时的错误日志
const logs = $input.all();
const errorCounts = {};

logs.forEach(log => {
  const key = log.json.error_type || 'Unknown';
  errorCounts[key] = (errorCounts[key] || 0) + 1;
});

const summary = Object.entries(errorCounts)
  .sort(([,a], [,b]) => b - a)
  .map(([type, count]) => `${type}: ${count}次`)
  .join('\n');

return [{
  json: {
    subject: `错误日志汇总 - ${new Date().toLocaleString('zh-')}`,
    body: `过去1小时共 ${logs.length} 个错误:\n\n${summary}`,
    : Object.values(errorCounts).some(c => c > 50)
  }
}];

工作流8:客户满意度自动评分

# 通过n8n的节点(需要配置Python环境)
import json

 = _input.first().json

# 简单情感分析
positive_words = ['好', '棒', '优秀', '满意', '喜欢', '推荐', 'excellent', 'great', 'love']
negative_words = ['差', '烂', '失望', '垃圾', '退款', 'terrible', 'awful', 'refund']

text = data.get('feedback', '').lower()
pos_count = sum(1 for w in positive_words if w in text)
neg_count = sum(1 for w in negative_words if w in text)

score = 3  # 默认中性
if pos_count > neg_count:
    score = min(5, 3 + pos_count - neg_count)
elif neg_count > pos_count:
    score = max(1, 3 - (neg_count - pos_count))

return [{"json": {"score": score, "feedback": text, "sentiment": "positive" if score > 3 else "negative" if score < 3 else "neutral"}}]

工作流9:多云存储文件同步

// 同步S3到Cloudflare R3
const AWS = require('aws-sdk');

// 源(S3兼容存储)
const source = new AWS.S3({
  endpoint: 'https://s3.amazonaws.com',
  accessKeyId: env.S3_ACCESS_KEY,
  secretAccessKey: env.S3_SECRET_KEY
});

// 目标(R3)
const target = new AWS.S3({
  endpoint: 'https://<account-id>.r2.cloudflarestorage.com',
  accessKeyId: env.R3_ACCESS_KEY,
  secretAccessKey: env.R3_SECRET_KEY,
  signatureVersion: ''
});

const bucket = 'my-bucket';
const objects = await source.listObjectsV2({ Bucket: bucket }).promise();

for (const obj of objects.Contents) {
  const data = await source.getObject({ Bucket: bucket, Key: obj.Key }).promise();
  await target.putObject({
    Bucket: 'r3-backup',
    Key: obj.Key,
    Body: data.Body,
    ContentType: data.ContentType
  }).promise();
}

return [{ json: { synced: objects.Contents.length, timestamp: new Date().toISOString() } }];

工作流10:智能客服路由

// 根据消息内容自动分类并路由到对应团队
const message = $input.first().json;

const categories = {
  billing: ['账单', '付费', '退款', '订阅', 'billing', 'payment', 'refund'],
  technical: ['报错', 'bug', '无法访问', '崩溃', 'error', 'crash', 'down'],
  sales: ['报价', '企业版', '定制', '', '', 'custom'],
  general: ['咨询', '了解', 'how', 'what', 'question']
};

let category = 'general';
let confidence = 0.5;

const text = message.text.toLowerCase();
for (const [cat, keywords] of Object.entries(categories)) {
  const matches = keywords.filter(k => text.includes(k)).length;
  if (matches > confidence) {
    category = cat;
    confidence = Math.min(matches / keywords.length + 0.3, 1);
  }
}

const routing = {
  billing: { channel: '#-support', priority: 'high' },
  technical: { channel: '#tech-support', priority: 'high' },
  sales: { channel: '#sales-team', priority: 'medium' },
  general: { channel: '#general-support', priority: 'low' }
};

return [{
  json: {
    ...message,
    category,
    confidence,
    routing: routing[category],
    autoReply: category === 'billing' ? '您的账单问题已收到,我们的财务团队将在2小时内回复。' : null
  }
}];

性能优化建议

执行模式配置

# 环境变量配置
EXECUTIONS_MODE=queue          # 使用队列模式
QUEUE_BULL_REDIS_HOST=redis    # Redis用于队列
EXECUTIONS_DATA_PRUNE=true     # 自动清理旧执行数据
EXECUTIONS_DATA_MAX_AGE=168    # 保留7天执行数据
N8N_PAYLOAD_SIZE_MAX=16        # 最大载荷16MB

监控n8n健康状态

# 健康检查端点
curl http://localhost:5678/healthz

# Prometheus指标(需要启用)
curl http://localhost:5678/metrics

安全加固清单

# 1. 启用HTTPS(必须)
# 2. 设置强密码
N8N_BASIC_AUTH_PASSWORD=$(openssl rand -base64 32)

# 3. 限制IP访问(Nginx层)
allow 10.0.0.0/8;
allow 172.16.0.0/12;
deny all;

# 4. 启用2FA
N8N_USER_MANAGEMENT_DISABLED=false

# 5. 定期更新
docker compose pull && docker compose up -d

常见问题排查

问题 原因 解决方案
Webhook无法接收 反向代理未配置WebSocket 添加WebSocket升级头
执行超时 默认30秒限制 设置EXECUTIONS_TIMEOUT=300
内存溢出 大数据量处理 使用流式处理,分批执行
定时任务不执行 时区配置错误 设置GENERIC_TIMEZONE=Asia/Shanghai
数据库锁定 SQLite并发限制 切换到PostgreSQL

n8n作为自托管自动化平台,在数据隐私和成本控制上有明显优势。对于日均执行量超过1万次的场景,建议使用PostgreSQL+Redis的生产配置,并启用队列模式进行水平扩展。

常见问题

为什么选择n8n而不是Zapier/Make

>为什么选择n8n而不是Zapier/Make 特性 n8n (自托管) Zapier Make 月费 $0 (自托管) $29.99起 $10.59起 执行次数限制 无限制 100次/月(免费) 1000次/月 集成数量 400+ 6000+ 1700+ 自定义代码 JavaScript/Python 仅JS 有限 数据主权 完全控制 第三方托管 第三方托管 可视化编辑器 ✅ ✅ ✅ 自定义节点 ✅ 开源 ❌ ❌

评论