Jibri setup and configuration - here’s how! FULL GUIDE

Hi all,
Jibri is the component that is used for recording, streaming and SIP video gateway.

I’ve spent a whole day trying to get the latest version of Jibri to work with a Jitsi meet instance. Even with some good guides out there I found it challenging as things changed in the latest version of Jibri. Eventually I had to combine knowledge from several guides so I decided to put forth all I found in one guide in the hopes it’ll help others figure out Jibri faster.
Same happened to me before with setting up region routing via OCTO which made write my previous guide (link in the first comment).

So… let’s get to it.
Writing this guide I’m assuming you already have a working instance of Jitsi that includes Jitsi meet, Jicofo, JVB.

In this guide we’ll create a separate server for Jibri and connect it to the Jitsi shard so we won’t infringe on one server’s resources.
With this topology (Jibri on a separate server) you can scale and add as many Jibri servers you need and scale your system up.

Before we begin
Please make sure your Jitsi meet instance has a SSL certificate from a SSL authority like ZeroSSL or Let’sencrypt. Self-signed certificate will not work.

Step 1 setting up servers and domain
Get your servers. Get a Debian 10 machine with 2GB of RAM at least. Through trial an error I tried using a 1 gig machine for recording and the service crashed after half a sec.

Get your domain A record for your Jibri server and point it to your server’s IP. You’ll need it to connect the Jitsi meet servers and Jibri.
In this example I’ll use “mydomain.com” as my domain.
The A record I set up for my Jibri server is “recording.mydomain.com”.

Step 2 installing Jibri and dependencies
First update your server

apt update -y
apt upgrade -y

Set your servers host name to match your domain’s A record.

hostnamectl set-hostname recording.mydomain.com

Configure your hosts file

nano /etc/hosts

Add your domain A record to your hosts file recording.mydomain.com {your machine’s name} localhost recording.mydomain.com

Get JAVA 8 (you have to get JAVA 8. Version 11 and probably higher will not work)
Make sure JAVA is not installed on your machine. Run

java -version

You should get

-bash: java: command not found

Install JAVA 8 and dependencies from AdoptOpenJDK Repo.

apt install wget gnupg software-properties-common -y

wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -

add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb

apt install adoptopenjdk-8-hotspot -y

Verify JAVA 8 is installed

java -version

You should get
> Openjdk version “1.8.0_242”
> OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_242-b08)
> OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.242-b08, mixed mode)

Now you’ll need to verify the path of your JAVA 8 using

update-alternatives --config java

You should get

There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/adoptopenjdk-8-hotspot-amd64/bin/java
Nothing to configure.

Now we’ll need to set the JAVA Home Environment Variable by running

nano ~/.bash_profile

Paste this line into the file - (verify the path below is the same as the one shown in the output of the command update-alternatives --config java)

export JAVA_HOME=/usr/lib/jvm/adoptopenjdk-8-hotspot-amd64/bin/java

Save and exit the file. Now source the file.

source ~/.bash_profile



You should get


Now we’ll install packages we’ll need to make changes to the kernel, in case you’re using a cloud provider like DigitalOcean. They install cloud kernel by default which we’ll need to remove.

apt install linux-image-amd64 unzip ffmpeg curl alsa-utils icewm xdotool xserver-xorg-input-void xserver-xorg-video-dummy -y

when prompt for Keyboard layout choose the one you use and press enter .

Once done, run the following command to see your installed kernels

apt list --installed | grep linux-image-

You should get something similar to this output with your machine’s kernel.

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

linux-image-4.19.0-10-cloud-amd64/now 4.19.132-1 amd64 [installed,local]
linux-image-4.19.0-13-amd64/stable,now 4.19.160-2 amd64 [installed,automatic]
linux-image-4.19.0-13-cloud-amd64/stable,now 4.19.160-2 amd64 [installed,automatic]
linux-image-amd64/stable,now 4.19+105+deb10u8 amd64 [installed]
linux-image-cloud-amd64/stable,now 4.19+105+deb10u8 amd64 [installed]

