aghost について
aghostは、ソーシャルアカウントを管理するチーム向けの投稿・Instagram DM自動化サービスです。コメント起点のDM、Instagram投稿の予約、複数サービスへの投稿を、ダッシュボード、REST API、MCPから利用できます。
主な機能
- 01コメントからDMへの自動化の作成と監視
- 02自動化に関連するInstagram投稿の予約
- 03Facebook、LinkedIn、X、Threads、YouTubeへの投稿
- 04各チャネルの分析と配信状況の確認
- 05受信トレイの会話の閲覧とメッセージ送信
活用シーン
- 01Instagram投稿へのコメントに自動でDMを送信
- 02DM施策に合わせたInstagram投稿の予約
- 03複数のソーシャルサービスへのコンテンツ投稿
- 04エージェントによるアカウント活動や受信トレイの確認
MCP 対応
`/api/mcp`のHTTP MCPエンドポイントを通じてaghostのワークスペース操作を提供し、ワークスペースAPIキーで認証します。エージェント用ツールでは、自動化、Instagram投稿、統計、アカウント、連絡先、受信トレイの会話、メッセージを扱えます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://aghost.app/api/mcpclaude mcp add --transport http thinking-sound-lab-aghost https://aghost.app/api/mcp{"mcpServers":{"thinking-sound-lab-aghost":{"type":"http","url":"https://aghost.app/api/mcp"}}}Cursor で開く{"servers":{"thinking-sound-lab-aghost":{"type":"http","url":"https://aghost.app/api/mcp"}}}VS Code で開く{"mcpServers":{"thinking-sound-lab-aghost":{"type":"http","url":"https://aghost.app/api/mcp"}}}{"mcpServers":{"thinking-sound-lab-aghost":{"serverUrl":"https://aghost.app/api/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
https://aghost.app/api/mcp認証が必要ツール
詳細
aghost
Instagram 向けのエージェント型 DM 自動化。
MCP、REST API、またはダッシュボードから、コメントをきっかけにした DM 自動化を作成、管理、監視し、その自動化が返信する Instagram 投稿をスケジュールできます。ダッシュボードからは Facebook、LinkedIn、X、Threads、YouTube へのクロスポストもでき、各チャンネルの分析機能も利用できます。MCP と API へのアクセスは、すべてのプランに含まれています。
スタック · アーキテクチャ · ローカルでの実行 · 設定 · API · MCP · 分析 · ブランド · 検索と AI アシスタント · テスト · デプロイ
スタック
| レイヤー | 使用技術 |
|---|---|
| Web | Next.js のマーケティングサイトとダッシュボード、Zustand、shadcn/ui · Vercel で稼働 |
| API | Node.js 22 上の Fastify、packages/api のドメインサービス · AWS ECS で稼働 |
| データと認証 | 行レベルセキュリティを備えた Supabase Postgres、Supabase Auth |
| チャンネル | 6つのプラットフォームのアカウント、公開、分析に Zernio を使用。Instagram の自動化、受信トレイ、連絡先も対応 |
| 分析 | プロダクトイベント、Web 分析、セッションリプレイに PostHog を使用 |
| インフラストラクチャ | TypeScript の AWS CDK、GitHub Actions、Turborepo、pnpm |
アーキテクチャ
flowchart LR
browser(["Browser"])
subgraph vercel["Vercel"]
web["Next.js<br/>site and dashboard"]
end
subgraph aws["AWS · default VPC"]
gateway["API Gateway<br/>HTTPS"] --> alb["Private<br/>load balancer"] --> api["Fastify API<br/>ECS Fargate"]
end
supabase[("Supabase<br/>Postgres and Auth")]
zernio["Zernio<br/>Instagram API"]
posthog["PostHog<br/>product analytics"]
browser -->|"pages and /api"| web
web -->|"/api/* rewrite"| gateway
web -->|"/relay/* rewrite"| posthog
api --> supabase
api <-->|"calls and webhooks"| zernio
api -->|"business events"| posthog
- ブラウザー向けのオリジンは1つです。 ページと
/apiは Web アプリの同じオリジンを共有し、Next.js が/api/*を API にリライトします。ローカル環境では、同じプロキシが Docker 内の API を参照します。 - UI はアプリに、ルールはパッケージに配置します。 ビジネスルールとプロバイダーへの呼び出しは
packages/apiに配置されています。Web アプリは UI を描画し、型付きクライアントを通じて API を呼び出します。 - テナントを分離します。 Supabase の行レベルセキュリティにより、読み取り対象はワークスペースに制限されます。また、API は特権を伴う書き込みの前にユーザーを検証します。アカウントの Webhook 更新と重複排除台帳のエントリーは、1つのトランザクションでコミットされます。
- ブラウザーに認証情報を置きません。 プロバイダーキーは API 内に保持されます。セッション Cookie は HttpOnly で、HTTPS オリジンでは Secure を使用します。
- エージェントからのアクセス。 REST と MCP には、それぞれ専用のルートモジュールと Settings タブがあります。ワークスペース API キーで両方のインターフェースを認証し、共通のビジネス操作、検証、権限を使用します。キーのハッシュはバックエンドのみで扱い、完全なトークンは一度だけ表示されます。
ローカルで実行する
Node.js 22 以降、pnpm、および Docker Compose を含む Docker が必要です。
pnpm install
pnpm dev
初回の実行時には停止し、Google OAuth クライアントの設定を求められます。詳しくはGoogle でのサインインをご覧ください。
pnpm dev はルートの .env を準備し、Docker で Supabase を起動して保留中のマイグレーションを適用し、Docker で API を起動した後、ホスト上で Next.js を起動します。API の変更はコンテナ内で再読み込みされ、Web の変更にはホットリロードが適用されます。
| サービス | アドレス |
|---|---|
| Web アプリ | localhost:3000 |
| API | 127.0.0.1:4000 |
| Supabase Studio | localhost:54323 |
Web プロセスを終了しても Docker サービスは実行されたままです。pnpm local:stop を実行すると、データベースを保持したまま停止します。
メモ
このスタックはローカルの固定ポートを使用するため、一度に実行できるワークスペースは 1 つです。Supabase CLI は
supabase/config.tomlからコンテナを管理し、compose.yamlは Supabase の Docker ネットワーク上で API を実行します。
コマンド
| コマンド | 内容 |
|---|---|
pnpm dev | Docker バックエンドを起動してから、Web アプリを起動します |
pnpm local:start | Docker バックエンドのみを起動または再ビルドします。環境変数や依存関係を変更した後に実行します |
pnpm local:stop | API、Webhook トンネル、Supabase を停止します。データベースのデータは保持されます |
pnpm local:logs | API のログを追跡します |
pnpm local:status | API コンテナの状態を表示します |
pnpm local:tunnel | マシン上で Zernio Webhook を受信します(下記) |
pnpm db:status | ローカルの Supabase サービスの状態を表示します |
pnpm db:types | packages/supabase/src/database.types.ts を再生成します |
pnpm db:reset | ローカルデータベースをリセットします。破壊的な操作:破棄可能なデータにのみ使用してください |
Google でのサインイン
サインイン方法は Google のみで、初回のサインイン時にアカウントが作成されます。Google との認証情報の交換は Supabase が行うため、OAuth クライアントは Supabase に設定します。
- Google Cloud コンソールで、ウェブアプリケーションタイプの OAuth クライアント ID を作成します。
- 許可するリダイレクト URI に
http://127.0.0.1:54321/auth/v1/callbackを追加します。 - ルートの
.envにSUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_IDとSUPABASE_AUTH_EXTERNAL_GOOGLE_SECRETを設定します。
Supabase は起動時に両方の値を読み込みます。これらを変更した後、またはサインイン設定が異なるブランチから切り替えた後は、pnpm local:stop を実行してから pnpm dev を実行してください。
プロバイダーの Webhook をローカルで受信する
Instagram アカウントの接続や切断、およびメッセージの送受信があると、Zernio から API に通知されます。メッセージイベントに応じて、フォローアップのリマインダーが予約またはキャンセルされます。これらのイベントをローカルマシンで受信するには、次を実行します。
pnpm local:tunnel
Cloudflare アカウントが不要な Cloudflare クイックトンネルを Docker で起動します。公開されるのは /api/webhooks/zernio と /api/webhooks/dodo のみで、その他のすべてのパスには Cloudflare が 404 を返します。Zernio を設定した状態でこのコマンドを実行すると、次の処理が行われます。
- ルートの
.envが空の場合、ZERNIO_WEBHOOK_SECRETを生成します。 - トンネルを参照し、
account.connected、account.disconnected、message.sent、message.receivedを購読するaghost local tunnelという名前の Zernio Webhook を作成または更新します。 - Zernio にトンネル経由でテストイベントを送信するよう依頼し、配信されなかった場合は失敗します。
ZERNIO_API_KEY または Dodo のテストモード API キーを設定してください。Dodo を設定している場合、コマンドはローカルのサブスクリプション/決済 Webhook も登録し、署名シークレットをルートの .env に保存して、API コンテナを再作成します。配信とそのステータスコードは pnpm local:logs に表示されます。401 は署名がシークレットと一致しなかったことを示します。
トンネルを起動するたびに trycloudflare.com のアドレスが変わるため、pnpm local:stop の実行後、または Docker の再起動後に pnpm local:tunnel を再実行してください。トンネルが停止している間は、以前のアドレスへの配信は失敗します。Zernio の Webhook ログから再送信できます。アカウントの接続にトンネルは必要ありません。認証後、/accounts/callback は Zernio からアカウント一覧を直接取得します。
設定
リポジトリのルートにある .env が、唯一のローカル設定ファイルです。 テンプレートは .env.example です。pnpm dev と pnpm setup:local はこのファイルを作成し、ローカルの Supabase キーを入力します。また、設定した値が上書きされることはありません。apps/server や apps/web の下に env ファイルを追加しないでください。
| 変数 | 読み取り元 | 用途 |
|---|---|---|
APP_URL | API, Web | ブラウザーに公開するオリジン。オリジンチェックと正規リンクに使用します |
API_URL | Web | Next.js が /api リクエストを転送する先 |
API_PORT | API | API がリッスンするポート |
API_HOST | API | API がリッスンするインターフェース |
SUPABASE_URL | API | ホストから見た Supabase のアドレス。テストでも使用します |
SUPABASE_PUBLISHABLE_KEY | API | セットアップ時に入力されます |
SUPABASE_SECRET_KEY | API | セットアップ時に入力されます |
SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID | Supabase | サインイン用の Google OAuth クライアント |
SUPABASE_AUTH_EXTERNAL_GOOGLE_SECRET | Supabase | このクライアントのシークレット |
ZERNIO_API_URL | API | Zernio API |
ZERNIO_API_KEY | API | Instagram 機能を有効にします。空の場合は利用できません |
ZERNIO_WEBHOOK_SECRET | API | Webhook の署名を検証します。pnpm local:tunnel で生成されます |
DODO_PAYMENTS_ENVIRONMENT | API | ローカルでは test_mode、本番環境の課金では live_mode |
DODO_PAYMENTS_API_KEY | API | チェックアウト、プラン変更、課金ポータルを有効にします |
DODO_PAYMENTS_WEBHOOK_KEY | API | Dodo のサブスクリプションおよび支払い Webhook の署名を検証します |
POSTHOG_KEY | API, Web | PostHog プロジェクトキー。空の場合は分析が無効になります |
POSTHOG_HOST | API, Web | プロジェクトのリージョンに対応する PostHog のアドレス |
ダッシュボード、REST API、MCP の利用にはプランが必要です。サインイン後、ワークスペースがサブスクリプションに登録するまではアプリにペイウォールのみが表示されるため、ローカルでも利用できるよう Dodo を設定してください。チャンネルを接続するには、ZERNIO_API_KEY も設定してください。Pro、Growth、Business の料金は、ソーシャルセット 1/2/10 件で月額 $29/$39/$49 です。各セットにはすべてのプラットフォームのアカウントが 1 つずつ含まれ、すべての国で米ドル建て、税金込みで請求されます。年払いは約 20% 割安で、前払いです。料金と課金の設定およびチャンネルをご覧ください。Dodo の認証情報がない場合はサインインできますが、誰もサブスクリプションに登録できません。Zernio の認証情報がない場合、Instagram 機能は利用できません。アプリがサンプルアカウントや分析データで代用することはありません。
- Next.js に渡されるのは
APP_URL、API_URL、PostHog のキーとホストだけです。PostHog のキーは設計上公開されます。Supabase、Zernio、Dodo の認証情報は API コンテナーにのみ渡され、Google クライアントは Supabase にのみ渡されます。環境ファイルは Git の対象外で、Docker イメージにも含まれません。 - Compose は API コンテナーに
SUPABASE_URLとしてhttp://supabase_kong_aghost:8000を設定するため、Docker ネットワーク経由で Supabase と通信します。 - 公開環境またはトンネルを使う設定では、
APP_URLを更新し、Supabase のリダイレクト URL に/api/auth/callbackを許可してください。Zernio は、認証済みの Instagram 接続を/accounts/callbackにリダイレクトします。 - デプロイ環境ではこれらの変数を直接設定します。環境ファイルは不要です。
API
Settings → APIを開き、+ API keyをクリックして、ダイアログでワークスペースキーに名前を付けます。作成後、ダイアログを閉じる前にキーをコピーして保存してください。キー全体は再表示されません。エージェントは、オートメーションの作成、編集、一時停止、有効化、削除、オートメーションを使ったInstagram投稿のスケジュール設定、編集、キャンセル、統計情報と配信アクティビティの確認、アカウント、投稿、連絡先、受信トレイの会話の閲覧、受信トレイメッセージの送信を行えます。
Authorization: Bearer <key>を指定して<APP_URL>/api/v1を呼び出します。新しいキーはエージェントの全機能を利用でき、有効期限はありません。アクセスを停止するには、Settingsでキーを取り消してください。GET /api/v1/openapi.jsonでREST APIの仕様を確認できます。リクエストとデプロイ要件については、REST APIガイドをご覧ください。
MCP
エンドポイントとクライアント設定を確認するには、Settings → MCPを開きます。Copy skillを使うと、Claude Code、Codex、Cursor、その他のエージェントに接続設定の手順を渡せます。HTTP MCPクライアントと、APIタブで作成したキーを使って<APP_URL>/api/mcpに接続します。新しいキーでは、Aghostのすべてのエージェントツールを利用できます。Claudeのカスタムコネクターなど、MCP サーバーにサインインするアプリにはURLだけが必要です。所有者がaghostでアプリを承認すると、アプリには専用のキーが付与されます。
MCPには、APIと同じサーバー上に専用のバックエンドルートモジュールがあります。クライアントのセットアップ、利用可能なツール、例については、MCPガイドをご覧ください。
分析
PostHogは、プロダクトの全工程にわたるデータを記録します。ブラウザーでは、同一オリジンの/relayを通じて、ページビュー、クリック、ウェブバイタル、エラー、セッションリプレイを記録します。APIでは、ダッシュボード、RESTまたはMCP経由のエージェント、Webhookのいずれで発生したかを問わず、サインアップ、チェックアウト、サブスクリプションの変更と収益、アカウント接続、オートメーション、すべてのエージェントツール呼び出しを記録します。ブラウザーとAPIのイベントは、サインイン中のユーザーIDを共有し、ワークスペースごとにグループ化されます。Instagramユーザーのメッセージと連絡先はリプレイに含まれません。
有効にするには、POSTHOG_KEYとPOSTHOG_HOSTを設定します。本番環境のセットアップ、イベントカタログ、分析で回答できる質問については、分析ガイドをご覧ください。
ブランド
マスコットがロゴです。mascot.pngが唯一の元画像で、ファビコン、Appleアイコン、apps/web/app内の共有画像は、すべてこの画像から作成されています。ダッシュボードではInterを使用しています。マーケティングページでは見出しにAnton、手書き風のメモにCaveat、本文にInterを使用しており、これらのフォントはNext.jsによってローカルから配信されます。
| 色 | Hex | 役割 |
|---|---|---|
| Aghost Green | #22DC72 | Primary |
| Blue | #145BFF | Accent |
| Cyan | #13C9D1 | Accent |
| Orange | #FFB213 | Accent |
| Red | #FF3B18 | Accent |
| Black | #000000 | Neutral |
| Gray | #687280 | Neutral |
| Off White | #F6F7F8 | Neutral |
色はglobals.css内のTailwindトークンで定義されています。たとえば、bg-brand、bg-brand-blue、text-brand-grayなどがあります。Aghost Greenの背景では白文字が薄くて読みにくいため、緑色のボタンには黒文字を使います。マーケティングサイトには、notebook.cssのスコープ付きスタイルを使って、罫線入りの紙、方眼紙、パステルカラーのメモ、テープで貼ったようなプロダクトプレビューを追加しています。ダッシュボードはニュートラルなデザインを保ち、ロゴのみを使用します。
検索と AI アシスタント
マーケティングページでは、検索エンジンや ChatGPT、Claude、Perplexity などの AI アシスタントに、読みやすい HTML を提供しています。これらのページでは、Instagram のコメントから DM への自動化、その要件、対応機能について説明しています。Instagram DM 自動化ガイドでは、ソーシャルメディア管理における aghost の役割を説明しています。aghost は、投稿への返信を自動化する機能とあわせて Instagram の投稿をスケジュールしますが、ほかのソーシャルネットワークは管理しません。
- テキストは一か所に集約。
content.tsには、事実、手順、機能、質問がまとめられています。ページ、構造化データ、/llms.txtはすべてここを参照するため、クローラーに訪問者が見る内容と同じ情報を伝えられます。 - エージェントからのアクセス。 ホームページ、機能デモ、専用のエージェントページでは、Claude Code、Codex、Cursor などの MCP クライアントを使って aghost を実行する方法を説明しています。
- 回答を最初に提示。 ガイドでは、最初に製品を定義し、セットアップ、ユースケース、要件、統計情報を説明する見出しを使用しています。フッターや機能ページへのリンクにより、JavaScript を使わなくてもページを見つけられます。
- 構造化データ。 ホームページでは、表示されているコンテンツを JSON-LD の
Organization、WebSite、WebApplication、FAQPageとして記述しています。ガイドには、表示されているパンくずリストに対応するWebPageとBreadcrumbListのデータを追加しています。どちらもレビューや評価を主張するものではありません。 - クロール。
robots.tsでは、公開ページへのクローラーを許可し、Googlebot、Bingbot、OpenAI 検索、Claude 検索、Perplexity 検索、およびユーザーのリクエストによる取得を明示的にグループ化しています。各グループは、公開セットアップスキル/api/mcp/skill.mdと分析リレー/relay/を除き、/api/へのアクセスを除外しています。sitemap.tsには公開ページを記載しています。サインインが必要なページにはnoindexを返します。 /llms.txt。 読み込むことを選択したアシスタント向けのプレーンテキストの概要です。エージェントのセットアップ詳細に先立ち、製品の説明、機能、最新の料金、サポートへのリンクを記載しています。これは利便性のためのものであり、インデックス登録や引用を保証するための必須要件ではありません。
正規リンク、サイトマップ、構造化データでは、サイトの公開オリジンを使用します。ローカルではAPP_URL、Vercel ではプロジェクトの本番ドメインを使用します。
公開後は、本番オリジンが正しいこと、公開ページがログインやボットへのチャレンジなしで HTTP 200 を返すこと、CDN またはファイアウォールが検証済みの検索クローラーを許可していることを確認してください。サイトマップを Google Search Console と Bing Webmaster Tools に送信し、インデックス登録状況とクローラーログを確認してください。ローカルでの確認では、本番環境でのインデックス登録や引用を確認できません。
この実装は、OpenAI のクローラーに関するガイダンス、Anthropic のクローラーに関するガイダンス、Perplexity のクローラーに関するガイダンス、AI 機能に関する Google のガイダンスに沿っています。これらのサービスは、インデックス登録や引用を行う情報源を選択します。クロールを許可し、役立つコンテンツを提供することで選ばれる可能性は高まりますが、特定のキーワードで表示される保証はありません。
プロジェクト構成
.
├── apps
│ ├── web/ Next.js pages, UI features, and Zustand stores
│ └── server/ Fastify entry point and Dockerfiles
├── packages
│ ├── api/ Contracts, client, services, routes, Supabase and Zernio adapters
│ ├── env/ Validation of environment variables
│ ├── supabase/ Database clients and generated types
│ └── ui/ Shared shadcn components
├── infra/ AWS CDK app for the API
├── supabase/ CLI config and forward-only migrations
├── scripts/ Local setup, env, and verification helpers
├── .github/ CI and deployment workflows
├── compose.yaml Local API container, webhook tunnel, and Supabase network
└── .env.example The configuration template
テスト
pnpm verify # unused code, types, lint, tests, and production builds
pnpm check:unused # unused files, dependencies, and exports across workspaces
pnpm verify:local # end-to-end checks against the running app
pnpm verify はローカルの Supabase スタックに対して統合テストを実行するため、まず pnpm setup:local または pnpm dev でスタックを起動してください。CI では pnpm setup:test を使用し、テストに必要なものだけを起動します。プロバイダーアダプターのテストではローカルの HTTP フィクスチャを使用し、実際の Instagram メッセージを送信することはありません。インフラストラクチャのテストでは、両方の CDK スタックをオフラインで合成します。
pnpm check:unused も CI で実行されます。その Knip 設定には、請求処理と CDK のコマンドラインエントリーポイントが含まれ、生成された Supabase ヘルパーが保持されます。また、設定を通じて読み込まれる PostCSS と CDK の依存関係も考慮されています。
OAuth 登録の飽和テストは、全体の1分間の予算を使い切るため、共有ローカルスタックではスキップされます。.env が専用のローカル Supabase データベースを指している場合は、AGHOST_TEST_ISOLATED_DATABASE=1 pnpm test を実行すると、このテストも含められます。CI では新しいデータベースでこのテストが有効になり、ほかの OAuth テストはフラグなしで実行されます。
アプリの実行中に pnpm verify:local を実行すると、ページ、Next.js プロキシ、Google サインインの開始を確認できます。具体的には、HttpOnly PKCE Cookie、ルートの .env にあるクライアントを使った Google へのリダイレクト、サインインが完了しなかった場合にログインページへ戻ることを確認します。Google アカウントでのサインイン、ブラウザー操作、目視での確認は、別途実施する確認項目です。
実際の OAuth とコメントから DM への配信には、Zernio の認証情報と、認証済みのプロフェッショナル Instagram アカウントが必要です。
デプロイ
flowchart LR
pr(["Pull request"]) --> checks["CI<br/>GitHub Actions"]
pr --> preview["Web preview<br/>Vercel"]
main(["Push to main"]) --> gate["CI"] --> migrate["Supabase<br/>migrations"] --> api["API<br/>AWS ECS"]
main --> web["Web<br/>Vercel"]
| ワークフロー | 実行時 | 手順 |
|---|---|---|
ci.yml | プルリクエスト、リリース | フォーマット、リント、型チェック、テスト、ビルド |
deploy.yml | main へのプッシュ、手動実行 | CI → 1つの Release ジョブ:マイグレーション → API |
actions/setup | すべてのジョブ | pnpm、Node.js 22、依存関係 |
main へのプッシュでは、バックエンドが1つのジョブでリリースされます。そのため、リリースに必要な承認は1回だけで、スキーマ、次にそれを使用する API の順に手順が実行されます。リリースできるのは main のみです。それ以外のブランチはワークフローと prod 環境の両方で拒否されます。変更のない API のデプロイは何も行わずに完了します。イメージはサーバーのパッケージだけからビルドされるため、CDK はイメージがすでに ECR にあることを検出し、CloudFormation は変更がないことを検出します。
Vercel 上の Web
マーケティングサイトとダッシュボードは、1つの Next.js アプリです。Vercel の Git 統合によってビルドされ、すべてのプルリクエストでプレビューが、main へのすべてのプッシュで本番環境が作成されます。GitHub には Vercel の認証情報は保存されません。
本番環境は https://aghost.app で提供されます。www.aghost.app はそこへリダイレクトされます。
メモ
Vercel と Release ジョブは同じプッシュを起点に並行して開始し、それぞれ独立して完了します。通常は Vercel が先に完了します。API の変更は、すでに稼働している Web アプリと互換性を保つか、先に API の変更をマージしてください。
Vercel CLI は .gitignore を読み込まないため、開発者のマシンから手動でデプロイする場合は .vercelignore によってローカルの環境ファイルがデプロイに含まれないようにしています。
AWS 上の API
infra/ では、AWS CDK を使用して API を定義しています。
- コンピューティング。 x86_64 の Fargate タスクを、CPU の需要に応じて 2〜4 個実行します。タスク数はオートスケーリングが管理するため、デプロイによってリセットされることはありません。
- アドレス。 ドメイン、DNS レコード、証明書が不要な API Gateway の HTTPS エンドポイントです。VPC リンクを介してプライベートロードバランサーに接続します。
- ネットワーク。 アカウントのデフォルト VPC を使用します。タスクには、Supabase、Zernio、ECR へのアウトバウンド通信に使うパブリックアドレスが割り当てられます。タスクのセキュリティグループが許可するのはロードバランサーからの通信のみで、ロードバランサーが許可するのは API Gateway からの通信のみです。
- イメージ。
turbo prune server --dockerの出力からビルドします。含まれるのは、サーバーのワークスペースパッケージとその依存関係のみです。 - シークレット。 Supabase と Zernio の認証情報は、タスクの起動時に Secrets Manager から取得します。
- リリース。 古いタスクを停止する前に、新しいタスクが
/api/healthに合格する必要があります。サーキットブレーカーは、正常な状態にならなかったリリースをロールバックします。ログは 30 日間保持されます。 - アクセス。 GitHub Actions は、AWS キーを保存せずに OIDC 経由でサインインします。そのロールで使用できるのは、
cdk bootstrapが作成したロールのみです。
infra
├── bin/app.ts Reads the stage's settings and creates the stacks
├── lib/config.ts Validates the settings and names any missing variable
├── lib/build-context.ts Prunes the repository to the server for the image
├── lib/stacks/api-stack.ts Default VPC, image, DNS zone, and credentials of a stage
├── lib/constructs/api-service.ts Fargate service, load balancer, health checks, scaling
├── lib/stacks/github-deploy-stack.ts The role GitHub Actions deploys with
└── test/ Assertions on the synthesized templates
1 回限りのセットアップ
1. AWS。 リポジトリのルートで、管理者の認証情報を使用して次を実行します。
export STAGE=prod AWS_ACCOUNT_ID=123456789012 AWS_REGION=ap-south-1 \
APP_URL=https://aghost.app SUPABASE_URL=https://your-project.supabase.co
pnpm --filter infra exec cdk bootstrap "aws://$AWS_ACCOUNT_ID/$AWS_REGION"
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com --client-id-list sts.amazonaws.com
aws secretsmanager create-secret --name aghost/prod/api --secret-string '{
"SUPABASE_PUBLISHABLE_KEY": "…",
"SUPABASE_SECRET_KEY": "…",
"ZERNIO_API_KEY": "…",
"ZERNIO_WEBHOOK_SECRET": "…",
"DODO_PAYMENTS_ENVIRONMENT": "live_mode",
"DODO_PAYMENTS_API_KEY": "…",
"DODO_PAYMENTS_WEBHOOK_KEY": "…"
}'
pnpm --filter infra exec cdk deploy --all
デプロイによって、手順 3 で使用する DeployRoleArn と、API のアドレスである ApiUrl が出力されます。
メモ
アカウントにすでに存在する場合は、
cdk bootstrapとcreate-open-id-connect-providerを省略してください。スタックは既存のものを使用します。リージョンのデフォルト VPC が削除されている場合は、aws ec2 create-default-vpcで再作成してください。supabase projects api-keys --revealを実行すると Supabase のキーが表示されます。--revealを指定しない場合、シークレットキーはマスクされ、使用できません。
2. Vercel。 ルートディレクトリを apps/web に設定したプロジェクトを作成して GitHub リポジトリに接続し、Production 環境と Preview 環境に API_URL=<ApiUrl> を追加します。APP_URL は Vercel がプロジェクトを配信するアドレスです。Web アプリはそのアドレスを Vercel 自身の VERCEL_PROJECT_PRODUCTION_URL から読み取るため、プロジェクトに APP_URL を設定する必要はありません。正規リンクに別のアドレスを公開する場合に限り、設定してください。
3. GitHub。 Settings → Environments で prod を作成し、デプロイ可能なブランチを main に限定して、次を追加します。
| 名前 | 種類 | 値 |
|---|---|---|
AWS_ACCOUNT_ID | 変数 | 12 桁のアカウント ID |
AWS_REGION | 変数 | 例:ap-south-1 |
AWS_DEPLOY_ROLE_ARN | 変数 | 手順 1 の DeployRoleArn |
APP_URL | 変数 | Web のオリジン。例:https://aghost.app |
SUPABASE_URL | 変数 | https://<project>.supabase.co |
SUPABASE_PROJECT_ID | 変数 | Supabase プロジェクトの参照 ID |
SUPABASE_POOLER_URL | 変数 | プロジェクトのセッションプーラーのアドレス |
SUPABASE_ACCESS_TOKEN | シークレット | スコープを設定した Supabase アクセストークン |
Supabase ダッシュボードの Account → Access Tokens でトークンを作成します。スコープはこのプロジェクトのみに設定し、Database: Read-write を指定してください。Release ジョブはこのトークンを使ってマイグレーション用の短期間のデータベースロールを作成するため、データベースのパスワードを保存する必要はありません。
GitHub のランナーには IPv6 がなく、データベースの直接アドレスは IPv6 専用のため、マイグレーションでは IPv4 セッションプーラーを介して接続します。アドレスにパスワードは含まれません。postgresql://postgres.<project>@<pooler-host>:5432/postgres を使用してください。このアドレスはダッシュボードの Connect → Session pooler に表示されるほか、supabase link によって supabase/.temp/pooler-url に保存されます。
ヒント
リリース開始前に承認できるよう、
prod環境に必須レビュアーを追加してください。
4. Supabase、Google、Zernio。 Supabase ダッシュボードの Authentication で、OAuth クライアントの ID とシークレットを使って Google プロバイダーを有効にし、Email プロバイダーを無効にして、リダイレクト URL に <APP_URL>/api/auth/callback を許可します。Google Cloud コンソールで、その OAuth クライアントの承認済みリダイレクト URI に https://<project>.supabase.co/auth/v1/callback を追加します。Zernio の Webhook を、同じシークレットを使って <ApiUrl>/api/webhooks/zernio に設定し、account.connected、account.disconnected、message.sent、message.received を購読します。API のリリース前に 20261016090000_carousels_and_follow_ups.sql を適用してください。機能のロールアウトを参照してください。
メモ
Google サインインの戻り先は
APP_URLで、API が書き込みを受け付けるのもそのオリジンからのみです。プレビューではサイトとダッシュボードを確認できますが、プレビューからサインインすることはできません。
ドメインの変更
サイトを別のドメインに移行するには、次の4つの手順を順番に実行します。手順3で新しいアドレスに移行するまでは、古いアドレスでもサインインできます。
- Vercel。 Settings → Domains で、プロジェクトにドメインを追加します。Vercel の Production 環境で
APP_URLが設定されている場合は、新しいオリジンに更新するか、削除してVERCEL_PROJECT_PRODUCTION_URLを使用します。その後、本番環境を再デプロイすると、正規リンク、サイトマップ、/llms.txtで新しいドメインが使用されます。 - Supabase。 Authentication → URL Configuration で、サイト URL を新しいオリジンに設定し、リダイレクト URL に
<new origin>/api/auth/callbackを追加します。 - GitHub。
prod環境でAPP_URLを設定し、Deploy ワークフローを実行します。これにより、API はサインイン、チェックアウト、Instagram 接続後の戻り先を新しいオリジンにし、ダッシュボードへの書き込みをそのオリジンからのみ受け付けるようになります。 - 古いアドレス。
/apiをそのままにする Vercel プロジェクトのルーティングルールを使って、古いアドレスのページを新しいオリジンにリダイレクトします。ホストは<old address>、パターンは^/(?!api/)(.*)$、宛先は<new origin>/$1、ステータスは 308 に設定します。API キーと Webhook 署名はオリジンに紐付いていないため、古いアドレスで設定されたエージェントと Webhook は引き続き動作します。パターンの先頭に^を付けてください。付けないと、/apiパス内でも一致します。
次に、新しいオリジンを PostHog プロジェクトの許可 URL に追加し、そのサイトマップを検索エンジンの各管理ツールに送信します。
インフラストラクチャの変更をレビューする
AWS 認証情報と手順1の変数を使って、変更内容とデプロイ済みの内容を比較します。
pnpm --filter infra exec cdk diff Aghost-prod-Api
合成処理ではアカウント内のデフォルト VPC を検索するため、認証情報が必要です。テストでは記録済みのコピーを使用するため、オフラインで実行できます。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。