n8nをVPSで動かす:落とし穴を先に潰す本番構成ガイド【2026年】

自動化・ノーコード(n8n)中級
n8nDockerVPSZapier自動化

TL;DR

n8n Community Editionは2026年現在もセルフホストで無料・実行回数無制限のまま維持されています。「クラウド版が有料化した」という情報が出回っていますが、それはクラウド版のフリープランの話であり、セルフホスト版は別物です。

  • 必要スペック: VPS 2GB RAM以上、Docker Compose、PostgreSQL(本番用)
  • 採用構成: Ubuntu 22.04/24.04 + Docker Compose + PostgreSQL + Nginx + Let’s Encrypt
  • この記事の対象: Dockerを扱えるエンジニア・情シス担当。「手順通りに起動した後、本番で止まる」を防ぐための構成ガイドです

Zapier Professional($19.99/月〜・タスク数で増加)に対して、ConoHa VPS 2GBプランなら月1,259円で無制限実行環境が整います。ただし「起動できる」と「安定稼働させられる」の間には7つの落とし穴があります。その全部を手順の前後で潰してから動かすのが、この記事の目的です。


なぜ今セルフホストに切り替えるのか

Zapierのコスト設計を一度整理しておく必要があります。

Zapierは「1ステップ=1タスク消費」の課金モデルです。5ステップで構成したワークフローを1,000回実行すると、5,000タスクを消費します。Professional プランは$19.99/月から始まりますが、ワークフローが複雑になるほどタスク消費が加速し、Team プラン($69/月〜)への移行圧力がかかります。

n8nの課金モデルは構造が異なります。同じ5ステップのワークフローを1,000回実行しても、カウントは1,000実行です。ステップ数が増えても消費は増えない。この非対称性が、ワークフローが複雑になればなるほど差を広げます。

n8n Community Editionのセルフホストは実行回数無制限で無料(2026年現在)です。コストはVPS代のみになります。

VPS月額の参考値(2026年6月時点):

  • ConoHa VPS 2GBプラン: 1,259円/月(まとめトクプラン)
  • さくらのVPS 最小プラン: 671円/月〜(仕様はさくらのVPS仕様ページで確認してください)

向かないケースも整理します。 バックアップ設計・サーバー管理・アップデート対応を自分でやりたくない場合や、運用工数ゼロを最優先にする場合は、n8n Cloud(Starter $24/月前後・2,500実行/月)が合理的です。管理コストをゼロにしたいニーズとセルフホストは相性が悪い。この前提を踏まえた上で、続きを読んでください。


構成の全体像を先に把握する

手順に入る前に、何を積み上げるのかを俯瞰します。

採用アーキテクチャ:

インターネット
    ↓ (443/80)
Nginx(HTTPS終端・リバースプロキシ)
    ↓ (5678 ローカルのみ)
n8n コンテナ(Docker Compose)

PostgreSQL コンテナ(Docker Compose)

なぜDockerか

公式の最推奨構成です。n8nのアップデートが docker compose pull && docker compose up -d の2コマンドで完結し、環境の再現性も保たれます。

なぜPostgreSQLか

n8nのデフォルトデータベースはSQLiteです。ただし公式ドキュメントはSQLiteを本番環境に非推奨としています。ワークフロー定義・実行ログ・クレデンシャルの参照メタデータは永続化が必要で、同時書き込みが発生する本番稼働ではPostgreSQLが適切です。

なぜNginxを挟むか

n8nはデフォルトでポート5678で起動します。このポートを外部に直接公開するのは避けるべきです。NginxをHTTPS終端として置くことで、外部通信は443/80のみに絞られ、n8nのポートはコンテナ内のローカル通信に限定されます。

「動かすこと」と「安定稼働」のギャップ

この手順通りに進めれば起動はできます。ただし後述する7つの落とし穴を踏むと、本番稼働後に予期しない問題が発生します。手順の中で各落とし穴への対処を組み込みながら進めます。


実装手順

Step 1 — VPSの準備とDockerインストール

