Cài n8n trên VPS bằng Docker cần đi hết ba phần: chạy ứng dụng, đưa dịch vụ ra Internet qua HTTPS và giữ được dữ liệu khi thay container. Tài liệu n8n hiện hướng người dùng sang Docker Compose; trang cài Docker riêng đã được đánh dấu lỗi thời. Hướng dẫn dưới đây dùng Compose với Caddy làm reverse proxy, phù hợp cho một triển khai đơn máy. Đây là cấu hình minh họa dựa trên tài liệu chính thức, chưa phải kết quả thử nghiệm trên VPS cụ thể.
1. Chuẩn bị VPS, Docker và tên miền
Chuẩn bị VPS Linux, quyền SSH và sudo, cùng tên miền bạn quản lý. Nếu dùng Ubuntu, hãy theo hướng dẫn cài Docker Engine đúng bản phân phối, thiết lập kho apt chính thức trước khi cài các gói bên dưới. Không gỡ Docker đang phục vụ ứng dụng khác chỉ để làm theo bài. Theo n8n, tự vận hành đòi hỏi kiến thức về máy chủ, bảo mật và quản lý tài nguyên; không nên xem việc container khởi động được là đã hoàn tất vận hành.
Sau khi cấu hình kho apt của Docker, cài và kiểm tra lần lượt:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker run hello-world
sudo docker compose version
Lệnh hello-world cần in thông báo xác nhận rồi thoát; lệnh cuối cần hiển thị phiên bản Compose. Nếu lỗi quyền truy cập Docker, dùng sudo như các ví dụ trong bài.
Trỏ bản ghi A của n8n.example.com về IPv4 VPS; nếu có AAAA, địa chỉ IPv6 cũng phải đúng. Thay tên miền minh họa bằng tên miền thật trong toàn bộ cấu hình. Theo Caddy, để cấp HTTPS tự động theo cấu hình thông thường, DNS phải trỏ đúng và cổng 80, 443 phải đến được Caddy. Nếu máy đã có web server chiếm hai cổng này, hãy tích hợp với proxy hiện hữu thay vì chạy chồng mẫu bên dưới. Khi chỉnh firewall, giữ đường SSH quản trị; Docker cũng cảnh báo cổng container được công bố có thể vượt qua quy tắc ufw.

2. Tạo Compose, HTTPS và URL webhook
Tạo thư mục riêng bằng hai lệnh lần lượt: mkdir n8n-compose và cd n8n-compose. Tạo tệp .env với nội dung sau:
N8N_IMAGE=n8nio/n8n:stable
CADDY_IMAGE=caddy:2
Đây là các nhãn theo kênh, không phải cam kết phiên bản cố định. Với môi trường vận hành, nên thay bằng nhãn phiên bản cụ thể đã kiểm tra và lưu lại giá trị cũ trước mỗi lần nâng cấp.
Tạo compose.yaml với nội dung minh họa:
services:
n8n:
image: ${N8N_IMAGE}
restart: unless-stopped
environment:
N8N_HOST: n8n.example.com
N8N_PORT: "5678"
N8N_PROTOCOL: https
N8N_WEBHOOK_URL: https://n8n.example.com/
N8N_PROXY_HOPS: "1"
GENERIC_TIMEZONE: Asia/Ho_Chi_Minh
TZ: Asia/Ho_Chi_Minh
volumes:
- n8n_data:/home/node/.n8n
caddy:
image: ${CADDY_IMAGE}
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
n8n_data:
caddy_data:
caddy_config:
Tạo tệp Caddyfile trước khi khởi động:
n8n.example.com {
reverse_proxy n8n:5678
}
Theo Docker, các service trong cùng mạng Compose tìm được nhau bằng tên, nên Caddy dùng n8n:5678. Mẫu không công bố cổng n8n ra máy chủ; lưu lượng công khai đi qua Caddy. Dữ liệu chứng chỉ được giữ trong volume /data theo hướng dẫn image Caddy.
Theo tài liệu n8n về reverse proxy, URL webhook phải phản ánh địa chỉ HTTPS công khai, dù ứng dụng nghe cổng 5678 bên trong. N8N_PROXY_HOPS=1 phù hợp với ví dụ chỉ có một proxy Caddy. Nếu thêm CDN hoặc proxy khác, cần rà lại chuỗi proxy và các header chuyển tiếp, không giữ nguyên giá trị một cách máy móc. Caddy mặc định thiết lập các header X-Forwarded-For, X-Forwarded-Proto và X-Forwarded-Host cho upstream.
Kiểm tra cấu hình rồi khởi động, chạy từng dòng trong thư mục dự án:
sudo docker compose config -q
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
sudo docker compose logs --tail=100 n8n caddy
Theo Docker, config dùng để phân tích và kiểm tra cấu hình; ps và logs giúp xem trạng thái, đầu ra dịch vụ. Chỉ tiếp tục khi không còn lỗi cấu hình hoặc container khởi động lặp. Mở tên miền HTTPS để hoàn tất thiết lập tài khoản chủ sở hữu khi giao diện yêu cầu.

3. Kiểm tra, sao lưu và khôi phục
Đề xuất kiểm tra nghiệm thu: xác nhận trình duyệt không báo lỗi chứng chỉ, URL webhook trong editor dùng đúng tên miền HTTPS và một workflow thử với dữ liệu giả nhận được yêu cầu từ bên ngoài. Nếu không truy cập được, kiểm tra DNS và kết nối 80/443 trước; nếu proxy báo lỗi upstream, xem log n8n và tên service. Sau khi tạo workflow thử, tái tạo container rồi kiểm tra workflow còn tồn tại để phát hiện cấu hình volume sai.
Theo n8n, triển khai SQLite mặc định lưu cơ sở dữ liệu và khóa mã hóa trong thư mục .n8n, tương ứng volume n8n_data ở mẫu này. Trước khi sao chép, dừng ứng dụng bằng sudo docker compose stop n8n để tránh bản sao SQLite thiếu nhất quán. Dùng sudo docker volume ls để xác định đúng tên volume thực tế, sao lưu volume theo hướng dẫn Docker và lưu thêm .env, compose.yaml, Caddyfile vào nơi được bảo vệ ngoài VPS; sau đó chạy sudo docker compose up -d n8n. Không dùng docker compose down -v để bảo trì: tùy chọn -v có thể xóa các volume dữ liệu.
Trước cập nhật, tạo bản sao đầy đủ và ghi lại image hiện tại. Sau khi chọn phiên bản đích trong .env, chạy sudo docker compose pull n8n rồi sudo docker compose up -d n8n, kiểm tra lại log, đăng nhập và workflow thử. Nếu phải rollback, dừng n8n, giữ riêng dữ liệu sau lỗi để điều tra, khôi phục volume cùng cấu hình trước nâng cấp và chạy image cũ tương ứng. Đừng chỉ hạ image rồi dùng tiếp cơ sở dữ liệu đã thay đổi. Nếu chuyển sang PostgreSQL, cần sao lưu cả database lẫn khóa mã hóa; chỉ xuất workflow không đủ để phục hồi toàn bộ hệ thống.

Nguồn tham khảo
n8n.io (5 tài liệu)
- /deploy/host-n8n/install-options/install-with-docker.md
- /deploy/host-n8n/install-options/use-a-cloud-provider/use-docker-compose.md
- /deploy/host-n8n/configure-n8n/basic-configuration/configuration-examples/configure-webhook-urls-with-reverse-proxy.md
- /deploy/host-n8n/keep-n8n-running/backup-and-restore.md
- /deploy/host-n8n/keep-n8n-running/update-n8n.md

