A high-performance TURN server written in Rust.
- STUN/TURN Protocol Support: RFC 5389/5766 compliant
- Web Admin Console: Built-in HTTP admin UI with real-time metrics dashboard
- TURN REST API: WebRTC credential generation with HMAC authentication
- User Management: Fixed, temporary, and API key users with per-user limits
- ACL Rules: IP-based access control with priority ordering
- Real-time Metrics: Live throughput and active allocations charts
- Config Persistence: UI changes auto-save to TOML
- Prometheus Metrics: Built-in metrics export
- TCP & UDP: Dual protocol support
cargo build --release
./target/release/miuturndocker run -p 3478:3478 -p 3478:3478/udp -p 8080:8080 docker.cnb.cool/miuda.ai/miuturn:latestdocker build -t miuturn .
docker run -p 3478:3478 -p 3478:3478/udp -p 8080:8080 miuturnCreate miuturn.toml:
[server]
realm = "miuturn"
external_ip = "YOUR PUBLIC IP HERE"
relay_bind_ip = "0.0.0.0"
start_port = 49152
end_port = 65535
max_concurrent_allocations = 1000
max_bandwidth_bytes_per_sec = 10485760
max_allocation_duration_secs = 3600
[[server.listening]]
protocol = "udp"
address = "0.0.0.0:3478"
[[server.listening]]
protocol = "tcp"
address = "0.0.0.0:3478"
[http]
address = "0.0.0.0:8080"
# Admin console credentials (separate from TURN users)
admin_username = "admin"
admin_password = "changeme"
turn_rest_enabled = true
turn_rest_secret = "your-secret-key"
turn_rest_default_lifetime = 3600
[auth]
use_auth_secret = true
secret = "your-secret-key"
lifetime = 3600 # optional; default lifetime for credential generation, in seconds
[[auth.users]]
username = "regular_user"
password = "userpass"
user_type = "fixed"
max_allocations = 5
bandwidth_limit = 1048576 # 1 MB/s limit
ip_whitelist = ["192.168.0.0/16"]
[[auth.users]]
username = "temp_user"
password = "temp123"
user_type = "temporary"
expires_at = 1735689600
max_allocations = 2
[auth.api_keys]
key1 = "admin"
[[auth.acl_rules]]
ip_range = "10.0.0.0/8"
action = "Allow"
priority = 10
[[auth.acl_rules]]
ip_range = "0.0.0.0/0"
action = "Deny"
priority = 1With [auth].use_auth_secret = true and a nonempty [auth].secret,
TURN protocol authentication uses only temporary credentials minted with that secret.
Stored user passwords are not accepted in this mode, including for usernames present
in [[auth.users]]. Set use_auth_secret = false or omit it to use stored-user authentication.
The optional auth.lifetime sets the credential manager's default generation lifetime
in seconds (3600 when omitted). Authentication checks the expiry embedded in the
provided username; this setting does not change credentials issued by RustPBX.
User/API management and ACL checks remain separate from this credential mode.
HTTP configuration is not required. The global password is used only by servers
without an auth manager.
The username is <expiry Unix timestamp>:<user id> and the password is the
standard padded Base64 encoding of HMAC-SHA1(secret, username), compatible with
coturn's TURN REST convention. Expired credentials are rejected. TURN authentication
reads these authentication settings at startup; changing them requires restarting miuturn.
The HTTP credential endpoint uses its own [http].turn_rest_secret setting. If
you use that endpoint to issue credentials for this server, configure both secrets
with the same value.
This replaces the previous hex output. Update credential issuers together with miuturn and fetch fresh credentials; previously issued hex passwords no longer work.
For RustPBX, configure its browser /iceservers endpoint with:
[[ice_servers]]
urls = ["turn:turn.example.com:3478", "turn:turn.example.com:3478?transport=tcp"]
secrete = "your-secret-key" # same as miuturn's [auth].secret
username = "rustpbx"
lifetime = 3600Only temporary credentials are returned to the browser. Keep the shared secret on the servers and fetch fresh ICE configuration before the credentials expire.
external_ip is the relay address advertised back to clients.
relay_bind_ip is the local interface used to bind relay sockets. If omitted, it defaults to 0.0.0.0. In NAT deployments, set external_ip to the public IP and keep relay_bind_ip as 0.0.0.0 (or a specific local interface IP if needed).
Access the web UI at http://localhost:8080/console
The admin console provides:
- Real-time Metrics Dashboard: Live chart showing throughput and active allocations
- Statistics Cards: Active/total allocations, bytes relayed, messages
- User Management: Add/edit/delete TURN users with bandwidth and duration limits
- ACL Rules: Manage IP-based access control with priority ordering
Configure admin credentials in [http] section:
[http]
admin_username = "admin"
admin_password = "changeme"Note: Admin console credentials are separate from TURN service users in [[auth.users]].
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Server health and stats |
/metrics |
GET | Prometheus metrics |
/api/v1/stats |
GET | Detailed stats + users |
/api/v1/users |
POST | Add user |
/api/v1/users |
PUT | Update user |
/api/v1/users |
DELETE | Delete user |
/api/v1/acl |
POST | Add ACL rule |
/api/v1/acl |
PUT | Update ACL rule |
/api/v1/acl |
DELETE | Delete ACL rule |
/api/v1/turn-credentials |
POST | Generate TURN credentials |
CONFIG: Path to config file (default:miuturn.toml)
MIT License - Powered by miuda.ai
