⚙️

【Mac mini】n8nをDocker+Caddyで常時稼働(HTTPS対応)

に公開

※本記事は、読者の方にとって分かりやすい構成となるようAIのサポート活用し、私自身の経験と裏取りを元に書き下ろしたものです。

1. はじめに

本記事では、Mac miniにてDockerを用いてn8nサーバーを構築し、24時間常時稼働させるための具体的な手順を解説します。

n8nはセキュリティ要件が厳しく、安全にログインするためにはHTTPS通信を利用してクッキーを付与する必要があります。

そこで今回は、ローカルネットワーク内からセキュアにアクセスできる環境を構築する方法として、自動でHTTPS化が可能なCaddyを組み合わせた構成を採用し、その理由と具体的な導入手順について詳しく説明します。

alt text

2. 準備

前提環境

  • 運用するMac miniのモデル: 2018年モデル(Intel Core i5 8GBメモリ)
  • OS: macOS Monterey バージョン 12.7.6
  • Dockerがインストール済みであること。
  • Mac miniの常時稼働設定: システム設定のディスプレイ設定や省エネルギー設定からスリープを無効化し、電源を常時接続しておいてください。

Caddyについて

https://github.com/caddyserver/caddy

Caddyは、Go言語で記述されたオープンソースのWebサーバープラットフォームです。

有名なWebサーバーソフトウェアとしてNginxやApache HTTP Serverなどが挙げられますが、それらと比較してCaddyは設定ファイルがシンプルである点が魅力です。

Webサーバーやリバースプロキシとして機能するだけでなく、他のWebサーバーソフトでは別途ツールや複雑な設定が必要になるような機能でも、Caddyであれば初期状態で本体に内蔵されていることが多く、環境構築の手間を削減することができます。

Caddyの主な特徴や強み

今回、数あるWebサーバーのなかでもローカル環境での運用にCaddyを採用する理由として、以下の機能が挙げられます。

  • Automatic HTTPS機能: ドメイン名と情報の転送先を数行指定するだけで、認証局と連携し、SSL証明書の取得とスケジューリングされた定期的な更新を自動化してくれます。

  • ローカル環境向け証明書の自動発行: インターネットに公開されたグローバルなドメインだけでなく、ローカルIPアドレスやプライベートのローカルドメインであると自動判別された場合、Caddy自身が内部にローカル専用の認証局を立ち上げて自己署名証明書の発行および管理を自動で行ってくれます。ネットワーク外部へ公開しないローカルサーバーであっても、手動で証明書を作成して埋め込む対応が不要になります。

  • 設定ファイル記述のシンプルさ: 複雑な設定構文が必要な従来のWebサーバーソフトウェアに比べて、Caddyfileという単一のテキストファイルに数行の設定を記述するだけで、リバースプロキシとして機能します。

ファイルの準備

本環境構築では、以下の2つのファイルを作成します。

  1. Caddyfile
    内部通信のプロキシ設定や、ローカルIPならびにドメインに対するHTTPS化の設定を記述します。
Caddyfile
{
    default_sni 192.168.x.x
}

https://192.168.x.x {
    tls internal
    reverse_proxy n8n:5678 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }
}

各設定項目の解説

  • default_sni 192.168.x.x

    • 役割: Caddy全体に適用されるグローバル設定です。暗号化通信を確立する仕様において、デフォルトのサーバー名としてこのローカルIPアドレスの値を指定します。
    • 無いとどうなるか: IPアドレスで直接アクセスしてしまうと、サーバー側が適切に証明書を渡してくれません。その結果として暗号化されていないHTTPの状態でリクエストを送ろうとしてしまい、安全な通信ではないと判断されてブラウザ上でエラーが出てしまいます。
  • https://192.168.x.x : 指定したローカルIPアドレスに対してHTTPSでリクエストを受け付けるブロックの宣言です。ご自身の環境のIPへ適宜書き換えてください。

  • tls internal : 外部のパブリックな認証局ではなく、Caddy内部のローカルCAを用いてローカル専用の証明書を自動発行します。

  • reverse_proxy n8n:5678 : アクセスを背後で動いているn8nコンテナの5678ポートへ転送する機能です。Dockerの内部ネットワークで繋がっているため、コンテナ名であるn8nという名前で宛先を指定できます。