推奨OS: Ubuntu 22.04 LTS または 24.04 LTS

推奨RAM: 2GB以上。1GBは並列実行・大量データ処理でOOM(Out of Memory)クラッシュのリスクがあります(n8nlab.ioが確認済み)。後述する落とし穴のうち「メモリ不足」が最も発生しやすいサイズです。コスト優先でも1GBは避けてください。

VPS初期設定(ユーザー作成・SSHキー設定・ファイアウォール設定)が完了した状態から始めます。

Dockerをインストールします。

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

インストール後、現在のユーザーをdockerグループに追加します。

sudo usermod -aG docker $USER
newgrp docker

newgrp docker で現在のセッションにグループ変更を反映できます。再ログイン不要で確認できます。

動作確認:

docker --version
docker compose version

Step 2 — ディレクトリと .env ファイルの作成

作業ディレクトリを作成します。

mkdir -p ~/n8n && cd ~/n8n

.env ファイルを作成します。設定値の意味を一つずつ確認しながら書いてください。後の落とし穴と直結する変数が2つあります。

nano .env
# PostgreSQL
POSTGRES_USER=n8n
POSTGRES_PASSWORD=YOUR_STRONG_DB_PASSWORD
POSTGRES_DB=n8n

# n8n基本設定
N8N_HOST=yourdomain.com
N8N_PORT=5678
N8N_PROTOCOL=https

# 暗号化キー(一度設定したら変更禁止)
N8N_ENCRYPTION_KEY=YOUR_GENERATED_KEY

# WebhookのベースURL
WEBHOOK_URL=https://yourdomain.com/

# タイムゾーン(2変数ともに設定が必要)
GENERIC_TIMEZONE=Asia/Tokyo
TZ=Asia/Tokyo

N8N_ENCRYPTION_KEY について(落とし穴⑤の予防)

n8nはこのキーを使ってデータベース内のクレデンシャルを暗号化します。強いキーを生成するには以下を使います。

openssl rand -hex 32

出力された値を N8N_ENCRYPTION_KEY に設定してください。このキーは一度設定したら変更禁止です。 変更すると、既存のクレデンシャル(APIキー・パスワード)がすべて復号できなくなります(GravityWP チュートリアル確認済み)。.env ファイルは必ずバックアップしておいてください。

WEBHOOK_URL について(落とし穴①の予防)

この設定を間違えると、GitHubやSlackからのWebhookが届きません。末尾のスラッシュを含めるのが正しい形式です。

# 誤り
WEBHOOK_URL=https://yourdomain.com:5678/webhook/abc123

# 正しい
WEBHOOK_URL=https://yourdomain.com/

GENERIC_TIMEZONE と TZ の両方を設定する理由(落とし穴④の予防)

n8nはスケジュールトリガーの処理に GENERIC_TIMEZONE を参照し、コンテナのシステム時刻に TZ を参照します。片方だけ設定するとスケジュールトリガーのズレが発生します。両方を Asia/Tokyo に揃えてください。


Step 3 — Dockerボリュームの作成

docker volume create n8n_data
docker volume create n8n_db_data

なぜボリュームが必要か。コンテナを削除・再作成したとき、ボリュームなしではデータが消えます。n8n_data には暗号化キー・ローカルファイルが含まれ、n8n_db_data はPostgreSQLのデータ本体です。この2行を省略すると、コンテナを再作成するたびにすべての設定が失われます(落とし穴⑤の防止策でもあります)。


Step 4 — docker-compose.yml の作成

nano docker-compose.yml
version: "3.8"

services:
  postgres:
    image: postgres:15
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - n8n_db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 5s
      timeout: 5s
      retries: 5

  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: unless-stopped
    ports:
      - "127.0.0.1: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_HOST=${N8N_HOST}
      - N8N_PORT=${N8N_PORT}
      - N8N_PROTOCOL=${N8N_PROTOCOL}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - WEBHOOK_URL=${WEBHOOK_URL}
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
      - TZ=${TZ}
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  n8n_data:
    external: true
  n8n_db_data:
    external: true

