Bedrud Documentación

Bedrud utiliza archivos de configuración YAML tanto para el servidor principal como para el servidor de medios LiveKit integrado.

Ver también: Inicio Rápido | Instalación | Guía de Implementación | Guía de Docker

Configuración Mínima de Producción

La configuración predeterminada funciona para desarrollo. Para producción, cambia estos valores en /etc/bedrud/config.yaml:

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

Reinicia después de los cambios:

sudo systemctl restart bedrud livekit

Referencia completa a continuación.


Configuración del Servidor

Ubicación: server/config.yaml (desarrollo) o /etc/bedrud/config.yaml (producción)

Referencia Completa

server:
  port: 8090                    # Puerto HTTP
  host: "localhost"             # Dirección de enlace
  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"                # Tipo de base de datos: sqlite o postgres
  path: "data.db"               # Ruta al archivo de base de datos SQLite
 
logger:
  level: "debug"                # Nivel de registro: debug, info, warn, error. Controla los registros de la app y las consultas SQL.
  outputPath: ""                # Ruta al archivo de registro (vacío = stdout)
 
livekit:
  host: "http://localhost:8090/livekit"  # URL externa de LiveKit
  internalHost: "http://127.0.0.1:7880"  # URL interna de LiveKit
  apiKey: "devkey"              # API key de LiveKit (auto-generated if empty)
  apiSecret: "devsecret"        # API secret de LiveKit
 
auth:
  jwtSecret: "your-jwt-secret"           # Secreto para firmar tokens JWT
  tokenDuration: 24                       # Expiración del token en horas
  sessionSecret: "your-session-secret"    # Secreto para cookies de sesión
  frontendURL: "http://localhost:8090"    # URL del frontend (para redirecciones OAuth)
  passkeyChallengeTTL: 5                # Caducidad del desafío Passkey en minutos
 
  # Proveedores OAuth (opcional)
  google:
    clientId: ""
    clientSecret: ""
  github:
    clientId: ""
    clientSecret: ""
  twitter:
    clientKey: ""
    clientSecret: ""
 
cors:
  allowedOrigins: "http://localhost:8090,http://localhost:3000"  # Separados por comas
  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

Configuraciones Clave

Base de Datos

Por defecto, Bedrud utiliza SQLite con un archivo en la path configurada. Para producción con mayor concurrencia, cambia a PostgreSQL proporcionando una cadena de conexión. Al usar PostgreSQL, el campo path contiene una cadena de conexión, no una ruta de archivo:

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

Autenticación

El jwtSecret se usa para firmar tokens de acceso y de actualización. Cámbialo del valor predeterminado en producción.

Los proveedores OAuth son opcionales. Si no los configuras, los botones de inicio de sesión social no aparecerán en la interfaz. Cada proveedor requiere registrar una app OAuth con el servicio respectivo y proporcionar el client ID y el secret.

CORS

La cadena allowedOrigins (separada por comas) debe incluir la URL donde se sirve tu frontend. En desarrollo, es http://localhost:3000. En producción, establécela a tu dominio (por ejemplo, https://meet.example.com).

Límite de velocidad

La limitación de velocidad protege los endpoints de autenticación contra ataques de fuerza bruta y DoS. Dos categorías:

  • Endpoints de autenticación (inicio de sesión, registro, renovación, Passkey) — predeterminado: 10 solicitudes por 60 segundos por IP
  • Invitado — predeterminado: 5 solicitudes por 60 segundos por IP

Omita la sección rateLimit para usar los valores predeterminados. Establezca authMaxRequests: 0 o guestMaxRequests: 0 para desactivar.

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.

Cola (sistema de tareas)

La cola interna de tareas procesa trabajos asíncronos en segundo plano como la eliminación de usuarios/salas, suspensión y cargas de chat.

  • pollInterval — frecuencia con la que el worker busca nuevas tareas (en ms). Valores más bajos reducen la latencia a costa de más consultas a la base de datos.
  • maxAttempts — número máximo de reintentos antes de marcar una tarea como fallida. Los reintentos usan backoff exponencial (2^intento * 5s, con un máximo de 1h).
  • concurrency — número de goroutines worker. Aumente para mayor rendimiento con PostgreSQL. SQLite está limitado a un solo worker (una conexión).

