こんにちは!技術の海を漂う皆さん、お元気でしたか?
最近、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_URLやAPP_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)で教えていただけると嬉しいです。皆さんの知見を共有し合い、より良い技術の探求をしていきましょう!

