Bedrud Documentation

Bedrud utilise des fichiers de configuration YAML pour le serveur principal et le serveur média LiveKit intégré.

Voir aussi : Démarrage rapide | Installation | Guide de déploiement | Guide Docker

Configuration minimale de production

La configuration par défaut fonctionne pour le développement. Pour la production, modifiez ces valeurs dans /etc/bedrud/config.yaml :

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

Redémarrez après les modifications :

sudo systemctl restart bedrud livekit

Référence complète ci-dessous.


Configuration du serveur

Emplacement : server/config.yaml (développement) ou /etc/bedrud/config.yaml (production)

Référence complète

server:
  port: 8090                    # Port HTTP
  host: "localhost"             # Adresse de liaison
  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"                # Type de base de données : sqlite ou postgres
  path: "data.db"               # Chemin vers le fichier de base de données SQLite
 
logger:
  level: "debug"                # Niveau de log : debug, info, warn, error. Contrôle les logs applicatifs et les requêtes SQL.
  outputPath: ""                # Chemin vers le fichier de log (vide = stdout)
 
livekit:
  host: "http://localhost:8090/livekit"  # URL externe LiveKit
  internalHost: "http://127.0.0.1:7880"  # URL interne LiveKit
  apiKey: "devkey"              # Clé API LiveKit (auto-generated if empty)
  apiSecret: "devsecret"        # Secret API LiveKit
 
auth:
  jwtSecret: "your-jwt-secret"           # Secret pour signer les jetons JWT
  tokenDuration: 24                       # Expiration du jeton en heures
  sessionSecret: "your-session-secret"    # Secret pour les cookies de session
  frontendURL: "http://localhost:8090"    # URL du frontend (pour les redirections OAuth)
  passkeyChallengeTTL: 5                # Expiration du défi Passkey en minutes
 
  # Fournisseurs OAuth (optionnels)
  google:
    clientId: ""
    clientSecret: ""
  github:
    clientId: ""
    clientSecret: ""
  twitter:
    clientKey: ""
    clientSecret: ""
 
cors:
  allowedOrigins: "http://localhost:8090,http://localhost:3000"  # Séparé par des virgules
  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

Paramètres clés

Base de données

Par défaut, Bedrud utilise SQLite avec un fichier au chemin path configuré. Pour la production avec une concurrence plus élevée, passez à PostgreSQL en fournissant une chaîne de connexion à la place. Lors de l’utilisation de PostgreSQL, le champ path contient une chaîne de connexion, pas un chemin de fichier :

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

Authentification

Le jwtSecret est utilisé pour signer les jetons d’accès et de rafraîchissement. Modifiez-le depuis la valeur par défaut en production.

Les fournisseurs OAuth sont optionnels. Si vous ne les configurez pas, les boutons de connexion sociale n’apparaîtront pas dans l’interface. Chaque fournisseur nécessite l’enregistrement d’une application OAuth avec le service correspondant et la fourniture de l’ID client et du secret.

CORS

La chaîne allowedOrigins (séparée par des virgules) doit inclure l’URL où votre frontend est servi. En développement, c’est http://localhost:3000. En production, définissez-la sur votre domaine (ex. https://meet.example.com).

Limitation de débit

La limitation de débit protège les points d’accès d’authentification contre les attaques par force brute et les dénis de service. Deux catégories :

  • Points d’accès Auth (connexion, inscription, rafraîchissement, Passkey) — défaut : 10 requêtes par 60 secondes par IP
  • Invité — défaut : 5 requêtes par 60 secondes par IP

Omettez la section rateLimit pour conserver les valeurs par défaut. Définissez authMaxRequests: 0 ou guestMaxRequests: 0 pour désactiver.

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.

File d’attente (système de tâches)

