AI Automation

Backup n8n đúng cách: encryption key, database và credential

Bạn chạy n8n trên VPS được vài tháng, có chục workflow tự động hoá xử lý email, gửi báo giá, đồng bộ dữ liệu giữa CRM và Google Sheets. Rồi một hôm, ổ cứng hỏng, hoặc bạn lỡ tay xoá nhầm container Docker. Bạn nghĩ "có snapshot máy ảo" là yên tâm. Nhưng khi restore lại n8n từ bản snapshot đó, mọi credential, API key, token, mật khẩu, đều báo lỗi "decryption failed". Đó là lúc bạn nhận ra: backup cả VPS thôi chưa đủ, bạn phải backup encryption key của n8n riêng biệt. Bài này hướng dẫn backup n8n đúng kiến trúc: encryption key, cơ sở dữ liệu PostgreSQL, và credential, kèm script tự động và cách kiểm tra restore để không còn bất ngờ.

Vì sao mất encryption key là mất sạch credential?

n8n mã hoá tất cả credential (API key, token kết nối) trước khi lưu vào database. Khoá giải mã là encryption key do bạn khai báo qua biến môi trường N8N_ENCRYPTION_KEY (hoặc ENCRYPTION_KEY với bản cũ). Nếu bạn restore database từ backup nhưng thiếu key gốc, n8n khởi động với key mới → không thể giải mã dữ liệu cũ. Kết quả: mọi workflow có kết nối tới dịch vụ bên ngoài (Slack, Gmail, Telegram, database…) đều đỏ. Bạn phải tạo lại toàn bộ credential thủ công, tốn hàng giờ.

Quy tắc sống còn: backup encryption key đi kèm với backup database. Hai thứ này phải được lưu ở ít nhất hai nơi khác nhau. Đừng để key nằm riêng biệt trong file docker-compose.yml trên cùng VPS đó.

Bước 1, Xác định kiến trúc n8n đang chạy

Trước khi viết script backup, bạn cần biết mình đang chạy n8n kiểu gì. Đa phần tự host n8n trên VPS dùng Docker Compose với stack: một service n8n + một service PostgreSQL. File cấu hình docker-compose.yml thường chứa encryption key dạng:

services:
  n8n:
    image: n8nio/n8n:latest
    environment:
      - N8N_ENCRYPTION_KEY=your-32-char-key-here
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      ...
  postgres:
    image: postgres:15
    environment:
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=strongpass
      - POSTGRES_DB=n8n

Bạn cần sao lưu 3 thành phần: (1) file docker-compose.yml (có chứa key), (2) database PostgreSQL (dump SQL), (3) thư mục .n8n nếu bạn có config tuỳ chỉnh (tùy chọn).

Bước 2, Script backup đầy đủ n8n

Script dưới đây chạy trên VPS Linux (Ubuntu 24.04 hoặc Debian 12). Nó backup dung lượng database PostgreSQL, copy encryption key, nén và đẩy ra thư mục riêng. Tạo file /usr/local/bin/backup-n8n.sh:

#!/bin/bash
# Backup n8n: database + encryption key
set -e

BACKUP_DIR="/var/backups/n8n"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR/$DATE"

# 1. Backup encryption key (từ docker-compose.yml)
cp /opt/n8n/docker-compose.yml "$BACKUP_DIR/$DATE/docker-compose.yml"

# 2. Backup PostgreSQL database
docker exec $(docker ps -qf "name=n8n-postgres") pg_dump -U n8n n8n > "$BACKUP_DIR/$DATE/n8n_dump.sql"

# 3. Nén và mã hoá (tuỳ chọn, dùng gpg nếu cần)
tar czf "$BACKUP_DIR/n8n_backup_$DATE.tar.gz" -C "$BACKUP_DIR" "$DATE"
rm -rf "$BACKUP_DIR/$DATE"

# 4. Xoá backup cũ hơn 30 ngày
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete

echo "Backup hoàn tất: $BACKUP_DIR/n8n_backup_$DATE.tar.gz"

Giải thích lệnh: pg_dump chạy bên trong container PostgreSQL, xuất ra file SQL. File docker-compose.yml chứa cả encryption key, nên được copy riêng (không nằm trong database). Bạn có thể thay docker exec bằng docker compose exec nếu dùng Compose v2.

Verify ngay: chạy thử script và kiểm tra file .tar.gz vừa tạo có dung lượng > 0:

bash /usr/local/bin/backup-n8n.sh
ls -lh /var/backups/n8n/

Output mong đợi: file n8n_backup_20260315_120000.tar.gz có size vài MB đến vài chục MB (tuỳ số workflow).

Bước 3, Tự động backup theo lịch với cron

Gắn script vào cron để chạy mỗi ngày một lần. Mở crontab cho root:

sudo crontab -e

Thêm dòng:

0 2 * * * /bin/bash /usr/local/bin/backup-n8n.sh

Giải thích: chạy lúc 2:00 sáng mỗi ngày. Nếu bạn lo ngại dung lượng backup ảnh hưởng đến hiệu năng I/O của VPS, đặc biệt nếu VPS dùng ổ NVMe có workload database nặng, thì nên đặt cron vào giờ thấp điểm (thường 2-4 giờ sáng). Kiểm tra cron đã active:

grep "backup-n8n" /var/log/syslog | tail -5

Nếu log không có, kiểm tra service cron daemon:

systemctl status cron

Bước 4, Diễn tập restore (bước quan trọng nhất nhưng ít ai làm)

