Dify × Claude × (HubSpot) を Railway で構築してみたら、翌朝全部落ちていた(前編)

最近、社内で「AIチャットボットをWebサイトに入れて、将来的にはHubSpotの情報も参照できるようにしたいよね」という話が出ました。

やりたいことは、ざっくりこんな感じです。

WordPressサイト

Difyチャット

Claude

HubSpot

サイトに来た人がチャットで質問すると、AIがいい感じに答えてくれる。
さらに将来的には、HubSpotに入っている案件情報や顧客情報をリアルタイムに見に行って、条件に合う情報を返す。

そんな構成を目指しています。

最初はDify Cloudでサクッと試す案もありました。
ただ、せっかくなのでOSS版のDifyをRailwayに立ててみよう、ということで検証を開始。

結果から言うと、Claudeが動くところまでいけました。

そして翌朝、全部落ちていました。

この記事はその前編です。
前編では、Railway上にDifyを立てて、Claudeが動くところまでを書きます。
後編では、翌朝の復旧とHubSpot連携まわりを書こうと思います。

目次

なぜDifyを使うのか

今回やりたいのは、ただのチャットボットではありません。

最終的には、こんなことをやりたいです。

ユーザーが希望条件を入力

HubSpot内の案件・顧客情報を検索

Claudeが条件に合う情報を整理

チャットで回答

この用途だと、Difyはかなり相性が良さそうでした。

Difyは、LLMアプリを作るための基盤です。
ClaudeやGPTのようなモデルを使いつつ、チャットUI、ワークフロー、外部ツール連携、ナレッジ検索などをまとめて扱えます。

今回の構成でいうと、役割はこんな感じです。

Dify = AIアプリ本体
Claude = 回答生成モデル
HubSpot = 参照したい業務データ
WordPress = 表示するWebサイト
Railway = Difyを動かす場所

「これ、Difyでいけそうじゃない?」ということで試してみました。

最初は「テンプレ押せば終わりでしょ」と思っていた

RailwayにはDify用のテンプレートがあります。
なので最初はかなり軽い気持ちでした。

「テンプレ選んで、Deploy押して、終わりでしょ」

くらいのテンションです。ところが、いきなりこれが出ます。

This template requires 5 volumes, but your plan only allows 3 volumes per project.
Upgrade to deploy this template.

無料プランだとVolume数が足りないとのこと。

Dify OSSは、単体アプリではなく、いろいろなサービスの集合体です。

Web
Api
Worker
Postgres
Redis
Storage
Sandbox
Plugin Daemon
Weaviate

この時点で、「あ、これは思ったよりちゃんと重いやつだ」となりました。

ということで、RailwayをHobbyプランにして再チャレンジしました。

デプロイしたら、まあまあ落ちる

HobbyプランにしてDifyテンプレートをデプロイすると、いくつかのサービスは立ち上がりました。

Postgres、Redis、Web、Storageなどは起動。
一方で、ApiやWorkerが落ちます。

ログを見ると、原因はこれでした。

FATAL: database "dify" does not exist

どうやら、本来は初期化用のDatabase ProvisionがPostgres内に dify というDBを作る想定だったようです。
ただ、そこがうまく動いていませんでした。つまり、

DifyのApiは dify というDBを見に行く

でもPostgres内に dify DBがない

Apiが落ちる

Workerも落ちる

という流れです。

このあたりから、「テンプレを押したら完成」ではなく、「RailwayとDifyの中身を見ながら直していく会」になってきました。

Postgresに手動でDBを作る

対処として、Postgresに手動で dify データベースを作ることにしました。
ただ、ここでも一手間あります。
Railway上のPostgresは、内部ネットワークではこんなホスト名で参照されます。

postgres.railway.internal

これはRailway内部からは見えますが、自分のMacからは名前解決できません。

つまり、ローカルから psql しようとしてもつながらない。

そこで、一時的にRailwayのPostgresで Public Networking、つまりTCP Proxyを有効化しました。

これで外部からPostgresに接続できるURLが発行されます。
そのURLを使ってローカルから接続し、以下を実行しました。

CREATE DATABASE dify;

その後、ApiとWorkerを再デプロイ。

これでようやくサービス全体が正常に近い状態になりました。

ちなみに、この作業が終わったらPostgresのPublic TCP Proxyは削除しました。
外部からDBへ接続できる入口を開けっぱなしにするのは怖いので、ここは忘れずに閉じます。

次の壁:Difyの初期化画面から進めない

ようやくサービスは立ち上がりました。

DifyのWeb画面にアクセスすると、管理者初期化パスワードの画面が表示されます。

「お、いけたか?」と思いました。

