Bedrud ドキュメント

server/ディレクトリとその内容のマップです。

プロジェクトツリー

server/ディレクトリにはGoバックエンドと埋め込みLiveKitメディアサーバーが含まれます。apps/ディレクトリにはクライアントアプリケーションが含まれます。

bedrud/
├── apps/                # Client Applications
│   ├── web/             # React Frontend (TanStack Start)
│   ├── android/         # Native Android Application
│   └── ios/             # Native iOS Application
├── server/              # Go Backend (The "Appliance")
│   ├── cmd/             # CLI Entry points (run, install)
│   ├── internal/        # Private application code
│   │   ├── auth/        # JWT, Passkeys, OAuth logic
│   │   ├── handlers/    # HTTP Controllers
│   │   ├── models/      # Database Schemas
│   │   ├── repository/  # GORM Data Access Layer
│   │   └── livekit/     # Media Server Management
│   ├── frontend/        # (Generated) Compiled web assets
│   ├── config.yaml      # Configuration template
│   └── Makefile         # Build & Deploy automation
└── docs/                # System Documentation (MkDocs)

ディレクトリマップ

/cmd/bedrud

  • main.go: アプリケーションのエントリポイントです。runinstalllivekitなどのCLIコマンドを処理します。

/config

  • config.go: Config構造体を定義し、config.yamlまたは環境変数から設定を読み込みます。
  • livekit.yaml: 埋め込みLiveKitサーバーのデフォルト設定。

/internal

  • /auth: JWT生成、OAuthプロバイダー、パスキー(WebAuthn)の登録・ログインのロジックを含みます。
  • /database: SQLiteまたはPostgreSQLへの接続を管理し、マイグレーションを実行します。
  • /handlers: Fiber HTTPハンドラ。各APIエンドポイントのロジックがここにあります(例: auth_handler.goroom_handler.go)。
  • /models: GORMデータベースモデル。データベースのテーブルを定義するファイルです。
  • /repository: 「データアクセス層」。ハンドラはDBクエリを直接記述する代わりにリポジトリを呼び出し、ハンドラのロジックをクリーンに保ちます。
  • /livekit: LiveKit Go SDKとの統合。ルームの作成を管理し、参加者用の「Join Token」を生成します。
  • /middleware: 認証チェック、ロギング、CORS用のカスタムFiberミドルウェア。
  • /server: すべてを結びつけるグルーコード。データベースとリポジトリを初期化し、Fiberサーバーを起動します。
  • /install: bedrud installコマンドのロジック。Linux上でsystemdとTLSの設定を自動化します。
  • /scheduler: バックグラウンドタスク(もしあれば)。
  • /utils: 小さなヘルパー関数(例: パスワードハッシュ化、ランダム文字列生成)。

/migrations

  • データベーススキーマ更新用のSQLまたはGoファイルを含みます。

/docs(server内)

  • Swagger/OpenAPIドキュメントファイルを含みます(swagで生成)。

技術的詳細

1. バイナリ埋め込み(「トリック」)

Bedrudは//go:embedディレクティブを使用してファイルをコンパイル済みバイナリにバンドルします。

  • フロントエンド: Reactのdist/client/フォルダ(プリレンダリングされたindex.htmlを含む)がserver/ui.goに埋め込まれます。静的ファイルはFiberのfilesystemミドルウェアを使用してメモリから直接配信されます。
  • LiveKitサーバー: プリコンパイル済みのlivekit-server実行可能ファイルがinternal/livekit/bin/に埋め込まれます。実行時に、Bedrudはこれを/tmp/bedrud-livekit-serverに展開し、バックグラウンドプロセスとして起動します(internal/livekit/server.go)。

2. LiveKitリバースプロキシ

複数のポート(シグナリング、APIなど)を開くことを避けるため、BedrudはすべてのLiveKitシグナリングトラフィックをメインのHTTP(S)ポート経由でルーティングします。

  • /livekitで始まるリクエストはinternal/server/server.goでインターセプトされます。
  • リバースプロキシhttputil.NewSingleHostReverseProxyを使用)がこれらのリクエストを内部LiveKitインスタンス(通常は127.0.0.1:7880で実行)に転送します。
  • プロキシは転送前に/livekitプレフィックスを削除し、LiveKitがルートアプリケーションであるかのように機能できるようにします。

3. ミドルウェアコンテキストとLocals

バックエンドはFiberの.Localsを使用してミドルウェアとハンドラ間でデータを渡します。

  • 認証ミドルウェア (internal/middleware/auth.go): JWTを検証し、Claimsオブジェクトをc.Locals("user")に保存します。
  • ハンドラ: 以下のように現在のユーザーのIDと権限にアクセスできます:
    claims := c.Locals("user").(*auth.Claims)
    userID := claims.UserID

4. 設定の上書き

Bedrudはconfig.yamlファイルを使用しますが、ほぼすべての設定は環境変数で上書きできます。これはDockerやCI/CD環境で重要です。

変数説明
SERVER_PORTバックエンドがリッスンするポート(デフォルト: 8090)。
SERVER_ENABLE_TLSHTTPSを有効にするブール値(true/false)。
SERVER_DOMAIN本番環境のドメイン(ACMEとパスキーRP IDに使用)。
DB_TYPEsqliteまたはpostgres
DB_PATH.dbファイルへのパス(SQLite使用時)。
LIVEKIT_HOSTLiveKitの公開URL(例: https://meet.example.com/livekit)。
LIVEKIT_API_KEYLiveKit認証用のキー。
JWT_SECRETAccess Tokenの署名に使用される秘密鍵。

コーディング規約とパターン

バックエンドは以下のパターンに従っています:

1. リポジトリパターン

ハンドラはデータベースに直接アクセスすべきではありません。リポジトリを使用してください。これにより、コードのテストが容易になり、APIハンドラを変更せずにデータベースロジックを変更できるようになります。

2. 標準化されたエラーハンドリング

APIハンドラは明確なエラーメッセージを返す必要があります。

  • バリデーションエラーにはc.Status(fiber.StatusBadRequest).JSON(...)を使用します。
  • 認証エラーにはc.Status(fiber.StatusUnauthorized).JSON(...)を使用します。
  • データベースやサーバーエラーにはc.Status(fiber.StatusInternalServerError).JSON(...)を使用します。

3. 構造化ロギング

バックエンドはZerologを使用してログを出力します。

  • log.Info(): 重要なイベント(例: サーバー起動)。
  • log.Error(): エラー。
  • log.Debug(): 詳細な開発情報。

コアロジックでのfmt.Printlnによるロギングは避けてください。

4. 命名規則

  • ファイル: snake_case(例: user_handler.go)。
  • 構造体/関数: PascalCase(例: GetUserByEmail)。
  • 変数: camelCase(例: hashedPassword)。