Self-host n8n trên VPS với Docker và HTTPS
Chạy n8n trên VPS bằng Docker Compose, Postgres và reverse proxy HTTPS. Tránh lỗi WEBHOOK_URL, encryption-key và các error string thường gặp.
Bạn sẽ xây dựng gì
n8n là một công cụ tự động hóa workflow: một trình chỉnh sửa trực quan, trong đó trigger, webhook, lịch hoặc lần gửi form sẽ kích hoạt một chuỗi node gọi API, biến đổi dữ liệu và ghi dữ liệu vào các hệ thống khác. n8n đã trở thành công cụ kết nối mặc định cho các workflow AI-agent vì nó giao tiếp được với mọi nhà cung cấp model và database mà không cần bạn tự viết service. Một docker run giúp bạn có một trình chỉnh sửa hoạt động trong hai phút. Hướng dẫn này tập trung vào chín mươi phần trăm còn lại: làm cho hệ thống bền vững bằng Postgres thay vì file SQLite mặc định, cho phép truy cập qua HTTPS và, đây là phần hầu như ai cũng cấu hình sai, làm cho webhook cung cấp một URL mà hệ thống bên ngoài thực sự có thể truy cập.
Stack hoàn chỉnh gồm hai container trên cùng một Docker network: chính n8n và một database Postgres lưu workflow cùng credential của n8n. Reverse proxy trên host thực hiện TLS termination và chuyển tiếp đến n8n qua localhost, nên không thành phần nào truy cập Internet trực tiếp ngoài reverse proxy. Stack này chạy cùng các service khác trong danh sách self-hosting đáng chú ý năm 2026.
Điều kiện tiên quyết và các giới hạn thực tế
Bạn cần một VPS có ít nhất 1 GB RAM; hãy dự trù 2 GB khi workflow bắt đầu xử lý công việc thực tế, vì các execution cùng runtime Node.js sẽ ngốn bộ nhớ, còn việc OOM killer dừng container giữa chừng là cách rất tệ để nhận ra điều đó. Một vCPU là đủ để bắt đầu. Nếu máy này cũng chạy dịch vụ nặng hơn, hãy chọn cấu hình dựa trên dịch vụ đó trước: thư viện ảnh thường là thủ phạm, và mức RAM thực tế tối thiểu cho PhotoPrism và Immich cao hơn nhiều so với yêu cầu của n8n. Media box cũng tương tự: một server Jellyfin cùng giao diện duyệt nội dung cho nó, chẳng hạn như Halcyon, công cụ dựng lại thư viện theo kiểu cửa hàng cho thuê băng đĩa thập niên 90, sẽ chiếm RAM và dư địa transcoding từ lâu trước khi n8n nhận thấy.
Bạn cần một domain hoặc subdomain, chẳng hạn n8n.example.com, có A record trỏ đến public IP của VPS và đã phân giải được trước khi bạn yêu cầu certificate. Cổng 80 và 443 phải được mở cho proxy; cổng riêng của n8n là 5678 không được public ra Internet. Bạn cần Docker Engine và Compose plugin. Nếu docker compose version báo lỗi docker: 'compose' is not a docker command thì bạn đang dùng standalone binary cũ; plugin là sudo apt install docker-compose-plugin.
Dùng SQLite để thử nghiệm là ổn, còn mọi thứ bạn phụ thuộc vào thì dùng Postgres
Database mặc định của n8n là một file SQLite tại /home/node/.n8n/database.sqlite. Để thử nhanh, cách này là đủ; không mount volume thì bạn sẽ mất database ngay lần recreate container đầu tiên, và đó cũng là một bài học riêng. Lý do chuyển sang Postgres không phải vì tốc độ thuần túy, mà vì SQLite chỉ cho phép một writer lock duy nhất. Do đó, một instance chạy nhiều workflow cùng lúc hoặc dùng queue mode mà sau này bạn sẽ cần sẽ phát sinh SQLITE_BUSY: database is locked khi có concurrency. Postgres không bị giới hạn như vậy, hỗ trợ backup rõ ràng bằng pg_dump, và đây là database mà tài liệu chính thức của n8n giả định khi server là thành phần bạn phụ thuộc vào. Chuyển đổi sau này đồng nghĩa với việc phải tự migrate dữ liệu, nên nếu máy này quan trọng, hãy bắt đầu với Postgres.
DNS và firewall
Trỏ bản ghi và mở các port trước để bước cấp chứng chỉ sau đó không fail vì hostname chưa phân giải được.
dig +short n8n.example.com
curl -s ifconfig.me
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow OpenSSH
sudo ufw enableKhông mở port 5678. File compose bind n8n vào 127.0.0.1:5678 nên chỉ reverse proxy trên host mới có thể truy cập n8n. Một ufw allow 5678 sẽ phá vỡ cơ chế cô lập đó.
Tệp Compose
Tạo một thư mục làm việc và một docker-compose.yml. Đây là toàn bộ stack: hai service, một network riêng, hai named volume.
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- n8n_net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
interval: 10s
timeout: 5s
retries: 5
n8n:
image: docker.n8n.io/n8nio/n8n:2.29.10
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
- N8N_HOST=n8n.example.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_PROXY_HOPS=1
- GENERIC_TIMEZONE=Europe/London
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- n8n_data:/home/node/.n8n
networks:
- n8n_net
depends_on:
postgres:
condition: service_healthy
volumes:
postgres_data:
n8n_data:
networks:
n8n_net:Cần nêu rõ một vài quyết định. DB_POSTGRESDB_HOST=postgres là tên service mà Docker phân giải trên network dùng chung, không phải localhost; bên trong container n8n, localhost có nghĩa là chính n8n. depends_on cùng với condition: service_healthy ngăn n8n chạy trước Postgres khi boot; nếu không có chúng, n8n khởi động, không tìm thấy database rồi thoát. Named volume n8n_data được mount tại /home/node/.n8n chứa encryption key và, khi dùng SQLite, cả database; đây là thư mục duy nhất bạn không được làm mất. Ghim image vào một version cụ thể, không bao giờ dùng latest; lý do được nêu trong phần nâng cấp bên dưới.
Tệp secrets
Không bao giờ đặt mật khẩu trong compose file. Hãy đặt chúng trong tệp .env cùng thư mục với compose file để Compose tự động đọc tệp này, đồng thời tạo mật khẩu bằng cách bảo đảm chúng thực sự ngẫu nhiên.
printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)" > .env
printf 'N8N_ENCRYPTION_KEY=%s\n' "$(openssl rand -hex 32)" >> .env
chmod 600 .envN8N_ENCRYPTION_KEY là chuỗi quan trọng nhất ở đây. Đây là key dùng để mã hóa mọi credential được lưu trữ. Hãy đặt key này một cách rõ ràng thay vì để n8n tự tạo, vì giá trị do bạn tạo có thể được ghi lại và khôi phục. Sau khi n8n đã mã hóa credential đầu tiên bằng key này, thay đổi key sẽ khiến mọi credential không thể giải mã, vì vậy hãy đặt key một lần ngay bây giờ và không bao giờ sửa lại dòng đó.
Các biến môi trường quyết định webhook có hoạt động hay không
Bốn biến kiểm soát cách n8n tự nhận diện với bên ngoài. Cấu hình sai các biến này là nguyên nhân phổ biến nhất trong các câu hỏi hỗ trợ n8n.
N8N_HOSTlà hostname public,n8n.example.com. Nếu giữ giá trị mặc địnhlocalhostkhi chạy sau proxy, editor sẽ cố tải API của chính nó từlocalhosttrong trình duyệt của bạn, nên sẽ lỗi.N8N_PROTOCOL=httpscho n8n biết dịch vụ được cung cấp qua TLS. Vì vậy, n8n đánh dấu session cookie làSecurevà tạo các URLhttps://.N8N_PORT=5678là cổng n8n lắng nghe bên trong container. Đây không phải cổng public; proxy quản lý cổng 443.WEBHOOK_URL=https://n8n.example.com/là biến dễ gây lỗi nhất. n8n tạo các địa chỉ webhook mà bạn dán vào Stripe, GitHub hoặc bất kỳ bên gọi bên ngoài nào bằng cách ghép các giá trị này. Nếu biến này chưa được đặt hoặc đặt sai, n8n sẽ dùngN8N_HOST:N8N_PORTvà cung cấp cho bạnhttps://n8n.example.com:5678/webhook/...hoặc tệ hơn làhttp://localhost:5678/webhook/.... Địa chỉ được in ra mà không có lỗi, trông hợp lệ nhưng không thể truy cập từ Internet, nên request của bên gọi sẽ âm thầm không bao giờ đến được. Đặt biến này thành base URL public chính xác, có dấu gạch chéo ở cuối. Sau đó xác nhận webhook node hiển thị URL không có port.
N8N_PROXY_HOPS=1 cho Express server của n8n biết có một proxy nằm phía trước. Nhờ đó, rate limiting và mọi tính năng đọc client IP sẽ thấy địa chỉ thật thay vì địa chỉ của proxy. Một biến bạn cố ý không đặt ở đây là N8N_RUNNERS_ENABLED: task runner, tức n8n chạy logic của Code node trong một process sandbox riêng, đã là mặc định từ phiên bản 1.69 và bắt buộc trong dòng 2.x mà guide này cố định. Vì vậy, tùy chọn opt-in cũ đã deprecated. Nếu đặt biến này ngay bây giờ, n8n chỉ ghi một thông báo yêu cầu bạn xóa nó.
Khởi động lần đầu
docker compose up -d
docker compose ps
docker compose logs -f n8nLần boot đầu tiên thành công kết thúc bằng dòng Editor is now accessible via:, bên trên là dòng n8n ready on ..., port 5678. docker compose ps phải hiển thị cả hai container Up, trong đó postgres được đánh dấu (healthy). Nếu n8n rơi vào vòng lặp Restarting, hãy đọc log. Nguyên nhân gần như luôn là kết nối database hoặc quyền trên volume được trình bày bên dưới.
TLS với reverse proxy
Bản thân n8n sử dụng HTTP thường trên cổng 5678; một thành phần phía trước sẽ thực hiện TLS termination. Có 2 lựa chọn gọn.
Nếu bạn đã chạy nhiều container, hãy đặt n8n phía sau reverse proxy Traefik tự động cấp certificate TLS chỉ với một vài label. Traefik sẽ request và tự gia hạn certificate cho bạn.
Nếu đây là app duy nhất trên máy, một nginx virtual host với certificate Let's Encrypt sẽ đơn giản hơn. Dùng cấu hình Certbot và nginx TLS cho Ubuntu 24.04 để lấy certificate, sau đó dùng server block này:
server {
listen 443 ssl;
server_name n8n.example.com;
ssl_certificate /etc/letsencrypt/live/n8n.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.example.com/privkey.pem;
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-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600;
client_max_body_size 16m;
}
}Các header Upgrade và Connection "upgrade" là bắt buộc. n8n đẩy các cập nhật execution đang chạy đến editor qua WebSocket. Nếu thiếu 2 dòng này, trang đăng nhập sẽ tải xong rồi bị treo với banner mất kết nối. proxy_read_timeout 3600 ngăn các execution chạy lâu bị nginx ngắt sau 60 giây mặc định. Header X-Forwarded-Proto $scheme đi kèm với N8N_PROXY_HOPS=1: nó cho n8n biết request ban đầu sử dụng HTTPS dù proxy kết nối đến n8n qua HTTP thường. Nhờ đó, n8n không xác định kết nối là không an toàn rồi từ chối cookie của chính nó.
Workflow đầu tiên: biến nó thành hoạt động thực tế
Mở https://n8n.example.com/, tạo tài khoản owner (ở phần tiếp theo), rồi xây dựng workflow nhỏ nhất để xác nhận luồng hoạt động: nhận webhook, gọi HTTP và trả response.
- Thêm node Webhook. Đặt method là
POSTvà path nhưhello. Node này hiển thị 2 URL: Test URL và Production URL. Đây là nguyên nhân của một nửa số báo cáo kiểu “webhook của tôi không hoạt động”. Test URL chỉ nhận 1 request và chỉ hoạt động khi bạn đã bấm Listen for test event; sau đó URL hết hiệu lực. Production URL nhận request bất cứ khi nào workflow ở trạng thái Active. - Thêm node HTTP Request phía sau node đó và trỏ đến bất kỳ public JSON API nào. GET đến
https://api.github.com/zensẽ trả về một chuỗi trên một dòng, như vậy là đủ. - Thêm node Respond to Webhook. Đặt tùy chọn Respond của node Webhook thành "Using Respond to Webhook node" để bên gọi nhận lại output của HTTP node.
- Bật workflow Active ở góc trên bên phải rồi gọi workflow bằng
curl -X POST https://n8n.example.com/webhook/hello. Bạn sẽ nhận lại dòng zen: POST đi vào, API được gọi, response trả ra. Đây là cấu trúc của phần lớn automation thực tế.
Biến thể chạy theo lịch sẽ thay node Webhook bằng Schedule Trigger và gọi một model endpoint. Bạn có thể dùng một model self-hosted từ Ollama chạy trên cùng VPS để xây dựng một tool tóm tắt chạy hằng đêm.
Quản lý người dùng, không phải basic auth
Các hướng dẫn n8n cũ yêu cầu bạn đặt N8N_BASIC_AUTH_ACTIVE=true. Những biến đó đã bị gỡ trong n8n 1.0 và hiện không còn tác dụng. Hiện nay, cơ chế xác thực là tài khoản owner: lần đầu bạn mở editor, n8n yêu cầu bạn tạo tài khoản owner bằng email và password, và bước chặn này là bắt buộc; không có chế độ anonymous. Hãy tạo tài khoản ngay sau lần boot đầu tiên, trước khi cung cấp URL cho bất kỳ ai: trong khoảng thời gian từ docker compose up đến lần gửi form đầu tiên, bất kỳ ai truy cập được instance cũng có thể chiếm quyền sở hữu. Thêm một lớp basic-auth ở reverse proxy là biện pháp khóa bổ sung hợp lý, nhưng đó là lớp thứ hai, không phải cơ chế xác thực chính. Tài khoản owner và mọi nội dung khác trong hướng dẫn này đều chạy được trên community edition miễn phí; nếu sau này bạn cần thêm user với role chi tiết hoặc SSO, hãy đọc những tính năng n8n nào cần license trả phí trước khi lập kế hoạch dựa trên các tính năng đó.
Sao lưu: ưu tiên key mã hóa, sau đó đến database
Có hai thứ cần sao lưu, và khả năng thay thế chúng không giống nhau.
N8N_ENCRYPTION_KEY. Mọi credential bạn lưu trong n8n, token API, mật khẩu database và secret OAuth đều được mã hóa khi lưu bằng key này. Workflow trong Postgres sẽ vô dụng nếu thiếu key: nếu restore database lên một máy mới bằng key khác, n8n không thể giải mã bất kỳ credential nào, đồng thời không có cách khôi phục hoặc reset. File .env chứa key này. Hãy copy file ra khỏi server ngay khi tạo, tốt nhất là lưu trong password manager. Đây mới là bản backup thực sự quan trọng.
Database Postgres, chứa workflow, lịch sử thực thi và chính các credential đã mã hóa:
docker compose exec -T postgres pg_dump -U n8n -d n8n \
| gzip > n8n-db-$(date +%F).sql.gzHãy chạy lệnh này theo lịch và copy dump ra khỏi máy. Để restore trên VPS mới: khởi động stack một lần để tạo database, stop n8n, nạp lại dump bằng psql, đặt đúng N8N_ENCRYPTION_KEY vào .env, rồi start n8n. Key giống nhau cộng với dump sẽ tạo ra một instance hoạt động; key mới sẽ khiến các workflow không thể sử dụng bất kỳ credential nào.
Nâng cấp: cố định tag
File compose cố định n8nio/n8n:2.29.10 thay vì latest có chủ đích. n8n phát hành một bản minor mới hầu như mỗi tuần và đôi khi thay đổi schema database hoặc hành vi của node giữa các bản này, nên latest có nghĩa là một lần pull không được giám sát có thể cấp cho bạn một build migrate database ngay khi khởi động. Hãy cố định một version, đọc ghi chú phát hành trước khi nâng version; n8n sẽ nêu các thay đổi có khả năng gây lỗi tương thích ở đó. Sau đó nâng cấp một cách có chủ đích:
docker compose exec -T postgres pg_dump -U n8n -d n8n | gzip > pre-upgrade.sql.gz
# edit the image tag in docker-compose.yml, then:
docker compose pull n8n
docker compose up -d n8n
docker compose logs -f n8nViệc nâng qua major version là lúc điều này quan trọng nhất. Chẳng hạn, dòng 2.0 mặc định chuyển N8N_BLOCK_ENV_ACCESS_IN_NODE thành true, nên mọi Code node đọc process.env sẽ âm thầm mất quyền truy cập cho đến khi bạn đặt lại thành false; cùng bản phát hành đó cũng bắt đầu áp dụng nghiêm ngặt quyền trên file settings. Hãy đọc trang thay đổi gây lỗi tương thích trong 2.0 trước khi vượt qua ranh giới major version. n8n tự động chạy mọi database migration cần thiết khi khởi động. Đó chính là lý do pg_dump trước khi nâng cấp là bước bắt buộc. Vì credentials được mã hóa bằng một key trong .env còn dữ liệu nằm trong Postgres, các container có thể bị thay thế: bạn nâng cấp bằng cách thay thế chúng, và rollback bằng cách cố định tag trước đó rồi khôi phục dump.
Các tình huống lỗi và chuỗi log bạn sẽ thấy
The requested webhook "POST hello" is not registered. 404 khi gọi webhook của workflow chưa ở trạng thái Active, hoặc khi gọi đường dẫn test lúc không có tiến trình nào đang lắng nghe. Đường dẫn test (/webhook-test/...) chỉ phản hồi sau khi bạn nhấp vào "Listen for test event"; đường dẫn production (/webhook/...) chỉ phản hồi khi bật workflow. Mã lỗi cùng nhóm This webhook is not registered for GET requests. Did you mean to make a POST request? nghĩa là method không đúng: node yêu cầu POST nhưng bạn gửi GET.
URL webhook hiển thị :5678 hoặc localhost. Node hiển thị https://n8n.example.com:5678/webhook/... hoặc http://localhost:5678/.... WEBHOOK_URL chưa được đặt hoặc đặt sai, nên n8n tạo địa chỉ từ N8N_HOST:N8N_PORT thay vì base URL public của bạn. Đặt WEBHOOK_URL=https://n8n.example.com/, tạo lại container bằng docker compose up -d, rồi port sẽ biến mất.
There was a problem loading init data trong trình duyệt. Editor đã tải nhưng không thể kết nối đến backend API của chính nó. Khi chạy sau proxy, nguyên nhân gần như luôn là N8N_HOST hoặc WEBHOOK_URL sai, proxy thiếu các header WebSocket Upgrade, hoặc N8N_PROTOCOL không khớp với cách bạn kết nối. Xác nhận 4 biến hướng ra public và bảo đảm proxy chuyển tiếp Upgrade và Connection.
password authentication failed for user "n8n" trong log, đồng thời container liên tục restart. Password n8n gửi không khớp với password đã dùng để khởi tạo database. Điểm dễ nhầm là Postgres chỉ đọc POSTGRES_PASSWORD khi khởi tạo một data directory trống. Khởi động stack một lần, sau đó đổi POSTGRES_PASSWORD trong .env, thì volume postgres_data hiện có vẫn giữ password cũ. Đặt lại password ban đầu hoặc, nếu không cần giữ dữ liệu, docker compose down và docker volume rm volume của Postgres, rồi khởi động lại từ đầu.
EACCES: permission denied, open '/home/node/.n8n/config' khi khởi động. n8n chạy dưới user node (UID 1000) và không thể ghi vào config directory. Lỗi này thường xảy ra khi bạn bind-mount một thư mục trên host (./n8n_data:/home/node/.n8n) đang thuộc sở hữu của root. Dùng named volume như phần trên, hoặc nếu nhất thiết phải bind mount thì chạy sudo chown -R 1000:1000 ./n8n_data trước.
Permissions 0644 for n8n settings file /home/node/.n8n/config are too wide. Changing permissions to 0600.. Từ dòng 2.x, n8n mặc định áp dụng 0600 cho settings file đó và tự sửa khi boot. Dòng log này nghĩa là n8n đã sửa mode, thường sau khi bind mount hoặc sau khi restore chép file trở lại với permissions quá rộng. Không cần làm gì; chỉ đặt N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false nếu filesystem của bạn thực sự không hỗ trợ permissions.
Mismatching encryption keys, dòng đầy đủ cho biết encryption key trong settings file /home/node/.n8n/config không khớp với N8N_ENCRYPTION_KEY trong environment của bạn. Key trong environment khác với key n8n đã ghi vào data volume trong lần chạy trước. Nguyên nhân thường gặp nhất là n8n đã tự tạo key ngẫu nhiên ở lần boot trước khi biến này chưa được đặt, sau đó bạn đặt một key khác. Khôi phục key ban đầu trong .env hoặc, chỉ khi bạn thực sự không có stored credentials nào cần giữ, xóa file config bên trong volume n8n_data rồi để n8n tạo lại. Các credentials hiện có sẽ không thể đọc được.
Banner đăng nhập báo secure cookies: Your n8n server is configured to use a secure cookie, however you are either visiting this via an insecure URL, or using Safari. Bạn đã đặt N8N_PROTOCOL=https nhưng truy cập n8n qua HTTP không mã hóa, thường do truy cập trực tiếp bằng IP và port thay vì qua HTTPS proxy. Hãy truy cập qua https://n8n.example.com/. Chỉ đặt N8N_SECURE_COOKIE=false nếu bạn thực sự không thể dùng HTTPS, và tuyệt đối không đặt trên máy chủ hướng ra Internet.
Để đưa language model vào các workflow đó, xem xây dựng workflow AI với Claude và n8n.
FAQ
Tôi nên dùng SQLite hay Postgres cho n8n?
SQLite (mặc định) phù hợp để thử n8n và chạy một instance cá nhân chỉ thực thi mỗi lần một workflow. Hãy chuyển sang Postgres cho mọi thứ quan trọng: single-writer lock của SQLite gây ra database is locked khi có concurrency, còn Postgres có thể backup sạch bằng pg_dump. Việc migrate sau này phải làm thủ công, nên nếu server này quan trọng, hãy dùng Postgres ngay từ đầu.
Tại sao webhook của n8n không bao giờ được gọi?
Gần như luôn là do WEBHOOK_URL. Khi biến này chưa được set hoặc có giá trị sai, n8n tạo địa chỉ webhook từ N8N_HOST:N8N_PORT, thường chứa :5678 hoặc localhost. Các địa chỉ này trông hợp lệ nhưng không thể truy cập từ Internet, nên request của bên gọi không bao giờ đến được. Hãy set WEBHOOK_URL=https://n8n.example.com/ và xác nhận node hiển thị URL không có port. Nguyên nhân thứ hai là gọi một webhook thuộc workflow chưa được bật Active, nên trả về The requested webhook ... is not registered.
Tôi phải backup những gì trong n8n?
Có 2 thứ. Thứ nhất là N8N_ENCRYPTION_KEY trong file .env của bạn, vì mọi credential được lưu đều được mã hóa bằng giá trị này. Nếu mất giá trị này, các credential sẽ vĩnh viễn không thể giải mã; hãy copy nó ra khỏi server ngay trong ngày tạo. Thứ hai là pg_dump của database Postgres chứa workflow, lịch sử và credential. Việc restore cần cả hai: đúng key và dump.
Làm thế nào để đặt n8n phía sau HTTPS?
n8n phục vụ HTTP thuần trên port 5678; reverse proxy phía trước sẽ thực hiện TLS termination. Bind n8n vào 127.0.0.1:5678 để chỉ proxy có thể truy cập, sau đó dùng Traefik với certificate tự động hoặc nginx với certificate Let's Encrypt. Set N8N_PROTOCOL=https và WEBHOOK_URL=https://your-host/, đồng thời bảo đảm proxy forward các header WebSocket Upgrade; nếu không, editor sẽ bị treo.
Làm thế nào để upgrade n8n an toàn?
Pin một image tag cụ thể thay vì latest, tạo pg_dump trước vì n8n tự động chạy migration khi khởi động, đọc release notes để kiểm tra breaking change, sau đó tăng tag và chạy docker compose pull n8n && docker compose up -d n8n. Container có thể tạo lại, nên để rollback, hãy pin tag trước đó và restore dump trước khi upgrade.