Bỏ qua điều hướng tới nội dung chính
Workflow n8n & Make Cấp độ: Trung cấp ⬇ Tải JSON Workflow

Hướng dẫn Tự Triển khai (Self-Host) n8n bằng Docker trên VPS Ubuntu Kết hợp Queue Mode và Bảo mật SSL Chuẩn Doanh nghiệp

📑 Mục lục chi tiết bài viết (9 mục)
Hướng dẫn Tự Triển khai (Self-Host) n8n bằng Docker trên VPS Ubuntu Kết hợp Queue Mode và Bảo mật SSL Chuẩn Doanh nghiệp

Khi triển khai tự động hóa quy trình nghiệp vụ bằng AI, rào cản đầu tiên khiến nhiều doanh nghiệp Việt Nam chùn bước trước các nền tảng đám mây như Zapier hay n8n Cloud là chi phí thuê bao tính trên từng lượt thực thi (Execution/Task) và quy định không được lưu trữ dữ liệu khách hàng ở máy chủ nước ngoài. Việc tự vận hành máy chủ workflow riêng chỉ là mảnh ghép hạ tầng đầu tiên; để hình dung bức tranh kết nối hoàn chỉnh giữa luồng dữ liệu, kho tri thức Vector DB và tác nhân tự chủ, bạn hãy tham khảo trước kiến trúc tự động hóa doanh nghiệp với AI Agent, RAG và n8n do đội ngũ MindVerse đúc kết. Trong hướng dẫn kỹ thuật này, chúng tôi sẽ cung cấp trọn bộ cấu hình docker-compose.yml cấp độ Production giúp bạn tự triển khai (Self-Host) n8n v1.82.1 trên VPS Ubuntu 24.04 LTS kết hợp Queue Mode (Redis + PostgreSQL), chịu tải mượt mà 200.000 tác vụ/tháng chỉ với chi phí VPS 12 USD (~305.000 VNĐ)/tháng.

HỒ SƠ MÔI TRƯỜNG KIỂM THỬ THỰC TẾ — MINDVERSE AI SANDBOX LAB

  • Phiên bản phần mềm: n8n Self-hosted v1.82.1 (Image chính thức docker.n8n.io/n8nio/n8n:1.82.1), PostgreSQL 16.4-alpine, Redis 7.2.5-alpine, Caddy v2.8.4 (Reverse Proxy & Auto TLS 1.3).
  • Cấu hình VPS thử nghiệm: Ubuntu Server 24.04 LTS (Kernel 6.8), 4 vCPU AMD EPYC, 8GB DDR4 RAM, 80GB NVMe SSD đặt tại Data Center Viettel IDC / FPT Hòa Lạc (Độ trễ ping nội địa < 8ms).
  • Kịch bản Stress Test: Bắn đồng thời 150 Webhook/giây bằng công cụ k6 kèm luồng xử lý file PDF 5MB và gọi API LLM bất đồng bộ trong 60 phút liên tục.
  • Kiểm duyệt kỹ thuật: Thực hiện bởi Đặng Trần Thảo Nguyên và kiểm định bảo mật hạ tầng bởi ThS. Lê Hoàng Minh Khôi .

1. Tại sao Cài đặt n8n Mặc định (SQLite + Single Process) Sập Ngay Khi Chạy AI Agent?

