VPS chạy n8n 24/7: setup Docker Compose từ A-Z (có HTTPS, backup)

Chia sẻ bài viết

Mục lục
💡 AI-ready skill doc: bạn đang vibe code với Claude Code/Cursor/Codex/Gemini? Copy nguyên bài này paste vào AI của bạn - nó sẽ đọc như một skill document và áp dụng đúng pattern này vào project mà không cần bạn giải thích lại. Tiện, gọn, dùng được luôn.
Minh họa VPS chạy n8n 24/7 Docker Compose

n8n cloud bản trả phí khoảng 20 USD/tháng nhưng giới hạn execution. Self-host n8n trên VPS Việt Nam chỉ ~600-1000k/tháng, không giới hạn workflow, dữ liệu tự lưu, integrate được internal tool nội bộ. Bài này hướng dẫn full setup n8n trên Ubuntu 24.04 với Docker Compose, PostgreSQL backend, Caddy auto HTTPS, daily backup, và secure env vars - chuẩn production cho dev solo và team nhỏ.

Tại sao self-host n8n trên VPS?

Năm 2026 n8n đã trở thành tool automation hàng đầu cho dev Việt - thay thế Zapier/Make với chi phí thấp hơn và full control. Lý do self-host:

  • Unlimited workflow execution: bản cloud giới hạn execution/tháng theo plan, self-host không giới hạn.
  • Data ở VPS của bạn: credential API key, webhook payload, customer data đều tự lưu - không qua server bên thứ ba.
  • Custom node + community node: install bất cứ community node nào, viết custom code node tự do.
  • Integrate hệ thống nội bộ: n8n trên VPS có thể gọi internal API (database công ty, intranet) qua private network mà n8n cloud không làm được.
  • Chi phí ổn định: 600-1000k/tháng cho VPS vs 240 USD/năm n8n cloud, lại không lo bị tăng giá.

Cấu hình VPS phù hợp chạy n8n

Use casevCPURAMDiskGói tham khảo
Cá nhân, <20 workflow, <100 execution/ngày22GB30GBVPS 30 (299k)
Team nhỏ, 20-50 workflow, 1k execution/ngày44GB50GBVPS 50 (639k)
Agency/team, 50+ workflow, 10k execution/ngày66GB80GBVPS 80 (999k)
Production, workflow nặng (LLM, AI)88GB160GBVPS 160 (1.790.000đ)
💡 Mẹo: n8n + PostgreSQL + Caddy cần ít nhất 2GB RAM idle. VPS 1GB không chạy nổi setup này. Nếu thấy n8n bị OOM kill, đó là dấu hiệu cần upgrade RAM.

Step 1: Đặt VPS Ubuntu 24.04 + cấu hình ban đầu

Đặt VPS với OS Ubuntu 24.04 LTS. Sau khi nhận IP và root password qua email, SSH vào:

# Từ máy bạn
ssh root@

# Update hệ thống
apt update && apt upgrade -y

# Tạo user non-root (đừng dùng root cho daily work)
adduser n8nadmin
usermod -aG sudo n8nadmin

# Copy SSH key sang user mới (để login không cần password)
rsync --archive --chown=n8nadmin:n8nadmin ~/.ssh /home/n8nadmin

# Logout, login lại với user mới
exit
ssh n8nadmin@

Step 2: Cài Docker + Docker Compose

# Cài Docker official
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Cho user dùng docker không cần sudo
sudo usermod -aG docker $USER

# Logout/login lại để áp dụng group
exit
ssh n8nadmin@

# Verify
docker --version
docker compose version

Docker Compose hiện đại đã tích hợp vào Docker CLI (lệnh là docker compose, không phải docker-compose kiểu cũ).

Step 3: Setup firewall (UFW)

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

