Back to tech

ローカルで動いている Dify を Cloudflare Tunnel で公開するメモ

4 min read
Table of Contents

こんにちは!技術の海を漂う皆さん、お元気でしたか?

最近、AI界隈で注目のOSSである Dify に魅せられて、LLM(大規模言語モデル)との対話に夢中になっています。

Difyはローカル環境で手軽に試せるのが嬉しいのですが、せっかくの強力なAI、もっと色々な場所からアクセスできるようにしたいですよね?
そこで今回は、Cloudflare Tunnel という魔法のトンネルを使って、ローカルで動くDifyをインターネット上に公開する、というちょっとした冒険に挑戦してみました。

備忘録という名の、この冒険の記録を皆さんにもシェアします。

環境

  • M4 Mac mini (OS 26.1)

  • Dify 1.11.1

前提条件

  • Dockerが、そう、あのコンテナの錬金術師が、あなたのPCにしっかりインストールされていること。

  • Cloudflareアカウント。インターネットの門番(?)とも言える、あのサービスですね。

  • Cloudflare Zero Trustダッシュボード。ここが今回の冒険の司令塔になります。

  • あなたのドメイン。インターネット上のあなたの「家」となるものです。

さて、DifyもCloudflare Tunnelも、今回はDockerコンテナの力を借りて動かします。まるで、AIとトンネル工事業者が協力するようなイメージでしょうか。

Cloudflare Tunnel のセットアップ

まずはCloudflare Zero Trustダッシュボードへログイン。そこで新しい「トンネル」を作成します。これで、あなたのローカル環境とインターネットの間に、安全な通路が開かれます。

トンネル作成の儀式を終えると、秘密の「トークン」が発行されます。これはDifyのドアを開ける鍵のようなもの。大切にメモしておきましょう。

トークン

Dify のセットアップ

次はDify本体です。公式GitHubリポジトリから、最新のコード(または今回利用したバージョン)をクローンしてきましょう。

git clone git@github.com:langgenius/dify.git

クローンした Dify のディレクトリ内にある docker フォルダへ移動し、docker-compose.yml ファイルを開きます。ここがDifyの動力源を定義する心臓部です。

% git diff docker-compose.yaml
diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml
index 825f0650c8..80c7773000 100644
--- a/docker/docker-compose.yaml
+++ b/docker/docker-compose.yaml
@@ -1529,6 +1529,13 @@ services:
     volumes:
       - ./volumes/unstructured:/app/data
 
+  cloudflared:
+    image: cloudflare/cloudflared:latest
+    command: tunnel --no-autoupdate run
+    environment:
+      TUNNEL_TOKEN: ${CLOUDFLARED_TUNNEL_TOKEN:-}
+    restart: always
+
 networks:
   # create a network between sandbox, api and ssrf_proxy, and can not access outside.
   ssrf_proxy_network:

このファイルに、cloudflared という、Cloudflare Tunnelを動かすためのサービス定義を追加します。まるで、AIのお城に、秘密の通路を管理する番人を配置するかのようですね。

次に、環境設定ファイルです。.env.example をコピーして .env という名前にしましょう。これが、Difyの「取扱説明書」になります。

cp .env.example .env

さあ、いよいよ「取扱説明書」の中身を、あなたの環境に合わせて書き換えていきます。ここが一番、愛を込める(?)部分かもしれません。

