Hey everyone,
I’m running Janus on an OVHCloud virtual machine and encountering consistent ICE failures right after the remote SDP description is applied.
Setup Details:
- Janus is running inside a Docker container using --network=host on an OVHCloud VM.
- I have a separate signaling server built using the Janode implementation (GitHub - meetecho/janode: A Node.js adapter for the Janus WebRTC server), which handles room creation, attaching plugins, and general signaling. This is also run in a Docker container but in bridge network mode.
- All communication between the client and Janus goes through this Janode server.
- The Janus config includes proper NAT settings like nat_1_1_mapping with the machine’s public IP.
- ice_lite = false, and Janus is bound to 0.0.0.0 to allow full ICE.
The Issue:
- The client sends and receives the SDP successfully.
- Remote description is applied without any problems.
- ICE candidates are gathered, but shortly after that, the ICE connection fails (ICE connection state = “failed”).
- TURN credentials are confirmed to be valid.
- UDP ports (10000–10200) are open both on the host and in OVHCloud’s control panel.
Tried So Far:
- Enabled full_trickle, disabled ice_tcp.
- Confirmed that iptables are not blocking any traffic.
- Verified that Janus is using the correct public-facing IP.
Questions:
- Could this setup (host-networked Janus container + bridge-mode Janode container) cause issues with ICE?
- Has anyone faced similar ICE failures on OVHCloud due to their networking layer?
- Are there any tips to debug candidate pairing at the Janus level?
Any help or ideas would be super appreciated!
My janus config:
certificates: {
cert_pem = "/etc/janus/certs/fullchain.pem"
cert_key = "/etc/janus/certs/privkey.pem"
#cert_pwd = "secretpassphrase"
dtls_accept_selfsigned = false
#dtls_ciphers = "your-desired-openssl-ciphers"
#rsa_private_key = false
}
media: {
ipv6 = true
ipv6_linklocal = false
min_nack_queue = 500
rtp_port_range = "10000-10200"
dtls_mtu = 1200
no_media_timer = 2
slowlink_threshold = 5
twcc_period = 200
dtls_timeout = 500
nack_optimizations = false
#dscp = 46
}
nat: {
stun_server = "stun1.l.google.com"
stun_port = 19302
nice_debug = true
full_trickle = true
ice_nomination = "regular"
ice_consent_freshness = true
ice_keepalive_conncheck = true
ice_lite = false
ice_tcp = false
hangup_on_failed = true
ignore_mdns = true
nat_1_1_mapping = "my.public.ip"
keep_private_host = false
turn_server = "relay1.expressturn.com"
turn_port = 3480
turn_type = "udp"
turn_user = "turn-user"
turn_pwd = "turn-pass"
#turn_rest_api = "http://yourbackend.com/path/to/api"
#turn_rest_api_key = "anyapikeyyoumayhaveset"
#turn_rest_api_method = "GET"
#turn_rest_api_timeout = 10
allow_force_relay = false
#ice_enforce_list = "eth0"
ice_ignore_list = "docker0,vmnet,172.16.0.0/12,127.0.0.1"
ignore_unreachable_ice_server = false
}
My client side config:
const config = {
iceServers: [
{ urls: 'stun:<stun-server>:<port>' },
{
urls: 'turn:<turn-server>:<port>',
username: '<turn-username>',
credential: '<turn-password>',
},
],
// iceTransportPolicy: "relay"
};