Michelle de68314e18
Build & Push Docker Image / build (push) Successful in 3m30s
Build & Push Docker Image / build (release) Successful in 3m36s
chore: bump version to 2.5.1 in package.json and package-lock.json
2026-08-23 17:04:26 +02:00
2026-06-21 22:16:42 +02:00
2026-06-21 22:16:42 +02:00
2026-02-24 18:14:16 +01:00

🔴 Redlight

⚠️ Warning: This project is entirely vibe coded and meant to be a fun/hobby project. Use at your own risk!

A modern, self-hosted BigBlueButton frontend with 25+ themes, federation, calendar, CalDAV, OAuth/OIDC, and powerful room management.

Node.js React License BigBlueButton

🖼️ Pictures

Click to expand screenshots

Home Dashboard Rooms

✨ Features

Core Features

  • 🎥 Video Conferencing - Integrated BigBlueButton support for professional video meetings
  • 🎨 25+ Themes - Dracula, Nord, Catppuccin, Rosé Pine, Gruvbox, Tokyo Night, Solarized, Everforest, Ayu, Kanagawa, Moonlight, Cyberpunk, Cotton Candy, and more
  • 📝 Room Management - Create unlimited rooms with custom settings, access codes, and moderator codes
  • 🔐 User Management - Registration, login, role-based access control (Admin/User)
  • 📹 Recording Management - View, publish, and delete meeting recordings per room
  • 📊 Learning Analytics - Collect and view per-room participant engagement data (talk time, messages, reactions) via BBB callbacks, secured with HMAC tokens
  • 📅 Calendar - Built-in calendar with event creation, sharing, customizable reminders, and room linking
  • 📆 CalDAV Server - Full CalDAV support for syncing calendars with Thunderbird, Apple Calendar, GNOME Calendar, DAVx⁵ (Android), and other standard clients
  • 🌍 Multi-Language Support - German (Deutsch) and English built-in, easily extensible
  • 🔔 In-App Notifications - Real-time notifications for room shares, federation invites, and calendar reminders
  • ✉️ Email Verification - Optional SMTP-based email verification for user registration
  • 🔑 OAuth / OIDC - Login via OpenID Connect providers (Keycloak, Authentik, etc.) with PKCE
  • 👤 User Profiles - Customizable display names, avatars, themes, and language preferences
  • 📱 Responsive Design - Works seamlessly on mobile, tablet, and desktop
  • 🌐 Federation - Invite users from remote Redlight instances via Ed25519-signed messages
  • 🐉 DragonflyDB / Redis - JWT blacklisting for secure token revocation on logout

Admin Features

  • 👥 User Administration - Manage users and roles
  • 🏢 Branding Customization - Custom app name, logos, and default theme
  • 📊 Dashboard - Overview of system statistics
  • 🔧 Settings Management - System-wide configuration
  • ✉️ Invite-Only Registration - Generate invite tokens for controlled user signup

Room Features

  • 🔑 Access Codes - Restrict room access with optional passwords
  • 🔐 Moderator Codes - Separate code to grant moderator privileges
  • 🚪 Guest Access - Allow unauthenticated users to join meetings (rate-limited)
  • ⏱️ Max Participants - Set limits on concurrent participants
  • 🎤 Mute on Join - Automatically mute new participants
  • ✅ Approval Mode - Require moderator approval for participants
  • 🎙️ Anyone Can Start - Allow participants to start the meeting
  • 📹 Recording Settings - Control whether meetings are recorded
  • 📊 Learning Analytics - Toggle per-room to collect participant engagement data after each meeting
  • 📑 Presentation Upload - Upload PDF, PPTX, ODP, DOC, DOCX as default slides
  • 🤝 Room Sharing - Share rooms with other registered users

Security

  • 🛡️ Comprehensive Rate Limiting - Login, register, profile, avatar, guest-join, OAuth, and federation endpoints
  • 🔒 Input Validation - Email format, field length limits, ID format checks, color format validation
  • 🕐 Timing-Safe Comparisons - Access codes and moderator codes compared with crypto.timingSafeEqual
  • 📏 Streaming Upload Limits - Avatar (5 MB) and presentation (50 MB) uploads reject early without buffering
  • 🧹 XSS Prevention - HTML-escaped emails, XML-escaped BBB parameters, SVG sanitization
  • 🔐 JWT Blacklist - Token revocation via DragonflyDB/Redis on logout
  • 🌐 CORS Restriction - Locked to APP_URL in production
  • ⚙️ Configurable Trust Proxy - TRUST_PROXY env var for reverse proxy setups
  • 🔏 HMAC-Secured Callbacks - Learning analytics callback URLs signed with HMAC-SHA256

