このドキュメントは、ActivityPub Relayの開発に関する詳細な情報を提供します。
このプロジェクトは、pnpm workspacesを使用したモノレポ構成になっています:
ActivityPub-Relay-Bun/
├── packages/
│ ├── contract/ # ORPC型定義と契約
│ │ ├── src/
│ │ └── package.json
│ ├── relay/ # バックエンド(Cloudflare Workers)
│ │ ├── src/
│ │ │ ├── activityPub/ # ActivityPub関連のロジック
│ │ │ ├── api/ # APIルーター
│ │ │ ├── lib/ # Prismaクライアント等
│ │ │ ├── service/ # ビジネスロジック
│ │ │ ├── types/ # 型定義
│ │ │ ├── utils/ # ユーティリティ関数
│ │ │ └── server.ts # エントリーポイント
│ │ ├── prisma/ # Prismaスキーマとマイグレーション
│ │ ├── wrangler.toml # Cloudflare Workers設定
│ │ └── package.json
│ └── frontend/ # フロントエンド(Vue 3)
│ ├── src/
│ │ ├── api/ # バックエンドAPIクライアント
│ │ ├── components/ # Vueコンポーネント
│ │ ├── composables/ # Composition API関数
│ │ ├── pages/ # ページコンポーネント
│ │ ├── router/ # Vue Router設定
│ │ ├── App.vue # ルートコンポーネント
│ │ └── main.ts # エントリーポイント
│ └── package.json
├── pnpm-workspace.yaml # pnpm workspace設定
├── biome.json # Biome設定
└── package.json # ルートpackage.json
ORPC (Type-safe RPC framework) を使用して、フロントエンドとバックエンド間の型安全な通信を実現します。
- APIの契約(contract)を定義
- フロントエンドとバックエンドで型定義を共有
- 型安全なAPIクライアントを自動生成
Cloudflare Workers上で動作するバックエンドサーバーです。
- activityPub/: ActivityPubプロトコルの実装(Follow, Undo, Relayロジック)
- api/: ORPCルーター、管理APIエンドポイント
- service/: ドメインルール、フォロー管理、設定管理などのビジネスロジック
- utils/: HTTP署名、ActivityPubヘルパー、ドメインブロックなどのユーティリティ
- lib/: Prismaクライアントの初期化
- types/: TypeScript型定義
Vue 3 + Viteで構築された管理ダッシュボードです。
- components/: 再利用可能なUIコンポーネント
- pages/: ページレベルのコンポーネント
- composables/: Composition API関数(状態管理、API呼び出し等)
- router/: Vue Routerのルート定義
- api/: ORPCクライアントを使用したバックエンドAPIとの通信
- Node.js: 18以上
- pnpm: 9以上
- Wrangler CLI: Cloudflare Workers開発ツール(pnpm installで自動インストール)
- OpenSSL: キー生成用
- リポジトリのクローン
git clone <repository-url>
cd ActivityPub-Relay-Bun- 依存関係のインストール
pnpm install- RSAキーペアの生成
# 秘密鍵を生成
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
# 公開鍵を抽出
openssl rsa -pubout -in private_key.pem -out public_key.pem- 環境変数の設定
packages/relay/.dev.vars.exampleをコピー:
cp packages/relay/.dev.vars.example packages/relay/.dev.vars.dev.varsを編集して、生成したキーとAPIキーを設定:
PUBLICKEY=-----BEGIN PUBLIC KEY-----
<public_key.pemの内容をここに貼り付け>
-----END PUBLIC KEY-----
PRIVATEKEY=-----BEGIN PRIVATE KEY-----
<private_key.pemの内容をここに貼り付け>
-----END PRIVATE KEY-----
API_KEY=<強力なランダム文字列>- D1データベースの作成
cd packages/relay
npx wrangler d1 create activitypub-relay出力されたdatabase_idをpackages/relay/wrangler.tomlに設定:
[[d1_databases]]
binding = "DB"
database_name = "activitypub-relay"
database_id = "<ここに出力されたID>"- データベースマイグレーション
# ルートディレクトリから実行
pnpm db:generate # Prismaクライアント生成
pnpm db:migrate # ローカルマイグレーション実行- 開発サーバーの起動
pnpm devこれにより以下が起動します:
- バックエンド: http://localhost:3000
- フロントエンド: http://localhost:5173
git checkout -b feature/your-feature-nameお好みのエディタで開発を行います。VS CodeやWebStormを推奨します。
Biomeを使用したコード品質チェック:
# 問題をチェック
pnpm check
# 自動修正
pnpm fix
# unsafe fixを含めて修正
pnpm fix-unsafe開発サーバーで動作を確認:
pnpm devgit add .
git commit -m "feat: your feature description"
git push origin feature/your-feature-name特定のパッケージのみを開発する場合:
# バックエンドのみ
pnpm dev:relay
# フロントエンドのみ
pnpm dev:frontend-
packages/relay/prisma/schema.prismaを編集 -
マイグレーションを作成:
cd packages/relay
npx prisma migrate dev --name your_migration_name- Prismaクライアントを再生成:
pnpm db:generateリクエスト
↓
server.ts (Honoアプリケーション)
↓
api/router.ts (ORPCルーター)
↓
service/* (ビジネスロジック)
↓
lib/prisma.ts (データベースアクセス)
外部サーバー → POST /inbox
↓
activityPub/relay.ts
↓
HTTP署名検証 (utils/httpSignature.ts)
↓
ドメインルールチェック (service/DomainRuleService.ts)
↓
フォロワーへの配信
- Hono: 軽量Webフレームワーク
- ORPC: 型安全なRPCフレームワーク
- Prisma: ORMとデータベースマイグレーション
- Cloudflare Workers: サーバーレス実行環境
- Cloudflare D1: SQLiteベースのサーバーレスデータベース
App.vue
↓
Router (router/index.ts)
↓
Pages (pages/*)
↓
Components (components/*)
↓
API Client (api/client.ts)
↓
Backend ORPC Endpoints
- Vue 3のComposition APIを使用
- Composablesで状態とロジックをカプセル化
- ORPCクライアントで型安全なAPI呼び出し
ActivityPubの標準に準拠したHTTP署名検証を実装しています(utils/httpSignature.ts):
Signatureヘッダーのパース- 署名文字列の構築
- 公開鍵の取得(リモートサーバーから)
- 署名の検証
ホワイトリスト/ブラックリストによるドメインフィルタリング(service/DomainRuleService.ts):
- ホワイトリストモード: 許可されたドメインのみ受け入れ
- ブラックリストモード: 禁止されたドメインを拒否
- デフォルト: すべてのドメインを受け入れ
管理APIはAPI_KEYによる認証を必須としています。
- 型安全性:
anyの使用を避け、明示的な型定義を行う - Null安全性:
null/undefinedチェックを適切に行う - 関数型プログラミング: 純粋関数とイミュータブルなデータ構造を優先
プロジェクトではBiomeを使用しています:
# コードチェック
pnpm check
# 自動修正
pnpm fixConventional Commits形式を推奨:
feat: 新機能を追加
fix: バグ修正
docs: ドキュメントの変更
style: コードスタイルの変更(機能に影響なし)
refactor: リファクタリング
test: テストの追加・修正
chore: ビルドプロセスやツールの変更
開発サーバーで基本的な動作確認:
pnpm dev実際のMastodonやMisskeyインスタンスとの連携テスト:
- ローカルサーバーをngrokなどで公開
- フォローリクエストを送信
- 投稿が正しくリレーされるか確認
ローカルD1データベースでのクエリテスト:
cd packages/relay
npx wrangler d1 execute activitypub-relay --local --command "SELECT * FROM Follower"Wranglerの開発モードはホットリロードとログ出力をサポート:
pnpm dev:relayconsole.log()やconsole.error()でログを出力できます。
ブラウザの開発者ツールを使用:
- Vue Devtools拡張機能を推奨
- NetworkタブでAPI通信を確認
- Consoleタブでエラーを確認
デプロイ後のログ確認:
npx wrangler tailまたは、Cloudflare Dashboardの「Logs」セクションを確認。
マイグレーションが失敗する場合:
# ローカルD1データベースをリセット
rm -rf .wrangler/state
# マイグレーションを再実行
pnpm db:migrate秘密鍵/公開鍵のフォーマットが正しいか確認:
# 秘密鍵の検証
openssl rsa -in private_key.pem -check
# 公開鍵の検証
openssl rsa -pubin -in public_key.pem -text開発サーバーのポートが使用中の場合:
# ポート3000を使用しているプロセスを確認
lsof -i :3000
# プロセスを終了
kill -9 <PID>フロントエンドからバックエンドへのリクエストでCORSエラーが発生する場合、packages/relay/src/server.tsのCORS設定を確認してください。
# ログアウト
npx wrangler logout
# 再ログイン
npx wrangler login- シークレットの設定
cd packages/relay
# 公開鍵を登録
npx wrangler secret put PUBLICKEY
# プロンプトで公開鍵の内容を貼り付け
# 秘密鍵を登録
npx wrangler secret put PRIVATEKEY
# プロンプトで秘密鍵の内容を貼り付け
# APIキーを登録
npx wrangler secret put API_KEY
# プロンプトでAPIキーを貼り付け- 本番データベースのマイグレーション
pnpm db:migrate:prod- デプロイ
# ルートディレクトリから
pnpm deployこれにより以下が実行されます:
- フロントエンドのビルド
- バックエンドのデプロイ(静的ファイルを含む)
- Cloudflare Dashboardでワーカーの状態を確認
- エンドポイントにアクセスして動作確認:
https://your-domain.workers.dev/actorhttps://your-domain.workers.dev/.well-known/webfinger?resource=acct:[email protected]
プルリクエストを歓迎します!以下の手順に従ってください:
- このリポジトリをフォーク
- フィーチャーブランチを作成 (
git checkout -b feature/amazing-feature) - 変更をコミット (
git commit -m 'feat: add amazing feature') - ブランチにプッシュ (
git push origin feature/amazing-feature) - プルリクエストを作成