Reliable videoconferencing

Conference Call

© Lead Image © Dan Barbalata, 123RF.com

© Lead Image © Dan Barbalata, 123RF.com

Author(s):

If you are looking for an alternative to commercial videoconferencing platforms, Jitsi offers an open source solution that lets you build and deploy online videoconferences.

Halfway through a phone conversation amid the doom and gloom of the global pandemic, someone complained about commercial online videoconferencing services creaking at the seams due to the massive increase in demand.

This led me to think about open source video conferencing options. After a little bit of reading, I discovered Jitsi [1], a truly impressive open source project for building and deploying secure videoconference services. Jitsi, courtesy of 8x8 Inc. [2], has an Apache2 license and includes Jitsi Meet [3], a free video conferencing platform, and Jitsi VideoBridge, a Selective Forwarding Unit (SFU) that powers multiperson videoconferencing. For an overview of the project, visit their website [4] or check out their GitHub page [5].

Jitsi offers secure and scalable videoconferences, either as a standalone app or embedded into your own web application. Jitsi has been around since 2003 in one incarnation or another, with continual fine tuning over recent years.

You do not need an account to start a video call with Jitsi, and it is very browser-friendly and mobile-compatible. Jitsi also allows screen sharing, voting with your hand, and online chat. In this article, I'll show you how to use Jitsi to create a fully encrypted, open source, free-to-use, videoconferencing service.

Getting Started

I'll walk you through what you need to get Jitsi up and running. Also, I'll assist in switching off as many network ports as possible so that you're only exposing the HTTPS port to the public, and I'll provide some fine-tuned firewall rules. To get an insight into all the features Jitsi offers, I will install the full suite of Jitsi software. You will be pleasantly surprised at how little the disk footprint is.

For my videoconferencing server, I'll use DigitalOcean [6], which refers to servers as "droplets." When creating the droplet, I'll ask the cloud platform to install Ubuntu 18.04 (Bionic Beaver) as it has a shelf life until April 2028. I'll assume that you can create a DigitalOcean account on your own. Setting up a droplet manually is easy – if you are new to DigitalOcean, visit their website for more information on setting up a droplet [7].

After logging in over SSH, run

apt update; apt upgrade -y

followed by a reboot to update the operating system software. After running the following command:

$ cat /etc/os-release

you will get the output shown in Listing 1, confirming that the server is running the correct Ubuntu version.

Listing 1

Confirming Operating System

NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

The next trick is to install Apache2 (or NGINX if you prefer). During installation, Jitsu will figure out which web server you are using and then work via that server. Install the Apache2 web server with:

$ apt install apache2

After entering the droplet's IP address into a browser, you will see that Apache2 is running as expected (Figure 1).

Figure 1: Happiness is Apache2 serving HTML as expected.

Next, I'll follow the installation instructions from Jitsi's website [8].

To ensure that I'm connecting to the right repository, as the root user, I'll set up the key for the Jitsi repository with the following:

$ wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | apt-key add -
OK

Then, I'll open up a file called /etc/apt/sources.list.d/jitsi-stable.list and save the following line to it:

deb https://download.jitsi.org stable/

After that, I'll do a quick update as shown in Listing 2.

Listing 2

Connection to Jitsi Repository

