Dify 1.11.4 を proxy がある環境にインストール

Dify 1.11.4 AI

ubuntu server 24.04 にインストールする手順です。Dify は docker compose でインストールします。

Next.js のセキュリティ問題をはじめ、いくつかのセキュリティ問題があるので 1.11.4 までは上げた方が良いです。

この中の例では proxyサーバは、 192.168.100.1:8080 とします。

システムの proxy 設定

今回は最低限にします

上手く動かなければ過去記事を参照してください

git の proxy 設定 (後述の環境変数の設定だけでも多分OK)

git config --global http.proxy  http://192.168.100.1:8080
git config --global https.proxy http://192.168.100.1:8080

確認: cat ~/.gitconfig

apt の proxy設定

vi /etc/apt/apt.conf.d/95proxy
Acquire::http::Proxy "http://192.168.100.1:8080/";
Acquire::https::Proxy "http://192.168.100.1:8080/";

確認&アップデート

apt update

※ 初期設定の場合なので色々バージョンアップして良ければ apt upgrade -y を実行

環境変数 (今回は curl に必要です)

vi ~/.bashrc

export http_proxy="http://192.168.100.1:8080"
export https_proxy="http://192.168.100.1:8080"

source ~/.bashrc

Docker のインストール

準備

apt install -y ca-certificates curl gnupg

Docker リポジトリの追加

# キーリングを保存するディレクトリを作成
mkdir -p /etc/apt/keyrings

# GPGキーを取得して、バイナリ形式で保存
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 取得したキーに読み取り権限を付与(全ユーザーで apt が使えるように)
chmod a+r /etc/apt/keyrings/docker.gpg

# リポジトリを登録
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
  | tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker のインストール

apt updateapt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Docker の動作確認

docker --version

Docker のproxyの設定

Docker デーモンがプロキシ経由で通信できるように設定します。

mkdir -p /etc/systemd/system/docker.service.d
vi /etc/systemd/system/docker.service.d/http-proxy.conf

以下の内容を記述します。

[Service]
Environment="HTTP_PROXY=http://192.168.100.1:8080"
Environment="HTTPS_PROXY=http://192.168.100.1:8080"

設定後、以下のコマンドで設定をリロードし、Docker を再起動します。

systemctl daemon-reload
systemctl restart docker

Dify のインストールと設定

面倒なので root で作業する。

sudo -i

順番に実行する

# 取得
git clone https://github.com/langgenius/dify.git dify1.11
cd dify1.11
# タグの指定 (メッセージがたくさん出るが気にしなくて良い)
git checkout tags/1.11.4
cd docker
cp .env.example .env
cp docker-compose.yaml docker-compose.yaml.org   # バックアップとしてコピーしておく

.env の末尾に以下の設定を追加する (環境変数と競合するので MY_ を付けています。特に NO_PROXY の設定に重要)

vi .env

# Proxy
MY_HTTP_PROXY=http://192.168.100.1:8080
MY_HTTPS_PROXY=http://192.168.100.1:8080
MY_NO_PROXY=localhost,127.0.0.1,dify.local,host.docker.internal,api,weaviate,qdrant,sandbox,plugin_daemon,ssrf_proxy,elasticsearch,opensearch,172.18.0.0/16

docker-compose.yaml を編集

※ 今回、最低限の設定をしています。

x-shared-env: &shared-api-worker-env
  HTTP_PROXY: ${MY_HTTP_PROXY}
  HTTPS_PROXY: ${MY_HTTPS_PROXY}
  NO_PROXY: ${MY_NO_PROXY}
  CONSOLE_API_URL: ${CONSOLE_API_URL:-}
  CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-}

旧手順ではたくさん足していましたが、今回は3行のみ追加しています。

<<: *shared-api-worker-env これが入っているサービス全てに反映されます

対象は、api, worker, worker_beat, plugin_daemon です。

その他のサービスで、proxy に接続して外部に出る必要があるものがあれば、そのサービスの environment: の中に上記の赤の3行を書きます

  # Frontend web application.
  web:
    image: langgenius/dify-web:1.11.4
    restart: always
    environment:
      HTTP_PROXY: ${MY_HTTP_PROXY}
      HTTPS_PROXY: ${MY_HTTPS_PROXY}
      NO_PROXY: ${MY_NO_PROXY}
      CONSOLE_API_URL: ${CONSOLE_API_URL:-}
      APP_API_URL: ${APP_API_URL:-}

ssrf_proxy の squid に proxy を設定

vi ssrf_proxy/squid.conf.template

以下のように記入

赤字のところを追記。青字の部分は自分の環境に合わせて書き換えます。

:
:
################################## Proxy Server ################################
http_port ${HTTP_PORT}
coredump_dir ${COREDUMP_DIR}
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern .               0       20%     4320

