n8n là nền tảng tự động hóa quy trình dạng kéo thả, tương tự Zapier hay Make nhưng có thể tự host. Khi cài n8n trên VPS, bạn giữ toàn quyền dữ liệu, không bị giới hạn số lần chạy theo gói và có thể kết nối với dịch vụ nội bộ. Bài này hướng dẫn cài n8n bằng Docker Compose trên Ubuntu, đặt sau Nginx với SSL Let's Encrypt, kèm cách giữ dữ liệu và cập nhật an toàn.

Hướng dẫn dựa trên tài liệu chính thức của n8n tại thời điểm 24/10/2026. Khi đó bản ổn định được docs ghi là 2.44.6.

Chuẩn bị VPS và tên miền

Yêu cầu VPS

Tài liệu n8n không đưa ra con số cấu hình tối thiểu cố định. Mức tài nguyên cần dùng phụ thuộc vào số workflow, tần suất trigger, dung lượng dữ liệu mỗi lần chạy và các node nặng như xử lý file hay gọi AI. Một số gợi ý thực tế:

  • Hệ điều hành: Ubuntu 22.04 hoặc 24.04 LTS, có quyền sudo.
  • RAM: Canh Deal khuyên bắt đầu từ 2GB RAM cho nhu cầu cá nhân hoặc nhóm nhỏ, và nên tạo swap để tránh bị kill tiến trình khi chạy workflow lớn.
  • Ổ cứng: SSD/NVMe. Lịch sử execution lưu trong cơ sở dữ liệu sẽ tăng dần theo thời gian.
  • Tên miền: một subdomain như n8n.tenmien.vn, đã có bản ghi A trỏ về IP VPS.

Nếu chưa có máy chủ, Canh Deal đề xuất VPS giá rẻ TDCloud từ 55.000đ/tháng cho gói 1 vCPU/1GB/20GB, hoặc gói VPS SALE 2-2 giá 599.000đ/năm phù hợp hơn với n8n (giá tham khảo ngày 24/10/2026, chưa gồm VAT).

Cài Docker và bảo mật cơ bản

Trước khi cài n8n, hãy thực hiện các bước bảo mật VPS Ubuntu trong 30 phút đầu: tạo user sudo, bật tường lửa UFW, mở cổng 22, 80, 443. Sau đó cài Docker Engine và plugin Compose từ kho chính thức của Docker. Chi tiết từng lệnh có trong bài cài Docker Compose trên Ubuntu với Nginx reverse proxy. Kiểm tra nhanh:

docker --version
docker compose version

Tạo thư mục dự án và file .env

Tạo một thư mục riêng cho n8n. Thư mục local-files dùng để chia sẻ file giữa máy chủ và container. Tài liệu n8n khuyên tạo trước để thư mục có đúng quyền sở hữu.

mkdir -p ~/n8n/local-files
cd ~/n8n
openssl rand -hex 32

Lệnh openssl sinh một chuỗi ngẫu nhiên để làm khóa mã hóa. Tạo file .env:

DOMAIN_NAME=tenmien.vn
SUBDOMAIN=n8n
GENERIC_TIMEZONE=Asia/Ho_Chi_Minh
N8N_ENCRYPTION_KEY=chuoi_ngau_nhien_vua_tao

Đặt quyền chỉ chủ sở hữu được đọc, vì file này chứa khóa bí mật:

chmod 600 .env

File compose.yaml cho n8n

Tài liệu n8n dùng Traefik làm reverse proxy. Ở đây chúng ta dùng Nginx cài trên máy chủ, nên chỉ cần dịch vụ n8n. Điểm quan trọng là cổng 5678 chỉ mở trên 127.0.0.1. Docker có thể ghi đè quy tắc UFW khi publish cổng, nên nếu publish ra mọi địa chỉ thì n8n có thể bị truy cập trực tiếp qua HTTP mà không đi qua Nginx.

services:
  n8n:
    image: n8nio/n8n:2.44.6
    restart: always
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - N8N_WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - N8N_PROXY_HOPS=1
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
      - TZ=${GENERIC_TIMEZONE}
      - N8N_RESTRICT_FILE_ACCESS_TO=/files
    volumes:
      - n8n_data:/home/node/.n8n
      - ./local-files:/files

volumes:
  n8n_data:

Nên ghi rõ phiên bản ở tag image thay vì để trống (tương đương latest). Khi đó bạn chủ động quyết định lúc nào nâng cấp.

Ý nghĩa các biến môi trường

BiếnTác dụng
N8N_HOST, N8N_PORT, N8N_PROTOCOLHost, cổng và giao thức n8n dùng để tạo URL
N8N_WEBHOOK_URLURL công khai cho webhook. Bắt buộc khi chạy sau reverse proxy. Thay cho WEBHOOK_URL, biến cũ bị deprecated từ bản 2.35.0
N8N_PROXY_HOPSSố proxy phía trước n8n. Đặt 1 khi chỉ có Nginx
N8N_ENCRYPTION_KEYKhóa mã hóa credentials trước khi lưu vào cơ sở dữ liệu
GENERIC_TIMEZONE, TZMúi giờ cho node Schedule/Cron và hệ thống
N8N_RESTRICT_FILE_ACCESS_TOGiới hạn các node đọc/ghi file chỉ trong thư mục /files

