<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Dify on K-Life Hack | システムアーキテクチャ &amp; DevOps</title><link>https://klifehack.com/tags/dify/</link><description>Recent content in Dify on K-Life Hack | システムアーキテクチャ &amp; DevOps</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Sat, 03 Oct 2026 10:14:28 +0900</lastBuildDate><atom:link href="https://klifehack.com/tags/dify/index.xml" rel="self" type="application/rss+xml"/><item><title>DockerとCaddyによるDifyセルフホスト環境の構築とセキュリティ硬化設計</title><link>https://klifehack.com/p/dify-self-hosting-docker-caddy-hardening/</link><pubDate>Sat, 03 Oct 2026 10:14:28 +0900</pubDate><guid>https://klifehack.com/p/dify-self-hosting-docker-caddy-hardening/</guid><description>&lt;p&gt;LLMオーケストレーションツールであるDifyをセルフホストする要求は、パブリッククラウド版の機能制限（作成可能なアプリケーション数やナレッジパイプラインの制約）を回避するために急速に高まっています。しかし、ローカル環境での運用は、マシンのスリープや動的IP、ファイアウォール越えといった可用性の課題を伴います。24時間稼働するLinux VPS上にDockerを用いてDifyを構築し、Caddyによる自動HTTPS化とセキュリティ硬化を施すことで、実用的な運用環境を確立できます。&lt;/p&gt;&#10;&lt;p&gt;本稿では、Dify &lt;code&gt;v1.17.x&lt;/code&gt; および Caddy &lt;code&gt;v2.11.x&lt;/code&gt; をベースに、ホストマシンのセキュリティを担保しつつ、リバースプロキシを介して安全に外部公開するためのインフラ設計と具体的な実装手順を解説します。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-システムアーキテクチャ設計"&gt;1. システムアーキテクチャ設計&#10;&lt;/h2&gt;&lt;p&gt;本環境におけるネットワークおよびコンテナの配置トポロジーは以下の通りです。&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;[ 外部クライアント / Webhook 送信元 ]&#10; │&#10; │ https://dify.&amp;lt;domain&amp;gt; (Port 443)&#10; ▼&#10;┌───────────────────────────────── VPS ホスト ─────────────────────────────────┐&#10;│ │&#10;│ Caddy リバースプロキシ (ACME SSL自動管理, Ports 80 / 443) │&#10;│ │ │&#10;│ │ reverse_proxy (ローカルループバック経由) │&#10;│ ▼ │&#10;│ 127.0.0.1:8080 │&#10;│ │ │&#10;│ │ Docker ポートマッピング │&#10;│ ▼ │&#10;│ dify-nginx (コンテナポート :80) │&#10;│ ├─ web / api / worker / worker_beat │&#10;│ ├─ db_postgres / redis / weaviate │&#10;│ └─ plugin_daemon (127.0.0.1:5003) │&#10;│ │&#10;└──────────────────────────────────────────────────────────────────────────────┘&#10;外部公開ポート: 80/tcp, 443/tcp, 443/udp (Caddy), SSH (カスタムポート)&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;セキュリティ上の最重要設計として、Difyを構成するコンテナ群（Nginx、PostgreSQL、Redis、Plugin Daemon等）は、ホストのグローバルネットワークインターフェース（&lt;code&gt;0.0.0.0&lt;/code&gt;）には一切バインドせず、ループバックアドレス（&lt;code&gt;127.0.0.1&lt;/code&gt;）にのみバインドします。外部からのトラフィックは、Caddyリバースプロキシがすべて受信し、SSL/TLSを終端した上で内部転送します。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="2-ホストインフラのプロビジョニング"&gt;2. ホストインフラのプロビジョニング&#10;&lt;/h2&gt;&lt;h3 id="2-1-システムパッケージの更新と依存関係の導入"&gt;2-1. システムパッケージの更新と依存関係の導入&#10;&lt;/h3&gt;&lt;p&gt;ホストOS（Ubuntu 22.04 LTS / 24.04 LTSを想定）のパッケージを最新化し、必要なツール群を導入します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt update &amp;amp;amp;&amp;amp;amp; sudo apt upgrade -y&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt install -y git curl jq acl&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-2-docker-engineの導入と検証"&gt;2-2. Docker Engineの導入と検証&#10;&lt;/h3&gt;&lt;p&gt;Docker Engineが未導入の場合は、公式のスクリプトを用いて導入します。Docker Composeのバージョンが &lt;code&gt;v2.24.0&lt;/code&gt; 以上であることを確認してください（後述の &lt;code&gt;!override&lt;/code&gt; 構文のサポートに必要です）。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker --version 2&amp;amp;gt;/dev/null &lt;span style="color:#f92672"&gt;||&lt;/span&gt; curl -fsSL https://get.docker.com | sudo sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker compose version&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl is-enabled docker&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-3-専用システムユーザーの作成と権限設定"&gt;2-3. 専用システムユーザーの作成と権限設定&#10;&lt;/h3&gt;&lt;p&gt;セキュリティ確保のため、&lt;code&gt;root&lt;/code&gt; ユーザーでのコンテナ実行を避け、専用の &lt;code&gt;dify&lt;/code&gt; ユーザーを作成して運用します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo adduser dify&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo usermod -aG docker dify&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo usermod -aG sudo dify&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-4-スワップ領域4gbの確保"&gt;2-4. スワップ領域（4GB）の確保&#10;&lt;/h3&gt;&lt;p&gt;Difyはバックエンドで複数のマイクロサービス（10以上のコンテナ）を同時に起動するため、アイドル時でも3〜5GBのメモリを消費します。メモリ不足によるカーネルのOOM（Out of Memory）キラーの作動を防ぐため、4GBのスワップ領域を明示的に確保します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo fallocate -l 4G /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo chmod &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mkswap /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo swapon /swapfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#39;/swapfile none swap sw 0 0&amp;#39;&lt;/span&gt; | sudo tee -a /etc/fstab&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo sysctl vm.swappiness&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#39;vm.swappiness=10&amp;#39;&lt;/span&gt; | sudo tee /etc/sysctl.d/99-swappiness.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;free -h&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="3-difyオーケストレーションのデプロイ"&gt;3. Difyオーケストレーションのデプロイ&#10;&lt;/h2&gt;&lt;p&gt;ここからの作業は、先ほど作成した &lt;code&gt;dify&lt;/code&gt; ユーザーに切り替えて実行します。&lt;/p&gt;&#10;&lt;h3 id="3-1-リポジトリの取得と環境変数の暗号化設定"&gt;3-1. リポジトリの取得と環境変数の暗号化設定&#10;&lt;/h3&gt;&lt;p&gt;最新のリリースバージョンをGitHub API経由で動的に取得し、クローンします。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ~&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone --branch &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;curl -s https://api.github.com/repos/langgenius/dify/releases/latest | jq -r .tag_name&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; https://github.com/langgenius/dify.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ~/dify/docker&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp .env.example .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chmod &lt;span style="color:#ae81ff"&gt;600&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;.env&lt;/code&gt; ファイル内の初期パスワードおよび暗号化キーを、高エントロピーなランダム文字列に書き換えます。初期値（&lt;code&gt;difyai123456&lt;/code&gt; など）のまま起動することは、外部からの不正アクセスのリスクを極めて高めるため厳禁です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# セッショントークン暗号化用のキー生成&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#34;s|^SECRET_KEY=.*|SECRET_KEY=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;openssl rand -base64 42&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;|&amp;#34;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# PostgreSQLおよびRedis用のパスワード生成&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;DBP&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;openssl rand -hex 24&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;RP&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;openssl rand -hex 24&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#34;s|^DB_PASSWORD=.*|DB_PASSWORD=&lt;/span&gt;$DBP&lt;span style="color:#e6db74"&gt;|&amp;#34;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#34;s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=&lt;/span&gt;$RP&lt;span style="color:#e6db74"&gt;|&amp;#34;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Celery Broker URLへのRedisパスワードの反映&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#34;s|^CELERY_BROKER_URL=.*|CELERY_BROKER_URL=redis://:&lt;/span&gt;$RP&lt;span style="color:#e6db74"&gt;@redis:6379/1|&amp;#34;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-2-ポートバインドのループバック限定化"&gt;3-2. ポートバインドのループバック限定化&#10;&lt;/h3&gt;&lt;p&gt;Dockerのデフォルト設定では、ポートマッピングを行うとホストの全インターフェース（&lt;code&gt;0.0.0.0&lt;/code&gt;）でポートが開放され、UFWなどのホスト側ファイアウォールをバイパスしてしまいます。これを防ぐため、&lt;code&gt;.env&lt;/code&gt; 内の露出ポート設定に &lt;code&gt;127.0.0.1:&lt;/code&gt; プレフィックスを明示的に付与します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#39;s|^NGINX_PORT=.*|NGINX_PORT=80|&amp;#39;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#39;s|^NGINX_SSL_PORT=.*|NGINX_SSL_PORT=443|&amp;#39;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#39;s|^EXPOSE_NGINX_PORT=.*|EXPOSE_NGINX_PORT=127.0.0.1:8080|&amp;#39;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#39;s|^EXPOSE_NGINX_SSL_PORT=.*|EXPOSE_NGINX_SSL_PORT=127.0.0.1:8443|&amp;#39;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#39;s|^EXPOSE_PLUGIN_DEBUGGING_PORT=.*|EXPOSE_PLUGIN_DEBUGGING_PORT=5003|&amp;#39;&lt;/span&gt; .env&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-3-plugin-daemonのバインド制限docker-compose-override"&gt;3-3. Plugin Daemonのバインド制限（Docker Compose Override）&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;plugin_daemon&lt;/code&gt; サービスは、デフォルトで &lt;code&gt;0.0.0.0:5003&lt;/code&gt; にバインドされる設定になっています。これを安全に上書きするため、&lt;code&gt;docker-compose.override.yaml&lt;/code&gt; を作成し、ループバックアドレスに制限します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ~/dify/docker/docker-compose.override.yaml&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;plugin_daemon&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;: !&lt;span style="color:#ae81ff"&gt;override&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1:5003:5003&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-4-コンテナの起動と初期ヘルスチェック"&gt;3-4. コンテナの起動と初期ヘルスチェック&#10;&lt;/h3&gt;&lt;p&gt;設定が完了したら、コンテナ群をバックグラウンドで起動します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker compose up -d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;起動後、APIサーバーが正常に応答するかローカルループバック経由で確認します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sleep &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s http://127.0.0.1:8080/console/api/setup&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;正常に起動していれば、&lt;code&gt;{&amp;ldquo;step&amp;rdquo;:&amp;ldquo;not_started&amp;rdquo;,&amp;ldquo;setup_at&amp;rdquo;:null}&lt;/code&gt; というJSONレスポンスが返ります。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="4-caddyによるhttpsリバースプロキシの構築"&gt;4. CaddyによるHTTPSリバースプロキシの構築&#10;&lt;/h2&gt;&lt;p&gt;Caddyを使用して、Let&amp;rsquo;s EncryptからSSL/TLS証明書を自動取得し、HTTPS通信を終端します。&lt;/p&gt;&#10;&lt;h3 id="4-1-caddyのインストール"&gt;4-1. Caddyのインストール&#10;&lt;/h3&gt;&lt;p&gt;公式リポジトリを追加し、Caddyを導入します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -1sLf &lt;span style="color:#e6db74"&gt;&amp;#39;https://dl.cloudsmith.io/public/caddy/stable/gpg.key&amp;#39;&lt;/span&gt; | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -1sLf &lt;span style="color:#e6db74"&gt;&amp;#39;https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt&amp;#39;&lt;/span&gt; | sudo tee /etc/apt/sources.list.d/caddy-stable.list&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt update &amp;amp;amp;&amp;amp;amp; sudo apt install -y caddy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-2-caddyfileの構成"&gt;4-2. Caddyfileの構成&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;/etc/caddy/Caddyfile&lt;/code&gt; を編集し、ドメインから内部の &lt;code&gt;127.0.0.1:8080&lt;/code&gt; へルーティングする設定を行います。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-caddy" data-lang="caddy"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# /etc/caddy/Caddyfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify.example.com {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;reverse_proxy&lt;/span&gt; 127.0.0.1:&lt;span style="color:#ae81ff"&gt;8080&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;※ &lt;code&gt;dify.example.com&lt;/code&gt; は、実際にDNSでVPSのパブリックIPを指すように設定したドメインに置き換えてください。&lt;/p&gt;&#10;&lt;p&gt;設定ファイルの構文チェックを行い、問題がなければCaddyサービスをリロードします。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo caddy validate --config /etc/caddy/Caddyfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemctl reload caddy&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="5-troubleshooting"&gt;5. Troubleshooting&#10;&lt;/h2&gt;&lt;p&gt;セルフホスト環境の構築および運用フェーズで直面しやすい代表的な摩擦点（Friction Points）と、その解決策を以下に示します。&lt;/p&gt;&#10;&lt;h3 id="5-1-dockerによるufwファイアウォールバイパス問題"&gt;5-1. DockerによるUFW（ファイアウォール）バイパス問題&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;b&gt;事象&lt;/b&gt;: ホスト側で &lt;code&gt;sudo ufw deny 8080/tcp&lt;/code&gt; を設定しているにもかかわらず、外部から &lt;code&gt;http://&amp;lt;VPS_IP&amp;gt;:8080&lt;/code&gt; に直接アクセスできてしまう。&lt;/li&gt;&#10;&lt;li&gt;&lt;b&gt;原因&lt;/b&gt;: Dockerはホストの &lt;code&gt;iptables&lt;/code&gt;（Netfilter）ルールを直接操作してコンテナへのルーティングを行うため、UFWのフィルタリングルールよりも優先してパケットがコンテナに到達します。&lt;/li&gt;&#10;&lt;li&gt;&lt;b&gt;解決策&lt;/b&gt;: &lt;code&gt;.env&lt;/code&gt; 内の &lt;code&gt;EXPOSE_NGINX_PORT&lt;/code&gt; に必ず &lt;code&gt;127.0.0.1:8080&lt;/code&gt; のようにIPアドレスを明示的に指定します。これにより、コンテナはループバックインターフェースにのみバインドされ、外部からの直接アクセスは物理的に遮断されます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="5-2-初回起動後のデータベース認証エラー"&gt;5-2. 初回起動後のデータベース認証エラー&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;b&gt;事象&lt;/b&gt;: 運用開始後に &lt;code&gt;.env&lt;/code&gt; の &lt;code&gt;DB_PASSWORD&lt;/code&gt; を変更したところ、&lt;code&gt;api&lt;/code&gt; コンテナが &lt;code&gt;FATAL: password authentication failed for user &amp;ldquo;postgres&amp;rdquo;&lt;/code&gt; を出力してクラッシュループに陥る。&lt;/li&gt;&#10;&lt;li&gt;&lt;b&gt;原因&lt;/b&gt;: PostgreSQLコンテナは、初回起動時（ボリュームが空の状態）にのみ &lt;code&gt;.env&lt;/code&gt; のパスワードを使用してデータベース初期化を行います。起動後に &lt;code&gt;.env&lt;/code&gt; の値を変更しても、コンテナ内のデータベースに保存されたパスワードは自動更新されないため、不一致が発生します。&lt;/li&gt;&#10;&lt;li&gt;&lt;b&gt;解決策&lt;/b&gt;: パスワードを変更する場合は、PostgreSQLコンテナ内で直接 &lt;code&gt;ALTER USER&lt;/code&gt; 構文を実行してデータベース側のパスワードを更新するか、データを破棄して再初期化（※データは全消失します）する必要があります。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="5-3-非同期タスクceleryの接続拒否"&gt;5-3. 非同期タスク（Celery）の接続拒否&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;b&gt;事象&lt;/b&gt;: ナレッジ（RAG）へのドキュメントアップロードやインデックス作成タスクが「進行中」のまま停止する。&lt;/li&gt;&#10;&lt;li&gt;&lt;b&gt;原因&lt;/b&gt;: Redisのパスワード（&lt;code&gt;REDIS_PASSWORD&lt;/code&gt;）を変更した際、&lt;code&gt;CELERY_BROKER_URL&lt;/code&gt; に含まれる接続パスワードの同期を忘れたため、非同期ワーカーがキューを取得できなくなっています。&lt;/li&gt;&#10;&lt;li&gt;&lt;b&gt;解決策&lt;/b&gt;: &lt;code&gt;.env&lt;/code&gt; 内の &lt;code&gt;CELERY_BROKER_URL&lt;/code&gt; が &lt;code&gt;redis://:&amp;lt;REDIS_PASSWORD&amp;gt;@redis:6379/1&lt;/code&gt; の形式になっており、現在の &lt;code&gt;REDIS_PASSWORD&lt;/code&gt; と完全に一致しているか確認し、コンテナを再起動します。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="5-4-nginxコンテナによる502-bad-gatewayのキャッシュ"&gt;5-4. Nginxコンテナによる「502 Bad Gateway」のキャッシュ&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;b&gt;事象&lt;/b&gt;: &lt;code&gt;api&lt;/code&gt; コンテナの再起動中、またはアップデート直後に、Caddyは正常であるにもかかわらずブラウザに &lt;code&gt;502 Bad Gateway&lt;/code&gt; が表示され続ける。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;b&gt;原因&lt;/b&gt;: DifyのフロントエンドNginxコンテナが、上流の &lt;code&gt;api&lt;/code&gt; コンテナの古いIPアドレスをキャッシュしている、または &lt;code&gt;api&lt;/code&gt; の起動完了前に名前解決に失敗してルーティングを停止しているケースがあります。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;b&gt;解決策&lt;/b&gt;: &lt;code&gt;api&lt;/code&gt; コンテナが完全に起動したことを確認した上で、Nginxコンテナのみを単独で再起動します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker compose restart nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="6-稼働状態の検証operational-verification"&gt;6. 稼働状態の検証（Operational Verification）&#10;&lt;/h2&gt;&lt;p&gt;デプロイ完了後、以下の検証コマンドを実行して、システムが設計通りにセキュアに稼働しているか確認します。&lt;/p&gt;&#10;&lt;h3 id="6-1-コンテナ稼働ステータスの確認"&gt;6-1. コンテナ稼働ステータスの確認&#10;&lt;/h3&gt;&lt;p&gt;すべてのコンテナが &lt;code&gt;Up&lt;/code&gt;（または &lt;code&gt;Up (healthy)&lt;/code&gt;）ステータスであることを確認します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker compose ps&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-api-1 langgenius/dify-api:0.15.3 &amp;#34;/bin/sh -c &amp;#39;./entry…&amp;#34; api 2 hours ago Up 2 hours (healthy) &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-db-1 postgres:15-alpine &amp;#34;docker-entrypoint.s…&amp;#34; db 2 hours ago Up 2 hours (healthy) 5432/tcp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-nginx-1 nginx:1.25-alpine &amp;#34;/docker-entrypoint.…&amp;#34; nginx 2 hours ago Up 2 hours 127.0.0.1:8080-&amp;amp;gt;80/tcp, 127.0.0.1:8443-&amp;amp;gt;443/tcp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-plugin_daemon langgenius/dify-plugin-daemon:0.15 &amp;#34;/entrypoint.sh&amp;#34; plugin_daemon 2 hours ago Up 2 hours (healthy) 127.0.0.1:5003-&amp;amp;gt;5003/tcp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-redis-1 redis:7.2-alpine &amp;#34;docker-entrypoint.s…&amp;#34; redis 2 hours ago Up 2 hours (healthy) 6379/tcp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-sandbox-1 langgenius/dify-sandbox:0.5.2 &amp;#34;/main&amp;#34; sandbox 2 hours ago Up 2 hours (healthy) &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-web-1 langgenius/dify-web:0.15.3 &amp;#34;/bin/sh -c &amp;#39;./entry…&amp;#34; web 2 hours ago Up 2 hours (healthy) &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-weaviate-1 semitechnologies/weaviate:1.19.0 &amp;#34;/bin/weaviate --hos…&amp;#34; weaviate 2 hours ago Up 2 hours (healthy) &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dify-worker-1 langgenius/dify-api:0.15.3 &amp;#34;/bin/sh -c &amp;#39;./entry…&amp;#34; worker 2 hours ago Up 2 hours (healthy) &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="6-2-ホストのリスニングポート監査"&gt;6-2. ホストのリスニングポート監査&#10;&lt;/h3&gt;&lt;p&gt;外部公開されているポートが、設計通り SSH（例: &lt;code&gt;2022&lt;/code&gt;）および Caddy（&lt;code&gt;80&lt;/code&gt;, &lt;code&gt;443&lt;/code&gt;）のみに制限されているか検証します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ sudo ss -tulnp | grep -vE &amp;#39;127\.0\.0\.|::1|%lo&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp LISTEN 0 4096 0.0.0.0:80 0.0.0.0:* users:((&amp;#34;caddy&amp;#34;,pid=1024,fd=6))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp LISTEN 0 4096 0.0.0.0:443 0.0.0.0:* users:((&amp;#34;caddy&amp;#34;,pid=1024,fd=7))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp LISTEN 0 128 0.0.0.0:2022 0.0.0.0:* users:((&amp;#34;sshd&amp;#34;,pid=821,fd=3))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;udp UNCONN 0 0 0.0.0.0:443 0.0.0.0:* users:((&amp;#34;caddy&amp;#34;,pid=1024,fd=8))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;※ &lt;code&gt;8080&lt;/code&gt; や &lt;code&gt;5003&lt;/code&gt;、&lt;code&gt;5432&lt;/code&gt; などのポートが &lt;code&gt;0.0.0.0&lt;/code&gt; に露出していないことを確認します。&lt;/p&gt;&#10;&lt;h3 id="6-3-エンドツーエンドのhttps接続検証"&gt;6-3. エンドツーエンドのHTTPS接続検証&#10;&lt;/h3&gt;&lt;p&gt;外部のクライアントマシンから、Caddyを介したHTTPS通信が正常に終端され、Difyのセットアップエンドポイントに到達できるかテストします。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ curl -I https://dify.example.com/console/api/setup&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HTTP/2 200 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;alt-svc: h3=&amp;#34;:443&amp;#34;; ma=2592000&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;content-type: application/json; charset=utf-8&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;date: Sat, 03 Oct 2026 14:22:15 GMT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server: Caddy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server: nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;レスポンスヘッダーに &lt;code&gt;server: Caddy&lt;/code&gt; および &lt;code&gt;server: nginx&lt;/code&gt; が順に出現し、ステータスコード &lt;code&gt;200&lt;/code&gt; が返れば、リバースプロキシチェーンは正常に機能しています。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="7-ライフサイクルダイナミクスとコンテナ更新"&gt;7. ライフサイクルダイナミクスとコンテナ更新&#10;&lt;/h2&gt;&lt;p&gt;Difyのバージョンアップや設定変更に伴うコンテナの再作成時には、一時的なサービスダウンタイムが発生します。Caddyはバックエンド（&lt;code&gt;127.0.0.1:8080&lt;/code&gt;）への接続が切断された場合、自動的に &lt;code&gt;502 Bad Gateway&lt;/code&gt; をクライアントに返します。&lt;/p&gt;&#10;&lt;p&gt;ローリングアップデート（ゼロダウンタイムに近い切り替え）を部分的に実現するためには、コンテナの停止前に新しいイメージをプリプル（事前取得）しておくことで、コンテナの再作成および起動にかかる時間を最小限に抑えるアプローチが有効です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ~/dify/docker&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git pull origin main&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker compose pull&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker compose up -d --remove-orphans&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これにより、イメージのダウンロード時間によるダウンタイムを排除し、コンテナの再起動にかかる数秒〜数十秒程度にサービス停止時間を圧縮できます。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="operational-notes"&gt;Operational Notes&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;💡 &lt;b&gt;バックアップの自動化&lt;/b&gt;: &lt;code&gt;dify-db-1&lt;/code&gt;（PostgreSQL）のデータボリュームおよび &lt;code&gt;.env&lt;/code&gt; ファイルは、システムの全設定とユーザーデータを保持しています。定期的に &lt;code&gt;pg_dump&lt;/code&gt; を実行し、ホスト外のセキュアなストレージにバックアップを退避するジョブを &lt;code&gt;cron&lt;/code&gt; に登録することを強く推奨します。&lt;/li&gt;&#10;&lt;li&gt;🛠️ &lt;b&gt;ログのローテーション&lt;/b&gt;: Dockerのデフォルト設定では、コンテナの標準出力ログが無限に肥大化し、ディスク容量を圧迫します。&lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; に &lt;code&gt;json-file&lt;/code&gt; ドライバの最大サイズ制限（例: &lt;code&gt;max-size: &amp;ldquo;10m&amp;rdquo;&lt;/code&gt;）を設定してください。&lt;/li&gt;&#10;&lt;li&gt;⚠️ &lt;b&gt;APIキーのライフサイクル&lt;/b&gt;: Dify内で連携する外部LLM（OpenAI、Anthropic等）のAPIキーは、&lt;code&gt;.env&lt;/code&gt; 内の &lt;code&gt;SECRET_KEY&lt;/code&gt; を用いて暗号化されデータベースに保存されます。このキーを変更すると、既存のすべての外部連携が破損するため、本番稼働後の &lt;code&gt;SECRET_KEY&lt;/code&gt; の変更は原則禁止とします。&lt;/domain&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item></channel></rss>