Bedrud 文档

Bedrud 使用 YAML 配置文件管理主服务器和嵌入式 LiveKit 媒体服务器。

另见: 快速开始 | 安装指南 | 部署指南 | Docker 指南

生产环境最低配置

默认配置适用于开发环境。生产环境中请在 /etc/bedrud/config.yaml 中修改以下值:

auth:
  jwtSecret: "change-to-random-string-32-chars"
  sessionSecret: "change-to-another-random-string"

修改后重启:

sudo systemctl restart bedrud livekit

完整参考如下。


服务器配置

路径: server/config.yaml(开发环境)或 /etc/bedrud/config.yaml(生产环境)

完整参考

server:
  port: 8090                    # HTTP 端口
  host: "localhost"             # 绑定地址
  maxParticipantsLimit: 1000    # Hard ceiling for room capacity (0 = unlimited). Env: SERVER_MAX_PARTICIPANTS_LIMIT
  maxRoomsPerUser: 100          # Max active rooms per user (0 = unlimited). Env: SERVER_MAX_ROOMS_PER_USER
 
database:
  type: "sqlite"                # 数据库类型:sqlite 或 postgres
  path: "data.db"               # SQLite 数据库文件路径
 
logger:
  level: "debug"                # 日志级别:debug、info、warn、error。控制应用日志和 SQL 查询日志。
  outputPath: ""                # 日志文件路径(空 = stdout)
 
livekit:
  host: "http://localhost:8090/livekit"  # 外部 LiveKit URL
  internalHost: "http://127.0.0.1:7880"  # 内部 LiveKit URL
  apiKey: "devkey"              # LiveKit API key (auto-generated if empty)
  apiSecret: "devsecret"        # LiveKit API secret
 
auth:
  jwtSecret: "your-jwt-secret"           # 签名 JWT token 的密钥
  tokenDuration: 24                       # Token 过期时间(小时)
  sessionSecret: "your-session-secret"    # Session cookie 的密钥
  frontendURL: "http://localhost:8090"    # 前端 URL(用于 OAuth 重定向)
  passkeyChallengeTTL: 5                # Passkey 挑战过期时间(分钟)
 
  # OAuth 提供者(可选)
  google:
    clientId: ""
    clientSecret: ""
  github:
    clientId: ""
    clientSecret: ""
  twitter:
    clientKey: ""
    clientSecret: ""
 
cors:
  allowedOrigins: "http://localhost:8090,http://localhost:3000"  # 逗号分隔
  allowedHeaders: "Origin, Content-Type, Accept, Authorization"
  allowedMethods: "GET, POST, PUT, DELETE, OPTIONS"
  allowCredentials: true
 
rateLimit:
  authMaxRequests: 10       # Max auth requests per window (login, register, refresh, passkey). 0 = disable
  authWindowSecs: 60         # Auth rate limit window in seconds
  guestMaxRequests: 5        # Max guest join requests per window. 0 = disable
  guestWindowSecs: 60        # Guest rate limit window in seconds
 
chat:
  maxUploadBytesPerUser: 524288000       # Per-user upload quota (500 MB). 0 = unlimited. Env: CHAT_MAX_UPLOAD_BYTES_PER_USER
  globalDiskThresholdBytes: 0            # Global storage ceiling across all users. 0 = unlimited. Env: CHAT_GLOBAL_DISK_THRESHOLD_BYTES
  maxMessageCount: 10000                 # Max chat messages kept per room (0 = unlimited). Env: CHAT_MAX_MESSAGE_COUNT
  messageTTLHours: 2160                  # Purge messages older than this in hours (0 = forever). 2160 = 90 days. Env: CHAT_MESSAGE_TTL_HOURS
 
 
recording:
  maxFileSizeMB: 2048           # Max recording file size in MB (0 = unlimited). Env: RECORDING_MAX_FILE_SIZE_MB
  storageDir: "./data/recordings"  # Local storage path for disk-backed recordings. Env: RECORDING_STORAGE_DIR
  maxRecordingsPerRoom: 100     # Max total recordings per room (0 = unlimited). Env: RECORDING_MAX_PER_ROOM
 
queue:
  pollInterval: 500              # ms between job polls. Env: QUEUE_POLL_INTERVAL
  maxAttempts: 3                 # retries before marking failed. Env: QUEUE_MAX_ATTEMPTS
  concurrency: 1                 # worker goroutines. Env: QUEUE_CONCURRENCY
 
email:
  smtpHost: ""                    # SMTP server hostname. Env: EMAIL_SMTP_HOST
  smtpPort: 587                   # SMTP server port. Env: EMAIL_SMTP_PORT
  username: ""                    # SMTP username. Env: EMAIL_USERNAME
  password: ""                    # SMTP password. Env: EMAIL_PASSWORD
  fromAddress: ""                 # From address. Env: EMAIL_FROM_ADDRESS
  fromName: "Bedrud"              # From display name. Env: EMAIL_FROM_NAME
  tlsSkipVerify: false       # Skip TLS certificate validation. Env: EMAIL_TLS_SKIP_VERIFY
  smtpsMode: false           # Direct TLS (SMTPS, port 465). Env: EMAIL_SMTPS_MODE