プロキシ通信時に付与する各ヘッダーの設定項目について

プロキシサーバーであるCaddyが間に入る仕組み上、それぞれのヘッダーで元々の通信状態がどのようなものであったかをn8nへ正しく伝える必要があります。

  • header_up Host {host}
    • 役割: クライアントがブラウザのURL欄に入力した本来のアクセス先情報をn8nへ伝えます。

    • 無いとどうなるか: Caddyからn8nへの通信宛先であるn8nコンテナ自体の名称が渡されてしまい、n8nにとって本来のドメインやIPが分からず、他のアプリとの連携機能などで正しいURLを生成できなくなる不具合が発生します。

    • header_up X-Real-IP {remote_host}

      • 役割: Webブラウザなど本来のアクセス元端末のIPアドレスを伝えます。
      • 無いとどうなるか: n8n側からはすべてのアクセスがCaddyなどの内部IPアドレスからのものとして扱われてしまい、アクセスログの記録が書き換わってしまうほか、IPアドレスを用いたアクセス制限などのセキュリティ機能が働かなくなってしまいます。
    • header_up X-Forwarded-Proto {scheme}

      • 役割: もともとのアクセスが安全なHTTPSであるというプロトコル情報をn8nに伝えます。
      • 無いとどうなるか: Caddyとn8nの間自体は暗号化されていないHTTP通信で行われているため、この設定がないとn8nはクライアントからのアクセスもHTTPであると誤認してしまいます。その結果、Webhook用のURLが誤って生成されるだけでなく、厳しいセキュリティ仕様の影響でセキュアクッキーを用いたログイン機能が完全に動作しなくなり、n8nへアクセスできなくなってしまいます。
  1. docker-compose.yml
    n8nとCaddyのコンテナ連携や、ディスクへデータを永続化するためのボリューム設定などを記述します。
docker-compose.yml
services:
  caddy:
    image: caddy:alpine
    container_name: caddy_proxy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - n8n

  n8n:
    image: n8nio/n8n:2.2.2
    container_name: n8n_app
    restart: unless-stopped
    environment:
      - GENERIC_TIMEZONE=Asia/Tokyo
      - N8N_ENCRYPTION_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      - N8N_HOST=192.168.x.x
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://192.168.x.x/
      - N8N_SECURE_COOKIE=false
      - N8N_COOKIE_SAMESITE=lax
      - N8N_BLOCK_PROXY_HEADERS=false
      - EXPLICIT_TRUST_PROXY=true
      - N8N_PROXY_HOPS=1
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:
  caddy_data:
  caddy_config:

各設定項目の解説