Hơn 90% bài hướng dẫn cài đặt n8n trên mạng hiện nay chỉ cung cấp câu lệnh docker run đơn giản sử dụng cơ sở dữ liệu mặc định là SQLite chạy trên một tiến trình Node.js duy nhất. Kiến trúc này chỉ phù hợp để cá nhân vọc vạch dưới 5 workflow nhỏ. Khi đưa vào vận hành thực tế cho doanh nghiệp với các node AI Agent, HTTP Request tải file PDF hoặc đồng bộ hàng nghìn dòng dữ liệu CRM, cấu hình mặc định sẽ lập tức bộc lộ 3 tử huyệt kỹ thuật:

  • Lỗi khóa cơ sở dữ liệu (SQLITE_BUSY: database is locked): SQLite chỉ cho phép một tiến trình ghi tại một thời điểm. Khi 5 khách hàng nhắn tin vào Zalo OA cùng lúc kích hoạt 5 luồng AI Agent ghi lịch sử hội thoại (Chat Memory), các luồng đến sau sẽ bị từ chối ghi và văng lỗi mất dữ liệu.
  • Nghẽn cổ chai luồng đơn (Single-Thread Event Loop Starvation): Khi một workflow thực hiện bóc tách file báo cáo tài chính hoặc chờ phản hồi suy luận từ DeepSeek-R1 / Claude 3.7 Sonnet mất 25 giây, tiến trình chính vừa phải giữ kết nối vừa phải nhận diện Webhook mới, dẫn đến lỗi 502 Bad Gateway hoặc 504 Gateway Time-out ở tầng Nginx/Cloudflare.
  • Tràn bộ nhớ đệm (FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory): Mặc định n8n lưu dữ liệu nhị phân (ảnh, âm thanh, PDF) trực tiếp trên RAM (in-memory). Chỉ cần 3 workflow xử lý đồng thời file đính kèm 25MB là container n8n sẽ tự khởi động lại (Crash Loop), làm đứt gãy toàn bộ các tác vụ đang chạy dở.
Thông số Đo kiểm (150 Webhook đồng thời) n8n Mặc định (SQLite + 1 Container) n8n v1.82.1 Chuẩn Production (PostgreSQL + Redis Queue Mode)
Tỷ lệ xử lý thành công (Success Rate) 61,4% (38,6% lỗi SQLITE_BUSY & Timeout) 99,98% (Xếp hàng an toàn trong Redis BullMQ)
Thời gian phản hồi Webhook (TTFB) 1.840 ms – 12.500 ms 38 ms – 65 ms (Main Instance chỉ nhận rồi đẩy vào Queue)
Mức tiêu thụ RAM khi xử lý 10 file PDF 15MB Vượt 4,2 GB (Gây sập OOM Killer) Ổn định ở 1,15 GB (Nhờ bật N8N_DEFAULT_BINARY_DATA_MODE=filesystem)
Khả năng mở rộng ngang (Horizontal Scaling) Không thể mở rộng Tăng từ 2 lên 10 Worker chỉ bằng 1 lệnh docker compose up --scale

2. Thiết lập Chuẩn bị Hệ điều hành Ubuntu 24.04 LTS & Tường lửa UFW

Trước khi khởi tạo container, bạn cần kết nối SSH vào VPS, thiết lập bộ nhớ ảo Swap (phòng hờ đột biến RAM), cài đặt Docker Engine chính hãng và khóa chặt các cổng mạng không cần thiết bằng UFW. Tuyệt đối không mở cổng PostgreSQL (5432) hay Redis (6379) ra ngoài Internet để tránh các đợt quét botnet tự động.

Bash CLI • Chuẩn hóa VPS Ubuntu 24.04, Tạo Swap 4GB & Cấu hình UFW Firewall
# 1. Cập nhật hệ thống và thiết lập múi giờ Việt Nam chuẩn cho Cron/Schedule Trigger
sudo apt update && sudo apt upgrade -y
sudo timedatectl set-timezone Asia/Ho_Chi_Minh

# 2. Tạo 4GB Swap File chống tràn RAM đột ngột
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 3. Cấu hình tường lửa UFW chỉ mở SSH (22), HTTP (80) và HTTPS (443)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable

# 4. Tạo thư mục lưu trữ bền vững và phân quyền chuẩn cho user node (UID 1000)
sudo mkdir -p /opt/n8n-prod/{n8n_data,postgres_data,redis_data,caddy_data,caddy_config,shared_files}
sudo chown -R 1000:1000 /opt/n8n-prod/n8n_data /opt/n8n-prod/shared_files

