AI Automation

Chuyển n8n từ SQLite sang PostgreSQL không mất workflow

SSH vào VPS của bạn, thấy n8n đang chạy ngon lành với SQLite mặc định. Nhưng khi workload lớn dần, bạn bắt đầu gặp vấn đề: execution history chậm, nhiều workflow chạy đồng thời dễ conflict, backup phải stop cả container. Đã đến lúc chuyển sang PostgreSQL. Bài viết này hướng dẫn bạn từng bước chuyển n8n từ SQLite sang PostgreSQL trên VPS Ubuntu 24.04, đảm bảo giữ nguyên rất cao workflow, credentials và lịch sử thực thi.

Yêu cầu trước khi bắt đầu

  • Một VPS chạy Ubuntu 24.04 LTS (nếu chưa có, bạn có thể thuê VPS Linux với full root để thao tác thoải mái).
  • User sudo non-root đã được cấu hình.
  • n8n đang chạy bằng Docker Compose với SQLite làm database mặc định.
  • Đã cài Docker và Docker Compose v2 (dùng lệnh docker compose).
  • Một chút kiên nhẫn, toàn bộ quá trình mất khoảng 15-20 phút.

Vì sao nên chuyển từ SQLite sang PostgreSQL?

SQLite là database file-based, phù hợp cho môi trường phát triển hoặc số workflow ít. Khi bạn chạy nhiều workflow song song, execution history dày đặc, hoặc muốn scale lên queue mode với Redis, PostgreSQL là lựa chọn bắt buộc. Nó hỗ trợ concurrent writes tốt hơn, không bị lock table khi ghi execution đồng thời, và cho phép bạn backup nóng mà không cần dừng dịch vụ. Bản thân n8n cũng khuyến nghị dùng PostgreSQL cho production từ vài phiên bản trước.

Bước 1, Backup dữ liệu SQLite hiện tại

Trước khi làm gì, bạn cần một bản backup an toàn. Việc này sẽ stop container n8n trong vài giây để dump dữ liệu chính xác.

cd /path/to/your/n8n-docker-compose-folder
docker compose down
docker run --rm -v $(pwd)/n8n_data:/data alpine sh -c "cp /data/database.sqlite /data/database.sqlite.backup-$(date +%Y%m%d%H%M%S)"

Lệnh trên dùng container alpine tạm thời để copy file database.sqlite ra một bản backup có timestamp. Kiểm tra file backup đã tồn tại:

ls -la n8n_data/database.sqlite.backup-*

Nếu thấy file dung lượng vài MB đến vài trăm MB (tuỳ số workflow/execution), bạn đã backup thành công.

Bước 2, Thiết lập PostgreSQL container

Không cần cài PostgreSQL riêng trên host. Bạn sẽ thêm một service PostgreSQL vào file docker-compose.yml hiện tại của n8n.

Mở file docker-compose.yml (thường nằm cùng thư mục với thư mục n8n_data):

nano docker-compose.yml

Thêm vào phần services: (nếu chưa có):

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=your_strong_password
      - POSTGRES_DB=n8n
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

Thêm volume postgres_data vào phần volumes: ở cuối file:

volumes:
  n8n_data:
  postgres_data:

Cập nhật service n8n để dùng PostgreSQL thay SQLite. Trong phần environment: của service n8n, sửa (hoặc thêm) các dòng:

      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=your_strong_password

Nhớ thay your_strong_password bằng mật khẩu bạn đã đặt ở service postgres. Đồng thời, xoá (hoặc comment) biến môi trường DB_SQLITE_POOL_SIZE nếu có, nó không dùng cho PostgreSQL.

Cuối cùng, khởi động PostgreSQL container trước:

docker compose up -d postgres
docker compose ps

Chờ vài giây cho PostgreSQL sẵn sàng. Kiểm tra health:

docker compose exec postgres pg_isready -U n8n

Nếu trả về localhost:5432 - accepting connections, database đã sẵn sàng.

Bước 3, Migrate dữ liệu từ SQLite sang PostgreSQL

n8n có built-in tool để migrate, và nó hoạt động rất tốt. Bạn chạy container n8n tạm thời với chế độ migrate.

docker compose run --rm n8n n8n export:workflow --all --output=/home/node/.n8n/workflows.json
docker compose run --rm n8n n8n export:credentials --all --output=/home/node/.n8n/credentials.json
docker compose run --rm n8n n8n import:workflow --input=/home/node/.n8n/workflows.json
docker compose run --rm n8n n8n import:credentials --input=/home/node/.n8n/credentials.json

Cảnh báo: Các lệnh trên export và import dữ liệu từ SQLite cũ (vì container n8n khi chạy sẽ mount volume n8n_data, nơi chứa SQLite). Nhưng có một lưu ý nhỏ: nếu bạn đã sửa environment variables để trỏ PostgreSQL, container sẽ không tìm thấy SQLite để export. Giải pháp là bạn cần tạo một file .env tạm thời hoặc set biến môi trường DB_SQLITE_POOL_SIZE=2 cho lệnh export.

Cách an toàn hơn: dùng một script migration chính thức của n8n. Từ phiên bản n8n 1.x, bạn có thể dùng lệnh n8n db:resetn8n db:migrate. Nhưng đơn giản nhất là export workflow + credentials rồi import vào database mới. Làm thủ công từng bước:

# Export workflow từ SQLite (tạm thời chạy container với SQLite config)
docker compose run --rm -e DB_SQLITE_POOL_SIZE=2 n8n n8n export:workflow --all --output=/home/node/.n8n/workflows.json

