Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This tutorial is for jitsi-meet installation using 2 server or more. *Update*: this tutorial is already deprecated, please check this newer tutorial instead: https://facsiaginsa.com/jitsi/install-jitsi-meet-with-multi-server-configuration

How to Install Jitsi Meet with Multi Server Configuration

This tutorial is for jitsi-meet installation using 2 server or more. The main server will contain jitsi-meet react source code, prosody, nginx, and jicofo. The videobridge will be installed seperatelly on the second server and so on.

Prerequisite

  1. Minimum 2 server with 1 IP Public each
  2. Ubuntu 18.04

Sudo Privileges

Before start we make sure that we will have no permission issue on the installation.

sudo su

Main Server

On this server we will run the nginx, prosody, and jicofo.

Update apt repo

apt-get update

Install NGINX

apt-get install nginx

note that we need to install nginx before installing jitsi-meet so the jitsi-meet not using jetty as the web server

Install Jitsi-Meet, nodejs, make, and latest prosody

wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -
sudo sh -c "echo 'deb https://download.jitsi.org stable/' > /etc/apt/sources.list.d/jitsi-stable.list"
echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list
wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add -
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt update
sudo apt install --no-install-recommends jitsi-meet && apt install lua-sec nodejs make

you will be asked the domain, and ssl option when installing jitsi-meet. For me, I prefer use let's encrypt and then change it later.

Cleaning Not Used Files & Service

remove default site config files on nginx

rm /etc/nginx/site-enabled/default
rm /etc/nginx/site-available/default

stop jitsi videbridge as it will be running on the second server, not in the main server

/etc/init.d/jitsi-videobridge stop

Prosody Global Config

open global prosody configuration file /etc/prosody/prosody.cfg.lua and add this statement:

component_interface = "0.0.0.0"
compinent_ports = { 5347 }
network_backend = "epoll"

Prosody Virtual Host Config

Open your config /etc/prosody/conf.d/<your.domain.com>.cfg.lua and adjust your file like this

-- plugin from repo
plugin_paths = { "/usr/share/jitsi-meet/resources/prosody-plugins/" }

-- domain mapper options, must at least have domain base set to use the mapper
muc_mapper_domain_base = "<your.domain.com>"

cross_domain_bosh = false
cross_domain_websocket = true
consider_bosh_secure = true
consider_websocket_secure = true

VirtualHost "<your.domain.com>"
        -- enabled = false -- Remove this line to enable this host
        authentication = "anonymous"
        -- Properties below are modified by jitsi-meet-tokens package config
        -- and authentication above is switched to "token"
        --app_id="example_app_id"
        --app_secret="example_app_secret"
        -- Assign this host a certificate for TLS, otherwise it would use the one
        -- set in the global section (if any).
        -- Note that old-style SSL on port 5223 only supports one certificate, and will always
        -- use the global one.
        ssl = {
                key = "/etc/prosody/certs/<your.domain.com>.key";
                certificate = "/etc/prosody/certs/<your.domain.com>.crt";
        }
        speakerstats_component = "speakerstats.<your.domain.com>"
        conference_duration_component = "conferenceduration.<your.domain.com>"
        -- we need bosh
        modules_enabled = {
            "bosh";
            "websocket";
            "pubsub";
            "ping"; -- Enable mod_ping
            "speakerstats";
            "conference_duration";
            "muc_lobby_rooms"
        }
        c2s_require_encryption = false
        lobby_muc = "lobby.<your.domain.com>"
        main_muc = "conference.<your.domain.com>"
        muc_lobby_whitelist = { "recorder.<your.domain.com>" }

Component "conference.<your.domain.com>" "muc"
    storage = "memory"
    modules_enabled = {
        "muc_meeting_id";
        "muc_domain_mapper";
    }
    admins = { "focus@auth.<your.domain.com>" }
    muc_room_locking = false
    muc_room_default_public_jids = true

-- internal muc component
Component "internal.auth.<your.domain.com>" "muc"
    storage = "memory"
    modules_enabled = {
      "ping";
    }
    admins = { "focus@auth.<your.domain.com>", "jvb@auth.<your.domain.com>" }
    muc_room_locking = false
    muc_room_default_public_jids = true

VirtualHost "auth.<your.domain.com>"
    ssl = {
        key = "/etc/prosody/certs/auth.<your.domain.com>.key";
        certificate = "/etc/prosody/certs/auth.<your.domain.com>.crt";
    }
    authentication = "internal_plain"

Component "focus.<your.domain.com>"
    component_secret = "S4TKfRmB"

Component "speakerstats.<your.domain.com>" "speakerstats_component"
    muc_component = "conference.<your.domain.com>"

Component "conferenceduration.<your.domain.com>" "conference_duration_component"
    muc_component = "conference.<your.domain.com>"