La file d’attente interne des tâches traite les tâches asynchrones en arrière-plan comme la suppression d’utilisateurs/salles, la suspension et les téléchargements de chat.

  • pollInterval — fréquence à laquelle le worker vérifie les nouvelles tâches (en ms). Des valeurs plus faibles réduisent la latence au prix de davantage de requêtes à la base de données.
  • maxAttempts — nombre maximum de tentatives avant qu’une tâche soit marquée comme échouée. Les tentatives utilisent un backoff exponentiel (2^tentative * 5s, plafonné à 1h).
  • concurrency — nombre de goroutines workers. Augmentez pour un débit plus élevé avec PostgreSQL. SQLite est limité à un seul worker (une connexion).

Notifications par e-mail

Bedrud peut envoyer des e-mails transactionnels (bienvenue, réinitialisation de mot de passe, invitation à une salle) via SMTP.

  • smtpHost / smtpPort — adresse du serveur SMTP. Le port 587 (STARTTLS) est la valeur par défaut.
  • username / password — identifiants d’authentification SMTP.
  • fromAddress / fromName — identité de l’expéditeur pour les e-mails sortants.
  • tlsSkipVerify — ignorer la validation du certificat TLS (pour les certificats auto-signés).
  • smtpsMode — TLS direct (SMTPS, port 465).

Configuration LiveKit

Emplacement : server/config/livekit.yaml (développement) ou /etc/bedrud/livekit.yaml (production)

port: 7880                      # Port HTTP/WebSocket LiveKit
 
rtc:
  port_range_start: 50000       # Début de la plage de ports UDP
  port_range_end: 60000         # Fin de la plage de ports UDP
  use_external_ip: true         # Utiliser l'IP externe pour RTC
 
turn:
  enabled: true
  domain: "localhost"
  tls_port: 5349
  udp_port: 3478
 
keys:
  devkey: "devsecret"           # Doit correspondre à la configuration du serveur
 
logging:
  level: info
 
room:
  auto_create: true              # Créer automatiquement des salles lorsque les participants rejoignent
  empty_timeout: 60              # Secondes avant suppression d'une salle vide
  departure_timeout: 60          # Secondes pour garder la salle après le départ de tous les participants
  max_participants: 20           # Maximum de participants par salle (0 = illimité)
  enable_remote_unmute: true     # Permettre le démappareillage côté serveur des participants

Les keys dans livekit.yaml doivent correspondre à livekit.apiKey et livekit.apiSecret dans le config.yaml du serveur.

Plage de ports RTC

LiveKit utilise des ports UDP pour les flux média. La plage par défaut 50000-60000 fonctionne pour la plupart des configurations. Si vous êtes derrière un pare-feu, assurez-vous que ces ports sont ouverts.

Voir Connectivité WebRTC pour l’architecture et le dépannage.

Serveur TURN

Le serveur TURN intégré relaie les médias pour les clients derrière des NAT restrictifs ou des pare-feux d’entreprise. Il est activé par défaut sur les ports 3478 (UDP) et 5349 (TLS).

TURN est un relais de dernier recours - la plupart des clients (~80%) se connectent directement via UDP et ne l’utilisent jamais. Lorsque TURN s’active, le serveur transporte toute la bande passante média relayée.

Exigence TLS : TURN/TLS (port 5349) nécessite un certificat TLS valide. Pour la production, définissez turn.tls_port: 443 et pointez cert_file/key_file vers votre certificat, ou placez un équilibreur de charge de couche 4 devant avec external_tls: true.

Voir le Guide du serveur TURN pour l’architecture, les détails de configuration, les calculs de bande passante et le dépannage.

Webhook (détection de déconnexion)

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.

Paramètres de salle

La section room: contrôle le comportement des salles de réunion :

  • auto_create - Crée automatiquement des salles lorsque les participants rejoignent (par défaut : true)
  • empty_timeout - Secondes avant suppression d’une salle qui n’a jamais été rejointe (par défaut : 60)
  • departure_timeout - Secondes pour garder la salle active après le départ de tous les participants (par défaut : 60)
  • max_participants - Maximum de participants par salle. Définissez à 0 pour aucune limite (par défaut : 20)
  • enable_remote_unmute - Permettre le muet/démuet côté serveur des participants (par défaut : true)