关键设置

数据库

默认情况下,Bedrud 使用 SQLite,数据库文件位于配置的 path。对于更高并发的生产环境,可切换到 PostgreSQL,提供连接字符串。使用 PostgreSQL 时,path 字段存放连接字符串而非文件路径:

database:
  type: "postgres"
  path: "postgres://user:password@localhost:5432/bedrud?sslmode=disable"

身份验证

jwtSecret 用于签名访问令牌和刷新令牌。生产环境中请更改默认值。

OAuth 提供者为可选配置。如果不配置,UI 中不会显示社交登录按钮。每个提供者需要在相应服务上注册 OAuth 应用,并提供 client ID 和 secret。

CORS

allowedOrigins 字符串(逗号分隔)必须包含前端服务的 URL。开发环境中为 http://localhost:3000。生产环境中设置为你的域名(如 https://meet.example.com)。

速率限制

速率限制保护认证端点免受暴力破解和拒绝服务攻击。两个类别:

  • 认证端点(登录、注册、刷新、Passkey登录/注册)— 默认:每IP每60秒10次请求
  • 访客加入 — 默认:每IP每60秒5次请求

省略 rateLimit 部分以保持默认值。设置 authMaxRequests: 0guestMaxRequests: 0 以禁用。

Chat History

Bedrud applies advisory retention limits to in-room chat messages. Since LiveKit — the real-time media layer — does not persist data channel messages server-side, these limits are enforced on the client:

  • maxMessageCount — caps the number of chat messages held in memory and sessionStorage per room. When exceeded, the oldest messages are trimmed. Default: 10000. Set to 0 for unlimited.
  • messageTTLHours — messages older than this threshold are purged from the local cache. Default: 2160 (90 days). Set to 0 to keep messages indefinitely.

Chat messages in Bedrud are transmitted exclusively through LiveKit data channels and are not stored on the server. The retention limits above control how many messages the frontend keeps in memory and sessionStorage. A dedicated chat history service (with server-side persistence) would be needed for true history across sessions — this is tracked as a future enhancement.

Recordings

Room recording is controlled by the RecordingsEnabled system setting (toggle in admin Settings → General). When enabled:

  • Moderators can start/stop composite MP4 recordings from the meeting controls bar
  • Recordings are stored alongside chat uploads using the configured storage backend (disk/S3)
  • Each room has a per-room recordingsAllowed toggle that must also be enabled
  • Failed/pending recordings over 7 days old are automatically cleaned up daily
  • Non-persistent rooms have a configurable per-room recording cap (maxRecordingsPerRoom) to prevent abuse
  • After a room is deleted, the recording creator can still access their recordings from the same room URL

YAML Reference:

  • maxFileSizeMB — maximum file size for a single recording in MB. 0 = unlimited. Default: 2048. Env: RECORDING_MAX_FILE_SIZE_MB
  • storageDir — directory for disk-backed recordings. Only used when S3 is not configured. Default: ./data/recordings. Env: RECORDING_STORAGE_DIR
  • maxRecordingsPerRoom — caps total recordings per room (all statuses: completed, failed, etc.). 0 = unlimited. Only enforced for non-persistent rooms. Default: 100. Env: RECORDING_MAX_PER_ROOM

See the Recordings Guide for full details.

队列(任务系统)

内部任务队列处理异步后台任务,如用户/房间删除、暂停和聊天上传。

  • pollInterval — 工作线程检查新任务的频率(毫秒)。较低的值可减少延迟,但会增加数据库查询次数。
  • maxAttempts — 任务标记为失败前的最大重试次数。重试使用指数退避(2^尝试次数 * 5s,上限为 1 小时)。
  • concurrency — 工作线程 goroutine 数量。使用 PostgreSQL 时可增加以提高吞吐量。SQLite 限制为单工作线程(一个连接)。

电子邮件通知

Bedrud 可以通过 SMTP 发送事务性电子邮件(欢迎、密码重置、房间邀请)。

  • smtpHost / smtpPort — SMTP 服务器地址。默认使用端口 587(STARTTLS)。
  • username / password — SMTP 身份验证凭据。
  • fromAddress / fromName — 外发邮件的发件人身份。
  • tlsSkipVerify — 跳过 TLS 证书验证(用于自签名证书)。
  • smtpsMode — 直接 TLS(SMTPS,端口 465)。

LiveKit 配置

路径: server/config/livekit.yaml(开发环境)或 /etc/bedrud/livekit.yaml(生产环境)

