Cách tự cài n8n trên VPS dùng Docker và HTTPS
Hướng dẫn cài n8n với Docker Compose và Postgres. Cách xử lý lỗi WEBHOOK_URL và encryption-key để đảm bảo workflow và webhook hoạt động ổn định.
Những gì bạn đang xây dựng
n8n là một công cụ tự động hóa workflow: một trình chỉnh sửa trực quan nơi một trigger — như webhook, lịch trình (schedule), hoặc gửi form — sẽ kích hoạt một chuỗi các node để gọi API, định dạng lại dữ liệu và ghi vào các hệ thống khác. Nó đã trở thành "chất keo" mặc định cho các workflow AI-agent vì nó có thể kết nối với mọi nhà cung cấp model và database mà bạn không cần phải tự viết service. Chỉ cần một docker run là bạn có một trình chỉnh sửa hoạt động được trong hai phút. Hướng dẫn này tập trung vào 90% còn lại: làm cho nó hoạt động bền bỉ bằng cách dùng Postgres thay vì file SQLite mặc định, giúp có thể truy cập qua HTTPS, và — phần mà hầu hết mọi người đều làm sai — làm sao để webhook trả về một URL mà thế giới bên ngoài thực sự có thể truy cập được.
Stack hoàn chỉnh gồm hai container trên một Docker network: bản thân n8n, và một Postgres database để lưu trữ workflow và credentials. Một reverse proxy trên host sẽ xử lý TLS và chuyển tiếp yêu cầu đến n8n trên localhost, vì vậy không có gì tiếp xúc với internet ngoại trừ thông qua proxy đó. Nó nằm cùng với các dịch vụ khác trong danh sách 2026 self-hosting shortlist.
Điều kiện tiên quyết, và những giới hạn thực tế
Bạn cần một VPS có ít nhất 1 GB RAM; hãy chuẩn bị sẵn 2 GB khi workflow bắt đầu chạy thực tế, vì các tiến trình thực thi cộng với runtime của Node.js ngốn rất nhiều bộ nhớ, và việc OOM killer (out-of-memory killer) kill container khi đang chạy là một trải nghiệm rất tệ. Một vCPU là đủ để bắt đầu.
Bạn cần một domain hoặc subdomain — ví dụ n8n.example.com — với một A record trỏ đến IP public của VPS và phải phân giải được trước khi bạn yêu cầu certificate. Các port 80 và 443 phải được mở cho proxy; port 5678 của riêng n8n không được mở ra internet. Bạn cần Docker Engine và plugin Compose; nếu docker compose version báo lỗi docker: 'compose' is not a docker command thì bạn đang dùng bản binary standalone cũ, và plugin là sudo apt install docker-compose-plugin.
SQLite dùng để test thì được, Postgres mới dùng để chạy thực tế
Database mặc định của n8n là một file SQLite tại /home/node/.n8n/database.sqlite. Để dùng thử thì không vấn đề gì — nếu không mount volume thì bạn sẽ mất dữ liệu ngay khi recreate container đầu tiên, đó cũng là một bài học kinh nghiệm. Lý do để chuyển sang Postgres không phải là tốc độ thuần túy; mà là vì SQLite sử dụng single writer lock, nên một instance chạy nhiều workflow cùng lúc, hoặc chế độ queue mà bạn sẽ cần sau này, sẽ gây ra lỗi SQLITE_BUSY: database is locked khi có concurrency. Postgres không gặp giới hạn đó, backup cực kỳ sạch sẽ với pg_dump, và là cấu hình mà tài liệu chính thức của n8n khuyến nghị cho một server chạy thực tế. Việc chuyển đổi sau này đồng nghĩa với việc phải migrate dữ liệu bằng tay, vì vậy nếu server này quan trọng, hãy bắt đầu với Postgres ngay từ đầu.
DNS và firewall
Hãy trỏ record và mở các port trước, để bước lấy certificate sau đó không bị lỗi do không phân giải được tên miền.
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 enableĐừng mở port 5678. File compose bind n8n vào 127.0.0.1:5678 để chỉ có reverse proxy của host mới có thể truy cập được, và một ufw allow 5678 sẽ phá vỡ sự cô lập này.
File Compose
Tạo một thư mục làm việc và một file docker-compose.yml. Đây là toàn bộ stack — hai service, một private network, 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:Một vài quyết định cần nêu rõ. DB_POSTGRESDB_HOST=postgres là service name, Docker sẽ resolve nó trên shared network — không phải localhost, cái mà bên trong container n8n có nghĩa là chính n8n. Việc dùng depends_on với condition: service_healthy giúp n8n không bị tranh chấp với Postgres khi boot; nếu không có nó, n8n sẽ khởi động, không tìm thấy database và thoát. Named volume n8n_data tại /home/node/.n8n giữ encryption key và (nếu dùng SQLite) là cả database — đây là thư mục duy nhất bạn tuyệt đối không được làm mất. Hãy pin image ở một version chính xác, đừng bao giờ dùng latest; lý do nằm ở phần upgrade bên dưới.
File secrets
Đừng bao giờ để password trong file compose. Hãy để chúng trong một file .env nằm cạnh nó để Compose tự động đọc, và hãy tạo chúng cho 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 — nó là key mà mọi credential được lưu trữ sẽ dùng để encrypt. Hãy set nó một cách tường minh thay vì để n8n tự generate, vì một giá trị bạn tự tạo là một giá trị bạn có thể ghi chép lại và khôi phục được. Một khi n8n đã encrypt credential đầu tiên bằng key này, việc thay đổi nó sẽ khiến mọi credential không thể giải mã được nữa — vì vậy hãy set một lần duy nhất, ngay bây giờ, và đừng bao giờ chạm vào dòng đó nữa.
Các biến env quyết định webhook có hoạt động hay không
Bốn biến sẽ kiểm soát cách n8n mô tả chính nó với thế giới bên ngoài, và việc cấu hình sai chúng là câu hỏi support n8n phổ biến nhất.
N8N_HOSTlà hostname công khai,n8n.example.com. Nếu để mặc định làlocalhostkhi chạy sau một proxy, trình chỉnh sửa sẽ cố gắng load API của chính nó từlocalhosttrong trình duyệt của bạn, và việc này sẽ thất bại.N8N_PROTOCOL=httpsbáo cho n8n biết nó đang chạy qua TLS, do đó nó sẽ đánh dấu session cookie làSecurevà xây dựng các URLhttps://.N8N_PORT=5678là port mà n8n lắng nghe bên trong container. Đây không phải là port public; proxy sẽ giữ port 443.WEBHOOK_URL=https://n8n.example.com/là biến gây rắc rối nhất. n8n in ra các webhook address mà bạn dán vào Stripe, GitHub hoặc bất kỳ bên gọi nào bằng cách build chúng từ các giá trị này. Nếu nó không được set hoặc bị sai, n8n sẽ fallback vềN8N_HOST:N8N_PORTvà trả vềhttps://n8n.example.com:5678/webhook/...hoặc tệ hơn làhttp://localhost:5678/webhook/...— nó in ra mà không có lỗi, trông có vẻ hợp lệ nhưng không thể truy cập được từ internet, khiến các request từ bên ngoài không bao giờ đến được. Hãy set nó thành URL base public chính xác kèm dấu gạch chéo ở cuối, sau đó xác nhận node webhook hiển thị một URL không có port.
N8N_PROXY_HOPS=1 báo cho Express server của n8n biết để tin tưởng một proxy đứng trước nó, giúp rate-limiting và các tính năng đọc client IP thấy được địa chỉ thật thay vì địa chỉ của proxy. Một biến mà bạn chủ động không set ở đây là N8N_RUNNERS_ENABLED: task runners — n8n chạy logic Code-node trong một process sandbox riêng biệt — đã là mặc định từ bản 1.69 và là bắt buộc từ dòng 2.x mà hướng dẫn này sử dụng, nên tùy chọn opt-in cũ đã bị deprecated. Hãy set nó ngay bây giờ và n8n sẽ chỉ log một thông báo bảo bạn hãy xóa nó đi.
Khởi động lần đầu
docker compose up -d
docker compose ps
docker compose logs -f n8nMột lần boot đầu tiên thành công sẽ kết thúc bằng một dòng Editor is now accessible via:, với một dòng n8n ready on ..., port 5678 ở phía trên. docker compose ps nên hiển thị cả hai container ở trạng thái Up, với postgres được đánh dấu là (healthy). Nếu n8n rơi vào vòng lặp Restarting, hãy đọc logs — hầu hết luôn là do kết nối database hoặc quyền của volume như đã đề cập bên dưới.
TLS với reverse proxy
Bản thân n8n chạy HTTP thuần trên port 5678; một thứ gì đó đứng trước sẽ xử lý TLS. Có hai lựa chọn gọn gàng.
Nếu bạn đã chạy sẵn nhiều container, hãy đặt n8n sau một Traefik reverse proxy tự động cấp TLS certificate với một vài labels — Traefik sẽ yêu cầu và gia hạn certificate cho bạn.
Nếu đây là app duy nhất trên server, một nginx virtual host với Let's Encrypt certificate sẽ đơn giản hơn. Sử dụng thiết lập 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 thực thi trực tiếp lên trình chỉnh sửa qua WebSocket, và nếu thiếu hai dòng này, trang login sẽ load xong rồi treo với banner "lost-connection". proxy_read_timeout 3600 giúp các tiến trình thực thi chạy lâu không bị ngắt bởi giới hạn 60 giây mặc định của nginx. Header X-Forwarded-Proto $scheme đi kèm với N8N_PROXY_HOPS=1: nó báo cho n8n biết request gốc là HTTPS mặc dù proxy kết nối với nó qua HTTP thuần, giúp n8n không coi kết nối là không an toàn và reject cookie của chính nó.
Workflow đầu tiên để kiểm chứng
Mở https://n8n.example.com/, tạo tài khoản owner (xem phần tiếp theo), và xây dựng một workflow nhỏ nhất để chứng minh đường truyền đã thông: một webhook nhận vào, một HTTP call, và một response trả về.
- Thêm một node Webhook. Set method là
POSTvà path kiểu nhưhello. Nó sẽ hiển thị hai URL: Test URL và Production URL — đây là nguồn cơn của một nửa các báo cáo "webhook của tôi không hoạt động". Test URL chỉ trả lời một lần duy nhất và chỉ khi bạn đã nhấn Listen for test event; sau đó nó sẽ hết hạn. Production URL sẽ trả lời bất cứ khi nào workflow ở trạng thái Active. - Thêm một node HTTP Request ngay sau đó, trỏ đến bất kỳ public JSON API nào — một lệnh GET tới
https://api.github.com/zentrả về một chuỗi một dòng là đủ. - Thêm một node Respond to Webhook, và set tùy chọn Respond của node Webhook thành "Using Respond to Webhook node" để bên gọi nhận được output từ node HTTP.
- Bật workflow sang Active (góc trên bên phải) và gọi nó:
curl -X POST https://n8n.example.com/webhook/hello. Bạn sẽ nhận lại được kết quả mong muốn — POST vào, gọi API, trả kết quả ra, đó chính là hình thái của hầu hết các automation thực tế.
Một biến thể theo lịch trình (scheduled) sẽ thay thế node Webhook bằng một Schedule Trigger và gọi đến một model endpoint — dùng một model tự host từ Ollama chạy trên cùng VPS là cách gọn gàng để xây dựng một bộ tóm tắt dữ liệu hàng đêm.
Quản lý người dùng, không phải basic auth
Các hướng dẫn n8n cũ bảo bạn hãy set N8N_BASIC_AUTH_ACTIVE=true. Những biến đó đã bị xóa trong n8n 1.0 và hiện không có tác dụng gì. Xác thực ngày nay dựa trên tài khoản owner: lần đầu bạn load trình chỉnh sửa, n8n yêu cầu bạn tạo một owner bằng email và password, và bước này là bắt buộc — không có chế độ ẩn danh. Hãy tạo nó ngay sau khi boot lần đầu, trước khi bạn đưa URL cho bất kỳ ai: giữa docker compose up và lần submit form đầu tiên đó, instance có thể bị chiếm quyền bởi bất kỳ ai đến trước. Một lớp basic-auth của reverse-proxy cài thêm là một lớp khóa bổ sung hợp lý, nhưng nó chỉ là yếu tố thứ hai, không phải là xác thực thực sự.
Backup: ưu tiên encryption key trước, rồi mới đến database
Có hai thứ cần backup, và chúng không có giá trị thay thế như nhau.
N8N_ENCRYPTION_KEY. Mọi credential bạn lưu trong n8n — API tokens, database passwords, OAuth secrets — đều được encrypt tại chỗ bằng key này. Các workflow trong Postgres sẽ vô dụng nếu thiếu nó: nếu bạn restore database lên một server mới với một key khác, n8n sẽ không thể decrypt được bất kỳ credential nào, và không có cách nào để khôi phục hay reset. File .env của bạn giữ key này; hãy copy nó ra khỏi server — dùng một password-manager là lý tưởng nhất — ngay ngày bạn tạo ra nó. Đây mới là bản backup thực sự quan trọng.
Postgres database, dùng cho workflow, lịch sử thực thi và chính các credentials đã được encrypt:
docker compose exec -T postgres pg_dump -U n8n -d n8n \
| gzip > n8n-db-$(date +%F).sql.gzHãy chạy lệnh đó theo lịch trình và copy file dump ra khỏi server. Để restore trên một VPS mới: hãy chạy stack lên một lần để database tồn tại, stop n8n, load dump trở lại bằng psql, đưa N8N_ENCRYPTION_KEY giống hệt vào .env, và start n8n. Cùng một key cộng với file dump sẽ tạo ra một instance hoạt động được; một key mới sẽ tạo ra các workflow không thể dùng được bất kỳ credential nào.
Upgrade: hãy pin tag
File compose cố tình pin n8nio/n8n:2.29.10 thay vì latest. n8n phát hành 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 đó, vì vậy latest có nghĩa là một lệnh pull tự động có thể đưa cho bạn một bản build sẽ migrate database ngay khi nó khởi động. Hãy pin một version cụ thể, đọc release notes trước khi nâng cấp — n8n có liệt kê các breaking changes ở đó — và hãy upgrade một cách chủ động:
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 n8nCác bước nhảy version lớn (major-version) là lúc điều này quan trọng nhất. Ví dụ, dòng 2.0 đã đổi N8N_BLOCK_ENV_ACCESS_IN_NODE thành true theo mặc định, nên bất kỳ Code node nào đọc process.env sẽ bị mất quyền truy cập âm thầm cho đến khi bạn set lại thành false; cùng bản release đó cũng bắt đầu áp dụng quyền nghiêm ngặt lên file settings. Hãy đọc trang breaking-changes của bản 2.0 trước khi bước qua một ranh giới major. n8n tự động chạy các database migrations cần thiết khi khởi động — đó chính là lý do tại sao bước pre-upgrade pg_dump là bắt buộc. Vì credentials được encrypt bằng một key trong .env và dữ liệu nằm trong Postgres, các container là có thể vứt bỏ được: bạn upgrade bằng cách thay thế chúng, và rollback bằng cách pin tag cũ và restore file dump.
Các lỗi thường gặp, kèm theo các chuỗi thông báo bạn sẽ thấy
The requested webhook "POST hello" is not registered. Lỗi 404 khi gọi một webhook mà workflow chưa ở trạng thái Active, hoặc khi gọi test path khi không có ai đang lắng nghe. Test paths (/webhook-test/...) chỉ trả lời khi bạn đã nhấn "Listen for test event"; production paths (/webhook/...) chỉ trả lời khi toggle workflow đang bật. Lỗi This webhook is not registered for GET requests. Did you mean to make a POST request? có nghĩa là method bị sai — node đang đợi POST nhưng bạn lại 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 bị unset hoặc sai, nên n8n đã build địa chỉ từ N8N_HOST:N8N_PORT thay vì base URL public của bạn. Hãy set WEBHOOK_URL=https://n8n.example.com/, recreate container với docker compose up -d, và port sẽ biến mất.
There was a problem loading init data trong trình duyệt. Trình chỉnh sửa đã load nhưng không thể kết nối tới backend API của chính nó. Khi chạy sau proxy, lỗi này hầu như luôn là do sai N8N_HOST hoặc WEBHOOK_URL, 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. Hãy xác nhận 4 biến public-facing và đảm bảo proxy forward Upgrade và Connection.
password authentication failed for user "n8n" trong logs, kèm theo việc container đang restart liên tục. Password n8n gửi đi không khớp với password lúc database được khởi tạo. Một cái bẫy: Postgres chỉ đọc POSTGRES_PASSWORD khi nó khởi tạo một data directory trống. Hãy chạy stack lên một lần, sau đó đổi POSTGRES_PASSWORD trong .env, và volume postgres_data hiện tại vẫn giữ password cũ. Hãy set lại về giá trị gốc, hoặc nếu bạn không có dữ liệu nào cần giữ, hãy docker compose down và docker volume rm volume postgres, rồi chạy 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 thư mục config. Lỗi này thường gặp với những người bind-mount một folder của host (./n8n_data:/home/node/.n8n) thuộc sở hữu của root. Hãy dùng named volume như trên, hoặc nếu bạn vẫn muốn dùng bind mount, hãy dùng 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 lên file settings đó và tự sửa lỗi khi boot — dòng log này có nghĩa là nó đã sửa mode, thường là sau khi bind mount hoặc sau khi restore file bị sai permission. Không cần làm gì cả; chỉ set N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false nếu filesystem của bạn thực sự không hỗ trợ permission.
Mismatching encryption keys — dòng đầy đủ hơn nói rằng encryption key trong file settings /home/node/.n8n/config không khớp với N8N_ENCRYPTION_KEY trong môi trường của bạn. Key trong môi trường khác với key mà n8n đã ghi vào data volume ở lần chạy trước — thường nhất là do n8n đã tự tạo một key ngẫu nhiên ở lần boot trước khi biến đó chưa được set, và sau đó bạn lại set một key khác. Hãy đưa key gốc trở lại .env, hoặc nếu bạn thực sự không có credential nào quan trọng, hãy xóa file config bên trong volume n8n_data và để n8n tự tạo lại — nhưng hãy chấp nhận rằng các credential cũ sẽ không thể đọc được nữa.
Thông báo login về 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 đã set N8N_PROTOCOL=https nhưng lại truy cập n8n qua HTTP thuần — thường là do bạn gõ trực tiếp IP và port thay vì qua HTTPS proxy. Hãy truy cập qua https://n8n.example.com/. Chỉ khi bạn thực sự không thể dùng HTTPS mới nên set N8N_SECURE_COOKIE=false, và tuyệt đối không set trên một server chạy public.
Để đưa một language model vào các workflow này, hãy xem xây dựng AI workflow với Claude và n8n.
FAQ
Tôi nên dùng SQLite hay Postgres cho n8n?
SQLite (mặc định) dùng để dùng thử n8n và cho một instance cá nhân chạy từng workflow một là ổn. Hãy chuyển sang Postgres cho bất cứ thứ gì bạn cần chạy thực tế: single writer lock của SQLite sẽ gây ra lỗi database is locked khi có concurrency, và Postgres hỗ trợ backup sạch sẽ với pg_dump. Việc migrate sau này là thủ công, nên nếu server quan trọng, hãy bắt đầu với Postgres.
Tại sao webhook n8n của tôi không bao giờ chạy?
Hầu hết luôn là do WEBHOOK_URL. Nếu không được set hoặc bị sai, n8n sẽ in ra các webhook address được build từ N8N_HOST:N8N_PORT — thường kèm theo :5678 hoặc localhost — trông có vẻ hợp lệ nhưng không thể truy cập được từ internet, khiến request không bao giờ đến được. Hãy set WEBHOOK_URL=https://n8n.example.com/ và xác nhận node hiển thị một URL không có port. Nguyên nhân thứ hai là gọi một webhook mà workflow chưa được bật Active, nó sẽ trả về The requested webhook ... is not registered..
Tôi cần backup những gì trong n8n?
Hai thứ. N8N_ENCRYPTION_KEY từ file .env của bạn, vì mọi credential được lưu trữ đều được encrypt bằng nó và nếu mất nó, chúng sẽ vĩnh viễn không thể giải mã — hãy copy nó ra khỏi server ngay ngày bạn tạo ra nó. Và một bản pg_dump của Postgres database để lưu workflow, lịch sử và credentials. Khi restore cần cả hai: cùng một key cộng với file dump.
Làm sao để chạy n8n qua HTTPS?
n8n chạy HTTP thuần trên port 5678; một reverse proxy đứng trước sẽ xử lý TLS. Hãy bind n8n vào 127.0.0.1:5678 để chỉ proxy mới truy cập được, sau đó dùng Traefik với auto-certificate hoặc nginx với Let's Encrypt. Set N8N_PROTOCOL=https và WEBHOOK_URL=https://your-host/, và đảm bảo proxy forward các header WebSocket Upgrade nếu không trình chỉnh sửa sẽ bị treo.
Làm sao để upgrade n8n an toàn?
Hãy pin một image tag cụ thể thay vì dùng latest, hãy take một pg_dump trước vì n8n tự chạy migrations khi khởi động, đọc release notes để xem các breaking changes, sau đó nâng tag và chạy docker compose pull n8n && docker compose up -d n8n. Container là có thể vứt bỏ, nên nếu lỗi hãy rollback bằng cách pin tag cũ và restore file dump trước khi upgrade.