Files
reflector/docs/video-jitsi.md
Mathieu Virbel d861d92cc2 docs: add comprehensive Jitsi Meet integration user guide
- Complete end-user configuration guide for self-hosted Jitsi Meet
- Covers installation, JWT authentication, and Prosody configuration
- Webhook event handling with mod_event_sync setup
- Jibri recording service configuration and finalize script
- Room creation, JWT token management, and security best practices
- Comprehensive troubleshooting with debug commands and solutions
- Performance optimization and scaling considerations
- Migration guidance from Whereby platform

🤖 Generated with Claude Code
2025-09-02 17:07:09 -06:00

14 KiB

Jitsi Meet Integration Configuration Guide

This guide explains how to configure Reflector to use your self-hosted Jitsi Meet installation for video meetings, recording, and participant tracking.

Overview

Jitsi Meet is an open-source video conferencing platform that can be self-hosted. Reflector integrates with Jitsi Meet to:

  • Create secure meeting rooms with JWT authentication
  • Track participant join/leave events via Prosody webhooks
  • Record meetings using Jibri recording service
  • Process recordings for transcription and analysis

Requirements

Self-Hosted Jitsi Meet

You need a complete Jitsi Meet installation including:

  1. Jitsi Meet Web Interface - The main meeting interface
  2. Prosody XMPP Server - Handles room management and authentication
  3. Jicofo (JItsi COnference FOcus) - Manages media sessions
  4. Jitsi Videobridge (JVB) - Handles WebRTC media routing
  5. Jibri Recording Service - Records meetings (optional but recommended)

System Requirements

  • Domain with SSL Certificate - Required for WebRTC functionality
  • Prosody mod_event_sync - For webhook event handling
  • JWT Authentication - For secure room access control
  • Storage Solution - For recording files (local or cloud)

Configuration Variables

Add the following environment variables to your Reflector .env file:

Required Variables

# Jitsi Meet Domain (without https://)
JITSI_DOMAIN=meet.example.com

# JWT Secret for room authentication (generate with: openssl rand -hex 32)
JITSI_JWT_SECRET=your-64-character-hex-secret-here

# Webhook secret for event handling (generate with: openssl rand -hex 16)
JITSI_WEBHOOK_SECRET=your-32-character-hex-secret-here

Optional Variables

# Application identifier (should match Jitsi configuration)
JITSI_APP_ID=reflector

# JWT issuer and audience (should match Jitsi configuration)
JITSI_JWT_ISSUER=reflector
JITSI_JWT_AUDIENCE=jitsi

Installation Steps

1. Jitsi Meet Server Installation

Quick Installation (Ubuntu/Debian)

# Add Jitsi repository
curl -fsSL https://download.jitsi.org/jitsi-key.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/jitsi-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/" | sudo tee /etc/apt/sources.list.d/jitsi-stable.list

# Install Jitsi Meet
sudo apt update
sudo apt install jitsi-meet

# Configure SSL certificate
sudo /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh

Docker Installation

# Clone Jitsi Docker repository
git clone https://github.com/jitsi/docker-jitsi-meet
cd docker-jitsi-meet

# Copy environment template
cp env.example .env

# Edit configuration
nano .env

# Start services
docker-compose up -d

2. JWT Authentication Setup

Update Prosody Configuration

Edit /etc/prosody/conf.d/your-domain.cfg.lua:

VirtualHost "meet.example.com"
    authentication = "token"
    app_id = "reflector"
    app_secret = "your-jwt-secret-here"

    -- Allow anonymous access for guests
    c2s_require_encryption = false
    admins = { "focusUser@auth.meet.example.com" }

    modules_enabled = {
        "bosh";
        "pubsub";
        "ping";
        "roster";
        "saslauth";
        "tls";
        "dialback";
        "disco";
        "carbons";
        "pep";
        "private";
        "blocklist";
        "vcard";
        "version";
        "uptime";
        "time";
        "ping";
        "register";
        "admin_adhoc";
        "token_verification";
        "event_sync";  -- Required for webhooks
    }

Configure Jitsi Meet Interface

Edit /etc/jitsi/meet/your-domain-config.js:

var config = {
    hosts: {
        domain: 'meet.example.com',
        muc: 'conference.meet.example.com'
    },

    // Enable JWT authentication
    enableUserRolesBasedOnToken: true,

    // Recording configuration
    fileRecordingsEnabled: true,
    liveStreamingEnabled: false,

    // Reflector integration settings
    prejoinPageEnabled: true,
    requireDisplayName: true
};

3. Webhook Event Configuration

Install Event Sync Module

# Download the module
cd /usr/share/jitsi-meet/prosody-plugins/
wget https://raw.githubusercontent.com/jitsi-contrib/prosody-plugins/main/mod_event_sync.lua

Configure Event Sync

Add to your Prosody configuration:

Component "conference.meet.example.com" "muc"
    storage = "memory"
    modules_enabled = {
        "muc_meeting_id";
        "muc_domain_mapper";
        "polls";
        "event_sync";  -- Enable event sync
    }

    -- Event sync webhook configuration
    event_sync_url = "https://your-reflector-domain.com/v1/jitsi/events"
    event_sync_secret = "your-webhook-secret-here"

    -- Events to track
    event_sync_events = {
        "muc-occupant-joined",
        "muc-occupant-left",
        "jibri-recording-on",
        "jibri-recording-off"
    }

4. Jibri Recording Setup (Optional)

Install Jibri

# Install Jibri package
sudo apt install jibri

# Create recording directory
sudo mkdir -p /var/recordings
sudo chown jibri:jibri /var/recordings

Configure Jibri

Edit /etc/jitsi/jibri/jibri.conf:

jibri {
    recording {
        recordings-directory = "/var/recordings"
        finalize-script = "/opt/jitsi/jibri/finalize.sh"
    }

    api {
        xmpp {
            environments = [{
                name = "prod environment"
                xmpp-server-hosts = ["meet.example.com"]
                xmpp-domain = "meet.example.com"

                control-muc {
                    domain = "internal.auth.meet.example.com"
                    room-name = "JibriBrewery"
                    nickname = "jibri-nickname"
                }

                control-login {
                    domain = "auth.meet.example.com"
                    username = "jibri"
                    password = "jibri-password"
                }
            }]
        }
    }
}

Create Finalize Script

Create /opt/jitsi/jibri/finalize.sh:

#!/bin/bash
# Jibri finalize script for Reflector integration

RECORDING_FILE="$1"
ROOM_NAME="$2"
REFLECTOR_API_URL="${REFLECTOR_API_URL:-http://localhost:1250}"

# Prepare webhook payload
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)
PAYLOAD=$(cat <<EOF
{
    "room_name": "$ROOM_NAME",
    "recording_file": "$RECORDING_FILE",
    "recording_status": "completed",
    "timestamp": "$TIMESTAMP"
}
EOF
)

# Generate signature
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$JITSI_WEBHOOK_SECRET" | cut -d' ' -f2)

# Send webhook to Reflector
curl -X POST "$REFLECTOR_API_URL/v1/jibri/recording-complete" \
    -H "Content-Type: application/json" \
    -H "X-Jitsi-Signature: $SIGNATURE" \
    -d "$PAYLOAD"

echo "Recording finalization webhook sent for room: $ROOM_NAME"

Make executable:

sudo chmod +x /opt/jitsi/jibri/finalize.sh

5. Restart Services

After configuration changes:

sudo systemctl restart prosody
sudo systemctl restart jicofo
sudo systemctl restart jitsi-videobridge2
sudo systemctl restart jibri
sudo systemctl restart nginx

Room Configuration

Creating Jitsi Rooms

Create rooms with Jitsi platform in Reflector:

curl -X POST "https://your-reflector-domain.com/v1/rooms" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -d '{
    "name": "my-jitsi-room",
    "platform": "jitsi",
    "recording_type": "cloud",
    "recording_trigger": "automatic-2nd-participant",
    "is_locked": false,
    "room_mode": "normal"
  }'

Meeting Creation

Meetings automatically use JWT authentication:

curl -X POST "https://your-reflector-domain.com/v1/rooms/my-jitsi-room/meeting" \
  -H "Authorization: Bearer $AUTH_TOKEN"

Response includes JWT-authenticated URLs:

{
  "id": "meeting-uuid",
  "room_name": "reflector-my-jitsi-room-123456",
  "room_url": "https://meet.example.com/room?jwt=user-token",
  "host_room_url": "https://meet.example.com/room?jwt=moderator-token"
}

Features and Capabilities

JWT Authentication

Reflector automatically generates JWT tokens with:

  • Room Access Control - Secure room entry
  • User Roles - Moderator vs participant permissions
  • Expiration - Configurable token lifetime (default 8 hours)
  • Custom Claims - Room-specific metadata

Recording Options

Recording Types:

  • "none" - No recording
  • "local" - Local Jibri recording
  • "cloud" - Cloud recording (requires external storage)

Recording Triggers:

  • "none" - Manual recording only
  • "prompt" - Prompt users to start
  • "automatic" - Start immediately
  • "automatic-2nd-participant" - Start when 2nd person joins

Event Tracking

Automatic participant tracking via webhooks:

  • Join/leave events update participant counts
  • Recording state changes trigger processing
  • Real-time meeting analytics

Testing and Verification

Health Check

Test Jitsi webhook integration:

curl "https://your-reflector-domain.com/v1/jitsi/health"

Expected response:

{
    "status": "ok",
    "service": "jitsi-webhooks",
    "timestamp": "2025-01-15T10:30:00.000Z",
    "webhook_secret_configured": true
}

JWT Token Testing