Developer Features

  • 🐳 Docker Support - Easy deployment with Docker Compose (includes PostgreSQL + DragonflyDB)
  • 🗄️ Database Flexibility - SQLite (default) or PostgreSQL support
  • 🔌 REST API - Comprehensive API for custom integrations
  • 📦 Open Source - Full source code transparency
  • 🛠️ Self-Hosted - Complete data privacy and control

📊 Comparison: Redlight vs Greenlight

Feature Redlight Greenlight
Theme System 25+ customizable themes Limited theming
Learning Analytics ✅ Per-room engagement data ❌ Not supported
Calendar / CalDAV ✅ Built-in calendar + CalDAV sync ❌ Not supported
OAuth / OIDC ✅ OpenID Connect (PKCE) ✅ Supported
Federation ✅ Cross-instance invites ❌ Not supported
Notifications ✅ In-app + calendar reminders ❌ Not supported
Language Support Multi-language ready Multi-language ready
UI Framework React + Tailwind (Modern) Rails-based (Traditional)
User Preferences Theme, language, avatar, display name Limited customization
Database Options SQLite / PostgreSQL PostgreSQL only
Docker ✅ Supported ✅ Supported
Admin Dashboard Modern React UI Legacy Rails interface
Room Sharing ✅ Share rooms with users ✅ Supported
Recording Management Full control per room Standard management
Presentation Upload ✅ Supported ✅ Supported
API RESTful JSON API RESTful API
Setup Complexity Simple (5 min) Moderate (10-15 min)
Customization Easy (Tailwind CSS) Requires Ruby/Rails

🚀 Quick Start

Prerequisites

  • Docker & Docker Compose
  • BigBlueButton server (with API access)
  • SMTP server (optional, for email verification)

Installation

  1. Clone the repository

    git clone https://git.scrunkly.cat/Michelle/redlight
    cd redlight
    
  2. Configure environment

    cp .env.example .env
    

    Edit .env with your settings:

    BBB_URL=https://your-bbb-server.com/bigbluebutton/api/
    BBB_SECRET=your-bbb-shared-secret
    JWT_SECRET=your-secret-key          # REQUIRED - app won't start without this
    APP_URL=https://your-domain.com     # Used for CORS and email links
    DATABASE_URL=postgres://redlight:redlight@postgres:5432/redlight
    
    POSTGRES_USER=redlight
    POSTGRES_PASSWORD=redlight
    POSTGRES_DB=redlight
    
    # DragonflyDB / Redis (JWT blacklist for logout)
    REDIS_URL=redis://dragonfly:6379
    
    # Reverse proxy trust (default: loopback)
    # TRUST_PROXY=loopback
    
    # Optional: Email verification
    # SMTP_HOST=smtp.gmail.com
    # SMTP_PORT=587
    # SMTP_USER=your-email@gmail.com
    # SMTP_PASS=your-app-password
    
    # Optional: Federation (cross-instance room invites)
    # FEDERATION_DOMAIN=your-domain.com
    
    # Optional: OAuth / OIDC login
    # OAUTH_ISSUER=https://auth.your-domain.com/realms/your-realm
    # OAUTH_CLIENT_ID=redlight
    # OAUTH_CLIENT_SECRET=your-client-secret
    
  3. Start the application

    docker compose up -d
    
  4. Access the application

    • Open http://localhost:3001 in your browser
    • Default admin: admin@example.com / admin123
    • Change password immediately!

🛠️ Development

Local Setup

  1. Install dependencies

    npm install
    
  2. Start development server

    npm run dev
    
  3. Build for production

    npm run build
    npm run preview
    