# cache_dir ufs /var/spool/squid 100 16 256
# upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
# cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default

# 上位プロキシを設定(外部ネットワークへのアクセスを有効化)
# ただし、sandbox は直接接続するようにする
cache_peer 192.168.100.1 parent 8080 0 no-query no-digest no-netdb-exchange default
acl sandbox_server dstdomain sandbox
never_direct deny sandbox_server
never_direct allow all
forwarded_for delete

################################## Reverse Proxy To Sandbox ################################
http_port ${REVERSE_PROXY_PORT} accel vhost
cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver
acl src_all src all
http_access allow src_all

docker の起動

docker compose up -d

初回起動時は、コンテナをダウンロードしてくるので少し時間がかかります。

以下のようにコンテナが 11個起動されます。

NAME                     IMAGE                                       SERVICE       
docker-api-1             langgenius/dify-api:1.11.4                   api          
docker-db_postgres-1     postgres:15-alpine                           db_postgres  
docker-nginx-1           nginx:latest                                 nginx        
docker-plugin_daemon-1   langgenius/dify-plugin-daemon:0.5.2-local    plugin_daemon
docker-redis-1           redis:6-alpine                               redis        
docker-sandbox-1         langgenius/dify-sandbox:0.2.12              sandbox       
docker-ssrf_proxy-1      ubuntu/squid:latest                          ssrf_proxy   
docker-weaviate-1        semitechnologies/weaviate:1.27.0             weaviate     
docker-web-1             langgenius/dify-web:1.11.4                   web          
docker-worker-1          langgenius/dify-api:1.11.4                   worker       
docker-worker_beat-1     langgenius/dify-api:1.11.4                   worker_beat          

起動後の初回アクセス

http://<hostのIP>/

初回アクセス時にオーナーのユーザとパスワードを設定します

LLM を登録

  1. 右上のユーザーアイコンから設定を選択する
  2. 左の列から「モデルプロバイダー」を選択する
  3. モデルプロバイダーもプラグインになっているので、利用するものを選択してインストールする
  4. 必要に応じてAPIキーなどを設定する
  5. システムモデルの設定をす
    • 最低限、システム推論モデルと埋め込みモデルを設定する

※ ここでは OpenAI を例にしていますが、ollama などでローカルLLM をセットアップすることで無料で試すこともできます。

実験する (ワークフローに python から API でアクセス)

チャットボットかチャットフローを作って試す。

※ 変数名は、後述のコードを合わせる必要があるので prompt としてください。

出力変数の名称は、コードと合わせる必要があるので text としてください

APIキーを取得

.env

DIFY_BASE_URL=http://192.168.59.101/v1
DIFY_USER=ikuboh
DIFY_WORKFLOW_API_KEY=app-4bG0IlBBYBN77oGThaetF2XL

01_dify_workflow.py

#
# workflow の呼び出し
#
import os, sys
from dotenv import load_dotenv
import requests

if not os.path.isfile(".env"):
    print("Error: ファイルが存在しません: .env")
    sys.exit(1)

load_dotenv()

dify_base_url = os.getenv("DIFY_BASE_URL")
dify_api_key = os.getenv("DIFY_WORKFLOW_API_KEY")
user = os.getenv("DIFY_USER")

# 設定のエラーチェック
if not dify_base_url:
    raise ValueError("DIFY_BASE_URL が指定されていません")
if not dify_api_key:
    raise ValueError("DIFY_WORKFLOW_API_KEY が指定されていません")
if not user:
    raise ValueError("DIFY_USER が指定されていません")

# URL を加工
dify_base_url = dify_base_url.rstrip("/")
if not dify_base_url.endswith("/v1"):
    dify_base_url += "/v1"

url = f"{dify_base_url}/workflows/run"

print(f"Dify URL = {url}")

headers = {
    "Authorization": f"Bearer {dify_api_key}",
    "Content-Type": "application/json",
}
payload = {
    "inputs": {"prompt": "こんにちは!"},
    "user": user,
    # "response_mode": "streaming",
}

try:
    print("start connect")
    res = requests.post(url=url, headers=headers, json=payload)
    if res.ok:
        data = res.json()
        # print(data)
        print(data.get("data",{}).get("outputs",{}).get("text"))
    else:
        print(f"Error: code={res.status_code} : {res.text}")
except Exception as e:
    print(f"Error: {str(e)}")

※ 赤のマーカーのところがワークフローの入力で指定した prompt という変数名

※ 青のマーカーのところがワークフローの出力で指定した text という変数名

python3 -m venv venv
source venv/Scripts/activate
pip install python-dotenv requests

(venv) $ python 01_dify_workflow.py
Dify URL = http://192.168.59.101/v1/workflows/run
start connect
こんにちは!お元気でござるか?
(venv) $