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
| Technology | Purpose |
|---|---|
| Go 1.24 | Core language |
| Fiber v2 | Web framework (Express-like) |
| GORM | ORM for SQLite and PostgreSQL |
| LiveKit Protocol SDK | WebRTC room and token management |
| Zerolog | Structured JSON logging |
| Goth | Multi-provider OAuth2 |
| go-passkeys | FIDO2/WebAuthn support |
| golang-jwt | JWT token creation and validation |
| gocron | Background 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.FSAt 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_verify、password_reset)与访问令牌共用签名密钥,但不能在Protected路由上当作访问令牌。 - 变更请求(已认证的 POST/PUT/PATCH/DELETE)须通过
RequireBearerForMutations携带 Bearer;仅 Cookie 的跨站 POST 会被拒绝(CSRF 防护)。 - 访问令牌吊销(登出 / 改密)持久化到数据库,可跨进程重启与多实例部署生效。
- 房间在线身份列表需要身份验证;公开房间可提供
?countOnly=1(仅人数,无身份)。
LiveKit Token Generation
When a user joins a room, the server:
- Validates room permissions
- Creates a LiveKit access token signed with the API secret
- Returns the token to the client
- The client connects directly to LiveKit using the token
录制与 LiveKit Egress
队列处理器 process_recording 与 recording_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:
Webhookmodel in database, CRUD viaWebhookRepository - 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
- Backend Code Structure - directory map and coding standards
- API Handlers - routing and request lifecycle
- Database and Models - GORM models and repository pattern
- Authentication Flow - JWT, OAuth, and passkey internals