各設定の意味を確認します。

  • restart: unless-stopped: VPSが再起動したときにコンテナを自動で起動させます。手動で docker compose stop した場合は再起動しません
  • depends_on: postgres: condition: service_healthy: PostgreSQLのヘルスチェックが通ってからn8nを起動します。PostgreSQLより先にn8nが起動してDB接続エラーになるのを防ぎます
  • ports: "127.0.0.1:5678:5678": ポート5678をlocalhostのみに制限します。外部から直接アクセスできない状態にします。NginxはこのlocalhostのポートにProxy Passします
  • image: docker.n8n.io/n8nio/n8n: n8nの公式イメージは docker.n8n.io/n8nio/n8n です。latest タグで自動追従するか、n8nio/n8n:X.XX.X のように特定バージョンを固定するかはチームのポリシーに従ってください。最新の安定版バージョンは n8n GitHubリリースページ(github.com/n8n-io/n8n/releases) で確認してください。バージョンを固定する場合、アップデート時はタグの明示的な変更が必要です

Step 5 — 起動と疎通確認

docker compose up -d

起動状態を確認します。

docker compose ps

Staterunning になっていることを確認します。PostgreSQLのヘルスチェックが通るまで数秒かかるため、起動直後は starting になることがあります。

VPS内からの疎通確認:

curl http://localhost:5678

n8nのHTMLレスポンスが返ってくれば起動しています。

この時点ではHTTPSが未設定のため、外部からのアクセスはまだ機能しません。ポート5678はファイアウォールで閉じたままにしてください。次のStep 6でNginxとSSLを設定してから、ブラウザでアクセスします。


Step 6 — NginxとLet’s EncryptでHTTPS設定

なぜHTTPSが必須か

WebhookはGitHub・Slack・Stripe等の外部サービスから呼ばれます。これらの多くはHTTPSのエンドポイントにしかリクエストを送りません。HTTPのまま稼働させると、Webhookトリガーを使ったワークフローがまったく機能しない状態になります。

2つの選択肢

Nginx + CertbotCaddy
SSL取得certbotコマンドで手動Caddyfileに記述するだけで自動
設定ファイルやや記述量が多いシンプル(2〜3行)
カスタマイズ細かく制御できる抽象化されている
枯れ具合実績が豊富近年採用が増加中

どちらを選んでも機能的な差はありません。設定ファイルを細かく制御したい場合はNginx、設定コストを最小化したい場合はCaddyが適しています。

Nginxを選ぶ場合

Nginxインストール後、n8n向けのsite configを /etc/nginx/sites-available/n8n に作成します。基本的な構成は proxy_pass http://localhost:5678; にProxy Passする形です。WebSocketを使うため proxy_http_version 1.1;UpgradeConnection ヘッダーの転送設定が必要です。

具体的なserver_name・ssl_certificate・ssl_certificate_keyの設定は、DigitalOceanの「How To Install Nginx on Ubuntu 22.04」チュートリアルおよびCertbotの公式手順(certbot.eff.org)を参照して進めてください。環境(ドメイン・ディストリビューション)によって差が出るため、一次ソースの手順に従うのが安全です。

Caddyを選ぶ場合

Caddyfileに以下を記述するだけでSSL取得・自動更新まで完結します。

yourdomain.com {
    reverse_proxy localhost:5678
}

HTTPS設定完了後、ファイアウォールの設定を確認します。

# UFW の場合
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# ポート5678は外部向けに閉じたまま
sudo ufw deny 5678/tcp

設定後、ブラウザで https://yourdomain.com にアクセスしてn8nのセットアップ画面が表示されれば完了です。


Step 7 — アップデート手順

n8nのアップデートは2コマンドで完結します。

cd ~/n8n
docker compose pull
docker compose up -d

docker compose pull で最新イメージを取得し、docker compose up -d で再起動します。バージョンを固定している場合は docker-compose.yml のイメージタグを変更してから実行します。

