Xserver VPSのDocker環境(Dify + n8n)にOpenClawを追加してLINE Bot化する全記録

Xserver VPSのDocker環境(Dify + n8n)にOpenClawを追加してLINE Bot化する全記録

誰かの役に立つように書き残す。ただし正直、これを再現できる人がどれだけいるかは分からない。ハマりポイント10個、所要時間6時間の記録。

背景

Xserver VPS上でDifyとn8nがDocker Composeで同居している環境に、OpenClawを追加。LINE Messaging API経由でAIエージェントとして動かし、LINEに話しかけるとAIが返事する構成を作った。

OpenClawの設計思想

OpenClawの創始者Peter Steinbergerは「ローカルファースト」のアーキテクチャを意図的に構築している。ただし「ローカル」とは「個人のMac限定」ではなく、「ユーザーが管理するインフラ上で動かす」という意味。ノートPC、Mac Mini、ラズパイ、VPS、全てが想定対象。公式スローガンは "Your assistant. Your machine. Your rules."

つまりVPSでの運用は公式に想定された構成の一つ。ただしDockerでのデプロイは別問題で、Dockerのネットワーク分離とOpenClawのセキュリティモデル(localhost以外を疑う設計)の相性が悪い。 これが今回のハマりポイントの大半の根本原因。

参考: Fortune - Who is OpenClaw creator Peter Steinberger?
参考: Y Combinator独占インタビュー

最終構成

所要時間

約6時間(ハマりポイント10個)


1. docker-compose.yaml にサービスを追加

既存の docker-compose.yaml に追記:

  # OpenClaw
  openclaw:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: docker-openclaw
    restart: unless-stopped
    ports:
      - "18789:18789"
    volumes:
      - ./openclaw/data:/root/.openclaw
    environment:
      - OPENCLAW_GATEWAY_PORT=18789

networks は既存サービスと同じに合わせる。指定なしならデフォルトネットワーク。

docker compose up -d openclaw

DifyやN8nは触らない。 個別サービスを指定して安全に追加する。


2. Nginx設定にlocationを追加

templateファイルの場所を特定

Dify付属のNginxは default.conf.template から設定が生成される:

docker inspect <nginx-container> --format='{{json .Mounts}}' | python3 -m json.tool | grep -A3 "conf.d"

最終的なNginx設定(完成形)

templateファイルに以下を追記:

    # OpenClaw ダッシュボード
    location /openclaw/ {
      proxy_pass http://openclaw:18789/;
      include proxy.conf;
      include /etc/nginx/conf.d/ws-upgrade.conf;
    }

    # OpenClaw WebSocket(末尾スラッシュなし対応)
    location = /openclaw {
      proxy_pass http://openclaw:18789;
      include proxy.conf;
      include /etc/nginx/conf.d/ws-upgrade.conf;
    }

    # LINE Webhook
    location /line/webhook {
      proxy_pass http://openclaw:18789/line/webhook;
      include proxy.conf;
    }

WebSocket設定の共通化

n8nとOpenClawでWebSocket設定を共有するため、共通ファイルを作成:

cp nginx/conf.d/n8n-ws.conf nginx/conf.d/ws-upgrade.conf

中身:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

⚠️ ハマりポイント①:WebSocketヘッダーでNginx死亡

proxy_set_header Upgrade $http_upgrade;直接templateに書くとNginxが起動しなくなる。Difyのtemplateは envsubst で処理されるため、$http_upgrade が環境変数として解釈されて空文字になる。必ず別ファイルに切り出してincludeすること。

⚠️ ハマりポイント②:WebhookパスはOpenClawのバージョンで違う

多くの記事では /webhooks/line と書かれているが、実際のパスは /line/webhook だった(v2026.4.2)。

# POSTで400が返るのが正解。404は間違い。
curl -s -o /dev/null -w "%{http_code}" -X POST http://localhost:18789/line/webhook \
  -H "Content-Type: application/json" -d '{"events":[]}'

GETで200でもPOSTでNot Foundになることがある。必ずPOSTでテストすること。

⚠️ ハマりポイント③:proxy_passのホスト名

Docker内ネットワークなので localhost ではなく docker-composeのサービス名openclaw)を指定。

⚠️ ハマりポイント④:ダッシュボードのWebSocket 1006エラー

ダッシュボードのJSが wss://domain/openclaw末尾スラッシュなし)でWebSocket接続する。location /openclaw/ だけではマッチせず、ルートの / にフォールして502になる。

解決策:location = /openclaw(完全一致)を追加する。 ただし proxy_pass に末尾スラッシュをつけてはいけない。つけるとInternal Server Errorになる。


3. gateway.bindを変更する(502対策)

デフォルトではOpenClawは 127.0.0.1(loopback)でしかリッスンしない。Docker環境ではNginxは別コンテナなので502になる。

docker exec docker-openclaw openclaw config set gateway.bind "lan"
docker compose restart openclaw