caddyサービスの設定について

  • ports - "80:80" ならびに - "443:443"

    • 役割: Mac miniへ届いた通信をCaddyコンテナへ渡すための扉の設定です。HTTP通信の標準である80番や、HTTPS標準の443番をそのまま利用することで、ブラウザでアドレスを入力する際に末尾の数値設定を省略してスムーズにアクセスできます。80番ポートは誤って暗号化されていない状態でアクセスしてきたユーザーを安全なHTTPSへと自動転送させる役割のほか、認証局がサーバーの所有権を確認する際の重要な通信窓口として機能します。一方の443番ポートはメインとなるHTTPS通信の出入り口であり、ここから入ってきた暗号化通信をCaddyが安全に解読し、内部のn8nへとリレーしてくれます。
    • 番号を変更するとどうなるか: 例えば8080番などに変更してしまうと、利用者がブラウザに入力する際にわざわざ毎回末尾へポートの数値を付与しなければアクセスできなくなってしまいます。さらに、利用者がURLのみを入力した際などに発生する無防備なHTTP通信は通常80番へ向かうため、Caddyが別の番号で待機していると通信を受け取れず、利用者を安全なHTTPSへと自動で転送させる機能が発動する前に通信エラーで切断されてしまいます。そのほか、外部の認証局も所有権の確認通信を必ず標準の80番ポートへ向けて強制的に送り込んでくる仕様があるため、設定変更により受信できず、証明書を自動更新させようとした際に更新エラーが発生する原因になってしまいます。
  • volumes - ./Caddyfile:/etc/caddy/Caddyfile

    • 役割: 手元で作成したリバースプロキシのルールが書かれた設定ファイルである Caddyfile 本体を、コンテナ内部へ読み込ませて共有するためのマウント設定です。
    • 無いとどうなるか: Caddyがどのように振る舞って通信を転送すればいいのかというルールを知ることができず、一切のプロキシ機能が動作しなくなります。
  • volumes - caddy_data:/data

    • 役割: Caddyが自動で取得および発行したSSL証明書本体や、通信の暗号化に用いる秘密鍵など、セキュリティに関与する最も重要なデータをホスト側のディスク領域へ永続化して残すための設定です。
    • 無いとどうなるか: コンテナを再構築する度に確保していた証明書データがすべて白紙にリセットされてしまいます。すると起動ごとに毎回新しい証明書を発行しようとするため、認証局が定めている発行回数の上限制限に引っかかってしまい、数日間まったく証明書が発行されずアクセスできなくなります。
  • volumes - caddy_config:/config

    • 役割: Caddyが稼働している現在の最新の通信状態や設定状況を自動でローカルへ保存し、不慮のトラブルが起きた際の予備データとして保管しておくための設定です。
    • 無いとどうなるか: 万が一新しいCaddyfileの記述にミスがあって起動に失敗したりクラッシュした際などに、直前まで正常に動いていた安全な状態へと自動で巻き戻る復旧機能が使えなくなり、システムエラーの解決が困難になってしまう場合があります。