Component "lobby.<your.domain.com>" "muc"
    storage = "memory"
    restrict_room_creation = true
    muc_room_locking = false
    muc_room_default_public_jids = true

You can comment or delete other line if there are any different with your file.

Restart Prosody

/etc/init.d/prosody restart

Look at JVB Password in Prosody

You can check the password by execute this command

cat /var/lib/prosody/auth%2e<your%2edomain%2ecom>/accounts/jvb.dat

This password will be used by jvb on the second server to connect to prosody

Second Server

On this server we will run the jitsi videobridge2.

Install Jitsi-Videobridge

wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -
sudo sh -c "echo 'deb https://download.jitsi.org stable/' > /etc/apt/sources.list.d/jitsi-stable.list"
sudo apt-get update
sudo apt-get install jitsi-videobridge2

you will be asked the domain, input the domain of the main server. This JVB server doesn't need a domain.

Config file

open /etc/jitsi/videobridge/config make sure you the config is already right:

# Jitsi Videobridge settings

# sets the XMPP domain (default: none)
JVB_HOSTNAME= --> leave this blank

# sets the hostname of the XMPP server (default: domain if set, localhost otherwise)
JVB_HOST= --> leave this blank

# sets the port of the XMPP server (default: 5275)
JVB_PORT=5347 --> adjust this value to prosody listen port 

# sets the shared secret used to authenticate to the XMPP server
JVB_SECRET=6iHFEg3U --> it doesn't matter anymore

# extra options to pass to the JVB daemon
JVB_OPTS="--apis=rest,"

# adds java system props that are passed to jvb (default are for home and logging config file)
JAVA_SYS_PROPS="-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/etc/jitsi -Dnet.java.sip.communicator.SC_HOME_DIR_NAME=videobridge -Dnet.java.sip.communicator.SC_LOG$

sip-communicator.properties file

open /etc/jitsi/videobridge/sip-communicator.properties and then add these statement

org.jitsi.videobridge.ENABLE_STATISTICS=true
org.jitsi.videobridge.STATISTICS_TRANSPORT=muc,colibri
org.jitsi.videobridge.xmpp.user.shard.HOSTNAME=<your.domain.com>
org.jitsi.videobridge.xmpp.user.shard.DOMAIN=auth.<your.domain.com>
org.jitsi.videobridge.xmpp.user.shard.USERNAME=jvb
org.jitsi.videobridge.xmpp.user.shard.PASSWORD=<your jvb password> --> from jvb.dat
org.jitsi.videobridge.xmpp.user.shard.MUC_JIDS=JvbBrewery@internal.auth.<your.domain.com>
org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAME=<unique name for the jvb>
org.jitsi.videobridge.xmpp.user.shard.DISABLE_CERTIFICATE_VERIFICATION=true

If your JVB server is behind NAT, also add this 2 statement on this file

org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>

Restart All Services

on main server

/etc/init.d/prosody restart
/etc/init.d/jicofo restart

on jvb server

/etc/init.d/jitsi-videobridge2 restart

Checking

To make sure all setup is success, you can check jicofo log

grep 'Added new videobridge' /var/log/jitsi/jicofo.log

You should see your videobridge nickname there.

Extra

To add more Videobridge, just install the jitsi-videobridge on the new server and follow the Second Server installation.

@krishnakanthpps
Copy link

krishnakanthpps commented Jun 23, 2020

How did you solve this issue?

2020-06-23 21:22:23.976 WARNING: [20] [hostname=localhost id=shard] MucClient.lambda$getConnectAndLoginCallable$7#643: [MucClient id=shard hostname=localhost] error connecting
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: 'localhost:5222' failed because: localhost/127.0.0.1 exception: java.net.ConnectException: Connection refused (Connection refused)
at org.jivesoftware.smack.SmackException$ConnectionException.from(SmackException.java:278)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration(XMPPTCPConnection.java:619)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:902)
at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:383)
at org.jitsi.xmpp.mucclient.MucClient.lambda$getConnectAndLoginCallable$7(MucClient.java:638)
at org.jitsi.retry.RetryStrategy$TaskRunner.run(RetryStrategy.java:193)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

@facsiaginsa
Copy link
Author

facsiaginsa commented Dec 11, 2020

How did you solve this issue?

2020-06-23 21:22:23.976 WARNING: [20] [hostname=localhost id=shard] MucClient.lambda$getConnectAndLoginCallable$7#643: [MucClient id=shard hostname=localhost] error connecting
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: 'localhost:5222' failed because: localhost/127.0.0.1 exception: java.net.ConnectException: Connection refused (Connection refused)
at org.jivesoftware.smack.SmackException$ConnectionException.from(SmackException.java:278)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration(XMPPTCPConnection.java:619)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:902)
at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:383)
at org.jitsi.xmpp.mucclient.MucClient.lambda$getConnectAndLoginCallable$7(MucClient.java:638)
at org.jitsi.retry.RetryStrategy$TaskRunner.run(RetryStrategy.java:193)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

