n8nはデフォルトでSQLiteを使用しますが、本番運用ではPostgreSQLへの移行が推奨されます。
SQLiteはファイルベースで手軽ですが、同時接続やスケーリングに制限があります。PostgreSQLを使用することで、データの永続化、バックアップ、高可用性を実現できます。
この記事では、n8nのPostgreSQL永続化について、Docker Compose設定から環境変数、バックアップ、SQLiteからの移行まで、本番運用に必要な技術を詳しく解説します。
なぜPostgreSQLが必要か?SQLiteとの比較
SQLiteの特徴と限界
| 項目 | SQLite | PostgreSQL |
|---|---|---|
| アーキテクチャ | ファイルベース | クライアント・サーバー型 |
| 同時接続 | 制限あり(書き込みロック) | 多数の同時接続に対応 |
| スケーリング | 単一インスタンスのみ | Queue Mode / Worker対応 |
| バックアップ | ファイルコピー | pg_dump / レプリケーション |
| 高可用性 | 非対応 | レプリケーション対応 |
| 推奨用途 | 開発・テスト・小規模 | 本番・大規模ワークフロー |
PostgreSQLが必要なケース
- Webhookを多数受け付ける
- ワークフローの実行頻度が高い
- 複数ワーカーでの分散処理(Queue Mode)
- データの確実なバックアップが必要
- 本番環境での安定運用
Docker Composeによる構築
n8nとPostgreSQLをDocker Composeで構築する方法を解説します。
ディレクトリ構成
n8n-production/
├── docker-compose.yml
├── .env
└── backups/
.envファイル
# PostgreSQL設定
POSTGRES_USER=n8n
POSTGRES_PASSWORD=your_strong_password_here
POSTGRES_DB=n8n
# n8n設定
N8N_ENCRYPTION_KEY=your_32_char_encryption_key_here
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=your_admin_password
N8N_HOST=n8n.yourdomain.com
N8N_PROTOCOL=https
WEBHOOK_URL=https://n8n.yourdomain.com/
GENERIC_TIMEZONE=Asia/Tokyo
重要:N8N_ENCRYPTION_KEYは32文字以上のランダムな文字列を設定してください。このキーは認証情報の暗号化に使用され、変更すると既存の認証情報が読めなくなります。
docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: n8n-postgres
restart: always
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- n8n-network
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER}']
interval: 10s
timeout: 5s
retries: 5
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: always
ports:
- "5678:5678"
environment:
# データベース設定
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
# n8n設定
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER}
- N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
- N8N_HOST=${N8N_HOST}
- N8N_PORT=5678
- N8N_PROTOCOL=${N8N_PROTOCOL}
- NODE_ENV=production
- WEBHOOK_URL=${WEBHOOK_URL}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
volumes:
- n8n_data:/home/node/.n8n
networks:
- n8n-network
depends_on:
postgres:
condition: service_healthy
volumes:
postgres_data:
n8n_data:
networks:
n8n-network:
driver: bridge
起動手順
# ディレクトリ作成
mkdir -p n8n-production && cd n8n-production
# .envとdocker-compose.ymlを作成(上記内容)
# 起動
docker compose up -d
# ログ確認
docker compose logs -f n8n
環境変数の詳細解説
データベース関連
| 環境変数 | 説明 | デフォルト値 |
|---|---|---|
| DB_TYPE | データベースタイプ | sqlite(postgresdbに変更) |
| DB_POSTGRESDB_HOST | PostgreSQLホスト名 | localhost |
| DB_POSTGRESDB_PORT | PostgreSQLポート | 5432 |
| DB_POSTGRESDB_DATABASE | データベース名 | n8n |
| DB_POSTGRESDB_USER | ユーザー名 | postgres |
| DB_POSTGRESDB_PASSWORD | パスワード | – |
| DB_POSTGRESDB_SCHEMA | スキーマ名 | public |
SSL接続(マネージドDB向け)
AWS RDSやCloud SQLなどのマネージドデータベースを使用する場合、SSL接続が必要です。
| 環境変数 | 説明 |
|---|---|
| DB_POSTGRESDB_SSL_CA | CA証明書のパス |
| DB_POSTGRESDB_SSL_CERT | クライアント証明書のパス |
| DB_POSTGRESDB_SSL_KEY | クライアント秘密鍵のパス |
| DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED | 証明書検証(true/false) |
暗号化キー
N8N_ENCRYPTION_KEY=your_32_char_encryption_key_here
重要なポイント
- 認証情報(Credentials)の暗号化に使用
- 設定しないと起動時に自動生成される
- キーを変更すると既存の認証情報が復号できなくなる
- 必ず安全な場所にバックアップすること
キーの生成方法
# OpenSSLでランダムな32文字を生成
openssl rand -hex 16
.n8nディレクトリの永続化
PostgreSQLを使用しても、.n8nディレクトリの永続化は引き続き必要です。
.n8nディレクトリに保存されるデータ
- 暗号化キー(N8N_ENCRYPTION_KEYを設定しない場合)
- インスタンスログ
- Source Control機能のアセット
- 一時ファイル
ボリュームマッピング
volumes:
- n8n_data:/home/node/.n8n
または、ホストディレクトリにマッピング:
volumes:
- ./n8n-data:/home/node/.n8n
バックアップ戦略
本番運用では、定期的なバックアップが必須です。
PostgreSQLのバックアップ
手動バックアップ(pg_dump)
# バックアップ実行
docker exec n8n-postgres pg_dump -U n8n -d n8n > backup_$(date +%Y%m%d_%H%M%S).sql
# 圧縮してバックアップ
docker exec n8n-postgres pg_dump -U n8n -d n8n | gzip > backup_$(date +%Y%m%d).sql.gz
自動バックアップスクリプト
#!/bin/bash
# backup.sh
BACKUP_DIR="/path/to/backups"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
# PostgreSQLバックアップ
docker exec n8n-postgres pg_dump -U n8n -d n8n | gzip > ${BACKUP_DIR}/n8n_db_${DATE}.sql.gz
# n8n_dataボリュームのバックアップ
docker run --rm -v n8n_data:/data -v ${BACKUP_DIR}:/backup alpine
tar czf /backup/n8n_data_${DATE}.tar.gz -C /data .
# 古いバックアップの削除
find ${BACKUP_DIR} -name "*.gz" -mtime +${RETENTION_DAYS} -delete
echo "Backup completed: ${DATE}"
cronで自動実行
# 毎日午前3時にバックアップ
0 3 * * * /path/to/backup.sh >> /var/log/n8n-backup.log 2>&1
リストア手順
PostgreSQLのリストア
# 圧縮ファイルからリストア
gunzip -c backup_20250101.sql.gz | docker exec -i n8n-postgres psql -U n8n -d n8n
# 非圧縮ファイルからリストア
cat backup.sql | docker exec -i n8n-postgres psql -U n8n -d n8n
n8n_dataボリュームのリストア
# 既存ボリュームを削除(注意)
docker volume rm n8n_data
# 新しいボリュームを作成してリストア
docker run --rm -v n8n_data:/data -v /path/to/backups:/backup alpine
tar xzf /backup/n8n_data_20250101.tar.gz -C /data
SQLiteからPostgreSQLへの移行
既存のSQLite環境からPostgreSQLに移行する手順です。
移行方法の選択肢
| 方法 | メリット | デメリット |
|---|---|---|
| ワークフローのエクスポート/インポート | 確実、クリーン | 実行履歴は移行されない |
| SQLダンプの変換 | データ完全移行 | スキーマ差異の調整が必要 |
| 新規構築 | シンプル | 再設定が必要 |
推奨:ワークフローのエクスポート/インポート
Step 1:ワークフローのエクスポート
- n8nの管理画面にログイン
- 各ワークフローを開いて「Export」→ JSONファイルを保存
- または、CLIでエクスポート:
# 全ワークフローをエクスポート
docker exec n8n n8n export:workflow --all --output=/home/node/.n8n/workflows.json
Step 2:認証情報のエクスポート
# 認証情報をエクスポート(暗号化されたまま)
docker exec n8n n8n export:credentials --all --output=/home/node/.n8n/credentials.json
Step 3:PostgreSQL環境の構築
上記のdocker-compose.ymlを使用して新しい環境を構築します。
重要:N8N_ENCRYPTION_KEYは元の環境と同じ値を使用してください。
Step 4:データのインポート
# ワークフローのインポート
docker exec n8n n8n import:workflow --input=/home/node/.n8n/workflows.json
# 認証情報のインポート
docker exec n8n n8n import:credentials --input=/home/node/.n8n/credentials.json
本番運用のベストプラクティス
ヘルスチェックの設定
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER}']
interval: 10s
timeout: 5s
retries: 5
PostgreSQLの準備が完了してからn8nを起動することで、接続エラーを防ぎます。
リスタートポリシー
restart: always
コンテナが停止した場合に自動的に再起動します。
リソース制限
services:
n8n:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
ログ管理
services:
n8n:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
リバースプロキシとSSL
本番環境では、Nginx / TraefikなどのリバースプロキシでSSL終端を行います。
Nginxの設定例
server {
listen 443 ssl http2;
server_name n8n.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost: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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
}
}
Queue Modeでのスケーリング
大規模なワークフロー処理には、Queue Mode + Redisを使用します。
Queue Mode構成
version: '3.8'
services:
postgres:
# ... 上記と同じ
redis:
image: redis:7-alpine
container_name: n8n-redis
restart: always
volumes:
- redis_data:/data
networks:
- n8n-network
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 5s
retries: 5
n8n:
# ... 基本設定に以下を追加
environment:
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
n8n-worker:
image: n8nio/n8n:latest
container_name: n8n-worker
restart: always
command: worker
environment:
# n8nと同じDB設定
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
# ... その他の設定
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
depends_on:
- postgres
- redis
volumes:
postgres_data:
redis_data:
n8n_data:
トラブルシューティング
よくある問題と解決方法
| 問題 | 原因 | 解決方法 |
|---|---|---|
| DB接続エラー | PostgreSQLが起動していない | healthcheckとdepends_onを設定 |
| 認証情報が読めない | 暗号化キーが異なる | N8N_ENCRYPTION_KEYを確認 |
| SQLiteにフォールバック | DB_TYPE未設定 | 環境変数を確認 |
| Permission denied | ボリュームの権限問題 | UID/GID設定またはchown |
| 起動時にハング | マイグレーション中 | 初回起動時は時間がかかる |
ログの確認方法
# n8nのログ
docker compose logs -f n8n
# PostgreSQLのログ
docker compose logs -f postgres
# 全サービスのログ
docker compose logs -f
データベース接続の確認
# PostgreSQLに直接接続
docker exec -it n8n-postgres psql -U n8n -d n8n
# テーブル一覧を確認
dt
# ワークフロー数を確認
SELECT COUNT(*) FROM workflow_entity;
よくある質問(FAQ)
Q. SQLiteからPostgreSQLへの移行は必須ですか?
A. 必須ではありませんが、本番運用では強く推奨されます。SQLiteは同時書き込みに制限があり、Webhookを多数受け付けるような使い方では問題が発生する可能性があります。
Q. マネージドPostgreSQL(RDS、Cloud SQL)は使えますか?
A. はい、使用できます。接続情報を環境変数で設定し、必要に応じてSSL接続を設定してください。
Q. N8N_ENCRYPTION_KEYを忘れた場合はどうなりますか?
A. 既存の認証情報が復号できなくなります。ワークフロー自体は残りますが、認証情報は再設定が必要です。キーは必ずバックアップしてください。
Q. PostgreSQLのバージョンは何を使うべきですか?
A. PostgreSQL 13以上が推奨です。2025年現在、PostgreSQL 15または16が安定しており推奨されます。
Q. 実行履歴(Executions)はどこに保存されますか?
A. PostgreSQLのexecution_entityテーブルに保存されます。実行履歴が増えるとディスク容量を消費するため、定期的なクリーンアップまたは保持期間の設定を検討してください。
まとめ
この記事では、n8nのPostgreSQL永続化について解説しました。
本番運用のための必須設定
- DB_TYPE=postgresdb で PostgreSQLを指定
- N8N_ENCRYPTION_KEY を固定値で設定
- .n8nディレクトリのボリューム永続化
- PostgreSQLデータのボリューム永続化
運用のポイント
- healthcheckでPostgreSQLの準備完了を待つ
- 定期的なバックアップ(pg_dump + ボリューム)
- 暗号化キーの安全な管理
- リバースプロキシでSSL終端
スケーリング時の追加設定
- Queue Mode + Redis
- n8n-workerの追加
PostgreSQLを使用することで、n8nの安定性と信頼性が大きく向上します。本番環境では必ずPostgreSQLを使用し、適切なバックアップ戦略を実装してください。

