Some checks failed
Build & Push Docker Image / build (push) Has been cancelled
- Updated import statements to remove invisible characters. - Standardized comments to use a consistent hyphen format. - Adjusted username validation error messages for consistency. - Enhanced email sending functions to include language support. - Added email internationalization configuration for dynamic translations. - Updated calendar and federation routes to include language in user queries. - Improved user feedback messages in German and English for clarity.
435 lines
16 KiB
Markdown
435 lines
16 KiB
Markdown
# 🔴 Redlight
|
|
|
|
A modern, self-hosted BigBlueButton frontend with beautiful themes, federation, and powerful features.
|
|
|
|

|
|

|
|

|
|

|
|
|
|
## ✨ Features
|
|
|
|
### Core Features
|
|
- 🎥 **Video Conferencing** - Integrated BigBlueButton support for professional video meetings
|
|
- 🎨 **15+ Themes** - Dracula, Nord, Catppuccin, Rosé Pine, Gruvbox, 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
|
|
- 🌍 **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 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
|
|
|
|
### 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, 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
|
|
|
|
### 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
|
|
│ └── 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, 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`
|
|
- **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 Ed25519 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 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:
|
|
```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
|