atama plus techblog
🛂

社内メンバー限定のDify環境をAWSにセルフホストした構成と実装まとめ

に公開

はじめに

こんにちは、atama plusでAIX(AI Transformation)に取り組んでいるTackungです。

現在、全社のAIX推進の一環として、社内メンバーが気軽にAIアプリ・エージェントを開発できる環境作りに取り組んでいます。
その中で、ノーコードでワークフロー・エージェントを作成でき、エンジニア以外のメンバーも比較的使いやすいツールとしてDifyを選定し、社内環境の整備を進めました。

今回の記事では、Google Workspaceアカウントを用いたOIDC連携(Cognito経由) でアクセスを社内に限定した、AWS上へのDifyセルフホスティングの事例を紹介します。
OSS版Difyを社内メンバーに限定して提供したい方の参考になれば幸いです!

こんな方向けの記事

  • AWS上に社内利用向けのDify環境をセルフホストしたい方
  • Google WorkspaceアカウントでアクセスをALBレベルで制限したい方
  • CDKを使ったIaC構成の実例を参考にしたい方

前提知識

下記については本記事では詳しく触れていません。

  • AWS(ECS、ALB、Cognito、CloudFormation等)の基礎知識
  • CDKの基本的な使い方
  • Difyの概要

背景

Cloud版 vs OSSセルフホスト版の比較

組織でDifyを利用するためには「Cloud版やEnterprise版を契約する」か、「OSS版を自社環境にセルフホストする」という選択肢があります。

https://dify.ai/jp/pricing

それぞれの特徴を下記の表にまとめました。

観点 Cloud版/Enterprise版 セルフホスト版
導入コスト 低(すぐ使える) 高(インフラ構築が必要)
アクセス制御 プラン依存
(SSO認証はEnterpriseプランのみで提供)
自前で自由に設計可
データ管理 Dify側に保存 自社インフラ内
カスタマイズ性 限定的 高い
登録ユーザ数 プラン依存
(Professional: 3人, Team: 50人, Enterprise: 無制限)
無制限
ランニングコスト プランごとの料金, 利用上限あり インフラコスト + AI利用の従量課金, 利用無制限

今回私たちは主に以下の理由からセルフホストを選びました。

  1. 比較的安価にユーザを限定したアクセス環境を構築したかった
  2. 機密性の高いデータを扱うワークフローも将来的に作りたかった
  3. ユーザー数の増加に対してコストをコントロールしたかった

セルフホスト方法の比較・選定

Difyのクラウド上へのセルフホスティングで活用できるフレームワークは、主に下記のようなものがありました(調査をした2026.01時点の情報です)。

種別 リポジトリ / リソース 提供元 概要
AMI AWS Marketplace 公式AMI AWS 公式ドキュメントにリンクされているEC2ベースのミニマム構成
CDK dify-self-hosted-on-aws aws-samples 3つのCDK実装例の中で最もシンプルで安価な構成
CDK solution-for-deploying-dify-on-aws aws-samples EKSデプロイ・OpenSearchを使った高可用性を重視した構成
CDK aws-cdk-for-dify LangGenius社 上記と概ね同様の構成
Helm dify-helm LangGenius社 公式Helmチャート(Kubernetes向け)
Terraform dify-google-cloud-terraform DeNA社 Google Cloud向けのTerraform構成

今回はシンプル構成を優先し、aws-samples/dify-self-hosted-on-aws を活用させていただきました。
こちらはAWSが公開しているDifyのAWS構築CDKサンプルリポジトリです。ECS Fargate + Aurora Serverless v2 + ElastiCache(Valkey) + ALB + CloudFrontという本番利用を想定しながらコストも考慮されたバランス型の構成となっています。
このリポジトリをforkして自社向けのカスタマイズを追加する形で構築を進めました。

アーキテクチャ

社内環境の全体構成図

最終的に下記の構成でDify社内環境を構築しました。

アーキテクチャ概要図

各コンポーネントは下記の役割をしています。

  • CloudFront + WAF ACL: 入口の防壁。不正なリクエストをWAFで弾き、国内からのアクセスのみに絞る
  • ALB: CognitoによるOIDC認証を実施。認証済みリクエストのみECSへ転送
  • Cognito + Google Cloud OAuth Client: Google WorkspaceアカウントをIdPとしたFederated Identity
  • ECS Fargate: Dify本体(Web / API / worker / sandbox / local MCP)をコンテナで実行
  • RDS Aurora PostgreSQL Serverless v2: Difyのメタデータ・設定データを永続化
  • ElastiCache Valkey: セッション・キューのキャッシュ
  • S3: アプリデータ・ストレージアクセスログ用

認証フローの概要

自社Dify環境へのアクセスをした際に下記のような認証フローが行われます。

(補足)Dify内部のアカウント管理について

