Bedrud 文档

The Bedrud server is a Go application that provides the REST API, serves the embedded web frontend, and manages the LiveKit media server.

Technology Stack

TechnologyPurpose
Go 1.24Core language
Fiber v2Web framework (Express-like)
GORMORM for SQLite and PostgreSQL
LiveKit Protocol SDKWebRTC room and token management
ZerologStructured JSON logging
GothMulti-provider OAuth2
go-passkeysFIDO2/WebAuthn support
golang-jwtJWT token creation and validation
gocronBackground job scheduling
Swagger (swaggo)API documentation generation

Directory Structure

server/
├── cmd/
│   ├── server/main.go        # Development entry point
│   └── bedrud/main.go        # Production entry point (with install/livekit flags)
├── internal/
│   ├── auth/                  # Authentication services
│   │   ├── auth.go            # Core auth service (register, login, OAuth)
│   │   ├── jwt.go             # JWT token creation and validation
│   │   └── session_store.go   # Gorilla session store for OAuth state
│   ├── database/              # Database initialization and migrations
│   ├── handlers/              # HTTP request handlers (controller layer)
│   │   ├── auth_handler.go    # Auth endpoints
│   │   ├── recording_handler.go # Recording start/stop/list/get
│   │   ├── room.go            # Room endpoints
│   │   └── users.go           # User management endpoints
│   ├── middleware/             # Fiber middleware
│   │   ├── auth.go            # JWT validation, permission checks
│   │   └── recordings_enabled.go # Recordings sys-setting gate
│   ├── models/                # GORM models (database schemas)
│   │   ├── user.go            # User model
│   │   ├── webhook.go         # Webhook model
│   │   ├── recording.go       # Recording model
│   │   ├── room.go            # Room model
│   │   └── passkey.go         # Passkey model
│   ├── repository/            # Data access layer (SQL via GORM)
│   │   ├── user_repository.go
│   │   ├── webhook_repository.go
│   │   ├── recording_repository.go
│   │   ├── room_repository.go
│   │   └── passkey_repository.go
│   ├── services/               # Business logic layer
│   │   ├── recording_service.go # Recording gate chain + LK egress
│   │   └── room_cleanup.go     # Room deletion/suspend cascade
│   ├── livekit/               # Embedded LiveKit server management
│   ├── scheduler/             # Background job scheduling
│   └── utils/                 # TLS and other utilities
├── frontend/                  # Embedded web frontend (populated at build time)
├── config.yaml                # Development configuration
├── livekit.yaml               # Development LiveKit configuration
├── go.mod
└── go.sum

Layered Architecture

The server follows a layered architecture:

flowchart TB
    HTTP[HTTP Request] */} Middleware
    Middleware["Middleware<br/>JWT validation, CORS, logging"] */} Handlers
    Handlers["Handlers<br/>Parse requests, call services, format responses"] */} Services
    Services["Services<br/>Business logic (auth, room management)"] */} Repository
    Repository["Repository<br/>Database queries via GORM"] */} Database
    Database["Database<br/>SQLite (dev) or PostgreSQL (production)"]

Key Patterns

Embedded Frontend

The web frontend is compiled to static files and embedded into the Go binary using //go:embed:

//go:embed frontend/*
var frontendFS embed.FS

At build time, bun run build:embed SSR pre-renders the React app and copies dist/client/ into server/frontend/. The Go compiler then bundles it into the binary. The Fiber server serves these files for any non-API route.

JWT 身份验证

中间件从 Authorization: Bearer <token> 请求头提取 JWT(读取时也可回退 Cookie),校验后将用户上下文附加到请求。受保护路由使用 RequireAccess 检查角色。

  • 用途令牌email_verifypassword_reset)与访问令牌共用签名密钥,但不能Protected 路由上当作访问令牌。
  • 变更请求(已认证的 POST/PUT/PATCH/DELETE)须通过 RequireBearerForMutations 携带 Bearer;仅 Cookie 的跨站 POST 会被拒绝(CSRF 防护)。
  • 访问令牌吊销(登出 / 改密)持久化到数据库,可跨进程重启与多实例部署生效。
  • 房间在线身份列表需要身份验证;公开房间可提供 ?countOnly=1(仅人数,无身份)。

LiveKit Token Generation

When a user joins a room, the server:

  1. Validates room permissions
  2. Creates a LiveKit access token signed with the API secret
  3. Returns the token to the client
  4. The client connects directly to LiveKit using the token

录制与 LiveKit Egress

队列处理器 process_recordingrecording_delete 已在 worker 上注册。LiveKit 的 egress_ended webhook 会入队 process_recording(下载 → 存储 → 标记完成 → 可选 recording.completed webhook)。

🚧 HTTP 录制路由(API 的 start/stop/list)在生产路由表上仍为 // TODO oncoming feature — 在正式提供前请勿依赖公开录制 REST 端点。recording: 下的 YAML 键配置处理流水线的存储。

Webhooks

Webhook system allows superadmins to register HTTP callbacks for real-time events. Active events: room.created, room.ended, participant.joined, and ping (test). recording.completed is reserved for a planned feature. Delivery headers: X-Bedrud-Signature, X-Bedrud-Event, X-Bedrud-Timestamp.

  • Storage: Webhook model in database, CRUD via WebhookRepository
  • Dispatch: Background job (dispatch_webhook) sends HMAC-SHA256 signed POST requests with 10s timeout
  • Secrets: Per-webhook HMAC secret, rotatable via admin panel
  • See the Webhooks API for endpoint details.

Swagger Documentation

API documentation is auto-generated from code annotations using swaggo. In development, it’s available at /api/swagger/.

Database

SQLite (Default)

For development and small deployments, Bedrud uses SQLite. The database file is stored at the configured database.path (default: data.db).

PostgreSQL

For production with higher concurrency requirements, configure a PostgreSQL connection string. GORM handles both dialects transparently.

Migrations

GORM auto-migrates the schema on startup based on the model structs. The models are defined in internal/models/.

Background Jobs

The gocron scheduler runs periodic tasks such as:

  • Cleaning up expired refresh tokens
  • Removing stale room participants

See also