Remove all the cloud kernels (type in the version of your kernel as shown in previous output.

apt remove linux-image-cloud-amd64 linux-image-4.19.0-10-cloud-amd64 linux-image-4.19.0-13-cloud-amd64

When prompt choose Yes then (pay attention - the question is if to abort or not) choose No
Kernels have been removed, You can verify by running the following command again.

apt list --installed | grep linux-image-

Reboot system.

systemctl reboot

Configure Alsa and loopback device to start on boot

echo “snd_aloop” >> /etc/modules

modprobe snd_aloop

Verify the module is loaded

lsmod | grep snd_aloop

You should get

snd_aloop 28672 1
snd_pcm 114688 1 snd_aloop
snd 94208 5 snd_timer,snd_aloop,snd_pcm

Get Google Chrome on your server. This will allow Jibri to join your conference as an invisible user and record it.

curl -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add

echo deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main > /etc/apt/sources.list.d/google-chrome.list

apt update

apt install google-chrome-stable -y

CHROME_DRIVER_VERSION=curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE

wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/

unzip ~/chromedriver_linux64.zip -d ~/

rm ~/chromedriver_linux64.zip

sudo mv -f ~/chromedriver /usr/local/bin/chromedriver

sudo chmod 0755 /usr/local/bin/chromedriver

Turn off warnings about scripted control in Chrome:

mkdir -p /etc/opt/chrome/policies/managed

echo ‘{ “CommandLineFlagSecurityWarningsEnabled”: false }’ >>/etc/opt/chrome/policies/managed/managed_policies.json

Install Jibri

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

sh -c “echo ‘deb https://download.jitsi.org stable/’ > /etc/apt/sources.list.d/jitsi-stable.list”

apt update
apt install jibri -y

Add Jibri’s user account to the necessary groups

usermod -aG adm,audio,video,plugdev jibri

That’s it, Jibri is all set. Now let’s connect the servers.

Step 3 connect the servers
On your Jicofo server we’ll need to make changes to the Prosody config file. We’ll add a MUC (Multi User Component) and the Jibri’s domain A record we created earlier.

cd into the folder

cd /etc/prosody/conf.avail/



and see what’s the name of your lua configuration file.

Open the configuration file

nano /etc/prosody/conf.avail/meet.mydomain.com.cfg.lua

Please note:

meet.mydomain.com → is your Jicofo server.
recording.mydomain.com → is your Jibri server.

You’ll get the config file with all Prosody’s configurations. Go to the end of that file and past the two parts one under the other.
(Please note the first line needs to be commented out using two dashes “–”)

– internal muc component, meant to enable pools of jibri and jigasi clients
Component “internal.auth.meet.mydomain.com” “muc”
modules_enabled = {
storage = “memory”
muc_room_cache_size = 1000

VirtualHost “recording.mydomain.com
modules_enabled = {
authentication = “internal_plain”

Save and exit. Go back into the file using

nano /etc/prosody/conf.avail/meet.mydomain.com.cfg.lua

Check if the quotation marks are shown properly and the values are in order. like “ping” at the bottom. If not mantually correct the file and save.

Reload Prosody

/etc/init.d/prosody reload

Create the necessary users for Jibri on Prosody. Make sure you write down the passwords you set for the users. Change the passwords below as you see fit.

prosodyctl register jibri auth.meet.mydomain.com {JibriPassword}
prosodyctl register recorder recording.mydomain.com {RecorderPassword}

Configuring Jicofo, open

nano /etc/jitsi/jicofo/sip-communicator.properties

Add the following lines


Reload Jicofo

/etc/init.d/jicofo reload

Configure Jitsi Meet, open

nano /etc/jitsi/meet/meet.mydomain.com-config.js

Search with Ctrl+w for the following options - uncomment and set to ‘true’

If you want to enable file recording
fileRecordingsEnabled: true,
If you want to enable live streaming
liveStreamingEnabled: true,

Add this line under one of the mentioned above options

hiddenDomain: ‘recording.mydomain.com’,

Save and exit the file.

Now let’s verify the options to record and stream are shown in the Jitsi menu.
For that open

nano /usr/share/jitsi-meet/interface_config.js

Under TOOLBAR_BUTTONS (run a search for it using Ctrl+w) locate ‘recording’ and ‘livestreaming’.
If they’re there you’re all set.

Configure your servers’ firewall to allow TCP 5222. Run

ufw allow 5222/tcp

And open the port on your external firewall as well.

Jibri’s configuration -
On your Jibri server we need to create the folder to store the recordings

mkdir /recordings
chown jibri:jitsi /recordings

Now configure Jibri’s configuration file, open

nano /etc/jitsi/jibri/config.json

You’ll see the file is empty - that’s because this type of config is considered legacy but Jibri still check for it and run it.

Paste this file content - make sure to change the passwords below with the passwords we previously set for Prosody:

    "finalize_recording_script_path": "/path/to/finalize_recording.sh",
    "xmpp_environments": [
            "name": "prod environment",
            "xmpp_server_hosts": [
            "xmpp_domain": "meet.mydomain.com",
            "control_login": {
                // The domain to use for logging in
                "domain": "auth.meet.mydomain.com",
                // The credentials for logging in
                "username": "jibri",
                "password": "{JibrisPassword}"
            "control_muc": {
                "domain": "internal.auth.meet.mydomain.com",
                "room_name": "JibriBrewery",
                "nickname": "jibri-nickname"
            "call_login": {
                "domain": "recording.mydomain.com",
                "username": "recorder",
                "password": "{RecordersPassword}"
            "room_jid_domain_string_to_strip_from_start": "conference.",
            "usage_timeout": "0"

Restart Jibri

service jibri restart

Check Jibri connected to your instance of Jitsi.

nano /var/log/jitsi/jibri/log.0.txt

Look for the line
2021-01-13 17:09:23.002 INFO: [25] org.jitsi.xmpp.mucclient.MucClient.log() Joined MUC: jibribrewery@internal.auth.meet.mydomain.com


If not:

  1. Circle back make sure all the characters saved properly.
  2. Verify no firewalls blocking your way.
  3. Restart all servers

service prosody restart
service jicofo resraet
service jibri restart

I wrote this guide then followed it myself. The only issue I noticed is weird characters when copying from the forum. Always verify your files changes.

That’s it - and very exciting. Open a Jitsi conference and click on start recording on the menu. Recordings will be saved in the recording folder we created before.


My OCTO FULL GUIDE for regional scaling

No, no, noooooo. This is not advisable. Config.json is being deprecated - Support for Jibri legacy config file (config.json) going away soon-ish - #4 by bbaldino Everybody should be moving to Jbri.conf - ESPECIALLY for those installing Jibri for the first time. And it’s actually untrue that you’ll see a config.json file after a new installation now; you don’t, you see a jibri.conf instead.

I appreciate the thoughts and time you put into this, but it’s just not current.


Thanks @Freddie
So the content of config.json should be in jibri.conf?

As is, jibri.conf is empty

You’re welcome, buddy.

Kind of, but not exactly. The values will be the same, but the field names are different (and this is very important to note because it’s the cause of problems for many people moving from the old Jibri). Jibri.conf will be empty with a new installation and you have to populate the file. Not trying to self-promote, but check out this post on how to configure the new Jibri - TUTORIAL - How to Install the NEW JIBRI

Thanks to @Freddie for pointing out the configuration of the new Jibri.conf. You can find it in /etc/jitsi/jibri

I’m using a deployment from July so this guide works well and to this date works well also with today’s latest versions but for future developments Use this configuration file


jibri {
// A unique identifier for this Jibri
// TODO: eventually this will be required with no default
id = “”
// Whether or not Jibri should return to idle state after handling
// (successfully or unsuccessfully) a request. A value of ‘true’
// here means that a Jibri will NOT return back to the IDLE state
// and will need to be restarted in order to be used again.
single-use-mode = false
api {
http {
external-api-port = 2222
internal-api-port = 3333
xmpp {
// See example_xmpp_envs.conf for an example of what is expected here
environments = [
name = “prod environment”
xmpp-server-hosts = [“your.domain.com”]
xmpp-domain = “your.domain.com

            control-muc {
                domain = "internal.auth.your.domain.com"
                room-name = "JibriBrewery"
                nickname = "jibri-nickname"

            control-login {
                domain = "auth.your.domain.com"
                username = "jibri"
                password = "JPwd"

            call-login {
                domain = "recorder.your.domain.com"
                username = "recorder"
                password = "RPwd"

           strip-from-room-domain = "conference."
            usage-timeout = 0
            trust-all-xmpp-certs = true

recording {
recordings-directory = “/srv/recordings”
# TODO: make this an optional param and remove the default
finalize-script = “/path/to/finalize_recording.sh”
streaming {
// A list of regex patterns for allowed RTMP URLs. The RTMP URL used
// when starting a stream must match at least one of the patterns in
// this list.
rtmp-allow-list = [
// By default, all services are allowed
chrome {
// The flags which will be passed to chromium when launching
flags = [
stats {
enable-stats-d = true
webhook {
// A list of subscribers interested in receiving webhook events
subscribers =
jwt-info {
// The path to a .pem file which will be used to sign JWT tokens used in webhook
// requests. If not set, no JWT will be added to webhook requests.
# signing-key-path = “/path/to/key.pem”

// The kid to use as part of the JWT
# kid = "key-id"

// The issuer of the JWT
# issuer = "issuer"

// The audience of the JWT
# audience = "audience"

// The TTL of each generated JWT.  Can't be less than 10 minutes.
# ttl = 1 hour

call-status-checks {
// If all clients have their audio and video muted and if Jibri does not
// detect any data stream (audio or video) comming in, it will stop
// recording after NO_MEDIA_TIMEOUT expires.
no-media-timeout = 30 seconds

// If all clients have their audio and video muted, Jibri consideres this
// as an empty call and stops the recording after ALL_MUTED_TIMEOUT expires.
all-muted-timeout = 10 minutes

// When detecting if a call is empty, Jibri takes into consideration for how
// long the call has been empty already. If it has been empty for more than
// DEFAULT_CALL_EMPTY_TIMEOUT, it will consider it empty and stop the recording.
default-call-empty-timeout = 30 seconds


2021-07-01 21:16:22.162 WARNING: [25] org.jitsi.xmpp.mucclient.MucClient.log() Disabling certificate verification!

Help I’ve done everything step by step but I’m still not getting
2021-01-13 17:09:23.002 INFO: [25] org.jitsi.xmpp.mucclient.MucClient.log() Joined MUC: jibribrewery@internal.auth.meet.mydomain.com

Send your logs

this is the Jibri Log

2021-07-01 21:22:14.162 INFO: [1] org.jitsi.jibri.Main.log() Jibri run with args [--config, /etc/j
2021-07-01 21:22:14.257 INFO: [1] org.jitsi.jibri.Main.log() Checking legacy config file /etc/jits
2021-07-01 21:22:14.258 INFO: [1] org.jitsi.jibri.Main.log() Legacy config file /etc/jitsi/jibri/c
onfig.json doesn't exist
2021-07-01 21:22:14.666 INFO: [1] org.jitsi.jibri.Main.log() Jibri starting up with id
2021-07-01 21:22:15.234 INFO: [1] org.jitsi.jibri.webhooks.v1.JwtInfo.log() got jwtConfig: {}
2021-07-01 21:22:15.235 INFO: [1] org.jitsi.jibri.webhooks.v1.JwtInfo.log() Unable to create JwtIn
fo: com.typesafe.config.ConfigException$Missing: /etc/jitsi/jibri/jibri.conf: 80: No configuration
 setting found for key 'signing-key-path'
2021-07-01 21:22:15.451 INFO: [1] org.jitsi.jibri.Main.log() Using port 3333 for internal HTTP API
2021-07-01 21:22:15.462 FINE: [16] org.jitsi.jibri.webhooks.v1.WebhookClient.log() Updating 0 subs
cribers of status
2021-07-01 21:22:15.759 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.log() Jibri reports its status 
is now JibriStatus(busyStatus=IDLE, health=OverallHealth(healthStatus=HEALTHY, details={})), publi
shing presence to connections
2021-07-01 21:22:15.767 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.log() Connecting to xmpp enviro
nment on meet.nodokter.com with config XmppEnvironmentConfig(name=prod environment, xmppServerHost
s=[meet.nodokter.com], xmppDomain=meet.nodokter.com, baseUrl=null, controlLogin=XmppCredentials(do
main=auth.meet.nodokter.com, port=null, username=jibri, password=PASSWORD), control
Muc=XmppMuc(domain=internal.auth.meet.nodokter.com, roomName=JibriBrewery, nickname=jibri-nickname
), sipControlMuc=null, callLogin=XmppCredentials(domain=recorder.meet.nodokter.com, port=null, use
rname=recorder, password=PASSWORD), stripFromRoomDomain=conference., usageTimeoutMi
ns=0, trustAllXmppCerts=true)
2021-07-01 21:22:15.768 INFO: [1] org.jitsi.jibri.api.xmpp.XmppApi.log() The trustAllXmppCerts con
fig is enabled for this domain, all XMPP server provided certificates will be accepted
2021-07-01 21:22:15.786 INFO: [1] org.jitsi.jibri.Main.log() Using port 2222 for HTTP API
2021-07-01 21:22:15.789 WARNING: [25] org.jitsi.xmpp.mucclient.MucClient.log() Disabling certifica
te verification!
2021-07-01 21:22:45.794 WARNING: [27] org.jivesoftware.smackx.ping.PingManager.pingServerIfNecessa
ry() XMPPConnection was not authenticated
2021-07-01 21:23:15.446 FINE: [16] org.jitsi.jibri.webhooks.v1.WebhookClient.log() Updating 0 subs
cribers of status
2021-07-01 21:23:16.297 WARNING: [25] org.jitsi.xmpp.mucclient.MucClient.log() [MucClient id=meet.
nodokter.com hostname=meet.nodokter.com] error connecting
org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: 'meet.n
odokter.com:5222' failed because: meet.nodokter.com/ exception: java.net.SocketTimeou
tException: connect timed out, meet.nodokter.com/ exception: java.net.SocketTimeoutEx
ception: connect timed out, meet.nodokter.com/2606:4700:3031:0:0:0:6815:3adf exception: java.net.C
onnectException: Network is unreachable (connect failed), meet.nodokter.com/2606:4700:3031:0:0:0:a
c43:d118 exception: java.net.ConnectException: Network is unreachable (connect failed)
        at org.jivesoftware.smack.SmackException$ConnectionException.from(SmackException.java:278)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration(XMPPTCPConnectio
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:902
        at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:383)

Are JMS and Jibri on the same server?

No they’re not they’re both running on separate 2 core/4gb ram Google Cloud Servers
The JMS is on a server using Ubuntu 20.04 (which is why I could set up jibri on the same server couldn’t change grub to linux generic so I can use snd-aloop)
and Jibri is running on Ubuntu 16.04 (switched to linux generic already and modprobe snd-aloop doesn’t throw a fatal)

This is a problem. You can’t run Jibri on specs so low.

The tutorial above said 2gb ram min. What would you recommend?

2GB has never been adequate for Jibri. And with the latest version, you need even better specs becaue it defaults to 1080p resolution. I’d recommend 4 cores and at least 4GB of RAM (even better if you can allocate more).

Okay thanks but it still doesn’t solve the problem that the jibri server isn’t connecting to the JMS server. I already have port 5222 opened.

Check, maybe prosody is listening on localhost only.

How do I check that?

TCP/5222 is not accessable

curl -m 5 http://meet.nodokter.com:5222/

What is the output for

netstat -taunp | grep 5222

Hello I have same server setup but when i start recording. its says recoding service unavailable and in log.

Jicofo 2021-07-08 02:20:27.851 INFO: [35] [room=controversialropesfillnext@conference.meet.erikakraljevic.com] ChatRoomRoleAndPresence.memberPresenceChanged#130: Chat room event PresenceUpdated member=ChatMember[controversialropesfillnext@conference.meet.erikakraljevic.com/d42fc051, jid: d42fc051-ab77-4a1a-817f-2dfa020ff654@meet.erikakraljevic.com/2174eed9-7a52-481a-8f67-d129591a913e]@13650970
Jicofo 2021-07-08 02:20:57.328 SEVERE: [36] JibriSession.startInternal#305: Unable to find an available Jibri, can’t start
Jicofo 2021-07-08 02:20:57.329 INFO: [36] [room=controversialropesfillnext@conference.meet.erikakraljevic.com] JibriRecorder.handleStartRequest#127: Failed to start a Jibri session, no Jibris available

Please help to solve.
Thanks in advance

Is jibri process running?