port: 7880                      # LiveKit HTTP/WebSocket 端口
 
rtc:
  port_range_start: 50000       # UDP 端口范围起始
  port_range_end: 60000         # UDP 端口范围结束
  use_external_ip: true         # RTC 使用外部 IP
 
turn:
  enabled: true
  domain: "localhost"
  tls_port: 5349
  udp_port: 3478
 
keys:
  devkey: "devsecret"           # 必须与服务器配置匹配
 
logging:
  level: info
 
room:
  auto_create: true              # 参与者加入时自动创建房间
  empty_timeout: 60              # 删除空房间的超时时间(秒)
  departure_timeout: 60          # 所有参与者离开后保持房间的时间(秒)
  max_participants: 20           # 每个房间最大参与者数(0 = 无限制)
  enable_remote_unmute: true     # 允许服务端对参与者解除静音

livekit.yaml 中的 keys 必须与服务器 config.yaml 中的 livekit.apiKeylivekit.apiSecret 匹配。

RTC 端口范围

LiveKit 使用 UDP 端口传输媒体流。默认范围 50000-60000 适用于大多数场景。如果在防火墙后运行,请确保这些端口已开放。

架构和故障排除请参阅 WebRTC 连接性

TURN 服务器

嵌入式 TURN 服务器为受限制的 NAT 或企业防火墙后的客户端中继媒体。默认在端口 3478(UDP)和 5349(TLS)上启用。

TURN 是最后的备选中继 - 大多数客户端(约 80%)通过 UDP 直连,不会使用它。当 TURN 激活时,服务器承载所有中继媒体带宽。

TLS 要求: TURN/TLS(端口 5349)需要有效的 TLS 证书。生产环境中请设置 turn.tls_port: 443,将 cert_file/key_file 指向你的证书,或在前方放置 Layer 4 负载均衡器并设置 external_tls: true

架构、配置详情、带宽计算和故障排除请参阅 TURN 服务器指南

Webhook(断线检测)

Bedrud receives webhook events from LiveKit to detect when participants disconnect unexpectedly (e.g., browser crash, network drop) and mark them as inactive in the database.

Endpoint: POST /api/livekit/webhook

Authentication: Uses LiveKit JWT signing with the same apiKey/apiSecret. No separate secret needed.

Embedded LiveKit: When Bedrud manages its own LiveKit server (default), the webhook URL is auto-configured in the generated LiveKit YAML. No user action needed.

External LiveKit (Cloud or self-hosted with external: true): Manually configure the webhook URL in your LiveKit dashboard:

https://<your-domain>/api/livekit/webhook

Events handled:

EventAction
participant_disconnectedMarks participant as inactive in room_participants
room_finishedMarks all participants + room as inactive

If apiKey is left empty in config, a random keypair is generated at startup. The embedded LiveKit server and webhook handler both use the same generated key — no manual configuration needed.

房间设置