Nếu không đặt N8N_WEBHOOK_URL, n8n sẽ ghép URL từ protocol, host và cổng 5678. Webhook đăng ký với dịch vụ bên ngoài sẽ sai địa chỉ.

Khởi động container và xem log:

docker compose up -d
docker compose logs -f n8n

Cấu hình Nginx reverse proxy và SSL

Trình soạn thảo n8n dùng WebSocket để cập nhật trạng thái theo thời gian thực. Nếu Nginx không chuyển tiếp header Upgrade, giao diện có thể báo "Connection lost". Tài liệu n8n cũng yêu cầu proxy cuối cùng gửi kèm các header X-Forwarded-For, X-Forwarded-Host và X-Forwarded-Proto.

Tạo file /etc/nginx/sites-available/n8n:

server {
    listen 80;
    server_name n8n.tenmien.vn;

    location / {
        proxy_pass http://127.0.0.1:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_read_timeout 300s;
        client_max_body_size 50m;
    }
}

Kích hoạt site và cấp chứng chỉ bằng Certbot:

sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d n8n.tenmien.vn

Certbot sẽ tự thêm khối listen 443 ssl và chuyển hướng HTTP sang HTTPS. Cách cài Certbot và kiểm tra tự gia hạn có trong bài cài SSL Let's Encrypt bằng Certbot cho Nginx. Sau đó truy cập https://n8n.tenmien.vn và tạo tài khoản owner đầu tiên. Hãy làm bước này ngay, vì ai mở trang trước sẽ là người tạo tài khoản quản trị.

Giữ dữ liệu n8n an toàn

Dữ liệu nằm ở đâu

Volume n8n_data gắn vào /home/node/.n8n trong container. Thư mục này chứa cơ sở dữ liệu SQLite (workflow, credentials, lịch sử chạy), file cấu hình có khóa mã hóa, log và dữ liệu source control. Xóa container không mất dữ liệu, nhưng xóa volume thì mất hết. Vì vậy tránh chạy docker compose down -v.

Docker Compose thêm tên dự án vào trước tên volume. Xem tên thật bằng:

docker volume ls | grep n8n

Sao lưu volume

Dừng n8n trong lúc sao lưu để file SQLite không bị ghi dở. Thay n8n_n8n_data bằng tên volume bạn thấy ở lệnh trên:

cd ~/n8n
docker compose stop
docker run --rm -v n8n_n8n_data:/data -v "$PWD":/backup alpine \
  tar czf /backup/n8n-data-$(date +%F).tar.gz -C /data .
docker compose start

Ngoài ra, n8n có lệnh CLI để xuất workflow và credentials ra file JSON, tiện khi chuyển máy chủ:

docker compose exec n8n n8n export:workflow --all --output=/files/workflows.json
docker compose exec n8n n8n export:credentials --all --output=/files/credentials.json

File credentials xuất theo cách trên vẫn ở dạng mã hóa, nên cần đúng N8N_ENCRYPTION_KEY để nhập lại. Hãy đưa file sao lưu ra khỏi VPS bằng rclone và đặt lịch bằng cron, như hướng dẫn sao lưu VPS tự động bằng rsync, cron và rclone.

Khi nào dùng PostgreSQL

SQLite là mặc định và đủ cho phần lớn nhu cầu cá nhân. Khi số execution lớn hoặc muốn chạy queue mode với nhiều worker, n8n hỗ trợ PostgreSQL qua DB_TYPE=postgresdb và nhóm biến DB_POSTGRESDB_*. Kể cả khi dùng PostgreSQL, tài liệu n8n vẫn khuyên giữ volume cho /home/node/.n8n vì thư mục này còn chứa khóa mã hóa và log.

Cập nhật n8n

n8n phát hành bản mới khá thường xuyên. Quy trình cập nhật an toàn:

  1. Đọc release notes của n8n để biết có thay đổi phá vỡ tương thích (breaking changes) hay không.
  2. Sao lưu volume như hướng dẫn ở trên.
  3. Sửa tag image trong compose.yaml sang phiên bản mới.
  4. Chạy các lệnh cập nhật theo tài liệu n8n.
cd ~/n8n
docker compose pull
docker compose down
docker compose up -d
docker compose logs -f n8n

Lệnh down không có -v nên volume dữ liệu được giữ nguyên. Khi khởi động, n8n tự chạy migration cơ sở dữ liệu nếu cần. Nếu gặp lỗi, quay về tag cũ và khôi phục bản sao lưu volume. Sau khi chắc chắn mọi thứ ổn, có thể dọn image cũ bằng docker image prune.

Lỗi thường gặp

  • Giao diện báo "Connection lost": thiếu header Upgrade và Connection trong Nginx.
  • URL webhook hiện cổng 5678 hoặc http: chưa đặt N8N_WEBHOOK_URL hoặc N8N_PROTOCOL=https.
  • Lỗi quyền ghi thư mục: nếu dùng bind mount thay cho named volume, thư mục trên máy chủ cần thuộc user có UID 1000 (user node trong image).
  • Node Schedule chạy sai giờ: kiểm tra GENERIC_TIMEZONE và múi giờ trong phần cài đặt của từng workflow.

Nguồn tham khảo