ログで listening on ws://0.0.0.0:18789 になっていれば成功。

注意: gateway.bind "0.0.0.0" は旧バージョンの書き方。v2026.4.2では lan / loopback / tailnet / auto のモード指定に変わっている。


4. trustedProxiesを設定する(最重要)

⚠️ ハマりポイント⑤:Docker環境の「pairing required」地獄

OpenClawはlocalhostからの接続だけを信頼し、それ以外は全てペアリングを要求する。Dockerでは全てのリクエストが 172.18.x.x(Dockerの内部NAT)経由になるため、ダッシュボードもLINE Webhookも全部拒否される。

docker exec docker-openclaw openclaw config set gateway.trustedProxies '["172.18.0.0/16"]'
docker compose restart openclaw

172.18.0.0/16 はDockerの内部ネットワーク。インターネットからは到達できないのでセキュリティ的に問題なし。


5. 初期セットアップ(onboard)

docker exec -it docker-openclaw openclaw onboard

対話ウィザードで設定:

⚠️ ハマりポイント⑥:Channel Access Token を間違える

LINE Developersコンソールには似た値が複数ある:

Channel IDをAccess Tokenと間違えると401エラーになる。確認方法:

docker exec docker-openclaw curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: Bearer <トークン>" https://api.line.me/v2/bot/info
# 200ならOK、401ならトークンが間違ってる

6. ペアリング(2種類)

OpenClawにはdevicesペアリングとLINEペアリングの2種類がある。

ダッシュボード用(devices)

ブラウザでダッシュボードにアクセスすると承認を求められる:

docker exec docker-openclaw openclaw devices list
docker exec docker-openclaw openclaw devices approve <Request ID>

SSHトンネル経由とNginx経由は別デバイスとして認識されるので、それぞれ承認が必要。

LINE用(pairing)

LINEで初めてメッセージを送るとペアリングコードが返ってくる:

docker exec docker-openclaw openclaw pairing approve line <コード>

7. LINE側の設定


8. ダッシュボードへのアクセス(2つの方法)

方法A:SSHトンネル経由

ssh -i ~/.ssh/your_key -N -L 18789:127.0.0.1:18789 root@<VPS-IP>

ブラウザで http://localhost:18789/#token=<gateway-auth-token>

方法B:Nginx経由(SSHトンネル不要)

controlUi.allowedOrigins に外部ドメインを追加:

docker exec docker-openclaw openclaw config set gateway.controlUi.allowedOrigins \
  '["http://localhost:18789","http://127.0.0.1:18789","https://your-domain"]'
docker compose restart openclaw

ブラウザで https://your-domain/openclaw/#token=<gateway-auth-token>

トークンの取得:

docker exec docker-openclaw openclaw dashboard

9. セキュリティメモ


10. 容量とリソース

コンポーネント ディスク RAM
OpenClaw本体 約500MB 300〜500MB
Dify - 1〜2GB
n8n - 300〜500MB
OS等 - 300〜500MB

Xserver VPSのRAM 6GBプランなら3サービス同居可能。


ハマりポイント一覧

# 問題 原因 解決策
1 Nginx起動しない $http_upgrade がenvsubstで空文字に 別ファイルに切り出してinclude
2 502 Bad Gateway OpenClawがloopbackでしかリッスンしてない gateway.bind "lan"
3 pairing required DockerのNATでlocalhostに見えない trustedProxies + devices approve
4 Webhook POST 404 パスが /webhooks/line ではなく /line/webhook POSTでパスを検証
5 LINE Access Token 401 Channel IDをAccess Tokenと間違えた 正しいTokenを再発行
6 LINE返信来ない LINEペアリング未承認 pairing approve line <code>
7 ダッシュボード1006 (pairing) devicesペアリング未承認 devices approve
8 ダッシュボード1006 (WebSocket) JSが末尾スラッシュなしでWS接続 location = /openclaw を追加
9 ダッシュボード origin拒否 allowedOriginsに外部ドメインがない allowedOriginsに追加
10 ローカルLLMのハルシネーション qwen2.5:3bが「公式クラウドゲートウェイ」を捏造 公式ドキュメントでダブルチェック

感想

OpenClawは「ローカルファースト」の設計思想で作られており、ノートPC・Mac Mini・VPS・ラズパイなど「ユーザーが管理するインフラ」での動作が想定されている。VPSでの運用は公式に想定された構成の一つ。

ただし、Docker Compose環境での運用は茨の道だった。 ハマりポイントの大半(gateway.bind、trustedProxies、devices approve)はDockerのネットワーク分離とOpenClawのセキュリティモデル(localhostを信頼する設計)の相性問題。VPSに直接インストール(Docker不使用)すればこれらの問題の大半は回避できたはず。

既にDify + n8nがDocker Composeで動いている環境に追加するという今回の構成は、「Docker特有の問題」を踏み越える必要があった。