room: 部分控制会议房间行为:

  • auto_create - 参与者加入时自动创建房间(默认:true
  • empty_timeout - 从未有人加入的房间被删除前的秒数(默认:60
  • departure_timeout - 所有参与者离开后保持房间活跃的秒数(默认:60
  • max_participants - 每个房间最大参与者数。设为 0 表示无限制(默认:20
  • enable_remote_unmute - 允许服务端对参与者取消静音(默认:true

容量调优建议:

  • 小型团队会议:max_participants: 10-20
  • 大型网络研讨会:max_participants: 100(或 0 表示无限制)
  • 资源受限的服务器:降低 max_participants 以减少 CPU/内存使用

环境变量

配置值可以通过环境变量覆盖。命名遵循按节前缀的约定:

Docker 部署请参阅 Docker 指南

export SERVER_PORT=8090
export DB_PATH=/var/lib/bedrud/bedrud.db
export JWT_SECRET=production-secret
export LIVEKIT_HOST=http://localhost:8090/livekit
export LIVEKIT_API_KEY=prodkey
export LIVEKIT_API_SECRET=prodsecret

环境变量完整参考

环境变量YAML 路径说明
SERVER_PORTserver.portHTTP 监听端口
SERVER_ENABLE_TLSserver.enableTLS启用 HTTPS(true/false
SERVER_CERT_FILEserver.certFileTLS 证书路径
SERVER_KEY_FILEserver.keyFileTLS 私钥路径
SERVER_DOMAINserver.domain域名
SERVER_EMAILserver.email用于 Let’s Encrypt 的邮箱
SERVER_USE_ACMEserver.useACME启用自动 Let’s Encrypt(true/false
SERVER_TRUSTED_PROXIESserver.trustedProxies逗号分隔的可信代理 IP
SERVER_PROXY_HEADERserver.proxyHeader读取客户端 IP 的头(如 X-Forwarded-For
DB_HOSTdatabase.host数据库主机(PostgreSQL)
DB_PORTdatabase.port数据库端口
DB_USERdatabase.user数据库用户
DB_PASSWORDdatabase.password数据库密码
DB_NAMEdatabase.dbname数据库名称
DB_TYPEdatabase.typesqlitepostgres
DB_PATHdatabase.pathSQLite 文件路径或 PostgreSQL 连接字符串
LIVEKIT_HOSTlivekit.host外部 LiveKit URL
LIVEKIT_INTERNAL_HOSTlivekit.internalHost内部 LiveKit URL
LIVEKIT_API_KEYlivekit.apiKeyLiveKit API key (auto-generated as gen-<32hex> if empty)
LIVEKIT_API_SECRETlivekit.apiSecretLiveKit API secret (64-char hex auto-generated if empty)
JWT_SECRETauth.jwtSecret签名 JWT token 的密钥
AUTH_FRONTEND_URLauth.frontendURLOAuth 重定向的前端 URL
AUTH_PASSKEY_CHALLENGE_TTLauth.passkeyChallengeTTLPasskey 挑战过期时间(分钟)
CORS_ALLOWED_ORIGINScors.allowedOrigins逗号分隔的允许来源
CORS_ALLOWED_HEADERScors.allowedHeaders允许的请求头
CORS_ALLOWED_METHODScors.allowedMethods允许的 HTTP 方法
CORS_ALLOW_CREDENTIALScors.allowCredentials允许凭证(true/false
CORS_EXPOSE_HEADERScors.exposeHeaders暴露给浏览器的头
CORS_MAX_AGEcors.maxAge预检缓存时长(秒)
RATELIMIT_AUTH_MAXrateLimit.authMaxRequests每个窗口的最大认证请求数
RATELIMIT_AUTH_WINDOWrateLimit.authWindowSecs认证速率限制窗口(秒)
RATELIMIT_GUEST_MAXrateLimit.guestMaxRequests每个窗口的最大访客加入请求数
RATELIMIT_GUEST_WINDOWrateLimit.guestWindowSecs访客速率限制窗口(秒)
LIVEKIT_CONFIG_PATHlivekit.configPathPath to external LiveKit YAML config
LIVEKIT_NODE_IPlivekit.nodeIPExplicit node IP for embedded LiveKit RTC (disables STUN)
SERVER_CERT_ALGORITHMserver.certAlgorithmKey algorithm for cert generation: ed25519, ecdsa256, rsa2048, rsa4096
SERVER_MAX_PARTICIPANTS_LIMITserver.maxParticipantsLimitHard ceiling for room capacity (default 1000)
SERVER_MAX_ROOMS_PER_USERserver.maxRoomsPerUserMax active rooms per user (default 100, 0 = unlimited)
CHAT_MAX_UPLOAD_BYTES_PER_USERchat.maxUploadBytesPerUserPer-user upload quota in bytes (default 524288000, 0 = unlimited)
CHAT_GLOBAL_DISK_THRESHOLD_BYTESchat.globalDiskThresholdBytesGlobal upload storage ceiling in bytes (default 0 = unlimited)
CHAT_MAX_MESSAGE_COUNTchat.maxMessageCountMax chat messages kept per room (default 10000, 0 = unlimited)
CHAT_MESSAGE_TTL_HOURSchat.messageTTLHoursMax age of chat messages in hours (default 2160 = 90 days, 0 = forever)
QUEUE_POLL_INTERVALqueue.pollIntervalJob poll interval in ms (default 500)
QUEUE_MAX_ATTEMPTSqueue.maxAttemptsMax job retries before marking failed (default 3)
QUEUE_CONCURRENCYqueue.concurrencyWorker goroutine count (default 1)
EMAIL_SMTP_HOSTemail.smtpHostSMTP server hostname
EMAIL_SMTP_PORTemail.smtpPortSMTP server port (default 587)
EMAIL_USERNAMEemail.usernameSMTP username
EMAIL_PASSWORDemail.passwordSMTP password
EMAIL_FROM_ADDRESSemail.fromAddressFrom email address
EMAIL_FROM_NAMEemail.fromNameFrom display name (default “Bedrud”)
EMAIL_TLS_SKIP_VERIFYemail.tlsSkipVerifySkip TLS certificate validation for self-signed SMTP certs
EMAIL_SMTPS_MODEemail.smtpsModeEnable direct TLS (SMTPS) mode for port 465

生产环境检查清单

  • jwtSecretsessionSecret 更改为强随机值
  • logger.level 设为 infowarn
  • 配置 TLS(通过安装程序或反向代理)
  • cors.allowedOrigins 设为生产域名
  • 按需配置 OAuth 提供者
  • 在防火墙中开放 LiveKit RTC 端口范围
  • /var/log/bedrud/ 设置日志轮转

完整的生产环境配置请参阅部署指南