OSS版のDifyは、インフラ前段のOIDC連携情報を使った自動アカウント作成機能は標準対応していません。
そのため、本構成では 「インフラレベル(ALB + Cognito)のアクセス制御」「アプリケーションレベル(Dify本体)の認証」 を分離した、二重のアクセス制御を行っています。

  1. インフラレベルの認可(ALB + Cognito)
    Google Workspaceアカウントで認証に成功した社内メンバーのみが、Difyのシステム(ECS)に到達可能。これにより、社外からのアクセスや不正なリクエストを前段で遮断。
  2. アプリケーションレベルの認証(Dify本体)
    Difyの画面に到達した後は、Dify標準のアカウント機能を使用してログインする。運用としては、管理者が事前にDify上で社内メンバーのメールアドレスを招待し、初回アクセス時にパスワードを設定してもらう形をとっています。

ユーザーにとっては「Googleログイン後にDifyのログインも求められる」という二重の手間が少し発生しますが、「Dify本体側に複雑なSSO連携を作り込むことなく、インフラ側で社内限定アクセスを担保できる」 というセキュリティと構築コストのバランスを取った運用を実現しました。

実装のポイント

ここからは、aws-samples/dify-self-hosted-on-awsに自社向けカスタマイズを加えた箇所についてのポイントをご紹介します。

ポイント1: ALBレベルでの認証とAPIパスの扱い

