Making the Isolation bearable: Self-hosted Audio/Video Conferencing with Jitsi Meet and Mumble
Update (2020-03-25): I published the Ansible role I wrote to set up the server. Feel free to use and improve it; it is still buggy though and does not include the manual fixes to the nginx config I mentioned below. Grep for FIXME and TODO.
Introduction and Story Hook
My wife and I have a pen&paper group (let’s get this out of the way). That means we meet every week for an evening to basically tell a story together, with some rules. It can be a very fun activity, but the isolation rules which have been put in place (rightfully!) rule out physically meeting up with each other.
In order to still be able to continue the story and get some social interaction, a solution had to be found.
I am active in the instant messaging standards community, however, I have never really delved into A/V conferencing. While it has been long on my to do list to implement one of the various standards which exist around the real-time transmission of audio and video data, I never got around to do it.
So, here goes. In the first part, this post will describe how I set up jitsi-meet on my own server. In addition, I’ll say a few words about Mumble. A few, because for one it is super easy to set up, but also because it is audio-only. I only deployed mumble as a fail-safe fallback option, which we luckily did not need.
In the second part of the post I will present some measurements I took during our pen&paper session last night. Six people, seven Jitsi Meet clients, five hours.
Let’s dive right in.
Setting up Jitsi Meet
Jitsi Meet is based on the XMPP messaging standard. However, Jitsi instances do not like to federate much and from my experience, it does not make sense to re-use any existing XMPP deployment and instead keep it completely separated.
My successful install of Jitsi Meet (I stubbornly tried it in a few different ways before that) was mostly based on the Quick Install guide from the Jitsi Meet team themselves. I suggest you go there, do that and then only look here if anything does not work.
Prerequisites
My system is a Debian buster virtual server with two CPUs and four gigabytes of RAM. To preempt a bit of the later measurements, the entire system did not exceed a usage of 1.2 GiB, so RAM-wise it is slightly overpowered.
Since Jitsi Meet is, among others, a web application, port 80 and 443 need to be free. In addition, you’ll have to be able to send and receive traffic on ports 4443/tcp and 10000/udp, via both IPv4 and IPv6 (if you have that; neither IPv4 nor IPv6 is a strict requirement, but you’ll need it if you have IPv4/IPv6-only users). If you are behind NAT, you can configure Jitsi Meet to understand that.
If you already have a webserver installed, you’ll have to configure the web part yourself. There is a Manual Install document which goes into some of the aspects you need to handle in such a case.
Installing Jitsi Meet
To install Jitsi Meet on Debian, you first have to enable the apt repository by the Jitsi developers. If you, like me, do not like enabling third-party repositories on productive servers, I suggest you put your Jitsi instance in an LXC-based container. Or maybe inside Docker. Though if you go with Docker, you may be interested in docker-jitsi-meet instead.
You need to follow the linked Quick Install document up to the point where apt install jitsi-meet is called. During the installation you’ll be asked for two things: A domain name under which you want to serve your instance (which you cannot easily change later) and whether you want to use existing certificates.
We’ll refer to the domain name you gave as $HOSTNAME in the following.
They then suggest to install Let’s Encrypt certificate using the script they provide. I found that this script downloads certbot-auto from the EFF website without further signature checking and executes it as root. This isn’t ideal.
You can instead use certbot, but you have to patch the nginx configuration created by the package slightly by adding the following lines to /etc/nginx/sites-enabled/$HOSTNAME.conf, where $HOSTNAME is the domain name you gave Jitsi during the installation with apt.
location ~ ^/\.well-known/.+$ { try_files $uri @root_path; }
Then you can install certbot (apt install certbot) and request a certificate:
# certbot certonly -d $HOSTNAME --webroot --webroot-path /usr/share/jitsi-meet
Again, replace $HOSTNAME with the domain name of your Jitsi Meet installation. Note that certbot automatically puts itself into crontab so renewal will happen automatically. It will, however, not auto-reload nginx. To achieve that, you can add your own crontab entry which calls systemctl reload nginx, for example once per day or week.
Jitsi Meet configured nginx to load the certificates from /etc/jitsi/meet/, so we have to create symlinks there so that nginx finds the correct certificates:
# rm /etc/jitsi/meet/$HOSTNAME.{crt,key} # ln -s /etc/letsencrypt/live/$HOSTNAME/fullchain.pem /etc/jitsi/meet/$HOSTNAME.crt # ln -s /etc/letsencrypt/live/$HOSTNAME/privkey.pem /etc/jitsi/meet/$HOSTNAME.key # systemctl reload nginx
If you want to use IPv6, you also need to fix the nginx configuration which will currently only offer the Jitsi service on IPv4. To do that, you need to duplicate the listen directives in /etc/nginx/sites-enabled/$HOSTNAME.conf to also listen on IPv6. So instead of listen 80;, you need the following:
listen 80; listen [::]:80;
And analogously for listen 443 ssl;.
At this point, you should already be able to reach the Jitsi Meet instance from your browser.
Authentication
As you noticed, your Jitsi Meet instance is currently available to anyone who knows the domain name. This is not ideal. You can secure the instance by enforcing authentication. This is documented in the Secure Domains section of the Jicofo service.
Setting up Mumble
Mumble is a low-latency audio team chat which has its origins in the gaming scene. It has been an early challenger of the proprietary TeamSpeak software. In contrast to Jitsi, it cannot be used from the browser but requires a client to be installed on each user’s machine. The client software is available for Linux, MacOS and Windows and there exist inofficial apps for Android and iOS.
It is very easy to set up. You need to be able to open a UDP and TCP port (by default this is 64738) and that’s it. Install mumble with apt:
# apt install mumble-server
... that’s it.
To allow your users to securely identify your mumble server, you can re-use the certificates you generated for Jitsi and tell mumble to use them via the config file in /etc/mumble-server.ini:
sslCert=/etc/letsencrypt/live/$HOSTNAME/fullchain.pem sslKey=/etc/letsencrypt/live/$HOSTNAME/privkey.pem
Remember to then also create a cron job to reload the certificates.
To log into your Mumble server as privileged user (for example, to add channels or distribute privileges to other users), you first need to set a super user password:
# cd /var/lib/mumble-server # murmurd -readsupw
This will ask for a password which will subsequently be the SuperUser password of the server. You may have to restart mumble after this and then you should be able to log into it as SuperUser.
Why even mumble when you have Jitsi? Videoconferencing and WebRTC are tricky technologies which are easily disturbed by machines which are not powerful enough or by network issues. Mumble is very resilient and low on resource consumption, so it may be an alternative if the circumstances do not allow the use of Jitsi Meet.
Using Jitsi Meet
Using Jitsi Meet is dead simple. You open the website (https://$HOSTNAME) of your installation in the browser and hit go. Then you can copy the link of the page you ended up on and send it to your friends and family.
If they want to join from mobile, there is a quirk. This requires an app to be installed. And rumor has it that it will only work if you set the Jitsi server in the settings (even though it is technically included in the URL already, so this doesn’t really make sense).
Typing the name in the current release of the App is kind of annoying because there is a weird bug with the text input. Copy&Pasting works though.
Once that is sorted out, users should be able to join your Jitsi Meet conferences even from their phones. In my short test, I was able to join a video conference with four users via mobile data while on the go outside.
Resource Consumption
Jitsi Meet is a video conferencing software, and as such it needs a bit of server resources (both CPU and network) to operate.
In contrast to the hardware solution, the Jitsi Meet videobridge software will not re-encode or mix video. This means that in theory the CPU use should not be too high. During our pen&paper session last night, I let Prometheus monitor the resource usage on the box where I installed Jitsi.
Experiment Setup
- Debian Buster VM at Hetzner (CX21, but with only 20 GB disk because I opted out of the disk resize when scaling up from the CX11 I had before)
- Jitsi Meet installed in an LXC container (managed via libvirt)
- IPv6 directly routed to the LXC container, IPv4 via DNAT (stateful, more on that later)
- Initially five people, later six people peak, with seven clients (more on that later)
- Monitoring with Prometheus:
- CPU time metrics of the VM via node-exporter
- Memory use metrics of the VM
- Network traffic on eth0 of the VM
- Network traffic on the various Jitsi ports (80, 443, 4443/tcp and 10000/udp) using nftables counters and the nftables_exporter
- The VM also functions as a shell server, so there were two poezio instances running which caused a baseline of CPU and memory use.
Timeline
First off, you can look at the data yourself. I took an interactive snapshot on my Grafana instance for you to look at.
For everyone else, there’s also a screenshot:

In the second graph on the left side, I marked a few points of interest. I will now go through them one by one.
A around 16:45, we set up the conference. My wife and I joined first, then shortly after 17:00, the first player came along. We chatted a bit and optimised the sound setup. Then the second player tried to join, but was unable to get audio or video to work.
I looked into it and found error messages indicating that no WebRTC session came to be between the Videobridge and the player’s computer. After a while of messing around, I noted that I forgot to configure Videobridge to make it aware of the IPv4 NAT, and this was the first person to not have IPv6. After applying the NAT configuration from the documentation ...
... I restarted the videobridge which kicked everyone out of the conference. The two players from before were able to join (this time with audio!) and a third player came along shortly thereafter. This worked for quite a while stably.
We had issues with one of the two Firefox users getting frozen video. This happened immediately as soon as a second Firefox user was present, which was odd. I recommended one of them to switch to Chromium. That fixed the issue for them, but the other Firefox user still had frozen video. The switch to Chromium is what caused the drop in traffic.
There are two reasons for this: First, the video quality actually dropped a bit when the player switched. Second, there is a problem with Jitsi Meet and Firefox. Normally, Jitsi Meet will continuously send three video streams to the Videobridge: A low definition one, a standard definition one and a high definition one. Then the other clients indicate which version of the streams they want and the videobridge will only send the requested one to the other clients.
Most of the time, you don’t have a participant in full screen, so getting a HD stream makes no sense; your Jitsi Meet in the browser will request SD (if you use the tiled view) or LD (if the participants are folded to the side) video streams.
Since Firefox isn’t able to send multiple stream versions, Jitsi Meet only sends the HD one. That means that everyone will always get the HD stream of all firefox participants, even if they’re only a 64x64 square on the side. We’ll see more data to support this in a bit.
The last player joined. They also joined with Firefox, and immediately we see the traffic jump up by a significant bit. We still had the issue that one member was getting frozen video streams.
At this time, we tried to fix the frozen video streams again (they didn’t go away by switching the other user to chromium).
I set up a victim firefox on my laptop to catch the "disease of the frozen streams" while the new player switched to chroimum. That worked. So I turned of video and audio for my firefox client and let it sit there for the rest of the session.
The drop in traffic was again caused by a player switching to Chrome, though this time without loss in video quality.
After the initial hiccups, Jitsi worked mostly smoothly. One player was having a bad connection and dropped out for a few seconds a few times, but other than that it was pretty good and reliable.
Resource Consumption summary
In the last section of the graph, the setup was continuously as follows:
- Seven clients
- Five clients which received video
- Five clients which sent audio
- Two firefox clients, only one of which sent video
- Five chrome/chromium clients
The CPU load in the graphs is normalised to full load on all cores. That means if you see a CPU load of 100% in the graph, it implies that all cores were fully utilised. Note that the blue line in the CPU graph is in fact the load5 metric of the system and uses the right axis, while the other data uses the left axis and is CPU time spent per second.
The Jitsi Meet conference thus used approximately 80% of a CPU core continuously. Due to the high amount of threads, the load5 was wiggling around 2.0. Memory use started out at ~950 MiB without Jitsi Meet running and then gradually rose to approximately 1.15 GiB. This means approximately 200 MiB of memory used by the server-side components of Jitsi Meet for seven clients.
The memory has not been fully released afterwards though, which makes me think that some of this is overhead caused by memory fragmentation.
The traffic totalled at about 75 GiB (50 GiB tx, 25 GiB rx) on the server side. With only one Firefox client sending video, we had about 2 MiB/s tx and 1 MiB/s rx on the server, which is quite low all over all. I suspect that eliminating the last Firefox client will improve the situation even more.
Summary
I hope this was interesting and/or helpful to someone. Here’s a quick summary:
- Jitsi Meet is easy to set up, if you have a box where you don’t have an HTTP or XMPP server running.
- Mumble is even easier, but we didn’t need it luckily.
- Jitsi Meet is a decent free video conferencing tool.
- However, it is no fun with Firefox. There is a reason they don’t officially support Firefox. Use Google Chrome or Chromium if you can.