Janus WebRTC Gateway Quick Deploy: Docker + Nginx Reverse Proxy + STUN/TURN

Server Technology Featured Articles 3 minutes |
Janus WebRTC Gateway Quick Deploy: Docker + Nginx Reverse Proxy + STUN/TURN

This guide targets developers working with the Janus WebRTC Gateway (janus-gateway), covering janus-gateway docker quick deployment and production rollout essentials.

We focus on getting things running first (a minimal setup), then add Docker-based deployment, HTTPS/WSS reverse proxy, and STUN/TURN integration—plus common troubleshooting.

References:

1) What is Janus (one-liner)

Janus is a general-purpose WebRTC media gateway with multiple plugins (e.g., videoroom, audiobridge, textroom, streaming). It can act as an SFU/media relay hub to power real-time audio/video sessions for your apps.

2) Quick start (minimal working)

For local development, get the core Janus services running and open the built-in demo pages to verify.

Tip: prefer HTTPS/WSS early to avoid browser security issues (see reverse proxy below).

2.1 Source/binaries (overview)

  • Option A: build from source (deps like libnice, libsrtp, libmicrohttpd, jansson, libwebsockets, etc.)
  • Option B: use packaged builds or container images (faster)

If you want the fastest path, jump to Docker.

3) Docker one-command deployment

Based on the community Docker project (ref: https://github.com/wangsrGit119/janus-webrtc-gateway-docker), here’s a practical flow to run the demos, set up reverse proxy/certificates, and wire up STUN/TURN.

3.1 Pull and start

  1. Prepare a conf/ directory in your project root and place Janus config files (see official conf templates).

    • e.g., janus.jcfg, janus.transport.http.jcfg, janus.eventhandler.sampleevh.jcfg.
  2. Write docker-compose.yml (from the repo README):

services:
  janus-gateway:
    image: 'sucwangsr/janus-webrtc-gateway-docker:latest'
    # Start only janus:
    #command: ["/usr/local/bin/janus", "-F", "/usr/local/etc/janus"]
    # Start nginx (8086) plus janus together:
    command: ["sh", "-c", "nginx && /usr/local/bin/janus -F /usr/local/etc/janus"]
    network_mode: "host"
    volumes:
      - "./conf/janus.transport.http.jcfg:/usr/local/etc/janus/janus.transport.http.jcfg"  # adminapi config
      - "./conf/janus.jcfg:/usr/local/etc/janus/janus.jcfg"
      - "./conf/janus.eventhandler.sampleevh.jcfg:/usr/local/etc/janus/janus.eventhandler.sampleevh.jcfg"
    restart: always
  1. Start services:
docker compose up -d
# or
docker-compose up -d

After startup you should have:

  • A running Janus gateway (with janus.transport.websockets/http)
  • Default config files inside the container (janus.jcfg, janus.transport.*.jcfg, janus.plugin.*.jcfg)

3.6 Important notes (from the repo README)

  • Double-check your configuration files before starting, including comments and syntax.
  • If using network_mode: "host", ensure host ports are free to avoid conflicts.
  • For multi-platform images (1.3.1+), prefer :latest or a pinned version; Docker auto-detects architecture.
  • For 1.3.0 and below, use architecture-specific tags (e.g., -slim vs -arm64).
  • You can start only Janus or start both nginx (port 8086) and Janus in the container.
  • The image is built from the official meetecho/janus-gateway source with streamlined modules.

3.2 Key configs (minimal set)

Configs live under conf/ in the container (paths vary by image):

  • janus.jcfg
    • stun_server / stun_port
    • turn_server / turn_port / turn_type / turn_user / turn_pwd
    • nat_1_1_mapping: public IP mapping if Janus is behind NAT
    • interface: bind interface/address
  • janus.transport.websockets.jcfg
    • ws / wss ports
    • secure, cert_pem, cert_key for WSS
    • http / https if using built-in HTTP(S)
  • janus.transport.http.jcfg
    • port / admin_port for REST/events
    • admin_secret for admin API (keep it safe)

Production tip: disable unused transports (e.g., only expose WSS/HTTPS).

3.3 Nginx reverse proxy (HTTPS/WSS)

If you use Nginx as the TLS terminator, proxy both WebSocket (/janus) and demo assets to Janus:

# 中文注释:示例,按需合并到你的站点配置
server {
  listen 443 ssl http2;
  server_name rtc.example.com;

  ssl_certificate     /etc/letsencrypt/live/rtc.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/rtc.example.com/privkey.pem;

  # Proxy Janus WebSockets (assume 8188/8989 in container)
  location /janus {
    proxy_pass http://127.0.0.1:8188; # or https://127.0.0.1:8989 (WSS)
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
  }

  # Demo site
  location / {
    root /var/www/your-janus-demo;
    index index.html;
  }
}

Alternatively, let Janus terminate WSS itself (set cert_pem/cert_key in janus.transport.websockets.jcfg) and use Nginx as a plain reverse proxy. Pick one strategy.

3.4 STUN/TURN integration

Connectivity heavily depends on network conditions. Typical snippet:

# janus.jcfg example
stun_server = "stun:stun.l.google.com"  # 中文注释:示例 STUN,生产建议自建或替换
stun_port   = 19302

# Fallback to TURN when direct P2P fails
turn_server = "turn:turn.example.com"
turn_port   = 3478
turn_user   = "user"
turn_pwd    = "pass"
turn_type   = "udp"  # udp/tcp/tls

# If Janus sits behind NAT, map to a public IP
nat_1_1_mapping = "203.0.113.10"

A self-hosted TURN (e.g., coturn) plus correct Janus/frontend SDP helps a lot under restrictive NATs.

3.5 Verify & troubleshoot

  • Open the official demos (or those in the container) and test videoroom/echotest/streaming.
  • Check DevTools → Network: WebSocket 101 upgrade on /janus.
  • Use Chrome chrome://webrtc-internals to inspect ICE candidates, state, and bitrate.
  • Inspect Janus logs (inside container, e.g., /var/log/janus/ or stdout).

4) Frontend integration (janus.js)

  • Session/handle: Janus.init → create session → attach desired plugin (e.g., janus.plugin.videoroom).
  • Negotiation: createOffer/Answer → signaling via Janus → receive remote SDP/ICE.
  • Codecs: align with browser support (VP8/VP9/H.264/Opus); constrain via SDP or room policy if needed.
  • Multi-subscribing: watch bandwidth/decoding pressure on mobile (resolution/FPS control).