n8nサービスの設定について

  • image: n8nio/n8n:2.2.2※Mac miniが古く、Dockerをアップデートできないため古いバージョンを指定しています。

    • 役割: n8nのコンテナイメージを指定します。今回使用しているMac miniが古いため、意図的に古いバージョンを指定しています。バージョンを指定することで、意図しないアップデートによる動作不良も防ぐことができます。
    • 無いとどうなるか: バージョンを指定しないと、常に最新のバージョンがインストールされてしまい、古い環境では予期せぬ不具合が発生する可能性があります。
  • GENERIC_TIMEZONE

    • 役割: システムのベースとなる標準時間を日本時間へ設定するための項目です。
    • 無いとどうなるか: n8nのタイマー機能やスケジュール機能の実行時刻が世界標準時を基準として処理されてしまい、思い通りの時間にワークフローが実行されなくなってしまいます。
  • N8N_ENCRYPTION_KEY

    • 役割: 外部サービスの認証情報など、データベースへ保存する機密データを暗号化するためのパスワードの役割を果たします。
    • 無いとどうなるか: コンテナを削除して再構築した際などにキーが変わってしまうと、以前まで保存していた外部との連携認証情報がすべて読み取れなくなり機能が利用できなくなってしまいます。
  • N8N_HOST

    • 役割: n8nシステム自身が、自分がどのドメインやIPアドレスで動作しているのかを認識するためのベース設定です。
    • 無いとどうなるか: ログイン時の画面遷移の割り当てや、システム内部でのリンク生成が乱れてしまい、ブラウザ上で正しく画面を移動できなくなるなどのエラーが発生しやすくなります。
  • WEBHOOK_URL

    • 役割: n8nが外部システムに向けて提示する、Webhook待ち受け用URLの完全なアドレスを指定します。
    • 無いとどうなるか: N8N_HOSTの設定だけではWebhook用のURLが正しく上書きされない場合があり、外部アプリとの連携機能で画面上に表示されるURLが初期設定の localhost などのままになって通信を受け取れなくなってしまいます。
  • N8N_PROTOCOL

    • 役割: n8nのシステムがHTTPSを用いた安全な環境で稼働していることを明示的に知らせます。
    • 無いとどうなるか: Caddyの背後で通信しているため内部的にはHTTPでシステムが動いており、これを明示しないと各種設定画面で発行されるエンドポイントURLが暗号化されていないhttpプロトコルのままになってしまいます。
  • NODE_ENV

    • 役割: 環境を本番運用向けに最適化して起動するための設定です。
    • 無いとどうなるか: メモリの扱いや機能の最適化などが開発者向けの重い状態となり、長期的に稼働させ続けた場合のパフォーマンスに影響が出る場合があります。
  • N8N_SECURE_COOKIE

    • 役割: システム内部でやり取りされるクッキーに対して、特定の暗号化通信環境でのみ許可するという強い制限の設定を制御します。
    • 無いとどうなるか: 今回のようなIPアドレスへのローカルアクセスや、内部通信がHTTPの中継環境である場合、ブラウザの仕様によっては認証クッキーの保存が拒否されてしまい、何度ログインしても初期画面に戻されてしまうという深刻なループ状態に陥ります。
  • N8N_COOKIE_SAMESITE

    • 役割: 外部のWebサービスなどとページを跨いで連携を行う際に、機能用のクッキーをどのくらい厳密に送信させるかというセキュリティレベルを調整します。
    • 無いとどうなるか: Chromeなどのモダンブラウザに搭載された仕様の制限に引っかかってしまい、別サイト遷移後やWebhook経由などでn8nと通信しようとした際にクッキーが送られず、セッションが途切れて認証エラーになってしまいます。
  • N8N_BLOCK_PROXY_HEADERS

    • 役割: プロキシから転送されてくる通信関連のヘッダー情報をすべて拒否するという、n8nの強固な初期セキュリティ設定をオフにします。
    • 無いとどうなるか: Caddy側でいくら元のIPなどのヘッダーを付与して送信しても、偽装された危険な情報だと判定されてしまいシステム入口ですべて破棄されてしまいます。
  • EXPLICIT_TRUST_PROXY

    • 役割: n8nのシステムの前段に、信頼できるリバースプロキシサーバーが確かに存在することをシステムへ明示的に認識させます。
    • 無いとどうなるか: そもそもプロキシが存在しない構成として扱われるため、送られてきたヘッダー情報を信用して処理に引き継ぐべきかという根本の判定ができず、アクセス制限の誤作動を招きます。
  • N8N_PROXY_HOPS

    • 役割: クライアントとn8nの本体との間に、プロキシサーバーが何台繋がっているかという数を指定します。今回はCaddy1台のみのため値は1とします。
    • 無いとどうなるか: 通信の深さが不明なままだと、送られてきたIPアドレス情報のうちどこからが本当のクライアントのアドレスなのかをn8nが計算できず、アクセス解析や通信制限といった機能が使えなくなってしまいます。

3. 立ち上げ

サーバーの起動

必要なファイルが準備できたら、コンテナを起動します。
ターミナルを開き、ファイルを作成したディレクトリで以下のコマンドを実行します。

docker compose up -d

ステータス確認

コンテナが正常に起動しているか確認します。

docker compose ps

docker compose psコンテナの起動確認

もし起動につまずいた場合やエラーが発生した場合は、以下のログ確認コマンドを使用して原因を調査します。

docker compose logs

4. 検証

ブラウザからのアクセス確認

ローカルネットワーク内にある別の端末、またはMac mini自身から指定したホスト名やローカルIPアドレスへHTTPSでアクセスします。

ブラウザからのHTTPSアクセス確認画面

プライバシー保護がされていないと出るので、詳細設定からアクセスを続行します。

無事にログインした後のn8nメイン画面

アカウント設定済みの場合は、画像のようにログイン画面が表示されます。
まだの場合は、初期設定画面が表示されます。

これで、常時稼働するn8nサーバーの構築は完了です。

5. まとめ

今回は、Mac mini上にDockerとCaddyを組み合わせて、n8nの要件を満たしたセキュアなローカルHTTPS環境を構築する手順を解説しました。

Mac miniでn8nを24時間稼働させることで、デバイスや時間を問わず自動化ワークフローを安定して運用することが可能になります。ぜひ日々のタスクや業務の効率化に役立てください。

GitHubで編集を提案
EMP Tech Blog

Discussion