$ apt update
Hit:1 http://security.ubuntu.com/ubuntu bionic-security InRelease
Get:2 http://mirrors.digitalocean.com/ubuntu bionic InRelease [242 kB]
Get:3 https://download.jitsi.org stable/ InRelease [2415 B]
Hit:4 http://mirrors.digitalocean.com/ubuntu bionic-updates InRelease
Hit:5 http://mirrors.digitalocean.com/ubuntu bionic-backports InRelease
Get:6 https://download.jitsi.org stable/ Packages [36.4 kB]
Fetched 281 kB in 1s (363 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
All packages are up to date.

As you can see from the output in Listing 2, the Jitsi repo has been connected to as hoped and accessed without complaint following the key that I installed.

Installing Jitsi

I'm now ready to install the videoconferencing suite, barring some firewall tweaking. The commands in Listing 3 install the full package.

Listing 3

Installing Jitsi

$ apt install jitsi-meet
ca-certificates-java fontconfig-config fonts-dejavu-core java-common jicofo jitsi-meet jitsi-meet-prosody jitsi-meet-web jitsi-meet-web-config jitsi-videobridge libavahi-client3 libavahi-common-data libavahi-common3 libcups2 libfontconfig1 libjpeg-turbo8 libjpeg8 liblcms2-2 libnspr4 libnss3 libpcsclite1 libxi6 libxrender1 libxtst6 lua-bitop lua-event lua-expat lua-filesystem lua-sec lua-socket lua5.1 openjdk-8-jre-headless prosody x11-common

As expected, the installation involves a reasonably large number of files, but it only takes about 215MB of extra space on my server. You might notice that the x11-common package will be installed; usually this package wouldn't be used on a headless server driven by the command line. Consequently, you might want to have this server dedicated to Jitsi.

The jitsi-meet package installs the whole suite, which I will do to show all of Jitsi's features. You also can just install the individual components you need as follows:

$ apt install jitsi-videobridge
$ apt install jicofo
$ apt install jigasi

Upon launching the jitsi-meet package, you will be asked for a hostname. Choose a sensible one. Assuming you own a domain name, create a DNS name (an A record) for your server's IP address to save time later. I've chosen this hostname:

call.chrisbinnie.tld    IN    A   123.123.123.123

Enter your hostname in the pop-up box and then choose Generate a new self-signed certificate on the next screen. (You will get a chance later to obtain a Let's Encrypt certificate.)

At this stage, screeds of data are flying up the terminal as the Jitsi software runs through its installation. Listing 4 shows the tail end of the output without errors before returning you to a prompt.

Listing 4

Generating a Self-Signed Certificate

Running hooks in /etc/ca-certificates/update.d...
done.
done.
Processing triggers for ureadahead (0.100.0-21) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...

Next Jitsi will auto-configure a Let's Encrypt certificate for free and associate it with your hostname. You need to wait for your DNS to become available (if your DNS isn't ready, then just run it again when the DNS is available) to run a sophisticated Let's Encrypt script. To confirm that your DNS is live, run this redacted command:

$ host -v -t a call.chrisbinnie.tld
  ns1.nameserver.tld

and then run the Let's Encrypt script:

$ /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh

In this brief process, you're prompted for an email address. Then, as if by magic, certificates are mysteriously installed, taking all the configuration pain away (Listing 5).

Listing 5

Let's Encrypt Installation Successful

 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/call.chrisbinnie.tld/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/call.chrisbinnie.tld/privkey.pem
   Your cert will expire on 2020-06-22. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
Configuring apache2

You can renew the certificate easily in the future by running the command again and look for the output as shown in Listing 5.

Firewall Rules

Your next step in to set up your firewall rules.

I won't lock down your SSH port to a specific IP address in this example, because I don't want you locked out mid-configuration. You can use iptables or even TCP Wrappers to lock down your SSH yourself. Once testing is finished, you also need to change the SSH port and harden your SSH daemon (if you wish).

In order to configure iptables from Netfilter, I'll first create a simple script, /root/iptables.sh (Listing 6), and then make it executable with the command

chmod +x /root/iptables.sh

Listing 6

iptables.sh

01 # Clear old config first
02 iptables -P INPUT ACCEPT
03 iptables -P FORWARD ACCEPT
04 iptables -P OUTPUT ACCEPT
05 iptables -t nat -F
06 iptables -t mangle -F
07 iptables -F
08 iptables -X
09
10 # Drop inbound and forwarding but allow outbound
11 iptables -P INPUT DROP
12 iptables -P FORWARD DROP
13 iptables -P OUTPUT ACCEPT
14
15 # Allow localhost in/out
16 iptables -A INPUT -i lo -j ACCEPT
17 iptables -A OUTPUT -o lo -j ACCEPT
18
19 # Allow established traffic to flow
20 iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
21
22 # Apparently Jitsi can use these ephemeral ports so allow them inbound
23 iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT
24
25 # Enable HTTPS access
26 iptables -A INPUT -p tcp --dport 443 -j ACCEPT
27
28 # Allow HTTP for Let's Encrypt temporarily
29 iptables -A INPUT -p tcp --dport 80 -j ACCEPT
30
31 # Change the default port in /etc/ssh/sshd_config from 22 after testing
32 iptables -A INPUT -p tcp --dport 2002 -j ACCEPT

so that I have a backup of my firewall rules.

These firewall rules are just an example, so you might need to adjust them according to your needs. You can always log in via the DigitalOcean console (in your browser) if you get stuck here and lose SSH access.

To run the script in Listing 6 enter:

$ /root/iptables.sh

To verify that the firewall rules are in place, use:

$ iptables -nvL

To make sure your custom iptables firewall rules persist after a reboot, install the very handy iptables-persistent package with:

$ apt install iptables-persistent

Then, choose yes to save IPv4 rules and select no for IPv6 rules as there aren't any. A quick reboot is needed to check that you can still get back into the server by SSH.

If I run the iptables -nvL command again to verify that the firewall rules have persisted, I will see the output displayed in Listing 7.

Listing 7

Firewall Rules Persist

Chain INPUT (policy DROP 23 packets, 1768 bytes)
 pkts bytes target  prot opt in  out  source     destination
  174 24898 ACCEPT  all  --  lo  *    0.0.0.0/0  0.0.0.0/0
   65  7817 ACCEPT  all  --  *   *    0.0.0.0/0  0.0.0.0/0  ctstate RELATED,ESTABLISHED
    0     0 ACCEPT  udp  --  *   *    0.0.0.0/0  0.0.0.0/0  udp dpts:10000:20000
    0     0 ACCEPT  tcp  --  *   *    0.0.0.0/0  0.0.0.0/0  tcp dpt:443
    0     0 ACCEPT  tcp  --  *   *    0.0.0.0/0  0.0.0.0/0  tcp dpt:80
    4  1095 ACCEPT  tcp  --  *   *    0.0.0.0/0  0.0.0.0/0  tcp dpt:22
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target  prot opt in  out  source     destination
Chain OUTPUT (policy ACCEPT 62 packets, 9148 bytes)
 pkts bytes target  prot opt in  out  source     destination
  174 24898 ACCEPT  all  --  *   lo   0.0.0.0/0  0.0.0.0/0

In short, the rules in Listing 7 mean that outbound traffic is allowed. However, inbound traffic is only permitted if it's part of a conversation already taking place and HTTP is open (close this soon after you finish testing since the script leaves it open, but note that your LetsEncrypt certificate refreshes need this port open) as well as HTTPS and SSH ports (which you should lock down yourself and change the port number). UDP ports are also enabled for ephemeral connections in the 10000-20000 range (this may not be required).

Start a Meeting

Now, for the moment of truth. To see if I can access my videoconferencing suite, I enter the following URL in my browser: https://call.chrisbinnie.tld. Success: Jitsi Meet's welcome screen appears with a clean, easy on the eyes design (Figure 2).

Figure 2: A warm welcome to Jitsi's videoconferencing suite.

In the scrolling text under the Start a new meeting box, random words appear to prevent someone from immediately guessing your meeting's name and joining without an invite. Remember this software is so accessible that you don't even need to sign up for an account. Note, however, that it's easy to add a password to the meeting to prevent unwelcome visitors.

Once you start a meeting, you can see Jitsi flex its muscles.

If you start Jitsi with your camera switched off, you will see the screen shown in Figure 3. On the bottom left, you'll find a screen sharing icon, a raise your hand to vote icon (or pay attention to me icon), and an icon to start text-based chats. In the middle at the bottom of the screen, there's the familiar mute/unmute, hang up, and start/stop video buttons. To the bottom right, a settings menu lets you do things like blurring the background so that your camera focuses on you for a bit more privacy (currently in beta, so use with caution – my CPU didn't like this feature much).

Figure 3: Starting a meeting in Jitsi with the camera disabled.

If you enter your name and an email address associated with Gravatar [9], then you will be associated with a graphical avatar.

Another setting lets you choose different microphones and webcams on your system. I have two of each; using WebRTC [10], both are available in Google Chrome without issue. Although Mozilla Firefox should work in the same way, there've been a few reports of issues, but I've had no issues with Chrome and Firefox. With Firefox I had the most success with screen sharing. If in doubt, clear your browser cache and then restart the browser; that seems to free up WebRTC resources again.

Join In

It's also remarkably easy to join video calls with standard telephony. According to the documentation, it's quite possible to connect to your server via multiple international telephone numbers if you set up Jigasi [11] (the Jitsi gateway to SIP) to use a SIP provider. (See [12] for an explanation of the difference between VoIP and SIP.)

On Jitsi Meet, a Chrome pop-up will encourage you to install a Chrome Extension to integrate Google Calendar and Office 365 (Figure 4).

Figure 4: You can join a Jitsi Meet call without installing anything. However, you're encouraged to integrate with Google Calendar and Office 365.

For iOS users, navigate to Jitsi Meet on IOS [13], where you can install a client on Apple devices. According to the website, it's available for iPhone, iPad, and Apple Watch, but sadly I can't test on these devices.

I can however confirm that the Android app [14] works. You don't need to install a server of your own either; it just uses Jitsi Meet automatically. The app is slick, simple, and fast and connects to my server (https://call.chrisbinnie.tld) instantly if I alter the settings under Server URL.

Jitsi also offers packages for F-Droid [15], React Native, and Electron.

The End Is Nigh

With Jitsi, there are no artificial user limits. Instead, bandwidth and server resources ultimately determine the number of users.

On DigitalOcean, I purposely chose a $5/month droplet for testing. I have had a few streams connected to it at once with no noticeable additional load. I've been monitoring the server as I've used it via SSH. If you notice drop-outs or other issues, then try getting your fellow participants to drop down from full HD streaming. Of course, you will need significant bandwidth and more servers for multiple chats in an organization, but the cloud makes light work of the required flexibility.

If you start creaking at the seams with just one server instance, you can scale a Jitsi installation as described in an article by Jan Doberstein [16]. The scaling seems fairly intuitive, once you know how. Doberstein says that the real resource hog is jitsi-videobridge, which you should scale first. Since this issue seems likely to arise at some point, I encourage you to read through Doberstein's article to find the fix and learn more about the software's innards. The article is current and any references to the latest release should apply.

Since creating my Jitsi server, I have made sure that I closed down the HTTP port and added more security to the default SSH installation, changing the port by locking it to my IP addresses. As an extra assurance, the iptables' default deny policy keeps out everything but SSH and HTTPS except for traffic that originates internally and wants to go outbound. I've also added simple scripts to alert me when updates are available so I don't miss them if I don't log in for a few days.

If you are looking for an alternative to overloaded commercial videoconferencing services, give Jitsi a try. I hope you will enjoy Jitsi as much as I have.