WebRTC applications require reliable ICE candidates and connectivity solutions to traverse NAT and firewalls. A highly available TURN/STUN server deployment across multiple geographic regions ensures low-latency media relay and optimal user experience for real-time communications. This comprehensive tutorial demonstrates deploying coturn servers with geographic load balancing, dual-stack networking, TLS encryption, and comprehensive monitoring.
What You Will Learn
By following this guide, you’ll establish a production-ready TURN/STUN infrastructure featuring:
- Multi-region coturn deployment with automatic failover
- GeoDNS routing for geographic optimization
- IPv4/IPv6 dual-stack configuration with TLS encryption
- Prometheus metrics collection and Grafana dashboards
- Security hardening and performance optimization
Prerequisites
Before starting this deployment, ensure you have:
- Two Ubuntu 24.04 LTS VPS instances (4GB RAM, 2 vCPU minimum)
- Onidel VPS in Amsterdam and Onidel VPS in New York with IPv4/IPv6 addresses
- Domain name with DNS management capabilities (Cloudflare recommended)
- TLS certificates (Let’s Encrypt or custom CA)
- Basic knowledge of TURN/STUN protocols and WebRTC
- SSH access with sudo privileges
System Requirements:
- Ubuntu 24.04 LTS with kernel 6.8+
- Minimum 4GB RAM per server (8GB recommended for high concurrency)
- Open ports: 3478 (STUN/TURN), 5349 (TURNS), 49152-65535 (media relay)
- IPv6 connectivity enabled
Step 1: System Preparation and Initial Setup
Start by updating both VPS instances and installing required dependencies:
sudo apt update && sudo apt upgrade -y
sudo apt install -y coturn prometheus-node-exporter certbot nginx-light
sudo systemctl enable prometheus-node-exporter
sudo systemctl start prometheus-node-exporter
Configure firewall rules for TURN/STUN services:
sudo ufw allow 3478/tcp
sudo ufw allow 3478/udp
sudo ufw allow 5349/tcp
sudo ufw allow 5349/udp
sudo ufw allow 49152:65535/udp
sudo ufw reload
Verify IPv6 connectivity on both Amsterdam and New York instances:
ip -6 addr show
ping6 -c 3 2001:4860:4860::8888
Step 2: Advanced coturn Configuration
Create the main coturn configuration file with dual-stack and TLS support:
sudo tee /etc/turnserver.conf << 'EOF'
# Listening interfaces
listening-port=3478
tls-listening-port=5349
listening-ip=0.0.0.0
listening-ip=::
# External IP addresses (replace with your actual IPs)
external-ip=YOUR_IPV4_ADDRESS
external-ip=YOUR_IPV6_ADDRESS
# Relay configuration
relay-ip=YOUR_IPV4_ADDRESS
relay-ip=YOUR_IPV6_ADDRESS
min-port=49152
max-port=65535
# Authentication
realm=turn.yourdomain.com
lt-cred-mech
user=webrtc:your_secure_password
# TLS configuration
cert=/etc/letsencrypt/live/turn.yourdomain.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.yourdomain.com/privkey.pem
dh-file=/etc/coturn/dhparam.pem
# Security settings
no-stdout-log
log-file=/var/log/turnserver.log
verbose
mobility
no-multicast-peers
no-loopback-peers
stale-nonce=600
# Performance settings
total-quota=100
bps-capacity=0
max-bps=0
# Prometheus monitoring
prometheus
prometheus-port=8080
EOF
Generate DH parameters for enhanced TLS security:
sudo mkdir -p /etc/coturn
sudo openssl dhparam -out /etc/coturn/dhparam.pem 2048
sudo chown turnserver:turnserver /etc/coturn/dhparam.pem
sudo chmod 600 /etc/coturn/dhparam.pem
Step 3: TLS Certificate Management
Obtain Let’s Encrypt certificates for your TURN domains:
# Amsterdam server
sudo certbot certonly --standalone \
-d turn-ams.yourdomain.com \
--email [email protected] \
--agree-tos --non-interactive
# New York server
sudo certbot certonly --standalone \
-d turn-nyc.yourdomain.com \
--email [email protected] \
--agree-tos --non-interactive
Configure certificate renewal automation:
sudo tee /etc/systemd/system/coturn-cert-reload.service << 'EOF'
[Unit]
Description=Reload coturn after certificate renewal
[Service]
Type=oneshot
ExecStart=/bin/systemctl reload coturn
EOF
sudo tee /etc/systemd/system/coturn-cert-reload.path << 'EOF'
[Unit]
Description=Watch for certificate changes
[Path]
PathModified=/etc/letsencrypt/live/turn.yourdomain.com/fullchain.pem
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable coturn-cert-reload.path
sudo systemctl start coturn-cert-reload.path
Step 4: GeoDNS Load Balancing Setup
Configure Cloudflare GeoDNS for optimal routing. Create DNS records for geographic distribution:
# Primary TURN service (GeoDNS)
turn.yourdomain.com A 300 YOUR_AMSTERDAM_IP (EU traffic)
turn.yourdomain.com A 300 YOUR_NEWYORK_IP (US traffic)
# Specific region endpoints
turn-ams.yourdomain.com A 300 YOUR_AMSTERDAM_IP
turn-nyc.yourdomain.com A 300 YOUR_NEWYORK_IP
# IPv6 records
turn.yourdomain.com AAAA 300 YOUR_AMSTERDAM_IPV6 (EU traffic)
turn.yourdomain.com AAAA 300 YOUR_NEWYORK_IPV6 (US traffic)
turn-ams.yourdomain.com AAAA 300 YOUR_AMSTERDAM_IPV6
turn-nyc.yourdomain.com AAAA 300 YOUR_NEWYORK_IPV6
# SRV records for WebRTC discovery
_turn._tcp.yourdomain.com SRV 10 5 5349 turn.yourdomain.com
_turn._udp.yourdomain.com SRV 10 5 3478 turn.yourdomain.com
_stun._tcp.yourdomain.com SRV 10 5 3478 turn.yourdomain.com
_stun._udp.yourdomain.com SRV 10 5 3478 turn.yourdomain.com
Step 5: Prometheus and Grafana Monitoring
Install and configure Prometheus on one of your servers (Amsterdam recommended):
# /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'coturn-amsterdam'
static_configs:
- targets: ['YOUR_AMSTERDAM_IP:8080']
scrape_interval: 10s
metrics_path: '/metrics'
- job_name: 'coturn-newyork'
static_configs:
- targets: ['YOUR_NEWYORK_IP:8080']
scrape_interval: 10s
metrics_path: '/metrics'
- job_name: 'node-exporter-amsterdam'
static_configs:
- targets: ['YOUR_AMSTERDAM_IP:9100']
- job_name: 'node-exporter-newyork'
static_configs:
- targets: ['YOUR_NEWYORK_IP:9100']
Install Grafana with Docker Compose for visualization:
# docker-compose.yml for Grafana
version: '3.8'
services:
grafana:
image: grafana/grafana:10.2.0
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=your_secure_password
volumes:
- grafana-storage:/var/lib/grafana
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards
- ./grafana/datasources:/etc/grafana/provisioning/datasources
restart: unless-stopped
volumes:
grafana-storage:
Step 6: Service Startup and Validation
Start coturn services on both servers:
sudo systemctl enable coturn
sudo systemctl start coturn
sudo systemctl status coturn
Test STUN/TURN connectivity from both regions:
# Test STUN functionality
stunserver-client YOUR_AMSTERDAM_IP 3478
stunserver-client YOUR_NEWYORK_IP 3478
# Test TURN authentication
turnutils_uclient -t -T -v \
-s turn-ams.yourdomain.com \
-u webrtc -w your_secure_password \
-p 3478
Verify TLS connectivity on port 5349:
openssl s_client -connect turn-ams.yourdomain.com:5349 -servername turn-ams.yourdomain.com
openssl s_client -connect turn-nyc.yourdomain.com:5349 -servername turn-nyc.yourdomain.com
Best Practices and Security Considerations
Performance Optimization:
- Implement connection limits to prevent resource exhaustion
- Monitor bandwidth usage and set appropriate quotas
- Use kernel bypassing for high-throughput scenarios
- Configure BBR congestion control for improved network performance
Security Hardening:
- Regularly rotate TURN credentials and use strong passwords
- Implement rate limiting to prevent abuse
- Monitor connection patterns for unusual activity
- Enable fail2ban protection against brute force attacks
Monitoring and Alerting:
- Set up alerts for high connection counts or bandwidth usage
- Monitor certificate expiration dates
- Track geographic distribution of connections
- Implement health checks for automatic failover
Conclusion
This tutorial established a robust, highly available TURN/STUN infrastructure across Amsterdam and New York regions with comprehensive monitoring and security features. The dual-stack IPv4/IPv6 configuration ensures broad compatibility, while GeoDNS optimization provides optimal performance for global users.
For expanding your WebRTC infrastructure, consider exploring our guides on building active-active VPS architectures and comprehensive observability stacks. The combination of Onidel VPS in Amsterdam and Onidel VPS in New York provides the perfect foundation for globally distributed real-time communication services.