DifyにはAPIキー認証のエンドポイント(/v1/* 等)とDify自身がセッション管理する管理画面用API(/console/api/*)が混在しており、すべてのパスに Cognito認証をかけると、APIキー経由のアクセスやDifyアプリ側の認証フローが破綻してしまいます。そのため、パスごとにALB側の認証有無を使い分ける必要がありました。

パス 認証 目的
/console/*, /apps/*, / ALB Cognito認証あり Web UI(ブラウザアクセス)
/console/api/*, /api/*, /v1/*, /files/*, /triggers/* バイパス(認証なし) APIキー等でのアクセスをブロックしないため
/health バイパス(認証なし) 外形監視用

実装上は、各サービス(API/Web)がパスを登録する際に skipAuth フラグを渡し、ALBのリスナールール優先度を 1〜100番台(認証なし)101〜200番台(Cognito認証あり) の2レンジに分けて管理することで、このパスベースの制御を実現しています。

実装サンプル(抜粋)

優先度レンジの分離(lib/constructs/alb-with-cloudfront.ts

// 1-100: 認証なし(APIエンドポイント等)
// 101-200: Cognito認証あり(Web UI)
private listenerPriorityNoAuth = 1;
private listenerPriorityWithAuth = 101;

// ...

const requiresAuth = !skipAuth && this.userPool && this.userPoolClient && this.userPoolDomain;

if (requiresAuth) {
  // Cognito認証アクション(優先度 101-200)
  const authenticateAction = new AuthenticateCognitoAction({
    userPool: this.userPool!,
    userPoolClient: this.userPoolClient!,
    userPoolDomain: this.userPoolDomain!,
    next: ListenerAction.forward([group]),
    sessionTimeout: Duration.hours(12),
    onUnauthenticatedRequest: UnauthenticatedAction.AUTHENTICATE,
  });
  this.listener.addAction(`${id}${i}`, {
    action: authenticateAction,
    conditions: [ListenerCondition.pathPatterns(slice)],
    priority: this.listenerPriorityWithAuth++,
  });
} else {
  // 認証なし - ターゲットグループへ直接転送(優先度 1-100)
  this.listener.addTargetGroups(`${id}${i}`, {
    targetGroups: [group],
    conditions: [ListenerCondition.pathPatterns(slice)],
    priority: this.listenerPriorityNoAuth++,
  });
}

APIサービスのパス登録(lib/constructs/dify-services/api.ts

APIパスはすべて skipAuth=true でバイパス登録します。

const paths = ['/console/api', '/api', '/v1', '/files', '/triggers', '/health'];
// APIパスはDifyアプリ側の認証に委ねるためALB認証をバイパス
// /health は外形監視のため意図的に認証なし
alb.addEcsService(
  'Api',
  service,
  port,
  '/health',
  [...paths, ...paths.map((p) => `${p}/*`)],
  true, // skip authentication
);
// プラグイン拡張パスも同様にバイパス
alb.addEcsService(
  'Extension',
  service.loadBalancerTarget({ containerName: 'PluginDaemon', containerPort: pluginDaemonPort }),
  pluginDaemonPort,
  '/health/check',
  ['/e', '/e/*'],
  true, // skip authentication
);

Webサービスのパス登録(lib/constructs/dify-services/web.ts

静的ファイル(/_next/static/* など)も認証なし(優先度1-100)で登録し、それ以外の /* はCognito認証あり(優先度101-200)で登録します。

// 静的ファイルは先に高優先度・認証なしで登録(/*より前に評価される必要がある)
const staticPaths = [
  '/_next/static/*',
  '/_next/image/*',
  '/serwist/*',
  '/sw.js',
  '/favicon.ico',
  '/logo/*',
  '/screenshots/*',
  '/embed.min.js',
  '/manifest.json',
];
alb.addEcsService('WebStatic', service, port, '/', staticPaths, true);

// それ以外のすべてのパスはCognito認証が必要とする
alb.addEcsService('Web', service, port, '/', ['/*'], false);

ポイント2: Cognito User PoolとGoogle Workspace OIDC連携

Cognito User PoolにGoogle IdPを設定してFederated Identityを構成します。

// lib/constructs/cognito.ts(抜粋)
this.userPool = new UserPool(this, 'UserPool', {
  // セルフサインアップ無効 = Google WS アカウントのみ受け入れ
  selfSignUpEnabled: false,
  signInAliases: { email: true, username: false },
  // ...
});

// Google IdP を接続
new UserPoolIdentityProviderGoogle(this, 'GoogleIdP', {
  userPool: this.userPool,
  clientId: props.googleOAuthClientId,
  // クライアントシークレットは Secrets Manager から動的取得
  clientSecretValue: SecretValue.secretsManager(props.googleOAuthClientSecretName),
  scopes: ['openid', 'email', 'profile'],
  // ...
});

ポイント:

  • selfSignUpEnabled: false にすることで事前に登録しているGoogle Workspaceアカウントのみを受け入れる(直接サインアップ不可)
  • クライアントシークレットはSecrets Managerで管理
  • Google Cloudコンソール側でOAuthクライアントIDを発行し、コールバックURLにALBのURLを登録

ポイント3: CDKによる環境分離

社内環境の構築にあたり、検証用と本番用で環境を分けて管理しています。

本記事の主題からは少し外れますが、config/environments.ts に環境ごとの設定値を集約し、デプロイ時に --context env=dev/prod で切り替える構成にしたことで、リソーススペックの違いを吸収しながら両環境をスムーズに立ち上げることができました。

// config/environments.ts(抜粋)
export const environmentConfig: Record<'dev' | 'prod', EnvironmentProps> = {
  dev: {
    domainName: 'our.domain.name',
    enableCognito: true,
    cognitoDomainPrefix: 'dify-dev',
    // dev環境ではAuroraをゼロスケール可能にしてコスト削減
    enableAuroraScalesToZero: true,
    isRedisMultiAz: false,
    enableDatabaseDeletionProtection: false,
    // ...
  },
  prod: {
    domainName: 'our.domain.name',
    enableCognito: true,
    cognitoDomainPrefix: 'dify-prod',
    // prod環境ではコスト削減設定をオフ
    enableAuroraScalesToZero: false,
    isRedisMultiAz: true,
    enableDatabaseDeletionProtection: true,
    // ...
  },
};
# 開発環境
npx cdk deploy --all --context env=dev --profile dev-account

# 本番環境(CircleCI上でmainブランチへのマージをトリガーに自動実行)
npx cdk deploy --all --context env=prod --profile prod-account

また、本記事では詳細は省きますがCircleCIによるCI/CDも導入しており、mainブランチへのマージが本番環境デプロイのトリガーになっています。これにより検証環境での確認後に本番環境への適用も楽に行うことができています。

やってみてどうだったか

aws-samplesのCDK実装をベースにしたことで、Cognitoによるアクセス制限やカスタムドメイン設定といった自社固有の要件を比較的少ない工数で追加でき、想定よりスムーズに環境を立ち上げることができました。
CDK × CircleCIの組み合わせも効いており、検証環境で確認してから本番に適用するサイクルも楽に回せています。

環境が整ったことで、エンジニア以外のメンバーも自分の業務向けにDifyでワークフローを作り始めています。
法務担当が法務監査AIのSlack botを実装したり、POが新プロダクトの仕様を回答する社内向けbotを作ったりと、すでにいくつかの活用事例が生まれており、まだ活用は始まったばかりですが「自分でも作れる」という体験が少しずつ社内に広がりつつあります。

おわりに

今回はaws-samplesのCDK実装をベースに、Google Workspace OIDCによるアクセス制限を加えた社内向けDify環境を構築しました。インフラをコードで管理できるCDKの恩恵もあり、想定よりもスムーズに立ち上げまで持っていけたと感じています。

現在は社内での活用を少しずつ広げている段階です。今後はより多くのメンバーが使いこなせるよう、できることの拡充やチュートリアルの整備も進めていきたいと考えています。

この記事が、社内限定のDify環境のセルフホスティングを検討している方の参考になれば幸いです。
最後までお読みいただきありがとうございました!

atama plus techblog
atama plus techblog

Discussion