-
Notifications
You must be signed in to change notification settings - Fork 255
Description
Describe the bug
Analytics callback URL construction fails in High Availability (HA) deployments behind a proxy or load balancer. The callback URL is built using URL_HOST which is set to an internal hostname for DNS rebinding protection, but BigBlueButton servers cannot reach the internal hostname when sending analytics callbacks. This results in failed analytics tracking and connection errors.
To Reproduce
Deployment:
- Deployment: Docker Compose HA deployment behind a proxy/load balancer (or any HA setup where
URL_HOSTis internal) - Versions: Scalelite v1.7+, BigBlueButton 2.4+, Docker Compose v2+
- Tools used for reproducing the issue: BigBlueButton API, curl, Docker Compose
Steps to reproduce the behavior:
- Deploy Scalelite using
docker-compose.ymlwithURL_HOSTset to internal hostname (e.g.,scalelite-apior0.0.0.0) - Set
DOMAIN_NAMEto public domain (e.g.,sl.example.com) - Register a BigBlueButton server with the Scalelite load balancer
- Create a meeting via Scalelite API:
curl -X POST "https://sl.example.com/bigbluebutton/api/create" \
-d "meetingID=test-123" \
-d "name=Test Meeting" \
-d "checksum=..." \
-d "meta_analytics-callback-url=https://sl.example.com/analytics"
- Wait for the meeting to end and recordings to process
- Check BigBlueButton server logs: Connection errors to unreachable analytics callback URL
- See error: Connection refused to
https://0.0.0.0/bigbluebutton/api/analytics_callbackor similar internal hostname
Expected behavior
The analytics callback URL should be constructed using the public-facing hostname (reachable from BigBlueButton servers), while URL_HOST continues to protect against DNS rebinding attacks. BigBlueButton servers should successfully send analytics callbacks to the Scalelite endpoint.
Actual behavior
Analytics callback URL is constructed as: https://0.0.0.0/bigbluebutton/api/analytics_callback or https://scalelite-api/bigbluebutton/api/analytics_callback
BigBlueButton servers attempt to POST analytics but fail because:
- The internal hostname is not resolvable from BigBlueButton servers
- Even if resolvable, the internal IP/hostname is not routable
Root Cause
File: app/handlers/analytics_callback_event_handler.rb (line 14)
host_name = Rails.configuration.x.url_hostURL_HOST serves conflicting purposes:
- Primary use: DNS rebinding protection in
config/environments/production.rb - Conflicting use: Analytics callback URL construction (should use public hostname)
Solution
Introduce new environment variable ANALYTICS_CALLBACK_URL_HOST with fallback to URL_HOST for backward compatibility:
File: config/application.rb
config.x.analytics_callback_url_host = ENV.fetch('ANALYTICS_CALLBACK_URL_HOST', nil)File: app/handlers/analytics_callback_event_handler.rb
def handle
return if analytics_callback_url.nil?
# Use ANALYTICS_CALLBACK_URL_HOST if set (for HA/proxy deployments)
# Otherwise fall back to URL_HOST (for direct deployments)
host_name = Rails.configuration.x.analytics_callback_url_host || Rails.configuration.x.url_host
params['meta_analytics-callback-url'] = if tenant.present?
"https://#{tenant.name}.#{host_name}/bigbluebutton/api/analytics_callback"
else
"https://#{host_name}/bigbluebutton/api/analytics_callback"
end
callback_attributes = { analytics_callback_url: analytics_callback_url }
callback_data = CallbackData.find_or_create_by!(meeting_id: meeting_id)
callback_data.update!(callback_attributes: callback_attributes)
endScreenshots
N/A - This is a configuration/networking issue
Additional context
Impact:
- 🔴 Critical for HA deployments behind proxy/load balancer
⚠️ No impact on single-instance direct deployments- ✅ Fully backward compatible when
ANALYTICS_CALLBACK_URL_HOSTnot set
Affected deployment scenarios:
- AWS ALB/NLB + Scalelite cluster
- Kubernetes ingress + Scalelite pod
- Any external load balancer + Scalelite cluster
- Any deployment where
URL_HOST≠ public hostname
Configuration examples:
Direct deployment (current, works):
URL_HOST=sl.example.com
HA behind proxy (currently broken, would be fixed with this change):
URL_HOST=scalelite-api # Internal for DNS rebinding
ANALYTICS_CALLBACK_URL_HOST=sl.example.com # Public for analytics callbacks