Notificaciones por correo electrónico

Bedrud puede enviar correos electrónicos transaccionales (bienvenida, restablecimiento de contraseña, invitación a sala) a través de SMTP.

  • smtpHost / smtpPort — dirección del servidor SMTP. El puerto 587 (STARTTLS) es el valor predeterminado.
  • username / password — credenciales de autenticación SMTP.
  • fromAddress / fromName — identidad del remitente para correos salientes.
  • tlsSkipVerify — omitir validación de certificado TLS (para certificados autofirmados).
  • smtpsMode — TLS directo (SMTPS, puerto 465).

Configuración de LiveKit

Ubicación: server/config/livekit.yaml (desarrollo) o /etc/bedrud/livekit.yaml (producción)

port: 7880                      # Puerto HTTP/WebSocket de LiveKit
 
rtc:
  port_range_start: 50000       # Inicio del rango de puertos UDP
  port_range_end: 60000         # Fin del rango de puertos UDP
  use_external_ip: true         # Usar IP externa para RTC
 
turn:
  enabled: true
  domain: "localhost"
  tls_port: 5349
  udp_port: 3478
 
keys:
  devkey: "devsecret"           # Debe coincidir con la configuración del servidor
 
logging:
  level: info
 
room:
  auto_create: true              # Crear salas automáticamente cuando los participantes se unen
  empty_timeout: 60              # Segundos antes de eliminar una sala vacía
  departure_timeout: 60          # Segundos para mantener la sala después de que todos los participantes salgan
  max_participants: 20           # Máximo de participantes por sala (0 = ilimitado)
  enable_remote_unmute: true     # Permitir silenciar/desilenciar participantes desde el servidor

Las keys en livekit.yaml deben coincidir con livekit.apiKey y livekit.apiSecret en el config.yaml del servidor.

Rango de Puertos RTC

LiveKit utiliza puertos UDP para los flujos de medios. El rango predeterminado 50000-60000 funciona para la mayoría de configuraciones. Si está detrás de un firewall, asegúrate de que estos puertos estén abiertos.

Consulta Conectividad WebRTC para la arquitectura y solución de problemas.

Servidor TURN

El servidor TURN integrado retransmite medios para clientes detrás de NAT restrictivos o firewalls corporativos. Está habilitado por defecto en los puertos 3478 (UDP) y 5349 (TLS).

TURN es un relay de último recurso: la mayoría de los clientes (~80%) se conectan directamente vía UDP y nunca lo usan. Cuando TURN se activa, el servidor soporta todo el ancho de banda de los medios retransmitidos.

Requisito de TLS: TURN/TLS (puerto 5349) necesita un certificado TLS válido. Para producción, establece turn.tls_port: 443 y apunta cert_file/key_file a tu certificado, o coloca un balanceador de carga de capa 4 delante con external_tls: true.

Consulta la Guía del Servidor TURN para arquitectura, detalles de configuración, cálculos de ancho de banda y solución de problemas.

Webhook (detección de desconexión)

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.

Configuración de Salas

La sección room: controla el comportamiento de las salas de reuniones:

  • auto_create - Crear salas automáticamente cuando los participantes se unen (predeterminado: true)
  • empty_timeout - Segundos antes de eliminar una sala que nunca fue ocupada (predeterminado: 60)
  • departure_timeout - Segundos para mantener la sala activa después de que todos los participantes salgan (predeterminado: 60)
  • max_participants - Máximo de participantes por sala. Establece a 0 para sin límite (predeterminado: 20)
  • enable_remote_unmute - Permitir silenciar/desilenciar participantes desde el servidor (predeterminado: true)

Ajuste para capacidad:

  • Reuniones de equipos pequeños: max_participants: 10-20
  • Webinars grandes: max_participants: 100 (o 0 para ilimitado)
  • Servidores con recursos limitados: Reduce max_participants para disminuir el uso de CPU/memoria

