n8nとは何か
n8nは、ノーコード/ローコードで業務ワークフローを自動化できるオープンソースのプラットフォームです。
Zapierのようなサービスを使ったことがある方ならイメージしやすいと思います。「Slackに通知が来たらGoogleスプレッドシートに記録する」「GitHubにPRが作られたらレビュアーに自動でアサインする」──こうしたワークフローを、GUIでノードをつなげるだけで構築できます。
n8nの特徴は、セルフホストできる点です。SaaSとして使うことも可能ですが、自分のサーバーにデプロイすれば、データの管理を完全に自分の手元に置けます。APIキーや機密データを外部に渡す必要がありません。
この記事では、Docker Composeを使ってLinuxサーバー上にn8nを構築する手順を、公式ドキュメントに沿って解説します。
検証環境
この記事の手順は、以下の環境で検証しています。
- Ubuntu 24.04 LTS
- Docker Engine 27.4
- Docker Compose v2.32
- n8n 1.76
- Traefik v3.3
バージョンが異なる場合、設定項目やオプションが変わっている可能性があります。公式ドキュメントも併せて確認してください。
前提知識
この記事では、以下の知識を前提としています。
- Linuxサーバーの基本的な操作(SSH接続、ファイル編集など)
- DockerとDocker Composeの基本概念
- DNSの仕組み(Aレコードの設定方法)
構成の全体像
最終的に、以下の構成でn8nが動作します。
インターネット
│
▼
[Traefik(リバースプロキシ)]
│ ・SSL/TLS証明書の自動管理(Let's Encrypt)
│ ・HTTPからHTTPSへのリダイレクト
│ ・ホスト名ベースのルーティング
▼
[n8n(ワークフローエンジン)]
│ ・ポート5678で動作
│ ・SQLiteでデータ永続化
│ ・ローカルファイルの読み書き
▼
[Docker Volumes]
├── n8n_data(データベース・暗号鍵)
├── traefik_data(SSL証明書)
└── local-files(ファイル共有ディレクトリ)
Traefikがリバースプロキシとして前段に立ち、SSL証明書の取得・更新を自動で行ってくれます。n8n本体はTraefikの後ろで動作し、HTTPS経由でアクセスできるようになります。
1. DockerとDocker Composeをインストールする
まず、サーバーにDockerとDocker Composeがインストールされている必要があります。すでにインストール済みの場合は、このステップは飛ばしてください。
インストール方法はLinuxディストリビューションによって異なります。以下の公式ドキュメントを参照してください。
インストール後、以下のコマンドで正しくインストールされたことを確認します。
docker --version
docker compose version
それぞれバージョン番号が表示されれば、インストールは完了です。
Docker Composeは、以前は docker-compose(ハイフン区切り)という別コマンドでしたが、現在は docker compose(スペース区切り)としてDocker CLIに統合されています。この記事では新しい形式を使います。
2.(任意)一般ユーザーでDockerを実行できるようにする
デフォルトでは、Dockerコマンドの実行に sudo が必要です。毎回 sudo を付けるのが面倒な場合は、現在のユーザーを docker グループに追加します。
sudo usermod -aG docker ${USER}
このコマンドで、現在ログインしているユーザーを docker グループに追加します。変更を反映するには、一度ログアウトしてからログインし直してください。
ログアウトせずに現在のセッションで反映したい場合は、以下のコマンドを実行します。
newgrp docker
別のユーザーに権限を付与したい場合は、${USER} の部分を対象のユーザー名に置き換えてください。
sudo usermod -aG docker <対象のユーザー名>
設定が反映されたかどうかは、以下のコマンドで確認できます。
groups
出力に docker が含まれていれば設定完了です。
docker グループに追加されたユーザーは、事実上root相当の権限を持つことになります。本番環境では、セキュリティポリシーに従って判断してください。
3. DNSを設定する
n8nをインターネットに公開するには、サーバーのIPアドレスにサブドメインを紐づけるDNS設定が必要です。
ドメインのDNS管理画面で、以下のようにAレコードを追加します。
| レコード種別 | ホスト名 | 値 |
|---|---|---|
| A |
n8n(任意のサブドメイン) |
サーバーのIPアドレス |
たとえば、example.com というドメインを持っていて、サブドメインを n8n にした場合、n8n.example.com でn8nにアクセスできるようになります。
DNSの反映には数分から最大48時間程度かかることがあります。設定後すぐにアクセスできなくても焦らず待ちましょう。
4. 環境変数ファイル(.env)を作成する
作業用のプロジェクトディレクトリを作成し、その中に .env ファイルを配置します。
mkdir n8n-compose
cd n8n-compose
.env ファイルを作成し、以下の内容を記述します。自分の環境に合わせて値を変更してください。
# ドメイン名(トップレベルドメイン)
DOMAIN_NAME=example.com
# サブドメイン名
SUBDOMAIN=n8n
# 上の設定の場合、https://n8n.example.com でアクセスできるようになる
# タイムゾーン(Cronノードなどのスケジュール実行に影響する)
GENERIC_TIMEZONE=Asia/Tokyo
# SSL証明書の発行に使うメールアドレス(Let's Encryptに登録される)
SSL_EMAIL=your-email@example.com
各項目について補足します。
-
DOMAIN_NAME / SUBDOMAIN: この2つの組み合わせで、n8nのアクセスURLが決まります。
SUBDOMAIN=n8n,DOMAIN_NAME=example.comならhttps://n8n.example.comです。 -
GENERIC_TIMEZONE: 日本で運用するなら
Asia/Tokyoに設定します。ワークフローのスケジュール実行やログのタイムスタンプに影響します。 - SSL_EMAIL: Let's EncryptがSSL証明書を発行する際に必要なメールアドレスです。証明書の有効期限が近づくと通知が届きます。
5. ローカルファイル共有ディレクトリを作成する
n8nのワークフローからホストマシン上のファイルを読み書きしたい場合に使う共有ディレクトリを作成します。
mkdir local-files
このディレクトリは、後述の compose.yaml でn8nコンテナの /files にマウントされます。n8nの「Read/Write Files from Disk」ノードを使って、ワークフローからファイルを読み書きできるようになります。
Docker Composeが自動でディレクトリを作成することもできますが、手動で作成しておくことで、所有者やパーミッションを正しく設定できます。
6. Docker Composeファイルを作成する
プロジェクトディレクトリ内に compose.yaml を作成します。これがn8n構築の中核となるファイルです。
services:
traefik:
image: "traefik"
restart: always
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- traefik_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
labels:
- traefik.enable=true
- traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.http.routers.n8n.tls=true
- traefik.http.routers.n8n.entrypoints=web,websecure
- traefik.http.routers.n8n.tls.certresolver=mytlschallenge
- traefik.http.middlewares.n8n.headers.SSLRedirect=true
- traefik.http.middlewares.n8n.headers.STSSeconds=315360000
- traefik.http.middlewares.n8n.headers.browserXSSFilter=true
- traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
- traefik.http.middlewares.n8n.headers.forceSTSHeader=true
- traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.n8n.headers.STSPreload=true
- traefik.http.routers.n8n.middlewares=n8n@docker
environment:
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- N8N_RUNNERS_ENABLED=true
- NODE_ENV=production
- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${GENERIC_TIMEZONE}
volumes:
- n8n_data:/home/node/.n8n
- ./local-files:/files
volumes:
n8n_data:
traefik_data:
ファイルの内容が多いので、ブロックごとに解説します。
Traefikコンテナの設定
traefik:
image: "traefik"
restart: always
Traefikは、HTTPSの終端処理とルーティングを担当するリバースプロキシです。restart: always により、サーバー再起動時にも自動で起動します。
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
-
--api.insecure=true: Traefikのダッシュボードを有効にします。ダッシュボードはポート8080で公開されるため、本番環境ではこの行を削除するか、アクセス制限をかけてください。 -
--providers.docker=true: Dockerコンテナのラベルからルーティングルールを自動検出します。 -
--providers.docker.exposedbydefault=false: 明示的にtraefik.enable=trueを指定したコンテナだけを公開します。
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
ポート80(HTTP)とポート443(HTTPS)でリクエストを受け付けます。HTTPでアクセスされた場合は、自動的にHTTPSにリダイレクトされます。
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
Let's Encryptを使ったSSL証明書の自動取得・更新の設定です。.env ファイルで指定したメールアドレスがここで参照されます。証明書のデータは /letsencrypt/acme.json に保存されます。
n8nコンテナの設定
n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
n8nの公式Dockerイメージを使用します。ポート5678は 127.0.0.1 にバインドしているため、外部から直接アクセスすることはできません。外部からのアクセスはTraefik経由でのみ可能です。
labels:
- traefik.enable=true
- traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
- traefik.http.routers.n8n.tls=true
- traefik.http.routers.n8n.entrypoints=web,websecure
- traefik.http.routers.n8n.tls.certresolver=mytlschallenge
Traefikに対して「このコンテナを公開する」「指定したホスト名でルーティングする」「TLS証明書を適用する」ことを伝えるラベルです。
- traefik.http.middlewares.n8n.headers.SSLRedirect=true
- traefik.http.middlewares.n8n.headers.STSSeconds=315360000
- traefik.http.middlewares.n8n.headers.browserXSSFilter=true
- traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
- traefik.http.middlewares.n8n.headers.forceSTSHeader=true
- traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
- traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
- traefik.http.middlewares.n8n.headers.STSPreload=true
セキュリティ関連のHTTPヘッダー設定です。HSTS(HTTP Strict Transport Security)を有効にして、ブラウザに「このサイトには必ずHTTPSでアクセスする」と記憶させます。XSSフィルターやContent-Typeのスニッフィング防止も設定しています。
environment:
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- N8N_RUNNERS_ENABLED=true
- NODE_ENV=production
- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${GENERIC_TIMEZONE}
n8nの動作に必要な環境変数です。
| 変数名 | 説明 |
|---|---|
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS |
設定ファイルのパーミッションを強制する |
N8N_HOST |
n8nが応答するホスト名 |
N8N_PORT |
n8nが使用するポート番号 |
N8N_PROTOCOL |
プロトコル(httpsを指定) |
N8N_RUNNERS_ENABLED |
ワークフローランナーを有効にする |
NODE_ENV |
Node.jsの実行モード(productionを推奨) |
WEBHOOK_URL |
Webhookトリガーで使用されるベースURL |
GENERIC_TIMEZONE / TZ
|
タイムゾーン設定 |
ボリューム設定
volumes:
n8n_data:
traefik_data:
2つのDocker Volumeと、1つのバインドマウントを使います。
| 名前 | 種別 | マウント先 | 用途 |
|---|---|---|---|
n8n_data |
Docker Volume | /home/node/.n8n |
SQLiteデータベースと暗号鍵の保存場所 |
traefik_data |
Docker Volume | /letsencrypt |
SSL証明書データの保存場所 |
./local-files |
バインドマウント | /files |
ホストとn8n間のファイル共有ディレクトリ |
7. Docker Composeを起動する
すべての準備が整ったら、n8nを起動します。
以降のコマンドでは sudo を付けています。ステップ2で docker グループへの追加が済んでいれば、sudo は不要です。
sudo docker compose up -d
-d オプションを付けることで、バックグラウンドで起動します。
コンテナの起動状態を確認するには、以下のコマンドを実行します。
sudo docker compose ps
2つのコンテナ(traefik と n8n)がどちらも Up 状態であれば正常に起動しています。
コンテナを停止したい場合は、以下を実行します。
sudo docker compose stop
8. 動作確認
ブラウザで .env に設定したURLにアクセスします。たとえば https://n8n.example.com です。
初回アクセス時には、管理者アカウントの作成画面が表示されます。ユーザー名、メールアドレス、パスワードを設定すれば、n8nのダッシュボードに入れます。
n8nはHTTPSでのみアクセス可能です。http:// でアクセスしようとすると、Traefikが自動でHTTPSにリダイレクトしますが、SSL証明書の発行が完了していない場合はエラーになることがあります。初回起動時は証明書の発行に少し時間がかかるため、数分待ってからアクセスしてください。
うまくいかないときのチェックポイント
構築中に問題が発生した場合、以下を確認してみてください。
アクセスできない場合
- DNSのAレコードが正しく設定されているか確認する。
dig n8n.example.comやnslookup n8n.example.comで名前解決ができるか試す。 - サーバーのファイアウォールで、ポート80と443が開放されているか確認する。
- SSL証明書の発行には、外部からポート443でアクセスできる必要がある。VPSのセキュリティグループやiptablesの設定を見直す。
コンテナが起動しない場合
ログを確認します。
sudo docker compose logs traefik
sudo docker compose logs n8n
よくある原因は、.env ファイルの記述ミス(スペルミスやクォーテーションの不備)です。
データを永続化できているか不安な場合
n8nのデータはDocker Volumeに保存されています。docker compose down でコンテナを停止・削除しても、ボリュームは残ります。ただし、docker compose down -v を実行するとボリュームごと削除されるので注意してください。
まとめ
この記事では、Docker Composeを使ってn8nをセルフホストする手順を解説しました。
手順を振り返ると、以下の流れです。
- DockerとDocker Composeをインストールする
- (任意)一般ユーザーにDocker実行権限を付与する
- DNSでサブドメインをサーバーに向ける
-
.envファイルで環境変数を設定する - ファイル共有ディレクトリを作成する
-
compose.yamlを作成する -
docker compose up -dで起動する - ブラウザからアクセスして初期設定を行う
TraefikによるSSL証明書の自動管理が含まれているため、一度構築してしまえば証明書の更新を手動で行う必要はありません。
n8nは400以上のインテグレーションに対応しており、構築後すぐにさまざまなワークフローを試せます。まずは簡単なワークフロー(たとえばWebhookを受け取ってSlackに通知する、など)から始めてみるのがおすすめです。