Tech Stack

  • Frontend: React 18, Tailwind CSS, React Router, Lucide Icons
  • Backend: Node.js 20, Express, JWT, Bcrypt
  • Database: SQLite / PostgreSQL with better-sqlite3 / pg
  • Cache: DragonflyDB / Redis (ioredis) - JWT blacklisting
  • Email: Nodemailer
  • CalDAV: xml2js-based WebDAV/CalDAV server
  • Auth: JWT + OAuth/OIDC (PKCE)
  • Build: Vite

📁 Project Structure

redlight/
├── server/                 # Node.js/Express backend
│   ├── config/            # Database, Redis, mailer, BBB, federation, OAuth & notification config
│   ├── i18n/              # Server-side translations (email templates)
│   ├── jobs/              # Background jobs (federation sync, calendar reminders)
│   ├── middleware/        # JWT authentication, logging & token blacklisting
│   ├── routes/            # API endpoints (auth, rooms, recordings, admin, branding,
│   │                      #   federation, calendar, caldav, notifications, oauth, analytics)
│   └── index.js           # Server entry point
├── src/                   # React frontend
│   ├── components/        # Reusable components (RecordingList, AnalyticsList, etc.)
│   ├── contexts/          # React context (Auth, Language, Theme, Branding, Notification)
│   ├── i18n/              # Translations (DE, EN)
│   ├── pages/             # Page components
│   ├── services/          # API client
│   ├── themes/            # 25+ theme definitions
│   └── main.jsx           # Frontend entry point
├── public/                # Static assets
├── uploads/               # User avatars, branding & presentations (runtime)
├── keys/                  # Federation Ed25519 key pair (auto-generated)
├── compose.yml            # Docker Compose (Redlight + PostgreSQL + DragonflyDB)
├── Dockerfile             # Multi-stage container image
└── package.json           # Dependencies

🔐 Security

  • JWT Authentication - Secure token-based auth with 7-day expiration and jti-based blacklisting via DragonflyDB/Redis
  • Mandatory JWT Secret - Server refuses to start without a JWT_SECRET env var
  • OAuth / OIDC - OpenID Connect with PKCE (S256) and cryptographic state tokens
  • HTTPS Ready - Configure behind reverse proxy (nginx, Caddy); trust proxy via TRUST_PROXY env
  • Password Hashing - bcryptjs with salt rounds 12, minimum 8-character passwords
  • Email Verification - Optional SMTP-based email verification with resend support
  • CORS Protection - Restricted to APP_URL in production, open in development
  • Rate Limiting - Login, register, profile, password, avatar, guest-join, OAuth, and federation endpoints
  • Input Validation - Email regex, field length limits, ID format checks, hex-color format checks
  • Timing-Safe Comparisons - Access codes and moderator codes compared via crypto.timingSafeEqual
  • Upload Safety - Streaming body size limits (avatar 5 MB, presentation 50 MB) abort early without buffering
  • XSS / Injection Prevention - HTML-escaped emails, XML-escaped BBB API parameters, SVG logos served as attachment
  • HMAC-Secured Callbacks - Learning analytics callback URLs signed with HMAC-SHA256 derived from BBB_SECRET
  • Admin Isolation - Role-based access control with strict admin checks
  • Network Isolation - Docker Compose uses an internal backend network for DB and cache

📦 API Endpoints

Authentication

  • POST /api/auth/register - Register new user
  • POST /api/auth/login - Login user
  • POST /api/auth/logout - Logout (blacklists JWT)
  • GET /api/auth/verify-email?token=... - Verify email with token
  • POST /api/auth/resend-verification - Resend verification email
  • GET /api/auth/me - Get current user info
  • PUT /api/auth/profile - Update profile (theme, language, display name)
  • PUT /api/auth/password - Change password
  • POST /api/auth/avatar - Upload avatar image
  • DELETE /api/auth/avatar - Remove avatar image

Rooms

  • GET /api/rooms - List user's rooms (owned + shared)
  • POST /api/rooms - Create new room
  • GET /api/rooms/:uid - Get room details
  • PUT /api/rooms/:uid - Update room (incl. learning analytics toggle)
  • DELETE /api/rooms/:uid - Delete room
  • POST /api/rooms/:uid/start - Start meeting
  • POST /api/rooms/:uid/join - Join meeting as authenticated user
  • POST /api/rooms/:uid/guest-join - Join meeting as guest (rate-limited)
  • POST /api/rooms/:uid/end - End meeting
  • GET /api/rooms/:uid/status - Check if meeting is running
  • GET /api/rooms/:uid/shares - List shared users
  • POST /api/rooms/:uid/shares - Share room with user
  • DELETE /api/rooms/:uid/shares/:userId - Remove share
  • POST /api/rooms/:uid/presentation - Upload default presentation
  • DELETE /api/rooms/:uid/presentation - Remove presentation