アップデート前の必須作業: PostgreSQLのバックアップを取ってから実行してください(バックアップ手順は次のセクション参照)。メジャーアップデートでDBスキーマが変わる場合があります。


本番稼働前に潰すべき落とし穴7点

手順通りに起動できても、本番で問題が出る典型パターンが7つあります。これが「起動できる」と「安定稼働させられる」の差です。

① WEBHOOK_URLの設定漏れ(最頻出)

Webhookが届かない問題の原因として最も多いのがこれです(blog.tamertemel.net確認済み)。

# 誤り(ポートが残っている)
https://yourdomain.com:5678/webhook/abc123

# 正しい(ドメインのみ・末尾スラッシュ)
https://yourdomain.com/webhook/abc123

WEBHOOK_URLhttps://yourdomain.com/(末尾スラッシュあり)の形式で設定します。ポート番号を含めないでください。Nginxが80/443で受けてからlocalhost:5678に転送するため、外部からはポートが見えません。

② メモリ不足(OOM Kill)

1GB RAMのVPSで並列実行・大量データ処理を行うとOOMクラッシュが発生します(n8nlab.io確認済み)。

n8nの公式ドキュメント(docs.n8n.io)に記載されているエラーメッセージ:

  • Execution stopped at this node (n8n may have run out of memory while executing it)
  • Allocation failed - JavaScript heap out of memory

このエラーが発生した場合の対処:

メモリ上限の引き上げ: docker-compose.yml のn8nサービスの environment に追加します。

- NODE_OPTIONS=--max-old-space-size=1024

ワークフローの分割: 大量データを一度に処理している場合、「Loop Over Items」ノードを使ってチャンク分割します。根本的な解決はVPSのRAMを2GB以上に変更することです。

③ SQLiteのまま本番稼働

この記事の手順(Step 4)でPostgreSQLを設定していれば回避済みです。ただし古い構成記事を参照してSQLiteのまま構築した場合、同時書き込みが発生する本番環境でデータ破損のリスクがあります。公式はSQLiteを本番環境に非推奨と明記しています。

④ タイムゾーン設定の不足

GENERIC_TIMEZONETZ のどちらか一方だけ設定するとスケジュールトリガーがズレます。両方を Asia/Tokyo に設定する必要があります(Step 2参照)。日本時間09:00実行のトリガーが別の時刻に動く場合、この設定を最初に確認してください。

⑤ N8N_ENCRYPTION_KEYの消失

コンテナを削除・再作成するとき、Dockerボリュームを永続化していない場合は暗号化キーが消えます。Step 3でボリュームを外部作成し、docker-compose.ymlで external: true を指定しているため、この手順通りに進めていれば回避済みです。

万が一キーが消えた場合、データベース内の既存クレデンシャルはすべて復号不可になります。.env ファイルのバックアップが唯一の復旧手段です。

⑥ Community Editionが有料化したという誤解

2025年にn8nの料金体系が変更され、「n8nが有料化した」という情報が広まりました(zeabur.com・instapods.com確認済み)。

正確な内容は以下です:

  • Community Edition(セルフホスト): 引き続き無料・実行回数無制限
  • Business Plan: SSO/SAML/LDAP等のエンタープライズ機能が新設(個人・中小チームには不要)
  • クラウド版フリープラン: 廃止済み(次の⑦)

セルフホストの無料継続に変更はありません。

⑦ クラウド版フリープランの廃止とセルフホストの混同

n8n Cloudのフリープランは廃止されました。現在のクラウド版最安はStarter($24/月前後・2,500実行/月・instapods.com記載値)です。

セルフホスト版はこの変更の影響を受けません。 n8n CloudとCommunity Editionは別のプロダクトです。「フリープランが廃止された」という情報を見てセルフホストを検討している場合、正しい動機です。


バックアップ設計

「動かせる」と「安心して運用できる」の間を埋める最重要ポイントです。

PostgreSQLのバックアップ

DockerコンテナのPostgreSQLを pg_dump でダンプする基本形:

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