環境変数のリストは、なかなかのボリュームで「うわっ!」となるかもしれませんが、大丈夫。一つずつ見ていきましょう。今回は特に以下の項目を調整しました。

  • URL 関連 をすべて自分のドメインに変更: CONSOLE_API_URLAPP_WEB_URL など、Difyが外部と通信するためのURLを、あなたのドメイン(例: https://dify.yourdomain.com)に書き換えてください。Difyが「自分はここだよ!」と正しく名乗れるようにします。

  • 言語設定を日本語に変更: DifyのUIを日本語(ja_JP.UTF-8)に設定。これで、AIとの会話もさらにスムーズに(?)なりますね。

  • SECRET_KEY, DB_PASSWORD, REDIS_PASSWORD は適宜変更: SECRET_KEY やデータベース、Redisのパスワードは、推測されにくい強力なものに変更してください。AIの安全は、こういった地道な設定から始まります。

  • CLOUDFLARED_TUNNEL_TOKEN を追加して、Cloudflare Tunnel のトークンを設定: そして、先ほどCloudflareで取得したトンネルトークンを CLOUDFLARED_TUNNEL_TOKEN として設定します。これで、Difyがトンネルの入り口を見つけられます。

% git diff .env
diff --git a/docker/.env b/docker/.env
index 04088b72a8..9388df3c0c 100644
--- a/docker/.env
+++ b/docker/.env
@@ -10,36 +10,36 @@
 # used to concatenate the authorization callback.
 # If empty, it is the same domain.
 # Example: https://api.console.dify.ai
-CONSOLE_API_URL=
+CONSOLE_API_URL=https://~
 
 # The front-end URL of the console web,
 # used to concatenate some front-end addresses and for CORS configuration use.
 # If empty, it is the same domain.
 # Example: https://console.dify.ai
-CONSOLE_WEB_URL=
+CONSOLE_WEB_URL=https://~
 
 # Service API Url,
 # used to display Service API Base Url to the front-end.
 # If empty, it is the same domain.
 # Example: https://api.dify.ai
-SERVICE_API_URL=
+SERVICE_API_URL=https://~
 
 # Trigger external URL
 # used to display trigger endpoint API Base URL to the front-end.
 # Example: https://api.dify.ai
-TRIGGER_URL=http://localhost
+TRIGGER_URL=https://~
 
 # WebApp API backend Url,
 # used to declare the back-end URL for the front-end API.
 # If empty, it is the same domain.
 # Example: https://api.app.dify.ai
-APP_API_URL=
+APP_API_URL=https://~
 
 # WebApp Url,
 # used to display WebAPP API Base Url to the front-end.
 # If empty, it is the same domain.
 # Example: https://app.dify.ai
-APP_WEB_URL=
+APP_WEB_URL=https://~
 
 # File preview or download Url prefix.
 # used to display File preview or download Url to the front-end or as Multi-model inputs;
@@ -50,7 +50,7 @@ APP_WEB_URL=
 #   Recommendation: use a dedicated domain (e.g., https://upload.example.com).
 #   Alternatively, use http://<your-ip>:5001 or http://api:5001,
 #   ensuring port 5001 is externally accessible (see docker-compose.yaml).
-FILES_URL=
+FILES_URL=https://~
 
 # INTERNAL_FILES_URL is used for plugin daemon communication within Docker network.
 # Set this to the internal Docker service URL for proper plugin file access.
@@ -58,8 +58,8 @@ FILES_URL=
 INTERNAL_FILES_URL=
 
 # Ensure UTF-8 encoding
-LANG=en_US.UTF-8
-LC_ALL=en_US.UTF-8
+LANG=ja_JP.UTF-8
+LC_ALL=ja_JP.UTF-8
 PYTHONIOENCODING=utf-8
 
 # ------------------------------
@@ -96,7 +96,7 @@ ENABLE_REQUEST_LOGGING=False
 # A secret key that is used for securely signing the session cookie
 # and encrypting sensitive information on the database.
 # You can generate a strong key using `openssl rand -base64 42`.
-SECRET_KEY=sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U
+SECRET_KEY=YOUR_SECRET_KEY_HERE
 
 # Password for admin user initialization.
 # If left unset, admin user will not be prompted for a password
@@ -234,8 +234,8 @@ NEXT_PUBLIC_ENABLE_SINGLE_DOLLAR_LATEX=false
 # Database type, supported values are `postgresql` and `mysql`
 DB_TYPE=postgresql
 # For MySQL, only `root` user is supported for now
-DB_USERNAME=postgres
-DB_PASSWORD=difyai123456
+DB_USERNAME=dify
+DB_PASSWORD=YOUR_DB_PASSWORD_HERE
 DB_HOST=db_postgres
 DB_PORT=5432
 DB_DATABASE=dify
@@ -332,7 +332,7 @@ MYSQL_INNODB_FLUSH_LOG_AT_TRX_COMMIT=2
 REDIS_HOST=redis
 REDIS_PORT=6379
 REDIS_USERNAME=
-REDIS_PASSWORD=difyai123456
+REDIS_PASSWORD=YOUR_REDIS_PASSWORD_HERE
 REDIS_USE_SSL=false
 # SSL configuration for Redis (when REDIS_USE_SSL=true)
 REDIS_SSL_CERT_REQS=CERT_NONE
@@ -373,7 +373,7 @@ REDIS_CLUSTERS_PASSWORD=
 # If use Redis Sentinel, format as follows: `sentinel://<redis_username>:<redis_password>@<sentinel_host1>:<sentinel_port>/<redis_database>`
 # For high availability, you can configure multiple Sentinel nodes (if provided) separated by semicolons like below example:
 # Example: sentinel://:difyai123456@localhost:26379/1;sentinel://:difyai12345@localhost:26379/1;sentinel://:difyai12345@localhost:26379/1
-CELERY_BROKER_URL=redis://:difyai123456@redis:6379/1
+CELERY_BROKER_URL=redis://:YOUR_REDIS_PASSWORD_HERE@redis:6379/1
 CELERY_BACKEND=redis
 BROKER_USE_SSL=false
 
@@ -1204,7 +1204,7 @@ OPENSEARCH_NOFILE_HARD=65536
 # ------------------------------
 # Environment Variables for Nginx reverse proxy
 # ------------------------------
-NGINX_SERVER_NAME=_
+NGINX_SERVER_NAME=your.domain.here
 NGINX_HTTPS_ENABLED=false
 # HTTP port
 NGINX_PORT=80
@@ -1435,3 +1435,6 @@ TENANT_ISOLATED_TASK_CONCURRENCY=1
 
 # The API key of amplitude
 AMPLITUDE_API_KEY=
+
+# CloudFlared
+CLOUDFLARED_TUNNEL_TOKEN=YOUR_CLOUDFLARED_TUNNEL_TOKEN_HERE
\ No newline at end of file

全ての準備が整いました!いよいよDockerコンテナたちを起動させましょう。

docker-compose up -d

これで、あなたのローカル環境の http://localhost にアクセスすれば、Difyの洗練されたUIが顔を出します。まるで、秘密基地の扉が開いたかのようですね。

Cloudflare 側へ戻って外部公開の設定

さて、次にCloudflare側に戻り、先ほど作成したトンネルの設定画面を開きます。ここからが、Difyを世界に解き放つための最終調整です。

「公開されたアプリケーション ルート」という項目に、http://nginx:80 を追加します。これは、Cloudflare Tunnelが、あなたのローカルにあるDify(実際にはDocker内のNginxが受け持っています)にどうやって繋がるか、という道順を教えてあげる作業です。

公開されたアプリケーション ルート

これで、あなたの設定したドメイン(例: https://dify.yourdomain.com)にアクセスすれば、インターネット経由でDifyが使えるようになります!おめでとうございます、あなたのDifyは今、世界へ羽ばたきました!

まとめ

以上、ローカルで動くDifyをCloudflare Tunnelでインターネット上に公開する、というちょっとした冒険の記録でした。

もし「ここはこうするともっと便利だよ!」とか、「あれ?この手順、ちょっと違ったかも?」といった発見があれば、ぜひX(旧Twitter)で教えていただけると嬉しいです。皆さんの知見を共有し合い、より良い技術の探求をしていきましょう!