Hướng dẫn · 19/09/2026

Hướng dẫn cài n8n bằng Docker Compose, PostgreSQL và HTTPS

n8n giúp kết nối API, webhook, lịch chạy và nhiều ứng dụng thành workflow tự động hóa. Self-host mang lại quyền kiểm soát dữ liệu và hạ tầng, nhưng cũng khiến bạn chịu trách nhiệm về secret, backup, HTTPS, cập nhật và khả năng khôi phục.

Hướng dẫn cài n8n bằng Docker Compose, PostgreSQL và HTTPS

n8n giúp kết nối API, webhook, lịch chạy và nhiều ứng dụng thành workflow tự động hóa. Self-host mang lại quyền kiểm soát dữ liệu và hạ tầng, nhưng cũng khiến bạn chịu trách nhiệm về secret, backup, HTTPS, cập nhật và khả năng khôi phục.

Hướng dẫn này triển khai một instance n8n đơn bằng Docker Compose, PostgreSQL và Nginx reverse proxy. Đây là cấu hình phù hợp cho nhóm nhỏ hoặc tải vừa; queue mode nhiều worker cần Redis và kiến trúc riêng.

Kiến trúc sẽ triển khai

  • Nginx nhận HTTPS tại automation.example.com.
  • n8n chỉ bind cổng 5678 vào localhost.
  • PostgreSQL nằm trong network nội bộ, không public port.
  • Database và thư mục /home/node/.n8n có volume bền vững.
  • Secret nằm trong file env có quyền hạn chế, không commit Git.
Backup database mà mất N8N_ENCRYPTION_KEY có thể khiến credential đã mã hóa không còn sử dụng được. Hãy bảo vệ key như dữ liệu quan trọng nhất của hệ thống.

1. Chuẩn bị máy chủ và DNS

Dùng một máy Linux được cập nhật, đã cài Docker Engine và Docker Compose plugin. Tạo record DNS cho automation.example.com trỏ tới IP máy chủ. Firewall chỉ mở SSH quản trị, HTTP và HTTPS; không mở 5432 hoặc 5678 ra Internet.

Trước khi triển khai, kiểm tra:

docker --version
docker compose version
df -h
free -h

Tách instance development và production nếu workflow có tác động thật như gửi email, tạo invoice hoặc xóa dữ liệu. Không thử node lạ trực tiếp trên production.

2. Tạo thư mục dự án

sudo mkdir -p /opt/n8n
sudo chown "$USER":"$USER" /opt/n8n
cd /opt/n8n
mkdir -p n8n_data postgres_data backups

Không đặt backup trong web root. Nếu dùng bind mount, kiểm tra UID/GID và quyền ghi của container; named volume có thể đơn giản hơn ở một số môi trường.

3. Tạo secret và file môi trường

Tạo password database và encryption key đủ dài:

openssl rand -base64 36
openssl rand -hex 32

Tạo file .env:

N8N_VERSION=2.5.5
POSTGRES_PASSWORD=replace-with-a-long-random-password
N8N_ENCRYPTION_KEY=replace-with-a-stable-random-key
N8N_DOMAIN=automation.example.com
GENERIC_TIMEZONE=Asia/Ho_Chi_Minh
chmod 600 .env

Phiên bản trên chỉ là ví dụ pin. Hãy chọn release đang được hỗ trợ, đọc release note và thử trước khi nâng. Không dùng latest cho production vì một lần pull có thể đưa thay đổi breaking không được kiểm soát.

4. Tạo Docker Compose

Tạo compose.yaml:

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

  n8n:
    image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "127.0.0.1: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: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_HOST: ${N8N_DOMAIN}
      N8N_PORT: 5678
      N8N_PROTOCOL: https
      N8N_PROXY_HOPS: 1
      WEBHOOK_URL: https://${N8N_DOMAIN}/
      N8N_EDITOR_BASE_URL: https://${N8N_DOMAIN}/
      GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
      TZ: ${GENERIC_TIMEZONE}
      EXECUTIONS_DATA_PRUNE: "true"
      EXECUTIONS_DATA_MAX_AGE: 336
    volumes:
      - ./n8n_data:/home/node/.n8n
    networks: [backend]