Réglage pour la capacité :

  • Petites réunions d’équipe : max_participants: 10-20
  • Grands webinaires : max_participants: 100 (ou 0 pour illimité)
  • Serveurs à ressources limitées : Réduisez max_participants pour diminuer l’utilisation CPU/mémoire

Variables d’environnement

Les valeurs de configuration peuvent être remplacées par des variables d’environnement. La convention de nommage suit un préfixe par section :

Pour les déploiements Docker, voir le Guide 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

Référence complète des variables d’environnement

Var d’envChemin YAMLDescription
SERVER_PORTserver.portPort d’écoute HTTP
SERVER_ENABLE_TLSserver.enableTLSActiver HTTPS (true/false)
SERVER_CERT_FILEserver.certFileChemin vers le certificat TLS
SERVER_KEY_FILEserver.keyFileChemin vers la clé privée TLS
SERVER_DOMAINserver.domainNom de domaine
SERVER_EMAILserver.emailE-mail pour Let’s Encrypt
SERVER_USE_ACMEserver.useACMEActiver Let’s Encrypt automatique (true/false)
SERVER_TRUSTED_PROXIESserver.trustedProxiesIPs de proxy de confiance séparées par des virgules
SERVER_PROXY_HEADERserver.proxyHeaderEn-tête pour lire l’IP client (ex. X-Forwarded-For)
DB_HOSTdatabase.hostHôte de base de données (PostgreSQL)
DB_PORTdatabase.portPort de base de données
DB_USERdatabase.userUtilisateur de base de données
DB_PASSWORDdatabase.passwordMot de passe de base de données
DB_NAMEdatabase.dbnameNom de base de données
DB_TYPEdatabase.typesqlite ou postgres
DB_PATHdatabase.pathChemin de fichier SQLite ou chaîne de connexion PostgreSQL
LIVEKIT_HOSTlivekit.hostURL externe LiveKit
LIVEKIT_INTERNAL_HOSTlivekit.internalHostURL interne LiveKit
LIVEKIT_API_KEYlivekit.apiKeyClé API LiveKit (auto-generated as gen-<32hex> if empty)
LIVEKIT_API_SECRETlivekit.apiSecretSecret API LiveKit (64-char hex auto-generated if empty)
JWT_SECRETauth.jwtSecretSecret pour signer les jetons JWT
AUTH_FRONTEND_URLauth.frontendURLURL du frontend pour les redirections OAuth
AUTH_PASSKEY_CHALLENGE_TTLauth.passkeyChallengeTTLDélai d’expiration du défi Passkey en minutes
CORS_ALLOWED_ORIGINScors.allowedOriginsOrigines autorisées séparées par des virgules
CORS_ALLOWED_HEADERScors.allowedHeadersEn-têtes de requête autorisés
CORS_ALLOWED_METHODScors.allowedMethodsMéthodes HTTP autorisées
CORS_ALLOW_CREDENTIALScors.allowCredentialsAutoriser les identifiants (true/false)
CORS_EXPOSE_HEADERScors.exposeHeadersEn-têtes exposés au navigateur
CORS_MAX_AGEcors.maxAgeDurée du cache préflight en secondes
RATELIMIT_AUTH_MAXrateLimit.authMaxRequestsNombre max de requêtes d’auth par fenêtre
RATELIMIT_AUTH_WINDOWrateLimit.authWindowSecsFenêtre de limitation en secondes
RATELIMIT_GUEST_MAXrateLimit.guestMaxRequestsNombre max de requêtes invité par fenêtre
RATELIMIT_GUEST_WINDOWrateLimit.guestWindowSecsFenêtre de limitation invité en secondes
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

Liste de contrôle pour la production

  • Changer jwtSecret et sessionSecret par des valeurs aléatoires fortes
  • Définir logger.level à info ou warn
  • Configurer TLS (via l’installateur ou un reverse proxy)
  • Définir cors.allowedOrigins à votre domaine de production
  • Configurer les fournisseurs OAuth si nécessaire
  • Ouvrir la plage de ports RTC LiveKit dans votre pare-feu
  • Configurer la rotation des logs pour /var/log/bedrud/

Pour une configuration complète de production, voir le Guide de déploiement.