でも、初期化パスワードを入力すると、一瞬だけ管理者アカウント作成画面に遷移して、すぐに元の画面に戻されます。これがなかなかしんどかったです。

原因は、WebとApiのドメイン構成でした。

Railwayでは、WebとApiがそれぞれ別の自動生成URLになります。

Web: https://web-production-xxxx.up.railway.app
Api: https://api-production-yyyy.up.railway.app

Difyでは、WebとApiが別サブドメインになる場合、CookieやCORSまわりの設定がかなり大事です。

特に初期化やログインのような認証フローでは、この設定がズレているとセッションが維持できません。

その結果、

パスワード検証は成功

でもセッションが維持できない

初期化画面に戻る

という、かなり悲しい状態になります。

検証用ドメインを取る

Railwayの自動URLのまま頑張るのは厳しそうだったので、検証用のドメインを取りました。

本番の会社ドメインではなく、PoC用のいらないドメインです。

構成はこうしました。

Web: https://dify.example.com
Api: https://dify-api.example.com
Cookie domain: example.com

実際には、お名前.comでドメインを取り、Railway側でWebとApiにCustom Domainを設定しました。

Railway側では、CNAMEだけでなくTXTレコードも求められました。

CNAMEは、アクセス先をRailwayに向けるため。
TXTは、ドメイン所有確認のためです。

お名前.com側には、こんな感じでレコードを追加します。

dify CNAME xxxx.up.railway.app
dify-api CNAME yyyy.up.railway.app
_railway-verify.dify TXT railway-verify=…
_railway-verify.dify-api TXT railway-verify=…

DNS反映にはそれなりに時間がかかりました。

Web側は先に通りましたが、Api側はしばらく Waiting for DNS update のまま。
「待てばいいのか、設定が間違っているのか」が分かりづらく、ここでも時間を使いましたが、時間経過で最終的には両方通りました。

環境変数を独自ドメインに合わせる

WebとApiの独自ドメインが通ったら、Dify側の環境変数を変更します。

Api側はこんな感じです。

CONSOLE_API_URL=https://dify-api.example.com
SERVICE_API_URL=https://dify-api.example.com
FILES_URL=https://dify-api.example.com
CONSOLE_WEB_URL=https://dify.example.com
APP_WEB_URL=https://dify.example.com
CONSOLE_CORS_ALLOW_ORIGINS=https://dify.example.com,*
WEB_API_CORS_ALLOW_ORIGINS=https://dify.example.com,*
COOKIE_DOMAIN=example.com

Web側はこんな感じ

APP_API_URL=https://dify-api.example.com
CONSOLE_API_URL=https://dify-api.example.com
FILES_URL=https://dify-api.example.com
NEXT_PUBLIC_COOKIE_DOMAIN=1

ポイントは COOKIE_DOMAIN です。

最初はRailway側の自動設定で up.railway.app になっていました。
でも独自ドメインにした後は、自分で取った親ドメインに変更する必要があります。

ここを直して、ApiとWebを再デプロイ。

ようやく初期化画面の先に進めました。

ついに管理者アカウント作成へ

環境変数を直して再デプロイした後、もう一度Difyにアクセス。
今度は無事に、管理者アカウント作成画面まで進めました。

長かった。

メールアドレス、名前、パスワードを設定して、Difyにログイン。

この時点で、ようやくDifyの管理画面に入れました。

ここまででできたことはこんな感じです。

Dify OSS on Railway 起動
Postgres / Redis / Web / Api / Worker 稼働
独自ドメイン設定
Cookie問題解消
管理者アカウント作成
ログイン確認

やっとAIアプリを作る準備が整いました。

ここまででもう、まあまあ一仕事です。

Claudeを接続する

次に、ClaudeをDifyに接続します。

DifyのModel Provider設定からAnthropicを選び、APIキーを登録します。

設定はこんな感じです。

認証名:Claude API
API Key:AnthropicのAPIキー
API URL:空欄

Anthropic公式APIをそのまま使う場合、API URLは空欄でOKでした。
プロキシや独自ゲートウェイを使う場合だけ指定するようです。

その後、システムモデル設定でClaudeを選びます。

今回はClaude Sonnet系のモデルを設定しました。

ここはわりとスムーズでした。
やっと普通の作業になった感じがします。

最初のチャットフローを作る

Difyではアプリタイプとして「チャットフロー」を選びました。

今回作りたいのは、ユーザーと会話するチャットUIです。
裏側の処理だけを実行するワークフローではなく、会話が前提なのでチャットフローにしました。

最初はHubSpot連携なしで、Claudeが返答できるかだけ確認します。