networks:
  backend:

PostgreSQL không có ports, nên chỉ container trong network truy cập được. n8n bind localhost để Nginx là cổng công khai duy nhất. WEBHOOK_URL rất quan trọng: nó quyết định callback URL n8n hiển thị cho webhook và OAuth.

EXECUTIONS_DATA_MAX_AGE cần điều chỉnh theo chính sách lưu trữ và nhu cầu điều tra. Lưu execution quá lâu có thể làm database phình to và giữ dữ liệu nhạy cảm.

5. Khởi động và kiểm tra container

docker compose config
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 n8n

docker compose config giúp phát hiện biến thiếu, nhưng output có thể chứa secret đã resolve; không đăng nó vào ticket hoặc chat công khai. Kiểm tra local:

curl -I http://127.0.0.1:5678

Nếu n8n không kết nối database, kiểm tra healthcheck, password, quyền thư mục và log PostgreSQL. Không xóa volume để “thử lại” khi chưa có backup.

6. Cấu hình Nginx reverse proxy

server {
    listen 80;
    server_name automation.example.com;

    location / {
        proxy_pass http://127.0.0.1:5678;
        proxy_http_version 1.1;
        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;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 300;
        proxy_send_timeout 300;
    }
}
sudo nginx -t
sudo systemctl reload nginx

Cấp chứng chỉ TLS bằng Certbot hoặc giải pháp của nhà cung cấp, bật redirect HTTP sang HTTPS rồi truy cập domain thật. n8n dùng kết nối thời gian dài cho editor và execution view, nên header WebSocket cùng timeout proxy phải đúng.

Nếu còn thêm CDN/load balancer trước Nginx, N8N_PROXY_HOPS phải phản ánh đúng số proxy tin cậy. Cấu hình sai có thể làm n8n hiểu sai protocol/IP hoặc tin header do client giả mạo.

7. Tạo owner và bảo vệ editor

Ở lần mở đầu, tạo tài khoản owner bằng email quản trị và mật khẩu duy nhất. Bật 2FA nếu phiên bản/edition hỗ trợ. Không dùng chung owner account; cấp quyền theo vai trò và thu hồi ngay khi nhân sự rời nhóm.

Editor có credential để truy cập email, database, cloud và API. Nếu chỉ đội nội bộ sử dụng, nên đặt sau VPN, identity-aware proxy hoặc allowlist IP ngoài HTTPS. Public webhook vẫn cần truy cập từ Internet, do đó có thể tách chính sách đường dẫn ở reverse proxy hoặc dùng kiến trúc ingress phù hợp.

8. Kiểm tra webhook từ đầu đến cuối

  1. Tạo workflow với Webhook node và Respond to Webhook.
  2. Dùng Test URL khi editor đang lắng nghe.
  3. Activate workflow rồi chuyển sang Production URL.
  4. Gửi request từ một máy bên ngoài, không chỉ localhost.
  5. Kiểm tra execution, status code và response.
curl -X POST https://automation.example.com/webhook/health-test \
  -H 'Content-Type: application/json' \
  -d '{"source":"external-check"}'

Bảo vệ webhook bằng secret header, chữ ký HMAC, OAuth hoặc cơ chế node hỗ trợ. URL khó đoán không phải authentication. Với webhook tạo side effect, thêm idempotency/dedup để provider retry không tạo tác vụ trùng.

9. Quản lý credential và encryption key

n8n mã hóa credential bằng encryption key. Giữ key ổn định qua restart, migration và restore. Nếu thay key tùy ý, credential cũ có thể không giải mã được.

  • Không đặt key trong Compose được commit lên Git.
  • Lưu bản sao trong password manager/secret manager và backup bảo mật.
  • Không xuất workflow kèm credential hoặc chia sẻ screenshot secret.
  • Dùng API credential riêng cho n8n, scope tối thiểu và có rotation.
  • Ưu tiên OAuth/service account thay vì tài khoản cá nhân.