Minimal pseudo structure (illustrative only):

// 中文注释:在 HTTPS 域名加载 janus.js,确保 /janus 可访问
Janus.init({debug: true, callback: () => {
  const janus = new Janus({
    server: 'wss://rtc.example.com/janus', // 你的反代地址
    success: () => {
      janus.attach({
        plugin: 'janus.plugin.videoroom',
        success: (pluginHandle) => {
          // 创建/加入房间,发布/订阅流
        },
        onmessage: (msg, jsep) => {
          // 处理 Janus 事件与 SDP
        },
        onremotestream: (stream) => {
          // 渲染远端流
        }
      });
    }
  });
}});

5) FAQ (selected)

  • No media/black screen: first check WSS reverse proxy and certificate chain; then STUN/TURN reachability.
  • Mobile stutter: adjust pub resolution/FPS/bitrate; consider SVC or multi-bitrate.
  • Janus behind NAT: set nat_1_1_mapping and expose correct ports; add TURN if needed.
  • Codec mismatch: constrain via SDP or room policy.

6) References

Tags

#Janus #WebRTC #Media Server #Docker #Nginx

Copyright Notice

This article is created by WebRTC.link and licensed under CC BY-NC-SA 4.0. This site repost articles will cite the source and author. If you need to repost, please cite the source and author.

Comments

Giscus

Comments powered by Giscus, based on GitHub Discussions

Related Articles

Explore more related content to deepen your understanding of WebRTC technology