The following addresses failed: 'localhost:5222' failed because: localhost/127.0.0.1 exception: java.net.ConnectException: Connection refused (Connection refused)

It is because of firewall blocked. make sure the firewall is open at port 5222

@guruatwork
Copy link

guruatwork commented Dec 23, 2020

If a conference connects to JVB on 2nd server, the user do not see speaker focus switch. They do see speaker focus if the conference is hosted on JVB running on the jicofo/prosody server. What might be missing?

@facsiaginsa
Copy link
Author

facsiaginsa commented Dec 28, 2020

Hmm.. maybe its the signaling part. Are you using websocket/sctp in your jvb configuration? @guruatwork

@vin070
Copy link

vin070 commented Feb 13, 2022

cross_domain_websocket = true;
consider_websocket_secure = true;
Thanks buddy, You saved my time.
After seeing your file, I got to know these parameters should be placed globally.

@vin070
Copy link

vin070 commented Feb 13, 2022

@krishnakanthpps , I was getting the same error.
Place below parameters globally in prosody file.
cross_domain_websocket = true;
consider_websocket_secure = true

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 3, 2022

Tried to setup the Jitsi with videobridge as per the procedure, but i am unable to add the videobridge.
while running :- grep 'Added new videobridge' /var/log/jitsi/jicofo.log
it lists the videobridge installed during jitsi-meet server. Doesnot list the second videobridge
Firewall NOT Enabled for Testing
Is there any changes to be made.
I have attached the files

Config Files

@facsiaginsa
Copy link
Author

facsiaginsa commented Apr 3, 2022

how about checking the jicofo log & jvb log, is there any error there?

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 4, 2022

Logs of Meet Server & Videobridge

JVB Log @ Videobridge : MucClient.lambda$getConnectAndLoginCallable$7#642: Failed to login. Disconnecting to trigger a re-connect.

meet-server-jicofo log
meet-server-jvb log
videobridge1-jvb log

@facsiaginsa
Copy link
Author

facsiaginsa commented Apr 5, 2022

on the JVB log it said that it failed to login, are you sure the org.jitsi.videobridge.xmpp.user.shard.PASSWORD is correct?

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 5, 2022

Yes, the password was wrong. Earlier used the Secret from cat /var/lib/prosody/auth%2e<your%2edomain%2ecom>/accounts/jvb.dat, which failed to connect.

When tried with the Password from JVB came along with Jitsi Meet, everyhing worked fine.

Not sure why secret from jvb.dat is not working. In jvb.dat, salt, stored_key and server_key are there which one should we use. Earlier, tried stored_key and server_key, but unfortunately both didn't work.

In Prosody config (/etc/prosody/conf.d/<your.domain.com>.cfg.lua), Under VirtualHost "auth.<your.domain.com>", authentication is "internal_hashed", but in the procedure it is internal_plain, if i change it internal_plain, normal jitsi meet also show error.

Kindly share your views which might help others facing such issue with current build.

@facsiaginsa
Copy link
Author

facsiaginsa commented Apr 5, 2022

hmm..

jvb.dat should contain the same Password from JVB that came along with Jitsi Meet. It is actually generated by "prosodyctl register" command.

Do you change the password on jvb.dat manually by editing the file?

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 5, 2022

cat /var/lib/prosody/auth%2e<your%2edomain%2ecom>/accounts/jvb.dat

return {
["salt"] = "3bc096c4-84e4-4ac7-955e-9dc7aa13b038";
["iteration_count"] = 4096;
["stored_key"] = "2c36cae1c2f95302cfc7ed6e13e937f324d5fa3a";
["server_key"] = "d194307bb5dc74c40472353d99313b0660baacd6";
};

But the password in jvb + jitsi meet installation

sudo nano /etc/jitsi/videobridge/sip-communicator.properties

org.jitsi.videobridge.xmpp.user.shard.USERNAME=jvb
org.jitsi.videobridge.xmpp.user.shard.PASSWORD=AYKcbJvZ

@facsiaginsa
Copy link
Author

facsiaginsa commented Apr 5, 2022

Oh, just notice that the jvb.dat format is different now. it was like this back then:

return {
["password"] = "dITC8A9t";
};

Maybe I will update this later. thanks for the info!!

@facsiaginsa
Copy link
Author

facsiaginsa commented Apr 18, 2022

@pkmkrishnakumar I have already updated the tutorial here: https://facsiaginsa.com/jitsi/install-jitsi-meet-with-multi-server-configuration

Many thanks for your input! This tutorial is for installing the latest stable jitsi as of April 2022

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 24, 2022

I followed the tutorial , while checking the installation https://<your.domain.com>/xmpp-websocket showed It works. So prosody configuration is correct.

