NEWS Earn Money with Onidel Cloud! Affiliate Program Details - Check it out

How to Deploy a Highly Available TURN/STUN (coturn) Edge Across Amsterdam VPS and New York VPS with GeoDNS, Dual‑Stack IPv4/IPv6, TLS, and Prometheus/Grafana Monitoring on Ubuntu 24.04 (2025 Tutorial)

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.

Share your love