Why Use a Reverse Proxy?
While technically not required, using a reverse proxy is highly recommended for production deployments:
HTTPS support : Secure communication with SSL/TLS certificates
Port management : Serve multiple applications on standard ports (80/443)
Performance : Static file caching and compression
Security : Additional layer of protection and access control
Running OTT without HTTPS is not supported. Always use a reverse proxy with SSL/TLS in production.
Proxy Requirements
Your reverse proxy must handle:
WebSocket upgrades : Required for real-time room synchronization
All requests for index.html : Proper SPA routing
Headers :
Forward Set-Cookie header in responses
Forward Authorization header in requests
Set X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Host
Nginx Configuration
Here’s a complete nginx configuration for OTT:
map $ http_upgrade $ connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2;
server_name example.com;
# SSL configuration (generated by certbot)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1 ;
# WebSocket support
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection "upgrade" ;
# Forward headers
proxy_set_header Host $ host ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $ scheme ;
proxy_set_header X-Forwarded-Host $ host ;
# Don't cache upgraded connections
proxy_cache_bypass $ http_upgrade ;
# Pass cookies
proxy_pass_header Set-Cookie;
# Optional: Prevent frequent disconnects
proxy_connect_timeout 7d ;
proxy_read_timeout 7d ;
proxy_send_timeout 7d ;
proxy_socket_keepalive on ;
}
}
# Redirect HTTP to HTTPS
server {
listen 80 ;
server_name example.com;
return 301 https://$ server_name $ request_uri ;
}
Configuration Breakdown
map $ http_upgrade $ connection_upgrade {
default upgrade;
'' close;
}
This creates a mapping to properly handle WebSocket upgrade requests. When the Upgrade header is present, it upgrades the connection; otherwise, it closes it.
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
Replace with your SSL certificate paths. Use Certbot to obtain free Let’s Encrypt certificates.
proxy_connect_timeout 7d ;
proxy_read_timeout 7d ;
proxy_send_timeout 7d ;
proxy_socket_keepalive on ;
These extended timeouts prevent WebSocket connections from being dropped. Use these settings if you experience frequent client disconnects and reconnects.
Trust Proxy Configuration
When using a reverse proxy, configure OTT to trust the proxy layer(s):
Set this to the number of proxy layers between the client and OTT:
1 proxy layer : nginx → OTT
2 proxy layers : Cloudflare → nginx → OTT
3 proxy layers : Cloudflare → load balancer → nginx → OTT
Setting trust_proxy incorrectly can lead to security issues or broken functionality. Count your proxy layers carefully.
Multiple Proxy Layers
If you have multiple reverse proxies (e.g., Cloudflare in front of nginx), ensure each layer forwards the headers correctly:
# If behind Cloudflare or another CDN
set_real_ip_from 0.0.0.0/0; # Or specific Cloudflare IP ranges
real_ip_header CF-Connecting-IP; # For Cloudflare
# real_ip_header X-Forwarded-For; # For other proxies
Then set trust_proxy = 2 (or higher) in your OTT configuration.
Caddy Configuration
If you prefer Caddy, here’s an equivalent configuration:
example.com {
reverse_proxy localhost:3000 {
# Headers are automatically forwarded
transport http {
keepalive 7d
keepalive_idle_conns 100
}
}
}
Caddy automatically handles:
HTTPS with automatic certificate management
WebSocket upgrades
Proper header forwarding
Apache Configuration
For Apache with mod_proxy:
< VirtualHost *:443 >
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
ProxyPreserveHost On
ProxyPass / http://localhost: 3000 /
ProxyPassReverse / http://localhost: 3000 /
# WebSocket support
RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "ws://localhost:3000/$1" [P,L]
# Forward headers
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port " 443 "
</ VirtualHost >
Enable required modules:
a2enmod proxy proxy_http proxy_wstunnel rewrite ssl headers
systemctl restart apache2
Traefik Configuration
For Traefik (v2+) with Docker:
services :
opentogethertube :
image : dyc3/opentogethertube:latest
labels :
- "traefik.enable=true"
- "traefik.http.routers.ott.rule=Host(`example.com`)"
- "traefik.http.routers.ott.entrypoints=websecure"
- "traefik.http.routers.ott.tls.certresolver=letsencrypt"
- "traefik.http.services.ott.loadbalancer.server.port=8080"
SSL Certificate Management
Let’s Encrypt with Certbot
Obtain free SSL certificates:
Install Certbot
# Ubuntu/Debian
sudo apt install certbot python3-certbot-nginx
# CentOS/RHEL
sudo yum install certbot python3-certbot-nginx
Obtain certificate
sudo certbot --nginx -d example.com
Certbot will automatically configure nginx for HTTPS.
Enable auto-renewal
sudo certbot renew --dry-run
Certbot automatically sets up renewal via systemd timer or cron.
Testing Your Configuration
Reload nginx
sudo systemctl reload nginx
Verify HTTPS
Visit https://example.com and verify:
Page loads correctly
No certificate warnings
WebSocket connection succeeds (check browser console)
Test SSL configuration
Use SSL Labs to verify your SSL configuration.
Troubleshooting
WebSocket connection fails
Verify the Upgrade and Connection headers are forwarded
Check that proxy_http_version 1.1 is set
Ensure firewall allows WebSocket connections
Incorrect client IP addresses
Verify X-Forwarded-For header is set correctly
Adjust trust_proxy setting to match your proxy layers
Check nginx set_real_ip_from configuration
Session/authentication issues
Ensure Set-Cookie header is forwarded
Verify proxy_pass_header Set-Cookie is set
Check that force_insecure_cookies is configured correctly
Frequent disconnects
Increase proxy timeout values
Enable proxy_socket_keepalive
Check for firewall connection timeout settings