Recordings

  • GET /api/recordings/room/:uid - List room recordings
  • PUT /api/recordings/:recordID/publish - Publish/unpublish recording
  • DELETE /api/recordings/:recordID - Delete recording

Learning Analytics

  • POST /api/analytics/callback/:uid?token=... - BBB callback (HMAC-secured)
  • GET /api/analytics/room/:uid - Get analytics for a room
  • DELETE /api/analytics/:id - Delete analytics entry

Calendar

  • GET /api/calendar - List calendar events
  • POST /api/calendar - Create event
  • PUT /api/calendar/:uid - Update event
  • DELETE /api/calendar/:uid - Delete event
  • GET /api/calendar/caldav-tokens - List CalDAV tokens
  • POST /api/calendar/caldav-tokens - Create CalDAV token
  • DELETE /api/calendar/caldav-tokens/:id - Delete CalDAV token

Notifications

  • GET /api/notifications - List notifications
  • PUT /api/notifications/:id/read - Mark as read
  • POST /api/notifications/read-all - Mark all as read
  • DELETE /api/notifications/:id - Delete notification

Admin

  • GET /api/admin/users - List all users
  • GET /api/admin/stats - System statistics
  • POST /api/admin/users - Create user (admin)
  • PUT /api/admin/users/:id - Update user
  • DELETE /api/admin/users/:id - Delete user

Branding

  • GET /api/branding - Get branding settings
  • PUT /api/branding - Update branding (admin only)
  • POST /api/branding/logo - Upload custom logo
  • DELETE /api/branding/logo - Remove custom logo

OAuth

  • GET /api/oauth/url - Get OAuth authorization URL
  • GET /api/oauth/callback - OAuth callback (PKCE exchange)

Federation

  • GET /.well-known/redlight - Instance discovery (domain, public key)
  • POST /api/federation/invite - Send invitation to remote user
  • POST /api/federation/receive - Receive invitation from remote instance (rate-limited)
  • GET /api/federation/invitations - List received invitations
  • PUT /api/federation/invitations/:id - Accept / decline invitation
  • DELETE /api/federation/invitations/:id - Delete invitation

CalDAV

  • PROPFIND /caldav/ - CalDAV discovery
  • REPORT /caldav/:user/calendar/ - Calendar query
  • GET/PUT/DELETE /caldav/:user/calendar/:uid.ics - Event CRUD

🌍 Internationalization (i18n)

Redlight comes with built-in support for multiple languages. Currently supported:

  • 🇩🇪 Deutsch (German)
  • 🇬🇧 English

Adding a new language

  1. Create src/i18n/xx.json (e.g., fr.json for French)
  2. Copy structure from de.json or en.json
  3. Translate all strings
  4. Update src/i18n/index.js to include the new language

🎨 Themes

Redlight includes 25+ themes:

  • ☀️ Light / 🌙 Dark (default)
  • 🐱 Catppuccin Mocha / Latte
  • 🧛 Dracula
  • ❄️ Nord
  • 🌊 Tokyo Night
  • 💜 One Dark
  • 🐙 GitHub Dark
  • 🌹 Rosé Pine / Rosé Pine Dawn
  • 🍂 Gruvbox Dark / Gruvbox Light
  • ☀️ Solarized Dark / Solarized Light
  • 🌲 Everforest Dark / Everforest Light
  • 🌊 Kanagawa
  • 🌙 Moonlight
  • 🎮 Cyberpunk
  • 🌸 Ayu Dark
  • 🔴 Red Modular Light
  • 🍬 Cotton Candy Light
  • 🐱 scrunkly.cat Dark

Themes are fully customizable by editing src/themes/index.js.


🐳 Docker Deployment

docker compose up -d

Services:

  • redlight - Node.js application (port 3001)
  • postgres - PostgreSQL 17 database
  • dragonfly - DragonflyDB (Redis-compatible) for JWT blacklisting

The compose.yml uses isolated networks: frontend (public) and backend (internal, no external access). Data is persisted via named volumes (pgdata, uploads, dragonflydata). Federation keys are mounted from ./keys.

Environment Variables

Variable Required Default Description
BBB_URL Yes - BigBlueButton API URL
BBB_SECRET Yes - BigBlueButton shared secret
JWT_SECRET Yes - Secret for signing JWTs (server won't start without it)
APP_URL Recommended - Public URL of the app (used for CORS + email links)
DATABASE_URL No SQLite PostgreSQL connection string
REDIS_URL No redis://localhost:6379 DragonflyDB / Redis URL
TRUST_PROXY No loopback Express trust proxy setting (number or string)
SMTP_HOST No - SMTP server for email verification
SMTP_PORT No 587 SMTP port
SMTP_USER No - SMTP username
SMTP_PASS No - SMTP password
FEDERATION_DOMAIN No - Domain for federation (enables cross-instance invites)
OAUTH_ISSUER No - OIDC issuer URL (enables OAuth login)
OAUTH_CLIENT_ID No - OIDC client ID
OAUTH_CLIENT_SECRET No - OIDC client secret
ADMIN_EMAIL No admin@example.com Default admin email (first start only)
ADMIN_PASSWORD No admin123 Default admin password (first start only)

Production Deployment

Behind a reverse proxy (nginx example):

upstream redlight {
  server localhost:3001;
}

server {
  listen 443 ssl http2;
  server_name your-domain.com;
  
  ssl_certificate /path/to/cert.pem;
  ssl_certificate_key /path/to/key.pem;
  
  client_max_body_size 5M;

  location / {
    proxy_pass http://redlight;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection upgrade;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Note: When running behind a reverse proxy, set TRUST_PROXY=1 (or the appropriate value) in .env so Express reads the correct client IP for rate limiting.


🌐 Federation

Federation allows users on different Redlight instances to invite each other into rooms.

Setup

  1. Set FEDERATION_DOMAIN=your-domain.com in .env.
  2. On first start, an Ed25519 key pair is generated automatically and stored in keys/federation_key.pem.
  3. In Docker, mount ./keys:/app/keys (already configured in compose.yml).
  4. Other instances discover your public key via GET /.well-known/redlight.

How it works

  1. User A on instance-a.com sends an invite to userB@instance-b.com.
  2. Redlight looks up instance-b.com/.well-known/redlight to discover the federation API.
  3. The invite payload is signed with instance A's private key and POSTed to instance B's /api/federation/receive.
  4. Instance B verifies the Ed25519 signature against instance A's public key.
  5. User B sees the invitation and can accept or decline. Accepting provides a join link to the remote room.

🐛 Troubleshooting

Issue: "ERR_ERL_PERMISSIVE_TRUST_PROXY"

Solution: Set TRUST_PROXY in .env. Use loopback (default) or 1 when behind a single reverse proxy.

Issue: "JWT_SECRET is not set"

Solution: The server requires a JWT_SECRET environment variable and will refuse to start without one. Add it to your .env file.

Issue: "Email verification not working"

Solution: Ensure SMTP is configured in .env. If SMTP_HOST is not set, email verification is disabled.

Issue: "BigBlueButton API error"

Solution: Verify BBB_URL and BBB_SECRET are correct. Test the connection with:

curl "https://your-bbb-server/bigbluebutton/api/getMeetings?checksum=..."

Issue: "Database connection failed"

Solution: Check DATABASE_URL format. For PostgreSQL: postgres://user:password@host:5432/redlight

Issue: "Theme not applying"

Solution: Clear browser cache (Ctrl+Shift+Del) or restart dev server with npm run dev.

Issue: "DragonflyDB connection error"

Solution: Ensure DragonflyDB (or Redis) is running and REDIS_URL is correct. If unavailable, the app still works - JWT blacklisting degrades gracefully (logout won't revoke tokens immediately).


📝 License

This project is licensed under the GNU GPL v3 (or later) - see LICENSE file for details.


🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open a Pull Request
2.5.1
Latest
2026-08-23 17:04:33 +02:00
Languages
JavaScript 96%
CSS 3.7%
Dockerfile 0.2%