この時点でプレビューでプロンプトを入力すると、Claudeから返答があります。

ようやくここで、

「Dify on RailwayでClaudeが動いた」

という状態になりました。この瞬間はちょっと嬉しかったです。

WordPressへの埋め込みコードも取れた

Difyでは、作成したアプリをWebサイトに埋め込むためのiframeコードも取得できます。

こんな感じです。

<iframe
src="https://dify.example.com/chatbot/xxxx"
style="width: 100%; height: 100%; min-height: 700px"
frameborder="0"
allow="microphone">
</iframe>

これをWordPressの固定ページにカスタムHTMLとして貼れば、サイト上にDifyチャットを表示できます。

ここまで来ると、PoCとしてはだいぶ形になってきました。

「Difyを自前で立てて、Claudeをつなげて、WordPressに埋め込む」

ここまでは達成です。

そして翌朝

夜の時点では、Difyにログインできて、Claudeも動いて、チャットフローも作れました。

ここまで来ると、人間はだいたい調子に乗ります。

「これはもう勝ったのでは?」
「明日はHubSpotつなぐだけでは?」

そんな気持ちで作業を終えました。

ただし、まだHubSpot連携はこれからです。

当初の目的である、HubSpotをリアルタイムに検索して回答するという検証は、次のステップでした。

DifyのHubSpotプラグインを使うのか。
ToolとしてHubSpot APIを呼ぶのか。
それとも結局n8nを挟むのか。

そのあたりを翌日検証しよう、というところで一旦終了。

そして翌朝。

コーヒーを飲みながらRailwayを開くと、そこには元気なDify……ではなく、赤い表示が並んでいました。

「あれ?」

昨日あれだけ頑張って起動したサービスたちが、きれいに全部死んでいます。

しかも、ログもまともに見れない。最初は普通に、自分の設定ミスを疑いました。

Cookie設定?
Worker?
Redis?
Volume?
Plugin Daemon?

ただ、どう考えてもおかしい。昨日の夜まで普通に動いていた構成が、朝になった瞬間に全部落ちている。

しかも、Railwayのダッシュボード自体も微妙に怪しい。
そこでStatusページを見に行くと、そこにはこう書かれていました。

Railway Service Disruption
Major Outage

Google Cloud has blocked our account

いや、スケールがデカい。

どうやら、自分のDifyが壊れたというより、Railway側がかなり大きめに死んでいたようです。

つまり、この時点でわたしにできることはほぼありません。

復旧作業=待つ
です。

もちろん、その間も人間は無駄に再デプロイしたり、ログを更新したりします。

でも結局、待つしかない。PoCをやっていると、

「自分の設定ミス」
なのか
「プラットフォーム側障害」
なのか

の切り分けが、本当に難しいです。

特に今回みたいに、前日の夜まで普通に動いていると、なおさら混乱します。

そして学びました。

AI時代でも、インフラは普通に壊れます。

前編まとめ

今回は、Dify × Claude × HubSpot構成の前段として、まずDify OSSをRailwayに立てました。

やったことはこんな感じです。

Railway Hobbyプラン化
Difyテンプレートをデプロイ
Postgresのdify DBを手動作成
独自ドメイン設定
Web / ApiのCookie設定
Dify管理者アカウント作成
Claude API接続
チャットフロー作成
WordPress埋め込みコード取得

最終的に、Claudeが返答するところまでは確認できました。

ただ、RailwayのDifyテンプレートは、PoC初手としてはなかなか手強かったです。

特にハマったのはこのあたりです。

無料枠ではVolume数が足りない
Database Provisionがうまく動かない
Postgresにdify DBが作られない
Railway内部DNSにローカルから接続できない
WebとApiの自動URL構成だとCookieで詰まる
独自ドメインとTXT認証が必要になる
環境変数の設定箇所が多い

テンプレートを押せばサクッと終わる、というよりは、
Difyの構成、Railwayのネットワーク、Cookie、DNS、DB初期化を少しずつ見ながら直していく感じでした。

そして何より大事なのは、

「動いた」と「運用できる」は全然違う

ということです。

夜に「いけた!」と思っても、翌朝には普通に全部落ちています。

しかも、その原因が自分なのか、Railwayなのか、Difyなのか、最初は全然分からない。

今回も最終的には、Railway側で大きめの障害が起きていました。

つまり、我々にできることは、

待つ

だけです。AIまわりは日々進化していますが、インフラはちゃんとインフラでした。

後編では(Railwayが復旧次第)、

HubSpotをリアルタイム検索できるのか?
DifyのHubSpotプラグインは実用になるのか?
PoCとしてどこまで成立するのか?

このあたりを検証していきます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次