But in JVB, got Error 404.

This is my nginx config in JVB:

server {
listen 443 ssl;
server_name main-server-domain;

    ssl_protocols TLSv1.1 TLSv1.2;


    ssl_certificate /etc/letsencrypt/live/main-server-domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/main-server-domain/privkey.pem;


    location ~ ^/colibri-ws/jvb1/(.*) {
            proxy_pass http://127.0.0.1:9090/colibri-ws/jvb1/$1$is_args$args;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            tcp_nodelay on;
    }

}

This is jvb.conf

videobridge {
http-servers {
public {
port = 9090
}
}

websockets {
    enabled = true
    domain = "main-server-domain:443"
    tls = true
    server-id = jvb1
}

}

This is the sip-communicator.properties config. I coudn't find the mistake.

org.ice4j.ice.harvest.DISABLE_AWS_HARVESTER=true
org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES=meet-jit-si-turnrelay.jitsi.net:443
org.jitsi.videobridge.ENABLE_STATISTICS=true
org.jitsi.videobridge.STATISTICS_TRANSPORT=muc, colibri
org.jitsi.videobridge.xmpp.user.shard.HOSTNAME=main-server-domain
org.jitsi.videobridge.xmpp.user.shard.DOMAIN=auth.main-server-domain
org.jitsi.videobridge.xmpp.user.shard.USERNAME=jvb
org.jitsi.videobridge.xmpp.user.shard.PASSWORD=TYMcbGvW
org.jitsi.videobridge.xmpp.user.shard.MUC_JIDS=JvbBrewery@internal.auth.wcf8.jit.ac.in
org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAME=jvb1

JVB Websocket Configuration

org.jitsi.videobridge.rest.jetty.port=9090
org.jitsi.videobridge.rest.COLIBRI_WS_DISABLE=false
org.jitsi.videobridge.rest.COLIBRI_WS_TLS=true
org.jitsi.videobridge.rest.COLIBRI_WS_DOMAIN=main-server-domain
org.jitsi.videobridge.rest.COLIBRI_WS_SERVER_ID=jvb1

org.jitsi.videobridge.xmpp.user.shard.DISABLE_CERTIFICATE_VERIFICATION=true

org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=local-ip
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=public-ip

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 24, 2022

By the way , when i try to share screen, it show blank screen for all users in console, i get following error.

can’t establish a connection to the server at wss://public-domain/colibri-ws/jvb1/12de72034fbe0d35/8cb5311c?pwd=6c0fs4qi31151k1oo9237hebrr

@facsiaginsa
Copy link
Author

facsiaginsa commented Apr 24, 2022

Try org.jitsi.videobridge.rest.COLIBRI_WS_DOMAIN=main-server-domain:443

Is that fix the issue?

Yes, The share screen is blank because the websocket configuration is not correct.

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 24, 2022

No luck.
Still i get error 404 on https://jvb.domain/colibri-ws/jvb1/

But screen sharing works with Firefox but not with Chrome based browsers.

@facsiaginsa
Copy link
Author

facsiaginsa commented Apr 24, 2022

Can get the jvb log to see the problem?

Try grep 'ws' /var/log/jitsi/jvb.log

And then, can you confirm that there is no space in your config before "colibri" text:

org.jitsi.videobridge.STATISTICS_TRANSPORT=muc, colibri

Lastly, does your videobridge has the same domain with the web domain? I see this configuration:

org.jitsi.videobridge.rest.COLIBRI_WS_DOMAIN=main-server-domain <-- it should be jvb domain

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 25, 2022

JVB Log:

root@wcf1:~# grep 'ws' /var/log/jitsi/jvb.log
JVB 2022-04-25 09:27:02.566 INFO: [1] ColibriWebSocketService.#40: Base URL: wss://main-server-domain:443/colibri-ws/jvb1 Relay URL: wss://main-server-domain:443/colibri-relay-ws/jvb1
JVB 2022-04-25 09:27:02.703 INFO: [1] ColibriWebSocketService.registerServlet#79: Registering servlet with baseUrl = wss://main-server-domain:443/colibri-ws/jvb1, relayUrl = wss://main-server-domain:443/colibri-relay-ws/jvb1

If org.jitsi.videobridge.rest.COLIBRI_WS_DOMAIN=jvb-server-domain

It shows blank screen while screen sharing, then its not even working with Firefox.
Not sure why it is so.

@pkmkrishnakumar
Copy link

pkmkrishnakumar commented Apr 25, 2022

By the way I have already added the Colibri block in Main Servers Ngnix as below.

# colibri (JVB) websockets for jvb1
location ~ ^/colibri-ws/jvb1/(.*) {
    proxy_pass http://<<local-ip-jvb1>>:9090/colibri-ws/jvb1/$1$is_args$args;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host main-server-domain;
    tcp_nodelay on;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment