Files
redlight/README.md
Michelle 2831f80ab4
All checks were successful
Build & Push Docker Image / build (push) Successful in 6m24s
Update README.md to reflect new features, security enhancements, and environment variable requirements
2026-02-28 20:11:14 +01:00

435 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🔴 Redlight
A modern, self-hosted BigBlueButton frontend with beautiful themes, federation, and powerful features.
![Node.js](https://img.shields.io/badge/Node.js-20+-green)
![React](https://img.shields.io/badge/React-18+-blue)
![License](https://img.shields.io/badge/License-MIT-yellow)
![BigBlueButton](https://img.shields.io/badge/BigBlueButton-Compatible-red)
## ✨ Features
### Core Features
- 🎥 **Video Conferencing** Integrated BigBlueButton support for professional video meetings
- 🎨 **15+ Themes** Dracula, Nord, Catppuccin, Rosé Pine, Gruvbox, and more (extensible via volume mount)
- 📝 **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
- 🌍 **Multi-Language Support** German (Deutsch) and English built-in, easily extensible
- ✉️ **Email Verification** Optional SMTP-based email verification for user registration
- 👤 **User Profiles** Customizable avatars, themes, and language preferences
- 📱 **Responsive Design** Works seamlessly on mobile, tablet, and desktop
- 🌐 **Federation** Invite users from remote Redlight instances via RSA-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
### 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
- 📊 **Presentation Upload** Upload PDF, PPTX, ODP, or image files as default slides
- 🤝 **Room Sharing** Share rooms with other registered users
### Security
- 🛡️ **Comprehensive Rate Limiting** Login, register, profile, avatar, guest-join, and federation endpoints
- 🔒 **Input Validation** Email format, field length limits, theme/language allowlists, 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
### 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** | 15+ customizable themes | Limited theming |
| **Federation** | ✅ Cross-instance invites | ❌ Not supported |
| **Language Support** | Multi-language ready | Multi-language ready |
| **UI Framework** | React + Tailwind (Modern) | Rails-based (Traditional) |
| **User Preferences** | Theme, language, avatar | 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 |
| **API** | RESTful JSON API | RESTful API |
| **Setup Complexity** | Simple (5 min) | Moderate (10-15 min) |
| **Customization** | Easy (Tailwind CSS) | Requires Ruby/Rails |
| **Community** | doesn't exist lol | Established |
---
## 🚀 Quick Start
### Prerequisites
- Docker & Docker Compose
- BigBlueButton server (with API access)
- SMTP server (optional, for email verification)
### Installation
1. **Clone the repository**
```bash
git clone https://git.scrunkly.cat/Michelle/redlight
cd redlight
```
2. **Configure environment**
```bash
cp .env.example .env
```
Edit `.env` with your settings:
```env
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://user:password@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
```
3. **Start the application**
```bash
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**
```bash
npm install
```
2. **Start development server**
```bash
npm run dev
```
- Frontend: http://localhost:5173
- Backend: http://localhost:3001
3. **Build for production**
```bash
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
- **Build**: Vite
---
## 📁 Project Structure
```
redlight/
├── server/ # Node.js/Express backend
│ ├── config/ # Database, Redis, mailer, BBB & federation config
│ ├── middleware/ # JWT authentication & token blacklisting
│ ├── routes/ # API endpoints (auth, rooms, recordings, admin, branding, federation)
│ └── index.js # Server entry point
├── src/ # React frontend
│ ├── components/ # Reusable components
│ ├── contexts/ # React context (Auth, Language, Theme, Branding)
│ ├── i18n/ # Translations (DE, EN)
│ ├── pages/ # Page components
│ ├── services/ # API client
│ ├── themes/ # Tailwind theme config (volume-mountable)
│ └── main.jsx # Frontend entry point
├── public/ # Static assets
├── uploads/ # User avatars, branding & presentations (runtime)
├── 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
- **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, and federation endpoints
- **Input Validation** Email regex, field length limits, theme/language allowlists, 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`
- **Admin Isolation** Role-based access control with strict admin checks
---
## 📦 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
- `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/running` 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 (PDF, PPTX, ODP, images)
- `DELETE /api/rooms/:uid/presentation` Remove presentation
### Recordings
- `GET /api/recordings/:roomUid` List room recordings
- `PUT /api/recordings/:recordingId` Publish/unpublish recording
- `DELETE /api/recordings/:recordingId` Delete recording
### 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
### 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
---
## 🌍 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 the following themes:
- 🌙 Dracula
- ❄️ Nord
- 🐱 Catppuccin
- 🌹 Rosé Pine
- 🍂 Gruvbox (Dark, Light)
- 💜 One Dark
- 🌊 Tokyo Night
- And more...
Themes are fully customizable by editing `src/themes/index.js`.
---
## 🐳 Docker Deployment
### Using Docker Compose (Recommended)
```bash
docker-compose up -d
```
Services:
- **redlight** Node.js application
- **postgres** PostgreSQL database
- **dragonfly** DragonflyDB (Redis-compatible) for JWT blacklisting
### 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) |
### Production Deployment
Behind a reverse proxy (nginx example):
```nginx
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 RSA 2048-bit key pair is generated automatically and stored in `server/config/federation_key.pem`.
3. 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 RSA 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:
```bash
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 MIT License see [LICENSE](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