一度動いてしまえばLINEから話しかけるだけでAIエージェントが使えるのは非常に強力。VPSなのでMacがスリープしても24/7動き続ける。

エンジニアでない人にOpenClawを使ってもらう一番の方法は、VPSに構築してLINEのBotとして提供すること。使う側はLINEを友だち追加するだけで良い。


参考リンク


⚠️ ハマりポイント⑪(最重要):ボリュームマウント先の間違い

OpenClawの公式Dockerイメージはnodeユーザーで動作し、設定は /home/node/.openclaw/ に保存される。しかし多くのガイドや自分の最初の設定では /root/.openclaw にマウントしていた。

# ❌ 間違い — ここには設定が保存されない
volumes:
  - ./openclaw/data:/root/.openclaw

# ✅ 正しい — nodeユーザーのホームディレクトリ
volumes:
  - ./openclaw/data:/home/node/.openclaw

これが間違っていると、コンテナを再作成するたびに全ての設定(gateway.bind、trustedProxies、LINEチャネル、gogのOAuth認証データ等)が消える。 最も被害の大きいハマりポイント。

同様にgogcliの設定は /home/node/.config/gogcli/ に保存されるので、これも永続化が必要:

volumes:
  - ./openclaw/data:/home/node/.openclaw
  - ./openclaw/gogcli:/home/node/.config/gogcli

⚠️ ハマりポイント⑫:gogバイナリの永続化

docker cpdocker exec でコンテナ内にインストールしたバイナリは、コンテナ再作成で消える。永続化ボリューム内にバイナリを置くこと。

# ❌ コンテナ再作成で消える
docker cp /tmp/gog docker-openclaw:/home/node/.local/bin/gog

# ✅ 永続化ボリューム内に置く(消えない)
mkdir -p /root/dify/docker/openclaw/data/bin
cp /tmp/gog /root/dify/docker/openclaw/data/bin/gog
chmod +x /root/dify/docker/openclaw/data/bin/gog
# コンテナ内からは /home/node/.openclaw/bin/gog で参照

docker-compose.yaml 最終形

  openclaw:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: docker-openclaw
    restart: unless-stopped
    ports:
      - "18789:18789"
    volumes:
      - ./openclaw/data:/home/node/.openclaw      # ← /root/.openclawではない!
      - ./openclaw/gogcli:/home/node/.config/gogcli  # gogのOAuthトークン永続化
    environment:
      - OPENCLAW_GATEWAY_PORT=18789
    env_file:
      - ./openclaw/.env   # GOG_ACCOUNT, GOG_KEYRING_PASSWORD

.envファイル(./openclaw/.env)

GOG_ACCOUNT=your-email@gmail.com
GOG_KEYRING_PASSWORD=your-keyring-password

chmod 600 で自分だけ読める権限に。

最終ハマりポイント一覧(12個)

# 問題 原因 解決策
1 Nginx起動しない $http_upgrade がenvsubstで空文字に 別ファイルに切り出してinclude
2 502 Bad Gateway OpenClawがloopbackでしかリッスンしてない gateway.bind "lan"
3 pairing required DockerのNATでlocalhostに見えない trustedProxies + devices approve
4 Webhook POST 404 パスが /webhooks/line ではなく /line/webhook POSTでパスを検証
5 LINE Access Token 401 Channel IDをAccess Tokenと間違えた 正しいTokenを再発行
6 LINE返信来ない LINEペアリング未承認 pairing approve line <code>
7 ダッシュボード1006 (pairing) devicesペアリング未承認 devices approve
8 ダッシュボード1006 (WebSocket) JSが末尾スラッシュなしでWS接続 location = /openclaw を追加
9 ダッシュボード origin拒否 allowedOriginsに外部ドメインがない allowedOriginsに追加
10 ローカルLLMのハルシネーション qwen2.5:3bが「公式クラウドゲートウェイ」を捏造 公式ドキュメントでダブルチェック
11 設定が全部消えた ボリュームマウント先が /root/.openclaw(間違い) /home/node/.openclaw に修正
12 gogバイナリが消えた コンテナ再作成でコンテナ内のファイルが消える 永続化ボリューム内(/home/node/.openclaw/bin/)に置く

⚠️ ハマりポイント⑬:環境変数が設定ファイルを上書きする

docker-compose.yamlの environmentOPENCLAW_GATEWAY_BIND=0.0.0.0 を書いていると、CLIで openclaw config set gateway.bind "lan" しても毎回上書きされる。しかも 0.0.0.0 は旧バージョンの書き方で新バージョンでは無効 → loopbackにフォールバック → 502。

「何度直しても元に戻る」場合は、docker-compose.yamlの環境変数を疑え。 環境変数は設定ファイルより優先される。

# ❌ これが残っていると設定ファイルを上書きする
environment:
  - OPENCLAW_GATEWAY_BIND=0.0.0.0

# ✅ 削除して、設定ファイル(openclaw.json)で管理する
# gateway.bind は openclaw config set で設定済み