# Export credentials từ SQLite
docker compose run --rm -e DB_SQLITE_POOL_SIZE=2 n8n n8n export:credentials --all --output=/home/node/.n8n/credentials.json

Sau đó, xoá file database.sqlite cũ (hoặc rename để dự phòng):

mv n8n_data/database.sqlite n8n_data/database.sqlite.old

Khởi động lại toàn bộ stack (lúc này n8n sẽ dùng PostgreSQL, database trống):

docker compose up -d

Kiểm tra log để chắc chắn n8n đã kết nối PostgreSQL thành công:

docker compose logs n8n | grep -i "database"

Nếu thấy dòng Database connected và không có error, bạn import dữ liệu vào:

docker compose exec n8n n8n import:workflow --input=/home/node/.n8n/workflows.json
docker compose exec n8n n8n import:credentials --input=/home/node/.n8n/credentials.json

Bước 4, Verify dữ liệu đã migrate

Sau khi import, bạn cần kiểm tra lại. Truy cập web UI của n8n (https://your-domain hoặc http://IP:port). Đăng nhập và kiểm tra:

  • Danh sách workflow có đủ các workflow cũ không.
  • Credentials (kết nối database, API keys, email…) còn hoạt động không.
  • Execution history có hiển thị không.

Nếu mọi thứ đều ok, bạn có thể xoá file backup SQLite cũ nếu muốn:

rm n8n_data/database.sqlite.old

Xử lý lỗi thường gặp

Lỗi "Cannot connect to PostgreSQL"

Kiểm tra tên service trong docker-compose.yml: DB_POSTGRESDB_HOST phải trỏ đúng tên service PostgreSQL (thường là postgres). Chạy docker compose logs postgres để xem log lỗi. Đảm bảo mật khẩu khớp giữa service postgres và biến môi trường của n8n.

Lỗi "Workflow not found" sau import

Thường do import sai thứ tự: credentials phải import trước workflow (vì workflow có thể tham chiếu đến credentials). Nếu vẫn lỗi, hãy kiểm tra file JSON export có đúng format không. Bạn có thể chạy docker compose exec n8n n8n import:workflow --input=/home/node/.n8n/workflows.json --debug để xem chi tiết.

Lỗi "Execution history trống"

n8n export/import workflow không bao gồm execution history (đây là design cố ý, vì execution lưu nhiều và không cần thiết cho migration thông thường). Nếu muốn giữ execution, bạn cần migrate trực tiếp từ SQLite sang PostgreSQL bằng công cụ như pgloader, nhưng phức tạp hơn. Hầu hết mọi người chỉ cần giữ workflow và credentials là đủ.

Lưu ý sau khi migrate

Sau khi chuyển thành công, bạn nên cấu hình backup cho PostgreSQL database định kỳ. Dùng lệnh pg_dump qua docker:

docker compose exec postgres pg_dump -U n8n n8n > n8n_backup_$(date +%Y%m%d).sql

Đặt script này vào cron (hoặc systemd timer) để chạy hàng ngày. Nếu bạn muốn dùng các tính năng nâng cao của n8n như queue mode (chạy worker riêng) với Redis, PostgreSQL là điều kiện tiên quyết. Lúc đó, bạn chỉ cần thêm service Redis vào docker-compose và set biến EXECUTIONS_DATA_PRUNE để quản lý dung lượng execution.

Với VPS có RAM 2GB trở lên, n8n + PostgreSQL chạy rất ổn định. Nếu VPS của bạn đang dùng RAM thấp, hãy cân nhắc nâng cấp. Bạn có thể tham khảo các gói VPS giá rẻ hoặc VPS n8n chuyên dụng nếu cần cấu hình mạnh hơn cho automation.

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

Có cần dừng n8n trong quá trình migrate không?

Có. Bạn cần stop container n8n trong lúc export dữ liệu từ SQLite để tránh ghi dữ liệu mới vào database cũ. Tuy nhiên thời gian dừng chỉ vài giây cho mỗi lệnh export.

Làm sao để giữ lại execution history?

n8n export/import không bao gồm execution history. Để giữ chúng, bạn phải dùng công cụ migrate trực tiếp SQLite → PostgreSQL như pgloader, hoặc chạy script custom copy bảng execution. Nhưng execution history thường chỉ có giá trị debug ngắn hạn, bạn có thể chấp nhận mất.

Tôi có thể chạy PostgreSQL trên VPS khác không?

Hoàn toàn được. Chỉ cần sửa biến DB_POSTGRESDB_HOST thành IP hoặc hostname của VPS chạy PostgreSQL, và mở port 5432 trên firewall (nhưng khuyến nghị dùng Docker network nội bộ cho độ trễ thấp nhất).

Nếu migrate thất bại, làm sao quay lại SQLite?

Đơn giản: stop stack, xoá hoặc rename file database.sqlite cũ, revert lại file docker-compose.yml về trạng thái dùng SQLite, và khôi phục file backup database.sqlite.backup-*. Chạy docker compose up -d lại là xong.

Tôi có cần cấu hình gì thêm cho PostgreSQL không?

Cơ bản thì không, n8n tự tạo bảng khi khởi động. Nhưng nếu bạn muốn tối ưu, có thể tăng shared_buffers lên 25% RAM khả dụng của VPS trong docker-compose.yml bằng command: command: ["postgres", "-c", "shared_buffers=512MB"] cho VPS 2GB RAM.

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ế.