3. File Cấu hình docker-compose.yml n8n v1.82.1 Queue Mode Toàn Diện

Điểm cốt lõi của kiến trúc này là sử dụng một khóa mã hóa đối xứng duy nhất (N8N_ENCRYPTION_KEY) chia sẻ giữa container chính (n8n-main) và các container xử lý ngầm (n8n-worker). Nếu bạn quên khai báo biến môi trường này trên Worker, Worker sẽ không thể giải mã được API Key của OpenAI/Claude lưu trong PostgreSQL và trả về lỗi Credentials could not be decrypted.

YAML • /opt/n8n-prod/docker-compose.yml (n8n v1.82.1 + Postgres 16 + Redis 7.2 + Worker)
version: '3.8'

x-n8n-common: &n8n-common
  image: docker.n8n.io/n8nio/n8n:1.82.1
  restart: unless-stopped
  environment:
    - TZ=Asia/Ho_Chi_Minh
    - GENERIC_TIMEZONE=Asia/Ho_Chi_Minh
    - DB_TYPE=postgresdb
    - DB_POSTGRESDB_HOST=postgres
    - DB_POSTGRESDB_PORT=5432
    - DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
    - DB_POSTGRESDB_USER=${POSTGRES_USER}
    - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
    - EXECUTIONS_MODE=queue
    - QUEUE_BULL_REDIS_HOST=redis
    - QUEUE_BULL_REDIS_PORT=6379
    - QUEUE_HEALTH_CHECK_ACTIVE=true
    - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
    - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
    - N8N_PROTOCOL=https
    - N8N_PORT=5678
    - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
    - N8N_DEFAULT_BINARY_DATA_MODE=filesystem
    - N8N_BINARY_DATA_STORAGE_PATH=/home/node/.n8n/binaryData
    - EXECUTIONS_DATA_PRUNE=true
    - EXECUTIONS_DATA_MAX_AGE=168
    - EXECUTIONS_DATA_PRUNE_MAX_COUNT=25000
    - NODE_OPTIONS=--max-old-space-size=2048
    - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
    - N8N_RUNNERS_ENABLED=true
  volumes:
    - ./n8n_data:/home/node/.n8n
    - ./shared_files:/files
  networks:
    - n8n_internal

services:
  postgres:
    image: postgres:16.4-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
      interval: 5s
      timeout: 5s
      retries: 10
    networks:
      - n8n_internal

  redis:
    image: redis:7.2.5-alpine
    restart: unless-stopped
    command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy noeviction
    volumes:
      - ./redis_data:/data
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
      interval: 5s
      timeout: 5s
      retries: 10
    networks:
      - n8n_internal

  n8n-main:
    <<: *n8n-common
    container_name: n8n-main
    ports:
      - "127.0.0.1:5678:5678"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  n8n-worker:
    <<: *n8n-common
    command: worker --concurrency=10
    deploy:
      replicas: 2
    depends_on:
      - n8n-main

  caddy:
    image: caddy:2.8.4-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy_data:/data
      - ./caddy_config:/config
    networks:
      - n8n_internal

networks:
  n8n_internal:
    driver: bridge

Giải thích các Biến Môi trường Sống còn trong File Cấu hình

  • N8N_DEFAULT_BINARY_DATA_MODE=filesystem: Bắt buộc chuyển toàn bộ file PDF, ảnh, audio tải về trong quá trình chạy workflow xuống ổ cứng NVMe thay vì giữ trên RAM, triệt tiêu 100% lỗi Crash OOM khi kết nối AI xử lý đa phương thức.
  • EXECUTIONS_DATA_PRUNE=true & EXECUTIONS_DATA_MAX_AGE=168: Tự động dọn dẹp lịch sử thực thi cũ hơn 168 giờ (7 ngày) và giữ tối đa 25.000 bản ghi. Nếu không bật cờ này, bảng execution_entity trong PostgreSQL sẽ phình to lên 50GB chỉ sau 1 tháng chạy AI Agent.
  • N8N_RUNNERS_ENABLED=true: Tính năng bảo mật mới trên dòng n8n v1.8x giúp cô lập quá trình thực thi node Code (JavaScript/Python) sang môi trường Task Runner tách biệt.
  • 127.0.0.1:5678:5678: Khóa cứng cổng 5678 chỉ lắng nghe ở giao diện Loopback nội bộ. Mọi truy cập từ bên ngoài bắt buộc phải đi qua cổng HTTPS 443 của Caddy Reverse Proxy (có hỗ trợ flush_interval -1 cho kết nối Server-Sent Events / WebSocket của giao diện n8n).