Backup không có restore = rác. Ít nhất mỗi quý một lần, bạn nên diễn tập restore trên một VPS khác (hoặc trên chính VPS sau khi snapshot). Các bước restore thực tế:

  1. Khôi phục file docker-compose.yml: copy lại file vào thư mục làm việc, nhưng đừng chạy docker compose up ngay. Kiểm tra encryption key còn nguyên không.
  2. Khôi phục database: tạo container PostgreSQL trống, sau đó chạy psql -U n8n n8n < n8n_dump.sql để nạp dữ liệu cũ.
  3. Khởi động n8n: chạy docker compose up -d rồi kiểm tra log: docker logs n8n -f, phải thấy "Server is ready" và không có lỗi "decryption failed".
  4. Kiểm tra credential thực tế: đăng nhập vào n8n, vào mục Credentials, mở một credential bất kỳ, phải hiển thị được giá trị (không báo lỗi).
  5. Chạy thử một workflow cũ: kích hoạt workflow có kết nối thật (ví dụ gửi email, call API) để kiểm tra credential hoạt động.

Mẹo: Nếu restore vào VPS n8n giá rẻ chạy sẵn, bạn chỉ cần copy file config và database, khởi động lại dịch vụ. Lưu ý IPv4 của VPS mới có thể khác, cập nhật DNS record nếu bạn trỏ domain tới VPS đó.

Xử lý lỗi thường gặp khi backup/restore n8n

Lỗi 1: "decryption failed" sau restore
Nguyên nhân: encryption key không khớp với database. Kiểm tra file docker-compose.yml bạn restore có đúng key gốc không. Nếu bạn dùng file .env riêng, kiểm tra biến N8N_ENCRYPTION_KEY trong file đó. Cách khắc phục: copy lại key gốc và chạy docker compose down && docker compose up -d.

Lỗi 2: pg_dump báo "connection refused"
Script backup chạy trước khi container PostgreSQL sẵn sàng, hoặc container đã down. Kiểm tra bằng docker ps | grep postgres. Thêm lệnh sleep vào script nếu cần: sleep 5 trước lệnh dump.

Lỗi 3: File backup bị corrupt do ổ đầy
Kiểm tra dung lượng trống: df -h /var/backups. Nếu ít hơn 2GB, backup có thể bị lỗi giữa chừng. Dùng thêm script cảnh báo: nếu backup không tạo ra file hoặc file 0 byte → gửi Telegram. Xem bài gửi cảnh báo hệ thống VPS qua Telegram bot để tham khảo cách triển khai.

Backup ra ngoài VPS, chiến lược hai nơi

Lưu backup trên cùng VPS là rủi ro: nếu VPS hỏng ổ, mất cả gốc lẫn backup. Bạn nên đẩy backup ra nơi khác. Các phương án phổ biến:

Phương án rẻ và đơn giản: rsync mỗi ngày tới VPS Linux thứ hai (có thể là gói VNLite 1 vCPU / 2 GB RAM). Bạn cần mở port SSH trên VPS backup và cấu hình key pair cho phép rsync tự động.

Thành phầnPhương pháp backupTần suất đề xuất
Encryption keyCopy file docker-compose.yml (hoặc .env)Mỗi lần thay đổi key
Database PostgreSQLpg_dumpHàng ngày
CredentialĐã nằm trong database backup(theo database)
Thư mục tùy chỉnh (nếu có)tar + rsyncHàng tuần

Câu hỏi thường gặp

Tôi có thể backup n8n bằng snapshot VPS thay vì dump database không?

Có, snapshot VPS là bản sao toàn bộ ổ đĩa, bao gồm database và encryption key. Nhưng snapshot không thay thế được dump database khi bạn cần restore riêng lẻ (ví dụ migrate lên VPS mới hoặc chỉ muốn lấy dữ liệu workflow). hàng đầu dùng cả hai.

Encryption key có thể thay đổi được không? Nếu tôi bị lộ key thì sao?

Không thể thay đổi encryption key sau khi n8n đã lưu credential, vì credential đã được mã hoá bằng key cũ. Nếu bị lộ, bạn phải tạo lại toàn bộ credential hoặc migrate sang instance n8n mới với key mới (rất phức tạp). Bảo vệ encryption key như bảo vệ mật khẩu gốc.

Script backup có chạy được với n8n dạng binary (không Docker) không?

Có, chỉ khác lệnh dump PostgreSQL: thay vì docker exec, bạn chạy pg_dump -U n8n n8n trực tiếp. Còn encryption key nằm trong file .n8n/config hoặc biến môi trường, cần backup riêng.

Làm sao để kiểm tra file backup không bị lỗi trước khi restore?

Giải nén file .tar.gz và kiểm tra: tar tzf backup.tar.gz xem có đủ 2 file không. Sau đó mở file dump SQL kiểm tra dòng đầu có chứa -- PostgreSQL database dump. Nếu không có, backup hỏng.

Tôi nên lưu backup ở định dạng SQL hay binary?

SQL (pg_dump) là lựa chọn an toàn nhất vì dễ đọc, dễ sửa lỗi. Binary (pg_dump -Fc) nhỏ hơn nhưng cần phiên bản PostgreSQL tương thích để restore. Với n8n, SQL là đủ.

Backup bao nhiêu lâu thì đủ? Có cần giữ backup cũ không?

Giữ 30 ngày là phổ biến cho VPS nhỏ. Nếu dữ liệu quan trọng, giữ backup theo chính sách: hằng ngày giữ 7 ngày, hằng tuần giữ 4 tuần, hằng tháng giữ 12 tháng. Script trên đã xoá tự động backup cũ hơn 30 ngày.

Bài viết liên quan

Lưu ý: Bài viết mang tính tham khảo, tổng hợp kiến thức chung. Mỗi hệ thống, hạ tầng và nhu cầu có đặc thù riêng, nên kiểm thử trong môi trường an toàn và tham vấn kỹ sư trước khi triển khai thực tế.