なぜ立てたか
最近、Xserver VPS借りて、misskey鯖を立てました!せっかくVPSを借りたので他にも活用してみたいと思い、元々興味のあったn8nをセルフホストしてみました。
今回の記事では、n8nをXserver VPSにセルフホストする手順を書いていきたいと思います。(同じサーバーでnginxがすでに稼働中であることが前提です)
1 n8nとは
n8n(エヌエイトエヌ)とは、「ノーコードでワークフローを構築でき、様々なWebサービスをつなぎ合わせて面倒な作業を自動化してくれるツール」です。
例えば
- 毎朝の天気やニュースを自動取得して、LINEやDiscordに通知する
- 受信した長文メールをAIに要約させたり、メールのカテゴリ分けをしたりする
- 銀行の入金通知メールから家計簿を自動更新する
など、複数のアプリやサービスを連携して自動化することができます。
さらに、n8nはノーコードで自動化フローを構築できるだけでなく、API連携やコードの埋め込みなどといった高度なカスタマイズが可能なため、柔軟な拡張をすることができます。
n8nの運用
n8nを運用していくには3つの選択肢があります。
- n8n Cloud — 公式のホスティングサービス。月額課金で、プランごとに実行数の上限あり
- ローカルPCでセルフホスト — Dockerやnpmで自分のPCに立てる。無料
- VPSでセルフホスト — VPSを借りて立てる(今回採用した方法)
| n8n Cloud | ローカル | VPS | |
|---|---|---|---|
| 初期設定 | ほぼ不要 | 簡単 | ドメイン・DNS・リバプロ・証明書が必要 |
| 費用 | 月額課金 | 無料 | VPS代のみ |
| 24時間稼働 | ◯ | ✕(PCの電源次第) | ◯ |
| Webhook受信 | ◯ | △(ngrok等が必要) | ◯ |
| 実行数の上限 | プランによる | なし | なし |
| 運用の手間 | なし | 小 | 全部自分持ち |
VPSでセルフホストするメリット
-
費用がVPS代だけ
VPSを借りるときに発生する料金がかかります。既にVPSを借りているなら追加コストはありません。 -
24時間動く
「毎朝7時に天気を通知」のようなスケジュール実行が、PCを閉じても止まらずに動いてくれます。 -
Webhookを外から受けられる
Discord・GitHub・各種SaaSからのWebhookをそのまま受信できます。ローカル環境だとngrokなどが必要になる部分です。 -
実行数を気にしなくていい
サーバーのリソースが許す限り回し放題です。 -
認証情報が自分の手元にある
APIキーも処理するデータも外部サービスを経由しません。 -
カスタマイズが自由
環境変数の設定、Codeノードでのnpmパッケージ利用、他のDockerコンテナとの連携など、好きに触れます。
デメリット
-
構築のハードルが高い
サブドメイン、DNS、リバースプロキシ、SSL証明書まで全部自分で用意する必要があります。 -
セキュリティの責任を負う
n8nは各種サービスのAPIキーの塊です。管理画面をインターネットに晒す以上、HTTPS化と認証は必須になります。 -
リソースの奪い合いが起きる
既存サービスと同居する場合、重いワークフローがメモリを食って隣のサービスに影響することがあります。 -
アップデートとバックアップは自分で
放置でも動きはしますが、Dockerボリュームが飛ぶとワークフローも認証情報も全部消えます。
このように少しハードルが高いですが、その分自由度も上がるので、VPSを借りている、またはVPSで何かのサービスを運用したいと思っている場合はn8nもVPSでセルフホストすることをおすすめします。
2 手順
ここから本題の環境構築です。
まずは、前提として必要な環境から書いていきます。
2-1 環境
- Xserver VPS(Ubuntu)
- ドメイン取得済み(サブドメインでn8nを公開)
- 同じサーバーでnginxがすでに稼働中
2-2 事前準備
サブドメインのDNS設定
n8nはHTTPS前提で運用するのが基本なので、専用のサブドメインを用意します。
DNSに以下のAレコードを追加:
n8n.your-domain.com → VPSのIPアドレス
Xserver VPSのパケットフィルター
Xserver VPSはVPSパネル側でポートが遮断されているので、「パネル→パケットフィルター設定」で80(HTTP)と443(HTTPS)を許可します。
既に開いている場合はそのままで大丈夫です。
Step1:Dockerのインストール
SSHでVPSに入り、Docker公式スクリプトでインストールします。
ssh ユーザー名@VPSのIP
# Docker公式のインストールスクリプト
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
上記のコマンドを利用すれば、一度ログアウト→再ログインでsudoなしでdockerが使えるようになります。
Step2:n8nの構成ファイルを置く
mkdir -p ~/n8n && cd ~/n8n
ファイルに移動出来たらdocker-compose.ymlを作成します。
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
environment:
- N8N_HOST=n8n.your-domain.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.your-domain.com/
- GENERIC_TIMEZONE=Asia/Tokyo
- TZ=Asia/Tokyo
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
-
127.0.0.1:5678:5678ーn8nをlocalhostにのみ公開し、外部からは既存のnginx経由でしかアクセスできないようにする -
GENERIC_TIMEZONE=Asia/Tokyoーこれを忘れるとスケジュール実行がUTC基準になる
起動は以下のコマンドで行います。
docker compose up -d
失敗談
実は最初は、この構成ではなくHTTPS化を自動でやってくれるCaddyをリバースプロキシとして同じcomposeに入れる構成で組んでいました。
リバースプロキシ
・インターネットとWebサーバーの間にある中継サーバー
・セキュリティ、パフォーマンス、および信頼性を向上させるために実装される
caddy:
image: caddy:latest
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
この構成でファイルを作成し、docker compose up -dして、https://n8n.ドメイン.comにアクセスすると、初回セットアップ画面が出るはずでしたが、結果はこのようになりました。