コンテナ名は環境によって異なります。docker compose ps で確認してください。

cronによる定期バックアップ

crontab -e

毎日深夜2時にバックアップを取る例:

0 2 * * * docker exec n8n-postgres-1 pg_dump -U n8n n8n > /home/youruser/backups/n8n_$(date +\%Y\%m\%d).sql

バックアップファイルはVPS上に置くだけでなく、外部ストレージ(S3・Cloudflare R2等)に転送することを推奨します。VPSごと障害になった場合に備えてです。

.n8nディレクトリのバックアップ

PostgreSQL以外に、Dockerボリューム n8n_data(マウントポイント: /home/node/.n8n)にも暗号化キー・ローカルファイルが格納されています。このボリュームも定期的にバックアップしてください。

# ボリュームの内容を tar でアーカイブする例
docker run --rm -v n8n_data:/data -v $(pwd):/backup ubuntu tar czf /backup/n8n_data_$(date +%Y%m%d).tar.gz /data

バックアップ設計全体(保持期間・S3転送・自動化の仕組み)は構成が複雑になります。本記事の手順で動かせた後、別途設計することを推奨します。


コスト総括

構成ごとのコストを整理します(2026年6月時点)。

構成月額コスト実行回数上限管理コスト
n8n Community + ConoHa 2GB VPS1,259円/月無制限自己管理(本記事の手順)
n8n Community + さくらのVPS(最小)671円/月〜無制限自己管理(RAM仕様はさくらのVPS仕様ページ参照)
n8n Cloud Starter$24/月前後(instapods.com記載値)2,500回/月ゼロ
n8n Cloud Pro$60/月前後(instapods.com記載値)10,000回/月ゼロ
Zapier Professional$19.99/月〜(タスク数で増加)(2026年6月時点・zapier.com/pricing 確認)タスク数依存ゼロ

セルフホストを選ぶ理由は「無制限実行を安く維持したい」場合です。n8n Cloudと比較した場合、チームにもよりますが年間$200〜700程度の節約になるとされています(instapods.com調査値)。ただしその分、サーバー管理・バックアップ設計・アップデート対応が自己責任になります。


構築がうまくいかないときの確認順序

手順通りに進めても詰まる場合、まず以下の順で確認します。

ログの確認:

docker compose logs n8n
docker compose logs postgres

エラーメッセージの大半はここに出ます。

症状別の確認ポイント:

  1. Webhookが届かない → まず .envWEBHOOK_URL を確認。https://yourdomain.com/ の形式になっているか。次にNginxの設定でproxy_passがlocalhost:5678に向いているかを確認

  2. 起動後しばらくしてクラッシュするdocker stats でメモリ使用量を確認。n8nコンテナが2GB近くを使っていればOOMの疑い。VPS RAMが1GBの場合は2GBプランへの変更が根本解決

  3. クレデンシャルが突然使えなくなった.envN8N_ENCRYPTION_KEY が変更されていないかを確認。キーが変わると既存のクレデンシャルは復号不可になります。バックアップした .env の値と一致しているかを照合

ここまで確認してもなお解決しない場合、構成の設計判断や環境固有の問題である可能性が高いです。


WEBHOOK_URL の誤設定 / OOMクラッシュ / バックアップ設計 —— この3点は、構成の判断が絡むため自己解決が難しいことがあります。確認済みの状況をメールで共有いただければ、詰まっているポイントを絞り込みます。PostgreSQL + Docker Compose + Nginx構成で詰まっている、またはZapierからn8nへの移行設計で迷っている場合が対象です。

自動化・n8n構築の相談はこちら

関連記事

自動化・ノーコード(n8n)n8n + Slack + Google Sheets:社内問い合わせ自動分類BOTの構築自動化・ノーコード(n8n)n8n vs Make vs Zapier vs Power Automate:法人用途での選び方2026自動化・ノーコード(n8n)業務自動化ROI計算シート:情シスが経営層に稟議を通すための試算フレーム
記事一覧に戻る