Variables de Entorno

Los valores de configuración se pueden sobreescribir con variables de entorno. La nomenclatura sigue una convención de prefijo por sección:

Para despliegues con Docker, consulta la Guía de 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

Referencia Completa de Variables de Entorno

Var de EntornoRuta YAMLDescripción
SERVER_PORTserver.portPuerto de escucha HTTP
SERVER_ENABLE_TLSserver.enableTLSHabilitar HTTPS (true/false)
SERVER_CERT_FILEserver.certFileRuta al certificado TLS
SERVER_KEY_FILEserver.keyFileRuta a la clave privada TLS
SERVER_DOMAINserver.domainNombre de dominio
SERVER_EMAILserver.emailCorreo electrónico para Let’s Encrypt
SERVER_USE_ACMEserver.useACMEHabilitar Let’s Encrypt automático (true/false)
SERVER_TRUSTED_PROXIESserver.trustedProxiesIPs de proxies de confianza separadas por comas
SERVER_PROXY_HEADERserver.proxyHeaderHeader para leer la IP del cliente (p. ej., X-Forwarded-For)
DB_HOSTdatabase.hostHost de la base de datos (PostgreSQL)
DB_PORTdatabase.portPuerto de la base de datos
DB_USERdatabase.userUsuario de la base de datos
DB_PASSWORDdatabase.passwordContraseña de la base de datos
DB_NAMEdatabase.dbnameNombre de la base de datos
DB_TYPEdatabase.typesqlite o postgres
DB_PATHdatabase.pathRuta al archivo SQLite o cadena de conexión PostgreSQL
LIVEKIT_HOSTlivekit.hostURL externa de LiveKit
LIVEKIT_INTERNAL_HOSTlivekit.internalHostURL interna de LiveKit
LIVEKIT_API_KEYlivekit.apiKeyAPI key de LiveKit (auto-generated as gen-<32hex> if empty)
LIVEKIT_API_SECRETlivekit.apiSecretAPI secret de LiveKit (64-char hex auto-generated if empty)
JWT_SECRETauth.jwtSecretSecreto para firmar tokens JWT
AUTH_FRONTEND_URLauth.frontendURLURL del frontend para redirecciones OAuth
AUTH_PASSKEY_CHALLENGE_TTLauth.passkeyChallengeTTLCaducidad del desafío Passkey en minutos
CORS_ALLOWED_ORIGINScors.allowedOriginsOrígenes permitidos separados por comas
CORS_ALLOWED_HEADERScors.allowedHeadersHeaders de solicitud permitidos
CORS_ALLOWED_METHODScors.allowedMethodsMétodos HTTP permitidos
CORS_ALLOW_CREDENTIALScors.allowCredentialsPermitir credenciales (true/false)
CORS_EXPOSE_HEADERScors.exposeHeadersHeaders expuestos al navegador
CORS_MAX_AGEcors.maxAgeDuración de caché preflight en segundos
RATELIMIT_AUTH_MAXrateLimit.authMaxRequestsMáx. solicitudes de autenticación por ventana
RATELIMIT_AUTH_WINDOWrateLimit.authWindowSecsVentana de límite de autenticación en segundos
RATELIMIT_GUEST_MAXrateLimit.guestMaxRequestsMáx. solicitudes de invitado por ventana
RATELIMIT_GUEST_WINDOWrateLimit.guestWindowSecsVentana de límite de invitado en segundos
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

Lista de Verificación de Producción

  • Cambiar jwtSecret y sessionSecret a valores aleatorios seguros
  • Establecer logger.level a info o warn
  • Configurar TLS (vía instalador o proxy inverso)
  • Establecer cors.allowedOrigins a tu dominio de producción
  • Configurar proveedores OAuth si es necesario
  • Abrir el rango de puertos RTC de LiveKit en tu firewall
  • Configurar rotación de registros para /var/log/bedrud/

Para la configuración completa de producción, consulta la Guía de Implementación.