New packages: - luci-app-webradio: Web radio management with Lyrion bridge tab - luci-app-turn: TURN/STUN server UI for WebRTC (Jitsi integration) - secubox-app-lyrion-bridge: Lyrion → Squeezelite → FFmpeg → Icecast pipeline - secubox-app-squeezelite: Squeezelite audio player with FIFO output - secubox-app-turn: TURN server with ACME SSL and Jitsi setup - secubox-app-webradio: Icecast/ezstream web radio server Features: - HTTPS streaming via HAProxy (stream.gk2.secubox.in) - Lyrion Music Server bridge for streaming playlists to Icecast - TURN server with time-limited credential generation - CrowdSec integration for WebRadio security - Schedule-based radio programming with jingles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
724 lines
18 KiB
Bash
724 lines
18 KiB
Bash
#!/bin/sh
|
|
# Jitsi Meet Control Script for SecuBox
|
|
# Manages Jitsi Meet Docker deployment
|
|
|
|
VERSION="1.0.0"
|
|
JITSI_DIR="/srv/jitsi"
|
|
CONFIG_DIR="$JITSI_DIR/.jitsi-meet-cfg"
|
|
TEMPLATE_DIR="/usr/share/jitsi"
|
|
ENV_FILE="$JITSI_DIR/.env"
|
|
COMPOSE_FILE="$JITSI_DIR/docker-compose.yml"
|
|
|
|
# Jitsi Docker image versions
|
|
JITSI_IMAGE_VERSION="stable-9location1"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${GREEN}[JITSI]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# ============================================================================
|
|
# Configuration Generation
|
|
# ============================================================================
|
|
|
|
generate_secret() {
|
|
openssl rand -hex 16 2>/dev/null || head -c 32 /dev/urandom | md5sum | cut -d' ' -f1
|
|
}
|
|
|
|
generate_config() {
|
|
log "Generating Jitsi configuration..."
|
|
|
|
mkdir -p "$JITSI_DIR"
|
|
mkdir -p "$CONFIG_DIR"/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}
|
|
|
|
# Read UCI configuration
|
|
local domain=$(uci -q get jitsi.main.domain || echo "meet.secubox.local")
|
|
local public_url=$(uci -q get jitsi.main.public_url)
|
|
[ -z "$public_url" ] && public_url="https://$domain"
|
|
local timezone=$(uci -q get jitsi.main.timezone || echo "UTC")
|
|
local letsencrypt=$(uci -q get jitsi.main.letsencrypt || echo "0")
|
|
local le_email=$(uci -q get jitsi.main.letsencrypt_email)
|
|
|
|
# Web config
|
|
local web_port=$(uci -q get jitsi.web.port || echo "8443")
|
|
local enable_guests=$(uci -q get jitsi.web.enable_guests || echo "1")
|
|
local enable_auth=$(uci -q get jitsi.web.enable_auth || echo "0")
|
|
local default_lang=$(uci -q get jitsi.web.default_language || echo "en")
|
|
|
|
# JVB config
|
|
local jvb_port=$(uci -q get jitsi.jvb.port || echo "10000")
|
|
local jvb_tcp=$(uci -q get jitsi.jvb.enable_tcp_fallback || echo "0")
|
|
local jvb_tcp_port=$(uci -q get jitsi.jvb.tcp_port || echo "4443")
|
|
local stun_servers=$(uci -q get jitsi.jvb.stun_servers || echo "meet-jit-si-turnrelay.jitsi.net:443")
|
|
|
|
# Security
|
|
local jwt_enabled=$(uci -q get jitsi.security.jwt_enabled || echo "0")
|
|
local jwt_app_id=$(uci -q get jitsi.security.jwt_app_id)
|
|
local jwt_secret=$(uci -q get jitsi.security.jwt_app_secret)
|
|
local lobby=$(uci -q get jitsi.security.lobby_enabled || echo "1")
|
|
|
|
# TURN
|
|
local turn_enabled=$(uci -q get jitsi.turn.enabled || echo "0")
|
|
local turn_server=$(uci -q get jitsi.turn.server)
|
|
local turn_user=$(uci -q get jitsi.turn.username)
|
|
local turn_pass=$(uci -q get jitsi.turn.password)
|
|
|
|
# Generate secrets if not already stored
|
|
local jicofo_secret=$(uci -q get jitsi.secrets.jicofo_component_secret)
|
|
local jicofo_auth_pass=$(uci -q get jitsi.secrets.jicofo_auth_password)
|
|
local jvb_auth_pass=$(uci -q get jitsi.secrets.jvb_auth_password)
|
|
|
|
if [ -z "$jicofo_secret" ]; then
|
|
jicofo_secret=$(generate_secret)
|
|
uci -q set jitsi.secrets=jitsi
|
|
uci -q set jitsi.secrets.jicofo_component_secret="$jicofo_secret"
|
|
fi
|
|
if [ -z "$jicofo_auth_pass" ]; then
|
|
jicofo_auth_pass=$(generate_secret)
|
|
uci -q set jitsi.secrets.jicofo_auth_password="$jicofo_auth_pass"
|
|
fi
|
|
if [ -z "$jvb_auth_pass" ]; then
|
|
jvb_auth_pass=$(generate_secret)
|
|
uci -q set jitsi.secrets.jvb_auth_password="$jvb_auth_pass"
|
|
uci commit jitsi
|
|
fi
|
|
|
|
# Determine auth type
|
|
local auth_type="internal"
|
|
[ "$enable_auth" = "1" ] && auth_type="internal_hashed"
|
|
[ "$jwt_enabled" = "1" ] && auth_type="jwt"
|
|
|
|
# Write .env file
|
|
cat > "$ENV_FILE" << EOF
|
|
# Jitsi Meet Configuration
|
|
# Generated by SecuBox jitsctl v$VERSION
|
|
# $(date)
|
|
|
|
# Core settings
|
|
CONFIG=$CONFIG_DIR
|
|
HTTP_PORT=8000
|
|
HTTPS_PORT=$web_port
|
|
TZ=$timezone
|
|
|
|
# Domain settings
|
|
PUBLIC_URL=$public_url
|
|
XMPP_DOMAIN=$domain
|
|
XMPP_SERVER=xmpp.$domain
|
|
JVB_BREWERY_MUC=jvbbrewery
|
|
XMPP_AUTH_DOMAIN=auth.$domain
|
|
XMPP_GUEST_DOMAIN=guest.$domain
|
|
XMPP_MUC_DOMAIN=muc.$domain
|
|
XMPP_INTERNAL_MUC_DOMAIN=internal-muc.$domain
|
|
XMPP_MODULES=
|
|
XMPP_MUC_MODULES=
|
|
XMPP_INTERNAL_MUC_MODULES=
|
|
|
|
# Authentication
|
|
ENABLE_AUTH=$enable_auth
|
|
ENABLE_GUESTS=$enable_guests
|
|
AUTH_TYPE=$auth_type
|
|
|
|
# JWT (if enabled)
|
|
EOF
|
|
|
|
if [ "$jwt_enabled" = "1" ]; then
|
|
cat >> "$ENV_FILE" << EOF
|
|
JWT_APP_ID=$jwt_app_id
|
|
JWT_APP_SECRET=$jwt_secret
|
|
JWT_ACCEPTED_ISSUERS=$jwt_app_id
|
|
JWT_ACCEPTED_AUDIENCES=$jwt_app_id
|
|
EOF
|
|
fi
|
|
|
|
cat >> "$ENV_FILE" << EOF
|
|
|
|
# XMPP secrets
|
|
JICOFO_COMPONENT_SECRET=$jicofo_secret
|
|
JICOFO_AUTH_USER=focus
|
|
JICOFO_AUTH_PASSWORD=$jicofo_auth_pass
|
|
JVB_AUTH_USER=jvb
|
|
JVB_AUTH_PASSWORD=$jvb_auth_pass
|
|
|
|
# JVB settings
|
|
JVB_PORT=$jvb_port
|
|
JVB_STUN_SERVERS=$stun_servers
|
|
JVB_TCP_HARVESTER_DISABLED=$([ "$jvb_tcp" = "1" ] && echo "false" || echo "true")
|
|
JVB_TCP_PORT=$jvb_tcp_port
|
|
|
|
# Features
|
|
ENABLE_LOBBY=$lobby
|
|
ENABLE_BREAKOUT_ROOMS=1
|
|
ENABLE_PREJOIN_PAGE=1
|
|
ENABLE_WELCOME_PAGE=1
|
|
ENABLE_CLOSE_PAGE=0
|
|
ENABLE_NOISY_MIC_DETECTION=1
|
|
ENABLE_TALK_WHILE_MUTED=1
|
|
ENABLE_REACTIONS=1
|
|
|
|
# UI settings
|
|
DEFAULT_LANGUAGE=$default_lang
|
|
DISABLE_AUDIO_LEVELS=0
|
|
DISABLE_POLLS=0
|
|
ENABLE_CALENDAR=0
|
|
EOF
|
|
|
|
# Add TURN config if enabled
|
|
if [ "$turn_enabled" = "1" ] && [ -n "$turn_server" ]; then
|
|
cat >> "$ENV_FILE" << EOF
|
|
|
|
# TURN server
|
|
TURN_CREDENTIALS=$turn_user
|
|
TURN_SECRET=$turn_pass
|
|
TURN_HOST=$turn_server
|
|
TURN_PORT=443
|
|
TURNS_HOST=$turn_server
|
|
TURNS_PORT=443
|
|
EOF
|
|
fi
|
|
|
|
# Add Let's Encrypt config
|
|
if [ "$letsencrypt" = "1" ] && [ -n "$le_email" ]; then
|
|
cat >> "$ENV_FILE" << EOF
|
|
|
|
# Let's Encrypt
|
|
ENABLE_LETSENCRYPT=1
|
|
LETSENCRYPT_DOMAIN=$domain
|
|
LETSENCRYPT_EMAIL=$le_email
|
|
LETSENCRYPT_USE_STAGING=0
|
|
EOF
|
|
fi
|
|
|
|
# Copy docker-compose.yml
|
|
cp "$TEMPLATE_DIR/docker-compose.yml" "$COMPOSE_FILE"
|
|
|
|
log "Configuration generated at $ENV_FILE"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Installation
|
|
# ============================================================================
|
|
|
|
install_jitsi() {
|
|
log "Installing Jitsi Meet..."
|
|
|
|
# Check Docker
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
error "Docker is required. Install with: opkg install docker docker-compose"
|
|
return 1
|
|
fi
|
|
|
|
# Create directories
|
|
mkdir -p "$JITSI_DIR"
|
|
mkdir -p "$CONFIG_DIR"
|
|
|
|
# Generate configuration
|
|
generate_config
|
|
|
|
# Pull images
|
|
log "Pulling Jitsi Docker images (this may take a while)..."
|
|
cd "$JITSI_DIR"
|
|
docker-compose pull
|
|
|
|
# Configure HAProxy if available
|
|
if [ -x /usr/sbin/haproxyctl ]; then
|
|
configure_haproxy
|
|
fi
|
|
|
|
# Configure firewall
|
|
configure_firewall
|
|
|
|
# Register with mesh
|
|
register_mesh_service
|
|
|
|
log "Jitsi Meet installed successfully!"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Set your domain: uci set jitsi.main.domain='meet.example.com'"
|
|
echo " 2. Commit changes: uci commit jitsi"
|
|
echo " 3. Regenerate: jitsctl generate-config"
|
|
echo " 4. Enable service: uci set jitsi.main.enabled=1 && uci commit jitsi"
|
|
echo " 5. Start: /etc/init.d/jitsi start"
|
|
echo ""
|
|
}
|
|
|
|
# ============================================================================
|
|
# HAProxy Integration
|
|
# ============================================================================
|
|
|
|
configure_haproxy() {
|
|
log "Configuring HAProxy for Jitsi..."
|
|
|
|
local domain=$(uci -q get jitsi.main.domain || echo "meet.secubox.local")
|
|
local web_port=$(uci -q get jitsi.web.port || echo "8443")
|
|
|
|
# Check if vhost already exists
|
|
local existing=$(uci show haproxy 2>/dev/null | grep "\.domain='$domain'" | head -1)
|
|
if [ -n "$existing" ]; then
|
|
warn "HAProxy vhost for $domain already exists"
|
|
return 0
|
|
fi
|
|
|
|
# Add backend
|
|
uci -q add haproxy backend
|
|
uci -q set haproxy.@backend[-1].name='jitsi_web'
|
|
uci -q set haproxy.@backend[-1].mode='http'
|
|
uci -q add_list haproxy.@backend[-1].server="jitsi 192.168.255.1:$web_port check"
|
|
|
|
# Add vhost
|
|
uci -q add haproxy vhost
|
|
uci -q set haproxy.@vhost[-1].enabled='1'
|
|
uci -q set haproxy.@vhost[-1].domain="$domain"
|
|
uci -q set haproxy.@vhost[-1].backend='jitsi_web'
|
|
uci -q set haproxy.@vhost[-1].ssl='1'
|
|
uci -q set haproxy.@vhost[-1].ssl_redirect='1'
|
|
uci -q set haproxy.@vhost[-1].websocket='1'
|
|
|
|
uci commit haproxy
|
|
|
|
# Reload HAProxy
|
|
/etc/init.d/haproxy reload 2>/dev/null
|
|
|
|
log "HAProxy configured for $domain"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Firewall
|
|
# ============================================================================
|
|
|
|
configure_firewall() {
|
|
log "Configuring firewall..."
|
|
|
|
local jvb_port=$(uci -q get jitsi.jvb.port || echo "10000")
|
|
local jvb_tcp_port=$(uci -q get jitsi.jvb.tcp_port || echo "4443")
|
|
|
|
# JVB UDP port (required for video)
|
|
if ! uci show firewall 2>/dev/null | grep -q "Jitsi-JVB"; then
|
|
uci add firewall rule
|
|
uci set firewall.@rule[-1].name='Jitsi-JVB'
|
|
uci set firewall.@rule[-1].src='wan'
|
|
uci set firewall.@rule[-1].dest_port="$jvb_port"
|
|
uci set firewall.@rule[-1].proto='udp'
|
|
uci set firewall.@rule[-1].target='ACCEPT'
|
|
uci set firewall.@rule[-1].enabled='1'
|
|
fi
|
|
|
|
# JVB TCP fallback port
|
|
local jvb_tcp=$(uci -q get jitsi.jvb.enable_tcp_fallback || echo "0")
|
|
if [ "$jvb_tcp" = "1" ]; then
|
|
if ! uci show firewall 2>/dev/null | grep -q "Jitsi-JVB-TCP"; then
|
|
uci add firewall rule
|
|
uci set firewall.@rule[-1].name='Jitsi-JVB-TCP'
|
|
uci set firewall.@rule[-1].src='wan'
|
|
uci set firewall.@rule[-1].dest_port="$jvb_tcp_port"
|
|
uci set firewall.@rule[-1].proto='tcp'
|
|
uci set firewall.@rule[-1].target='ACCEPT'
|
|
uci set firewall.@rule[-1].enabled='1'
|
|
fi
|
|
fi
|
|
|
|
uci commit firewall
|
|
/etc/init.d/firewall reload 2>/dev/null
|
|
|
|
log "Firewall configured"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Mesh Integration
|
|
# ============================================================================
|
|
|
|
register_mesh_service() {
|
|
local mesh_enabled=$(uci -q get jitsi.mesh.enabled || echo "0")
|
|
[ "$mesh_enabled" != "1" ] && return 0
|
|
|
|
local domain=$(uci -q get jitsi.main.domain)
|
|
local web_port=$(uci -q get jitsi.web.port || echo "8443")
|
|
|
|
# Register with P2P daemon
|
|
if [ -x /usr/sbin/secubox-p2p ]; then
|
|
/usr/sbin/secubox-p2p register-service jitsi-meet "$web_port" 2>/dev/null
|
|
log "Registered Jitsi with mesh network"
|
|
fi
|
|
|
|
# Add DNS entry if DNS federation enabled
|
|
local dns_enabled=$(uci -q get secubox-p2p.dns.enabled || echo "0")
|
|
if [ "$dns_enabled" = "1" ]; then
|
|
local dns_domain=$(uci -q get secubox-p2p.dns.base_domain || echo "mesh.local")
|
|
local hostname=$(echo "$domain" | cut -d'.' -f1)
|
|
log "Mesh DNS: $hostname.$dns_domain"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# User Management
|
|
# ============================================================================
|
|
|
|
add_user() {
|
|
local username="$1"
|
|
local password="$2"
|
|
|
|
if [ -z "$username" ] || [ -z "$password" ]; then
|
|
echo "Usage: jitsctl add-user <username> <password>"
|
|
return 1
|
|
fi
|
|
|
|
local domain=$(uci -q get jitsi.main.domain)
|
|
|
|
log "Adding user: $username"
|
|
|
|
docker exec jitsi-prosody prosodyctl register "$username" "$domain" "$password"
|
|
|
|
if [ $? -eq 0 ]; then
|
|
log "User $username added successfully"
|
|
else
|
|
error "Failed to add user $username"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
remove_user() {
|
|
local username="$1"
|
|
|
|
if [ -z "$username" ]; then
|
|
echo "Usage: jitsctl remove-user <username>"
|
|
return 1
|
|
fi
|
|
|
|
local domain=$(uci -q get jitsi.main.domain)
|
|
|
|
log "Removing user: $username"
|
|
|
|
docker exec jitsi-prosody prosodyctl unregister "$username" "$domain"
|
|
|
|
if [ $? -eq 0 ]; then
|
|
log "User $username removed"
|
|
else
|
|
error "Failed to remove user $username"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
list_users() {
|
|
local domain=$(uci -q get jitsi.main.domain)
|
|
|
|
echo "Registered users for $domain:"
|
|
docker exec jitsi-prosody ls -1 /config/data/"$domain"/accounts/ 2>/dev/null | sed 's/\.dat$//'
|
|
}
|
|
|
|
# ============================================================================
|
|
# Status & Logs
|
|
# ============================================================================
|
|
|
|
show_status() {
|
|
echo ""
|
|
echo "========================================"
|
|
echo " Jitsi Meet Status v$VERSION"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
local enabled=$(uci -q get jitsi.main.enabled)
|
|
local domain=$(uci -q get jitsi.main.domain)
|
|
local public_url=$(uci -q get jitsi.main.public_url)
|
|
[ -z "$public_url" ] && public_url="https://$domain"
|
|
|
|
echo "Configuration:"
|
|
echo " Enabled: $([ "$enabled" = "1" ] && echo -e "${GREEN}Yes${NC}" || echo -e "${RED}No${NC}")"
|
|
echo " Domain: $domain"
|
|
echo " Public URL: $public_url"
|
|
echo ""
|
|
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
echo -e "Docker: ${RED}Not installed${NC}"
|
|
return
|
|
fi
|
|
|
|
echo "Containers:"
|
|
for container in jitsi-web jitsi-prosody jitsi-jicofo jitsi-jvb; do
|
|
local state=$(docker inspect -f '{{.State.Status}}' "$container" 2>/dev/null)
|
|
if [ "$state" = "running" ]; then
|
|
echo -e " $container: ${GREEN}Running${NC}"
|
|
elif [ -n "$state" ]; then
|
|
echo -e " $container: ${YELLOW}$state${NC}"
|
|
else
|
|
echo -e " $container: ${RED}Not found${NC}"
|
|
fi
|
|
done
|
|
echo ""
|
|
|
|
# Show ports
|
|
local jvb_port=$(uci -q get jitsi.jvb.port || echo "10000")
|
|
local web_port=$(uci -q get jitsi.web.port || echo "8443")
|
|
echo "Ports:"
|
|
echo " Web: $web_port/tcp"
|
|
echo " JVB Media: $jvb_port/udp"
|
|
echo ""
|
|
|
|
# Show active conferences (if available)
|
|
local stats=$(docker exec jitsi-jvb curl -s http://localhost:8080/colibri/stats 2>/dev/null)
|
|
if [ -n "$stats" ]; then
|
|
local conferences=$(echo "$stats" | jsonfilter -e '@.conferences' 2>/dev/null || echo "0")
|
|
local participants=$(echo "$stats" | jsonfilter -e '@.participants' 2>/dev/null || echo "0")
|
|
echo "Active:"
|
|
echo " Conferences: $conferences"
|
|
echo " Participants: $participants"
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
show_logs() {
|
|
local service="$1"
|
|
local lines="${2:-50}"
|
|
|
|
cd "$JITSI_DIR"
|
|
|
|
case "$service" in
|
|
web|prosody|jicofo|jvb)
|
|
docker-compose logs --tail="$lines" "$service"
|
|
;;
|
|
all|"")
|
|
docker-compose logs --tail="$lines"
|
|
;;
|
|
*)
|
|
echo "Usage: jitsctl logs [web|prosody|jicofo|jvb|all] [lines]"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
shell() {
|
|
local container="${1:-jitsi-prosody}"
|
|
|
|
log "Connecting to $container..."
|
|
docker exec -it "$container" /bin/bash 2>/dev/null || docker exec -it "$container" /bin/sh
|
|
}
|
|
|
|
# ============================================================================
|
|
# Upgrade
|
|
# ============================================================================
|
|
|
|
upgrade() {
|
|
log "Upgrading Jitsi Meet..."
|
|
|
|
cd "$JITSI_DIR"
|
|
|
|
# Pull latest images
|
|
docker-compose pull
|
|
|
|
# Restart with new images
|
|
docker-compose down
|
|
docker-compose up -d
|
|
|
|
# Cleanup old images
|
|
docker image prune -f
|
|
|
|
log "Jitsi Meet upgraded"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Backup / Restore
|
|
# ============================================================================
|
|
|
|
backup() {
|
|
local backup_file="${1:-/tmp/jitsi-backup-$(date +%Y%m%d-%H%M%S).tar.gz}"
|
|
|
|
log "Creating backup..."
|
|
|
|
tar -czf "$backup_file" \
|
|
-C / \
|
|
etc/config/jitsi \
|
|
"$CONFIG_DIR" \
|
|
"$ENV_FILE" \
|
|
2>/dev/null
|
|
|
|
if [ -f "$backup_file" ]; then
|
|
local size=$(ls -lh "$backup_file" | awk '{print $5}')
|
|
log "Backup created: $backup_file ($size)"
|
|
else
|
|
error "Backup failed"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
restore() {
|
|
local backup_file="$1"
|
|
|
|
if [ -z "$backup_file" ] || [ ! -f "$backup_file" ]; then
|
|
echo "Usage: jitsctl restore <backup_file>"
|
|
return 1
|
|
fi
|
|
|
|
log "Restoring from $backup_file..."
|
|
|
|
# Stop service
|
|
/etc/init.d/jitsi stop 2>/dev/null
|
|
|
|
# Extract backup
|
|
tar -xzf "$backup_file" -C /
|
|
|
|
# Restart
|
|
/etc/init.d/jitsi start
|
|
|
|
log "Restore complete"
|
|
}
|
|
|
|
# ============================================================================
|
|
# TURN Server Integration
|
|
# ============================================================================
|
|
|
|
setup_turn() {
|
|
local turn_domain="${1:-turn.secubox.in}"
|
|
|
|
log "Setting up TURN server for Jitsi..."
|
|
|
|
# Check if turnctl is available
|
|
if ! command -v turnctl >/dev/null 2>&1; then
|
|
error "turnctl not found. Install secubox-app-turn first."
|
|
echo " opkg install secubox-app-turn"
|
|
return 1
|
|
fi
|
|
|
|
# Setup TURN server for Jitsi
|
|
local jitsi_domain=$(uci -q get jitsi.main.domain || echo "meet.secubox.local")
|
|
turnctl setup-jitsi "$jitsi_domain" "$turn_domain"
|
|
|
|
# Get the TURN credentials
|
|
local turn_secret=$(uci -q get turn.main.static_auth_secret)
|
|
local external_ip=$(uci -q get turn.main.external_ip)
|
|
|
|
if [ -z "$turn_secret" ]; then
|
|
error "TURN server not configured. Run 'turnctl setup-jitsi' first."
|
|
return 1
|
|
fi
|
|
|
|
# Update Jitsi UCI config
|
|
uci set jitsi.turn=jitsi
|
|
uci set jitsi.turn.enabled='1'
|
|
uci set jitsi.turn.server="$turn_domain"
|
|
uci set jitsi.turn.use_secret='1'
|
|
uci set jitsi.turn.secret="$turn_secret"
|
|
uci commit jitsi
|
|
|
|
# Update STUN servers
|
|
uci set jitsi.jvb.stun_servers="$turn_domain:3478"
|
|
uci commit jitsi
|
|
|
|
# Regenerate config
|
|
generate_config
|
|
|
|
log "TURN configured for Jitsi!"
|
|
echo ""
|
|
echo "TURN Server: $turn_domain"
|
|
echo "External IP: $external_ip"
|
|
echo ""
|
|
echo "Restart Jitsi to apply: jitsctl restart"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Main
|
|
# ============================================================================
|
|
|
|
show_help() {
|
|
cat << EOF
|
|
Jitsi Meet Control v$VERSION
|
|
|
|
Usage: jitsctl <command> [options]
|
|
|
|
Commands:
|
|
install Install Jitsi Meet Docker stack
|
|
generate-config Generate/update configuration from UCI
|
|
status Show service status
|
|
logs [svc] [n] Show container logs
|
|
shell [container] Access container shell
|
|
|
|
start Start all containers
|
|
stop Stop all containers
|
|
restart Restart all containers
|
|
upgrade Upgrade to latest images
|
|
|
|
add-user <u> <p> Add authenticated user
|
|
remove-user <u> Remove user
|
|
list-users List registered users
|
|
|
|
backup [file] Create configuration backup
|
|
restore <file> Restore from backup
|
|
|
|
configure-haproxy Add HAProxy vhost
|
|
configure-fw Configure firewall rules
|
|
setup-turn [dom] Configure TURN server for NAT traversal
|
|
|
|
Examples:
|
|
jitsctl install
|
|
jitsctl status
|
|
jitsctl logs jvb 100
|
|
jitsctl add-user admin secretpassword
|
|
|
|
EOF
|
|
}
|
|
|
|
case "$1" in
|
|
install)
|
|
install_jitsi
|
|
;;
|
|
generate-config)
|
|
generate_config
|
|
;;
|
|
status)
|
|
show_status
|
|
;;
|
|
logs)
|
|
show_logs "$2" "$3"
|
|
;;
|
|
shell)
|
|
shell "$2"
|
|
;;
|
|
start)
|
|
cd "$JITSI_DIR" && docker-compose up -d
|
|
;;
|
|
stop)
|
|
cd "$JITSI_DIR" && docker-compose down
|
|
;;
|
|
restart)
|
|
cd "$JITSI_DIR" && docker-compose restart
|
|
;;
|
|
upgrade)
|
|
upgrade
|
|
;;
|
|
add-user)
|
|
add_user "$2" "$3"
|
|
;;
|
|
remove-user)
|
|
remove_user "$2"
|
|
;;
|
|
list-users)
|
|
list_users
|
|
;;
|
|
backup)
|
|
backup "$2"
|
|
;;
|
|
restore)
|
|
restore "$2"
|
|
;;
|
|
configure-haproxy)
|
|
configure_haproxy
|
|
;;
|
|
configure-fw)
|
|
configure_firewall
|
|
;;
|
|
setup-turn)
|
|
setup_turn "$2"
|
|
;;
|
|
-h|--help|help)
|
|
show_help
|
|
;;
|
|
*)
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
exit 0
|