10. Xử lý file và dữ liệu execution

Workflow có file lớn có thể nhanh chóng đầy disk. Giới hạn kích thước đầu vào, đặt execution retention và giám sát volume. Không lưu binary hoặc payload nhạy cảm lâu hơn nhu cầu nghiệp vụ.

Tránh đưa secret vào dữ liệu node vì execution log có thể lưu input/output. Dùng Credential store và environment/secret mechanism phù hợp. Với lưu lượng cao hoặc binary lớn, đánh giá tính năng external storage theo edition và tài liệu phiên bản đang dùng.

11. Backup đúng ba thành phần

Cần bảo vệ:

  1. PostgreSQL chứa workflow, execution và metadata.
  2. Thư mục n8n_data chứa dữ liệu instance cục bộ.
  3. N8N_ENCRYPTION_KEY và cấu hình deployment.
cd /opt/n8n

docker compose exec -T postgres \
  pg_dump -U n8n -d n8n -Fc \
  > backups/n8n-$(date +%F).dump

tar -czf backups/n8n-data-$(date +%F).tar.gz n8n_data

Copy backup sang storage khác, mã hóa, đặt retention và kiểm tra restore trên máy thử. File nằm cùng VPS không bảo vệ khỏi mất disk hoặc bị xâm nhập.

12. Cập nhật an toàn

  1. Đọc release note và breaking changes.
  2. Backup database, data directory và encryption key.
  3. Thử phiên bản mới trên staging với workflow quan trọng.
  4. Đổi N8N_VERSION sang phiên bản đã duyệt.
  5. Pull và recreate container trong cửa sổ thay đổi.
  6. Kiểm tra login, webhook, schedule, credential và execution.
docker compose pull
docker compose up -d
docker compose logs --tail=200 n8n

Migration database có thể khiến rollback image không đơn giản. Xác minh tài liệu downgrade, giữ backup trước migration và không tự động cập nhật production không kiểm soát.

13. Giám sát và cảnh báo

  • Container restart, health và log error.
  • CPU, RAM, disk, inode và volume growth.
  • PostgreSQL connection, size, slow query và backup age.
  • Workflow failure rate, duration và số execution chờ.
  • Webhook latency, 4xx/5xx và certificate expiry.
  • Schedule không chạy đúng hạn và credential hết hạn.

Tạo một monitor bên ngoài gọi health/webhook không có side effect. Cảnh báo phải đi qua kênh không phụ thuộc hoàn toàn vào chính n8n, nếu không workflow cảnh báo cũng im lặng khi n8n down.

14. Hardening bổ sung

  • Chỉ cài community node đã review; node có thể chạy code và truy cập credential.
  • Giới hạn Code/Execute Command và node rủi ro theo nhu cầu.
  • Chặn outbound network tới metadata/internal service nếu không cần.
  • Chạy security audit của n8n định kỳ.
  • Cập nhật host, Docker, image và dependency theo lịch.
  • Tách credential development và production.
  • Dùng least privilege cho database và mọi integration.

Checklist production

  1. Image được pin phiên bản và đã thử trên staging.
  2. PostgreSQL/5678 không public; editor chỉ qua HTTPS.
  3. WEBHOOK_URL, timezone và proxy hops đúng.
  4. Encryption key cố định, được backup và không nằm trong Git.
  5. Owner/2FA/quyền user được kiểm soát.
  6. Webhook có authentication, validation và idempotency.
  7. Execution/binary retention phù hợp và disk được giám sát.
  8. Database + data + secret đã được restore thử.
  9. Có monitor ngoài hệ thống và runbook rollback.

Kết luận

Self-host n8n production không kết thúc ở lệnh docker compose up. Cấu hình tốt cần database bền vững, encryption key được bảo vệ, URL webhook đúng, reverse proxy HTTPS, credential tối thiểu và backup đã thử restore. Khi nền tảng được vận hành như một dịch vụ production, workflow tự động hóa mới thực sự đáng tin cậy.

Tài liệu tham khảo

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.