Cài đặt n8n tự động hóa trên VPS Debian

SSH vào VPS Debian mới, việc mình làm trước tiên không phải cài ngay mà là dựng n8n theo cách chịu được lâu dài: container hóa, database tách riêng, có reverse proxy và SSL. Dưới đây là quy trình mình vẫn dùng để cài đặt n8n tự động hóa trên VPS Debian 12, chạy được sau khi copy-paste và không phải sửa lại sau vài tuần.
- n8n chạy trong Docker Compose cùng PostgreSQL, dữ liệu workflow lưu bền ngoài container.
- Nginx đứng trước làm reverse proxy, SSL cấp bằng Let's Encrypt và tự gia hạn.
- Webhook chỉ mở qua domain có HTTPS, không phơi port 5678 ra Internet.
- Yêu cầu tối thiểu: VPS Debian 12, 2 vCPU / 4 GB RAM, 20 GB NVMe trống.
Yêu cầu trước khi bắt đầu
- VPS chạy Debian 12 (Bookworm), có IPv4 riêng và quyền
sudo(hoặc root). - Một domain/subdomain đã trỏ bản ghi A về IP VPS (ví dụ
n8n.tenmien.vn), DNS đã propagate. - Có thể đăng nhập SSH bằng key. Nếu chưa cấu hình, xem lại cách bảo mật đăng nhập SSH trước khi mở dịch vụ ra ngoài.
- Kiến thức cơ bản về Docker, Nginx và dòng lệnh Linux. Nếu cần một nền tảng gọn cho automation, thuê VPS Linux Debian làm base là lựa chọn hợp lý.
Vì sao nên self-host n8n trên Debian
Debian nổi tiếng vì kho gói ổn định, chu kỳ phát hành chậm mà chắc, phù hợp cho máy chủ chạy dịch vụ dài hạn. So với Ubuntu, package của Debian ít thay đổi đột ngột hơn, ít "bất ngờ" khi nâng cấp, đúng kiểu bạn muốn cho một hệ thống automation chạy trong giờ hành chính.
Bản n8n self-host không giới hạn số workflow, không bị tính theo số execution như bản cloud. Đổi lại bạn tự lo database, backup, nâng cấp. Trên một VPS có IPv4 Việt Nam, độ trễ tới API và dịch vụ trong nước thấp hơn hẳn so với thuê máy ở xa, rất hợp với các workflow có nhiều bước gọi qua lại.
Bước 1 - Cập nhật hệ thống và cài Docker
Debian 12 chưa có Docker mặc định, nên cài từ repo chính thức. Cách này cho bản mới và có thể nâng cấp bằng apt về sau.
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Plugin docker-compose-plugin cho bạn lệnh docker compose (v2, có dấu cách), không dùng docker-compose kiểu cũ nữa. Kiểm tra lại:
docker --version
docker compose version
Kết quả mong đợi: hiện ra số phiên bản Docker 2x và Compose v2.x. Nếu báo lỗi quyền, thêm user vào nhóm docker (đăng nhập lại sau đó):
sudo usermod -aG docker $USER
Bước 2 - Chuẩn bị thư mục và file .env
Tạo thư mục riêng cho stack và một file biến môi trường. Đừng để lộ mật khẩu database trong file compose.
mkdir -p ~/n8n && cd ~/n8n
POSTGRES_PASSWORD=$(openssl rand -hex 16)
N8N_ENCRYPTION_KEY=$(openssl rand -hex 24)
cat > .env <<EOF
POSTGRES_USER=n8n
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
POSTGRES_DB=n8n
N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
DOMAIN=n8n.tenmien.vn
EOF
cat .env
Lưu ý quan trọng: N8N_ENCRYPTION_KEY dùng để mã hoá credential đã lưu. Mất key này thì phải nhập lại toàn bộ credential, nên sao lưu file .env ra nơi an toàn ngay từ giờ. Nhớ thay DOMAIN bằng domain thật của bạn.
Bước 3 - Viết docker-compose.yml cho n8n và PostgreSQL
File compose dưới đây tách n8n và PostgreSQL thành hai service, dữ liệu lưu trong volume để không mất khi xoá container.
cat > docker-compose.yml <<'EOF'
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
n8n:
image: docker.n8n.io/n8nio/n8n:latest
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=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_HOST=${DOMAIN}
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://${DOMAIN}/
- GENERIC_TIMEZONE=Asia/Ho_Chi_Minh
volumes:
- n8n_data:/home/node/.n8n
volumes:
postgres_data:
n8n_data:
EOF
Hai điểm đáng chú ý: port được bind vào 127.0.0.1 chứ không phải 0.0.0.0, nên n8n chỉ nghe nội bộ, Nginx sẽ là cửa vào riêng biệt. Timezone đặt theo giờ Việt Nam để lịch chạy khớp với thực tế. Khởi động:
docker compose up -d
docker compose ps
Cả hai service phải ở trạng thái running và postgres báo healthy. Kiểm tra log n8n:
docker compose logs -f n8n
Chờ tới khi thấy dòng Editor đã sẵn sàng tại port 5678, nhấn Ctrl+C để thoát log.
Bước 4 - Cài Nginx làm reverse proxy
Nginx nhận traffic từ ngoài, chuyển vào n8n ở localhost. Cài Nginx và tạo site:
sudo apt install -y nginx
sudo rm -f /etc/nginx/sites-enabled/default
sudo nano /etc/nginx/sites-available/n8n
Dán nội dung sau (thay n8n.tenmien.vn bằng domain của bạn):
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-Proto $scheme;
proxy_read_timeout 3600;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Lệnh nginx -t phải trả về syntax is ok và test is successful. Sau đó mở firewall cho web:
sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Kiểm tra bằng sudo ufw status, bạn sẽ thấy 22, 80, 443 được phép. Đừng quên mở cùng các port này ở firewall của nhà cung cấp VPS nếu có.
Bước 5 - Cấp SSL Let's Encrypt cho n8n
Certbot lo phần lấy và tự gia hạn chứng chỉ. Cài bằng snap cho đúng khuyến nghị chính thức:
sudo apt install -y snapd
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx -d n8n.tenmien.vn
Certbot sẽ sửa file Nginx, thêm khối HTTPS và redirect HTTP sang HTTPS. Xác nhận lại và kiểm tra tự gia hạn:
sudo certbot renew --dry-run
curl -I https://n8n.tenmien.vn
Kết quả mong đợi: HTTP/2 200 kèm header server: nginx. Giờ mở trình duyệt tới domain, bạn sẽ thấy màn hình tạo tài khoản owner cho n8n. Đặt email và mật khẩu mạnh ngay, đây là tài khoản quản trị toàn bộ workflow.
Bước 6 - Bảo mật và vận hành n8n an toàn
Self-host nghĩa là bạn tự chịu rủi ro. Vài thứ mình làm cố định cho mọi deployment n8n:
- Không mở port 5678 ra ngoài. Chỉ Nginx được phép truy cập qua localhost.
- Bật 2FA cho tài khoản n8n trong phần Settings nếu luồng công việc có dữ liệu nhạy cảm.
- Giới hạn quyền của API key và webhook chỉ dùng cho đúng integration cần thiết.
- Đặt lịch backup database định kỳ, cả file
.env. Có thể đẩy sang object storage hoặc một ổ khác. - Cài
fail2banbảo vệ SSH và theo dõi log Nginx để phát hiện truy cập bất thường.
Về backup, cách đơn giản là dump định kỳ:
docker compose exec -T postgres pg_dump -U n8n n8n > ~/n8n-backup-$(date +%F).sql
Chạy lệnh này theo lịch cron hàng ngày, xoá bản cũ sau 14 ngày là đủ dùng cho phần lớn hệ thống nhỏ. Khi số workflow tăng, chuyển hàng loạt job nặng sang n8n ở queue mode với Redis và worker riêng.
Nếu bạn chạy nhiều instance automation, việc tách worker và giám sát queue qua dashboard trực quan là lúc nên cân nhắc một VPS chạy Docker hoặc VPS n8n cấu hình sẵn để đỡ công dựng từ đầu.
Bước 7 - Kiểm tra workflow đầu tiên
Tạo một workflow đơn giản để xác nhận toàn bộ pipeline chạy đúng: dùng node Schedule Trigger chạy mỗi 5 phút, nối vào node Set để sinh một biến, rồi node HTTP Request gọi https://httpbin.org/get. Bấm Execute Workflow và kiểm tra output.
Nếu workflow có webhook, URL dạng https://n8n.tenmien.vn/webhook/... phải trả 200. Kiểm tra hai thứ hay gặp lỗi: biến WEBHOOK_URL trong compose đúng domain (thiếu dấu gạch chéo cuối vẫn chạy nhưng dễ lệch đường dẫn), và lịch hệ thống máy ảo đã đúng timezone.
timedatectl
docker compose exec n8n printenv | grep -E 'N8N_HOST|WEBHOOK_URL|GENERIC_TIMEZONE'
Xử lý lỗi thường gặp
n8n báo "ECONNREFUSED postgres". Database chưa kịp healthy khi n8n khởi động. Compose đã dùng depends_on: condition: service_healthy, nhưng nếu vẫn gặp, kiểm tra log postgres bằng docker compose logs postgres và xác nhận mật khẩu trong .env khớp với biến trong compose.
Trang n8n trắng xoá hoặc redirect sai host. Sai N8N_HOST hoặc N8N_PROTOCOL. Sửa trong compose, chạy docker compose up -d để nạp lại biến.
Webhook production không nhận request. Kiểm tra Nginx đã chuyển đúng proxy_set_header Host $host chưa, và webhook đã bật trạng thái active chưa (workflow ở chế độ test chỉ dùng endpoint /webhook-test).
Chứng chỉ SSL hết hạn. Certbot đã thêm timer tự gia hạn; xác nhận bằng systemctl list-timers | grep certbot và chạy certbot renew --dry-run để kiểm tra trước khi tin tưởng.
Câu hỏi thường gặp
n8n trên Debian cần bao nhiêu RAM?
Tối thiểu 2 GB để chạy thử, nhưng 4 GB là mức mình khuyên cho môi trường thật. Nếu chạy nhiều workflow nặng hoặc dùng queue mode với worker, nên từ 8 GB trở lên.
Có nên dùng SQLite thay PostgreSQL không?
SQLite đủ cho demo, nhưng PostgreSQL ổn định và chịu tải tốt hơn khi workflow tăng, đồng thời là bước chuẩn bị cho queue mode. Với một VPS Debian 4 GB RAM, PostgreSQL không tốn kém và đáng dùng ngay từ đầu.
Làm sao backup n8n đúng cách?
Backup hai thứ: dump database PostgreSQL (lệnh pg_dump như trên) và file .env chứa N8N_ENCRYPTION_KEY. Thiếu key, credential đã lưu sẽ không giải mã được khi phục hồi.
Có cần mở port 5678 ra ngoài không?
Không. Chỉ cần Nginx tiếp cận qua localhost và mở 80/443 cho người dùng. Việc ẩn port 5678 giảm hẳn bề mặt tấn công.
ThueVPS có hỗ trợ Debian không?
Có. VPS Linux của thueVPS cho bạn chọn Debian, Ubuntu, AlmaLinux... với full root, IPv4 Việt Nam và NVMe, đủ cho một stack n8n + PostgreSQL như bài này.
Nâng cấp n8n lên bản mới thế nào?
Đổi latest thành số phiên bản cụ thể trong compose nếu muốn ổn định, rồi chạy docker compose pull && docker compose up -d. Backup trước khi nâng cấp, đọc release notes để biết có migration database nào không.
Bài viết liên quan
- Cách cài n8n trên VPS bằng Docker
- Cấu hình Nginx reverse proxy và SSL cho n8n
- Chuyển n8n từ SQLite sang PostgreSQL


