Prog blog

Deploy own libp2p WebRTC Star

Deploy own libp2p WebRTC Star

WebRTC (Web Real-Time Communication) is a real-time communication in the Web. This technology enables making calls, making video calls, conferences or transferring files from a browser. It was created as an answer to the growing demand for smooth communication. This technology was used in js-libp2p library as a solution for browsers to communicate with p2p network.

To create an initial connection between p2p network users, a special initial server is required to exchange information needed to establish a connection between the users. With some exceptions, further communication no longer takes place with the relay server.

You don't need much to run the WebRTC server, just VPS for $1 per month. Reviews of super cheap VPS servers can be found at For air hockey game I bought cheapest server in racknerd.

On the js-libp2p-webrtc-star project page there is a deployment instruction. Using the ready-made docker-compose we have a full instance with an ssl certificate from letsencrypt.

Below you will find a simple script that automates the setting of needed programs on a clean machine. It is important to set the server's IP to a specific domain before running the docker-compose up, otherwise letsencrypt will not give us an ssl certificate.

I connect to the address, which has an A record in the DNS from the IP of the cheapest racknerd server.

└── docker-compose.yml

scp -r wrtc-star root@$DOMAIN:
ssh root@$DOMAIN << EOF
  set -xe
  apt update
  apt -yy install docker-compose
  cd ~/wrtc-star
  DOMAIN=$DOMAIN docker-compose up -d

The script copies the folder wrtc-star which contains docker-compose.yml from the libp2p-wrtc-star deployments. Next, it connects to the machine via ssh, installs the docker, enters the wrtc-star directory, and runs the docker-compose up -d with the domain

Example configuration needed to use a webrtc server in js-libp2p.

const p2p = await Libp2p.create({
  addresses: {
    listen: [
  modules: {
    transport: [Websockets, WebRTCStar],
    connEncryption: [NOISE],
    streamMuxer: [Mplex],
    dht: KadDHT,
    pubsub: Gossipsub,
  config: {
    peerDiscovery: {
      autoDial: true,
      dht: {
        enabled: true,
      webRTCStar: {
        enabled: true,
    pubsub: {
      enabled: true,

As it turned out later, apart from the WebRTC Star server, you also need a TURN server for all users behind NAT (unfortunately js-libp2p has no nicely described how to do it according to p2p circuit/relay). In the js-libp2p documentation there is an example with the listenerOptions configuration where you can add iceServers but after testing this it turned out that this configuration does not work for the RTCPeerConnection and you have to do it completely differently. By overwriting the default configuration of libp2p-webrtc-peer.

import Peer from "libp2p-webrtc-peer";

Peer.config = {
  iceServers: [
      urls: [
      urls: "",
      username: "any",
      credential: "any",
  sdpSemantics: 'unified-plan'

To create a TURN server we will use an open-source coturn project.

├── docker-compose.yml
└── turnserver.conf


version: "3.3"
    image: instrumentisto/coturn
    network_mode: "host"
      - ./turnserver.conf:/etc/turnserver.conf

Coturn configuration:



In the same way as with the server webrtc-star below I put a simple script to automate the setting of needed programs on a clean machine.

scp -r turn root@$DOMAIN:
ssh root@$DOMAIN << EOF
  set -xe
  apt -yy install docker-compose
  cd ~/turn
  docker-compose up -d

Finally, it is best to check the connectivity of our server using Trickle ICE.

Trickle ICE TURN test success

There should be at least one relay type candidate. Then we are sure that our TURN server works correctly with WebRTC.