Chỉ mở port 22 (SSH), 80 (HTTP, cho Let's Encrypt verify), 443 (HTTPS). PostgreSQL và n8n internal không mở public.

Step 4: Trỏ domain về VPS

Vào DNS provider (Cloudflare, namesilo, godaddy), tạo A record:

Type: A
Name: n8n  (hoặc subdomain bạn muốn)
Value: 
TTL: Auto / 300
Proxy status: DNS only (TẮT proxy Cloudflare lúc đầu để Let's Encrypt verify được)

Test DNS đã propagate:

dig n8n.yourdomain.com +short
# Phải trả ra IP VPS

Step 5: Tạo cấu trúc thư mục và file .env

mkdir -p ~/n8n-stack/{caddy,n8n,postgres,backups}
cd ~/n8n-stack

# Tạo file .env
cat > .env <<'EOF'
# Domain
DOMAIN=n8n.yourdomain.com
[email protected]

# n8n
N8N_ENCRYPTION_KEY=
N8N_USER_MANAGEMENT_JWT_SECRET=

# PostgreSQL
POSTGRES_USER=n8n
POSTGRES_PASSWORD=
POSTGRES_DB=n8n
EOF

# Set permission file env (CHỈ owner đọc được)
chmod 600 .env

Generate random secret:

# Trên VPS
openssl rand -hex 32
# Copy output, paste vào .env cho N8N_ENCRYPTION_KEY và JWT_SECRET (mỗi cái 1 string riêng)

# Generate password Postgres
openssl rand -base64 24
⚠️ Lưu ý: N8N_ENCRYPTION_KEY dùng để mã hóa credential trong n8n. Nếu MẤT key này, mọi credential trong workflow bị mất (phải nhập lại). LƯU key này vào password manager (1Password, Bitwarden) ngay khi tạo.

Step 6: Viết docker-compose.yml

cat > docker-compose.yml <<'EOF'
services:
  caddy:
    image: caddy:2-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - n8n-net
    environment:
      - DOMAIN=${DOMAIN}
      - ACME_EMAIL=${ACME_EMAIL}

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

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      - 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}
      - N8N_HOST=${DOMAIN}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://${DOMAIN}/
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_USER_MANAGEMENT_JWT_SECRET=${N8N_USER_MANAGEMENT_JWT_SECRET}
      - GENERIC_TIMEZONE=Asia/Ho_Chi_Minh
      - TZ=Asia/Ho_Chi_Minh
    volumes:
      - n8n_data:/home/node/.n8n
    networks:
      - n8n-net

volumes:
  caddy_data:
  caddy_config:
  postgres_data:
  n8n_data:

networks:
  n8n-net:
    driver: bridge
EOF

Step 7: Viết Caddyfile (auto HTTPS)

cat > caddy/Caddyfile <<'EOF'
{$DOMAIN} {
    tls {$ACME_EMAIL}

    reverse_proxy n8n:5678 {
        flush_interval -1
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }

    encode gzip

    header {
        Strict-Transport-Security "max-age=31536000;"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        Referrer-Policy "strict-origin-when-cross-origin"
    }
}
EOF

Lưu ý quan trọng: flush_interval -1 cần cho n8n vì workflow lâu chạy (long-running), không có flush này thì connection bị buffer và đứt giữa chừng.

Step 8: Khởi động stack

cd ~/n8n-stack
docker compose up -d

# Theo dõi log
docker compose logs -f

# Stop log: Ctrl+C

Lần đầu Caddy sẽ request certificate từ Let's Encrypt - mất 10-30 giây. Khi log Caddy hiện "certificate obtained successfully", truy cập https://n8n.yourdomain.com.

Trang setup n8n hiện ra - tạo owner account đầu tiên (email + password). Đây là admin của instance.

Step 9: Daily backup database tự động

Backup quan trọng vì mất DB = mất tất cả workflow. Tạo script backup:

cat > ~/n8n-stack/backup.sh <<'EOF'
#!/bin/bash
set -e

BACKUP_DIR=~/n8n-stack/backups
DATE=$(date +%Y%m%d_%H%M%S)
KEEP_DAYS=14

cd ~/n8n-stack

# Dump database
docker compose exec -T postgres pg_dump -U n8n n8n | gzip > $BACKUP_DIR/n8n_db_${DATE}.sql.gz

# Backup volume n8n_data (chứa credential encryption seed)
docker run --rm \
    -v n8n-stack_n8n_data:/data \
    -v $BACKUP_DIR:/backup \
    alpine tar czf /backup/n8n_data_${DATE}.tar.gz -C /data .

# Xóa backup cũ hơn KEEP_DAYS ngày
find $BACKUP_DIR -name "*.gz" -mtime +$KEEP_DAYS -delete

echo "Backup completed: $DATE"
EOF

chmod +x ~/n8n-stack/backup.sh

Schedule cron chạy 3h sáng mỗi ngày:

crontab -e

# Thêm dòng:
0 3 * * * /home/n8nadmin/n8n-stack/backup.sh >> /home/n8nadmin/n8n-stack/backup.log 2>&1

Test chạy thử backup:

./backup.sh
ls -lh backups/

Step 10: Upload backup ra cloud storage (S3/R2)

Backup local không đủ - VPS chết là mất hết. Upload lên cloud storage:

# Cài AWS CLI
sudo apt install awscli -y

# Cấu hình credential cho Cloudflare R2 (rẻ + miễn phí egress)
aws configure --profile r2
# AWS Access Key ID: 
# AWS Secret Access Key: 
# Default region: auto
# Default output: json

# Sửa backup.sh thêm phần upload
cat >> ~/n8n-stack/backup.sh <<'EOF'

# Upload to Cloudflare R2
aws s3 cp $BACKUP_DIR/n8n_db_${DATE}.sql.gz \
    s3://your-bucket/n8n-backups/ \
    --endpoint-url https://.r2.cloudflarestorage.com \
    --profile r2

aws s3 cp $BACKUP_DIR/n8n_data_${DATE}.tar.gz \
    s3://your-bucket/n8n-backups/ \
    --endpoint-url https://.r2.cloudflarestorage.com \
    --profile r2
EOF

Step 11: Update n8n định kỳ (an toàn)

n8n release version mới đều đặn. Update:

cd ~/n8n-stack

# Backup TRƯỚC khi update
./backup.sh

# Pull image mới
docker compose pull

# Recreate container (giữ volume data)
docker compose up -d

# Verify
docker compose logs n8n --tail 50

Nếu update gây lỗi (rare), rollback bằng cách pin version cụ thể trong docker-compose.yml:

# Thay vì
image: n8nio/n8n:latest
# Pin cụ thể version đang chạy stable
image: n8nio/n8n:1.65.2  # ví dụ

Step 12: Bảo mật bổ sung

SSH key only, disable password

sudo nano /etc/ssh/sshd_config
# Sửa: PasswordAuthentication no
# Sửa: PermitRootLogin no
sudo systemctl restart ssh

Fail2ban chống brute force

sudo apt install fail2ban -y
sudo systemctl enable fail2ban

Auto security update

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades

Webhook secret cho từng workflow

Trong n8n, khi tạo Webhook node, set "Authentication" = "Header Auth" hoặc check token trong workflow logic. Không để webhook public không xác thực - bot scan internet liên tục để abuse webhook.

Monitoring n8n: biết khi nào workflow fail

Built-in n8n có "Execution List" - xem history tất cả execution. Nhưng cần alert chủ động khi workflow fail.

Cách 1: Tạo Error Workflow trong n8n - trigger khi bất kỳ workflow nào fail, gửi notification về Telegram/Slack/Email. Workflow:

  1. Tạo workflow mới tên "Error Handler".
  2. Node 1: Error Trigger (auto trigger khi workflow khác fail).
  3. Node 2: Telegram Send Message với chi tiết error.
  4. Vào Settings từng workflow quan trọng, set "Error Workflow" = "Error Handler".

Cách 2: External monitoring qua UptimeRobot - ping HTTPS healthcheck endpoint, alert qua email/Telegram khi n8n down.

Troubleshooting thường gặp

n8n container restart liên tục, log "OOM killed"

RAM không đủ. Upgrade VPS hoặc giảm worker. Check: docker stats xem container nào ngốn RAM.

Webhook không nhận được request từ ngoài

Check firewall UFW có open 443. Check Cloudflare proxy (orange cloud) - n8n cần WebSocket hỗ trợ, một số rule Cloudflare có thể block. Test: curl https://n8n.yourdomain.com/webhook-test/abc.

Caddy không lấy được cert HTTPS

DNS chưa propagate đúng IP, hoặc port 80 bị block. Test curl -I http://n8n.yourdomain.com - phải trả 308 redirect tới HTTPS.

Workflow chạy chậm hoặc timeout

Tăng timeout trong workflow setting. Cân nhắc tách workflow nặng sang queue mode (n8n có doc về queue mode với BullMQ Redis).

Use case n8n self-host phổ biến cho dev Việt

  • Sync data giữa Google Sheet và database SaaS: mỗi khi sales nhập lead vào sheet, n8n tự push sang CRM.
  • Auto-reply Zalo OA/Facebook: webhook nhận message, gọi OpenAI/Claude, gửi response.
  • Báo cáo daily Slack/Telegram: mỗi 8h sáng, n8n query database, gửi report doanh số đêm qua.
  • Backup tự động cross-platform: dump database mỗi đêm, upload R2, gửi notification.
  • RPA cho ads: mỗi giờ check Google Ads/Meta Ads spend, alert khi vượt budget.
  • Workflow AI: input từ form → OpenAI process → save Notion/Airtable.

Bài viết liên quan

VPS phù hợp chạy n8n self-host?

TND Cloud VPS 50 (4vCPU/4GB/50GB - 639k/tháng) là sweet spot cho n8n cá nhân/team nhỏ. Lên VPS 80 nếu workflow nhiều. Ceph SSD NVMe + RAM ECC + datacenter VN/US.

Xem bảng giá Cloud VPS

Tổng kết: self-host n8n trên VPS giúp dev/team kiểm soát hoàn toàn workflow automation với chi phí thấp hơn nhiều bản cloud. Stack đề xuất: VPS Việt Nam giá tốt + Ubuntu 24.04 + Docker Compose + PostgreSQL + Caddy auto HTTPS + cron backup hàng ngày + upload R2 + monitoring qua Error Workflow. Setup ban đầu khoảng 1-2 giờ, sau đó chạy ổn định nhiều tháng không cần can thiệp. Bắt đầu với VPS 50 cho cá nhân, scale lên VPS 80/160 khi workflow tăng.

2009
15+ năm vận hành liên tục
10+
tập đoàn lớn tin dùng
100+
doanh nghiệp SMB Việt
30 ngày
đổi key lỗi miễn phí
Phần mềm bản quyền chính hãng chúng tôi cung cấp
Bản quyền chính hãng Hóa đơn VAT đầy đủ Đổi key lỗi 30 ngày Vận hành từ 2009 MST 0200994870 Hotline 0225.999.6666