$ docker compose ps
NAME IMAGE STATUS
n8n-caddy-1 caddy:latest Restarting (1) 5 seconds ago ← 再起動ループ
n8n-n8n-1 docker.n8n.io/n8nio/n8n Up 2 minutes
Caddyのログを見ると以下のようになっていました。
Error: adapting config using caddyfile: EOF
さらにポートの使用状況を確認すると
$ sudo ss -tlnp | grep -E ':80|:443'
LISTEN 0 511 0.0.0.0:80 users:(("nginx",...))
LISTEN 0 511 0.0.0.0:443 users:(("nginx",...))
ログのEOFはCaddyfileの内容が正しく読み込めていないエラーです。ただ、そこを直しても、既存のnginxがポート80/443をつかんでおり、そもそもCaddyがポートをとれる余地がありませんでした。
nginxは既に他のサイトを配信中なので、既存nginxに相乗りさせる方針に切り替えました。
Step3:既存nginxにn8nのリバースプロキシ設定を追加
n8n用のファイルを作成
sudo nano /etc/nginx/sites-available/n8n
server {
listen 80;
server_name n8n.your-domain.com;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
client_max_body_size 50m;
}
}
下記のコマンドで有効化して反映します。
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Step4:certbotでHTTPS化
既にnginxでHTTPSサイトを運用しているならcertbotは入っている可能性が高いので、確認してから実行します。
certbot --version || sudo apt install -y certbot python3-certbot-nginx
-
||によって、「左のコマンドが失敗した時だけ右を実行する」という挙動になっています
もし、certbot --versionが失敗した場合は、右側のインストールが走ります。 -
-yは確認プロンプトへ自動でyesと答えるオプション
| パッケージ | 役割 |
|---|---|
certbot |
Let's Encryptから証明書を取得・更新する本体 |
python3-certbot-nginx |
nginx用プラグイン。設定ファイルの自動編集と、認証時のnginx制御を担当 |
sudo certbot --nginx -d n8n.your-domain.com
-
--nginxがプラグインの指定、-dが対象ドメインの指定です。 - これ1本で、証明書の取得からnginx設定への反映まで全部やってくれます
-
server_name n8n.your-domain.comのserverブロックを探す - Let's Encryptが
http://n8n.your-domain.com/に実際にアクセスしてドメイン所有を確認 - 証明書を
/etc/letsencrypt/live/に保存 - nginx設定に443のserverブロックとリダイレクトを自動追記してreload
- 自動更新のタイマーに登録
自動更新のタイマーに登録してくれるため、既存のサイトの更新スケジュールに相乗りする形になり、以後メンテ不要となります。
これが成功するとこんな出力になります。
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/n8n.your-domain.com/fullchain.pem
Deploying certificate
Successfully deployed certificate for n8n.your-domain.com to /etc/nginx/sites-enabled/n8n
Congratulations! You have successfully enabled HTTPS on https://n8n.your-domain.com
Step5:動作確認
https://n8n.your-domain.comにアクセスして、n8nのオーナーアカウント作成画面(Set up owner account)が表示されれば完了です。管理画面はこのアカウント認証で保護されます。
3 まとめ
- まっさらなVPSなら「n8n+Caddy」のcompose一発が最短
- 既にnginxが動いているVPSでは、Caddyはポートを取れず再起動ループする
・その場合はn8nを127.0.0.1:5678にのみ公開し、既存nginxにリバースプロキシ設定を1ファイルに追加+certbotでHTTPS化するのがきれい
以上となります。
今回は既存のnginxに同居させる形で、n8nをXserverに同居させる手順を紹介しました。
n8nは幅広い使い方ができ、日常のタスクを自動化することができるため、ぜひ使ってみてください!
参考
- 「リバースプロキシとは?|プロキシサーバーの説明」https://www.cloudflare.com/ja-jp/learning/cdn/glossary/reverse-proxy/
- 「n8nで自動化!便利な活用事例」https://note.com/kakazuastro/n/n17282f4d7856
- 「【入門】n8nとは?クラウド版とセルフホストの違い・始め方を分かりやすく解説」https://qiita.com/kaz_saito803/items/f3a4acd1e3960ad7d5ae
- 「n8nのセルフホスト完全ガイド|VPSのインストールから運用まで」https://humanoid-inc.net/owned-media/n8n-self-host-guide