Verify JWT generation works:

# Create a test meeting
MEETING=$(curl -X POST "https://your-reflector-domain.com/v1/rooms/test-room/meeting" \
  -H "Authorization: Bearer $AUTH_TOKEN" | jq -r '.room_url')

echo "Test meeting URL: $MEETING"

Webhook Testing

Test event webhook manually:

curl -X POST "https://your-reflector-domain.com/v1/jitsi/events" \
  -H "Content-Type: application/json" \
  -H "X-Jitsi-Signature: test-signature" \
  -d '{
    "event": "muc-occupant-joined",
    "room": "test-room-name",
    "timestamp": "2025-01-15T10:30:00.000Z",
    "data": {}
  }'

Troubleshooting

Common Issues

JWT Authentication Failures

Symptoms: Users cannot join rooms, "Authentication failed" errors

Solutions:

  1. Verify JITSI_JWT_SECRET matches Prosody configuration
  2. Check JWT token hasn't expired (default 8 hours)
  3. Ensure system clocks are synchronized between servers
  4. Validate JWT issuer/audience configuration matches

Debug JWT tokens:

# Decode JWT payload
echo "JWT_TOKEN_HERE" | cut -d'.' -f2 | base64 -d | jq

Webhook Events Not Received

Symptoms: Participant counts not updating, no recording events

Solutions:

  1. Verify mod_event_sync is loaded in Prosody
  2. Check webhook URL is accessible from Jitsi server
  3. Validate webhook signature generation
  4. Review Prosody and Reflector logs

Debug webhook connectivity:

# Test from Jitsi server
curl -v "https://your-reflector-domain.com/v1/jitsi/health"

# Check Prosody logs
sudo tail -f /var/log/prosody/prosody.log

Recording Issues

Symptoms: Recordings not starting, finalize script errors

Solutions:

  1. Verify Jibri service status: sudo systemctl status jibri
  2. Check recording directory permissions: /var/recordings
  3. Validate finalize script execution permissions
  4. Monitor Jibri logs: sudo journalctl -u jibri -f

Test finalize script:

sudo -u jibri /opt/jitsi/jibri/finalize.sh "/test/recording.mp4" "test-room"

Meeting Creation Failures

Symptoms: HTTP 500 errors when creating meetings

Solutions:

  1. Check Reflector logs for JWT generation errors
  2. Verify all required environment variables are set
  3. Ensure Jitsi domain is accessible from Reflector
  4. Test JWT secret configuration

Debug Commands

# Verify Prosody configuration
sudo prosodyctl check config

# Check Jitsi services status
sudo systemctl status prosody jicofo jitsi-videobridge2

# Test JWT generation
curl -X POST "https://your-reflector-domain.com/v1/rooms/test/meeting" \
  -H "Authorization: Bearer $TOKEN" -v

# Monitor webhook events
sudo tail -f /var/log/reflector/app.log | grep jitsi

# Check SSL certificates
sudo certbot certificates

Performance Optimization

Scaling Considerations

Single Server Limits:

  • ~50 concurrent participants per JVB instance
  • ~10 concurrent Jibri recordings
  • CPU and bandwidth become bottlenecks

Multi-Server Setup:

  • Multiple JVB instances for scaling
  • Dedicated Jibri recording servers
  • Load balancing for high availability

Resource Monitoring

# Monitor JVB performance
sudo systemctl status jitsi-videobridge2
sudo journalctl -u jitsi-videobridge2 -f

# Check Prosody connections
sudo prosodyctl mod_admin_telnet
> c2s:show()
> muc:rooms()

Security Best Practices

JWT Security

  • Use strong, unique secrets (32+ characters)
  • Rotate JWT secrets regularly
  • Implement proper token expiration
  • Never log or expose JWT tokens

Network Security

  • Use HTTPS/WSS for all communications
  • Implement proper firewall rules
  • Consider VPN for server-to-server communication
  • Monitor for unauthorized access attempts

Recording Security

  • Encrypt recordings at rest
  • Implement access controls for recording files
  • Regular security audits of file permissions
  • Comply with data protection regulations

Migration from Whereby

If migrating from Whereby to Jitsi:

  1. Parallel Setup - Configure Jitsi alongside existing Whereby
  2. Room Migration - Update room platform field to "jitsi"
  3. Test Integration - Verify meeting creation and webhooks
  4. User Training - Different UI and feature set
  5. Monitor Performance - Watch for issues during transition
  6. Cleanup - Remove Whereby configuration when stable

Support and Resources

Jitsi Community Resources

Professional Support

  • 8x8 Commercial Support - Professional Jitsi hosting and support
  • Community Consulting - Third-party Jitsi implementation services

Monitoring and Maintenance

  • Monitor system resources (CPU, memory, bandwidth)
  • Regular security updates for all components
  • Backup configuration files and certificates
  • Test disaster recovery procedures