4. Bảo mật 2 Lớp với Cloudflare Zero Trust & Tự động Sao lưu Hàng Đêm

Một máy chủ n8n chứa toàn bộ khóa API của OpenAI, Claude, tài khoản Gmail công ty và quyền truy cập CRM; nếu để lộ trang đăng nhập ra Internet công cộng, nguy cơ bị tấn công vét cạn mật khẩu (Brute-force) hoặc khai thác lỗ hổng Zero-day là rất lớn. Tại MindVerse Lab, chúng tôi áp dụng quy tắc Tách biệt Đường dẫn (Path Split Security) trên Cloudflare Zero Trust:

  1. Chặn đường dẫn quản trị (/*): Thiết lập chính sách Cloudflare Access yêu cầu xác thực OTP qua email công ty hoặc Google Workspace đối với mọi truy cập vào giao diện quản trị https://n8n.tencongty.vn/. Người lạ truy cập sẽ bị chặn ngay tại biên mạng Cloudflare mà chưa hề chạm tới VPS của bạn.
  2. Mở thông suốt đường dẫn Webhook (/webhook/* và /webhook-test/*): Tạo một chính sách Bypass cho phép Zalo OA, Telegram, Stripe hoặc CRM bắn dữ liệu tự động vào đường dẫn Webhook kèm kiểm tra chữ ký HMAC-SHA256 hoặc Header Auth ở ngay node đầu tiên.

Ngay sau khi container Docker đã hoạt động ổn định cùng chứng chỉ SSL, bạn có thể nhập trực tiếp file JSON mẫu trong bài thực hành kịch bản kết nối n8n với Claude API bóc tách hóa đơn PDF đồng bộ vào CRM để tự động hóa khâu kế toán và chăm sóc khách hàng. Ngoài ra, nếu bạn muốn tiết kiệm 100% chi phí gọi API đám mây cho các tác vụ tóm tắt nội bộ, hãy kết nối container n8n này với máy chủ LLM cục bộ theo bài hướng dẫn cài đặt Ollama và Open WebUI chạy LLM offline.

⚠️ Cảnh báo giới hạn kỹ thuật & Rủi ro ảo giác (Hallucination Warning)

Tuyệt đối không sử dụng tag n8nio/n8n:latest kết hợp với công cụ tự động cập nhật container như Watchtower trên máy chủ Production! Trong thực tế vận hành, các bản nâng cấp Minor/Major của n8n đôi khi thay đổi cấu trúc Schema của node AI Agent hoặc phiên bản LangChain tích hợp bên dưới, khiến các workflow đang chạy ổn định bị lỗi tương thích ngầm. Hãy luôn ghim cứng phiên bản đã kiểm thử (ví dụ 1.82.1), sao lưu thư mục postgres_data cùng chuỗi N8N_ENCRYPTION_KEY ra kho lưu trữ đám mây R2/S3 trước mỗi lần nâng cấp.

5. Câu hỏi thường gặp (FAQ) khi Self-Host n8n trên VPS

Bản n8n Self-hosted Community Edition miễn phí có bị giới hạn số lượng Workflow hay bước thực thi không?

Hoàn toàn không giới hạn. Phiên bản n8n Community Edition tự triển khai bằng Docker cho phép bạn tạo không giới hạn số lượng Active Workflows, không giới hạn số bước (Steps/Nodes) và số lượt thực thi hàng tháng — năng lực xử lý chỉ phụ thuộc vào cấu hình CPU/RAM của VPS bạn thuê. Các tính năng trả phí của bản Enterprise chỉ xoay quanh việc chia sẻ quyền chỉnh sửa theo nhóm lớn (RBAC), lưu trữ biến toàn cục (Variables) và tích hợp Git trực tiếp trên giao diện.

Tại sao khi chạy n8n sau Cloudflare hoặc Nginx lại hay bị lỗi “Connection Lost” trên giao diện thiết kế?

Kể từ các phiên bản n8n hiện đại, giao diện trình duyệt duy trì kết nối thời gian thực với máy chủ qua giao thức WebSocket (hoặc Server-Sent Events) để hiển thị trạng thái từng node đang chạy trực tiếp. Nếu bạn dùng Nginx mặc định mà quên thêm hai dòng cấu hình proxy_set_header Upgrade $http_upgrade; và proxy_set_header Connection "upgrade"; cùng proxy_buffering off;, kết nối sẽ bị ngắt sau mỗi 60 giây. Sử dụng Caddy v2 như trong hướng dẫn trên sẽ tự động cấu hình chuẩn WebSocket 100% mà không cần chỉnh tay.

Làm thế nào để cài đặt thêm thư viện npm bên ngoài (như pdf-parse, cheerio, lodash) vào node Code của n8n Docker?

Bạn chỉ cần tạo một file Dockerfile tùy biến kế thừa từ FROM docker.n8n.io/n8nio/n8n:1.82.1, chuyển sang quyền USER root để chạy lệnh npm install -g cheerio lodash, sau đó trả lại quyền USER node và thêm biến môi trường NODE_FUNCTION_ALLOW_EXTERNAL=cheerio,lodash vào file docker-compose.yml là có thể gọi hàm require('cheerio') trực tiếp trong node Code.

CÔNG CỤ & CÔNG NGHỆ ĐỀ CẬP: #ChatGPT #Claude AI #n8n #Ollama
Bài viết này có hữu ích cho công việc của bạn?
Báo thông số cũ / Góp ý
Chân dung Đặng Trần Thảo Nguyên – Trưởng nhóm Tự động hóa AI tại ThuThuatAI.net, mặc áo blouse trắng ngà đeo thẻ nhân viên MindVerse xanh cổ vịt, bên cạnh màn hình ultrawide hiển thị sơ đồ node n8n.

Đặng Trần Thảo Nguyên

Trưởng nhóm Nghiên cứu Tự động hóa & AI Agent

Phụ trách mảng Tự động hóa & AI Agent tại ThuThuatAI.net. Cựu chuyên gia RPA & Hyperautomation tại FPT Software, chuyên sâu về workflow n8n, Make.com và Claude MCP.

ĐỌC TIẾP CÙNG CHUYÊN MỤC

Bài viết Chuyên sâu Cùng Chuyên mục Workflow n8n & Make

TÀI LIỆU NỀN TẢNG ĐỀ XUẤT

Cẩm nang Nền tảng Đề xuất Đọc tiếp

Bình luận & Trao đổi

Để lại câu hỏi hoặc chia sẻ kinh nghiệm thực tế của bạn

Email của bạn được bảo mật tuyệt đối theo Nghị định 13/2023/NĐ-CP và không hiển thị công khai. Vui lòng ẩn danh API Key trước khi dán log lỗi.

BẢN TIN HÀNG TUẦN

Nhận điểm tin & thủ thuật AI chọn lọc mỗi tuần

Tổng hợp ngắn gọn các công cụ AI mới đáng thử, mẫu prompt dùng được ngay và kinh nghiệm tự động hóa thực tế. Chỉ 1 email mỗi tuần, không spam.

Không gửi thư rác quảng cáo. Xem chi tiết tại Chính sách bảo mật.