# Jibri: recording and streaming a Jitsi Meet conference from a dedicated machine

> Jibri is the Jitsi BRoadcasting Infrastructure, a service that launches Chrome inside a virtual framebuffer and captures and encodes the output with ffmpeg so a Jitsi Meet conference can be recorded or streamed. It is designed to run alone on a separate machine or VM, and it needs a full Jitsi Meet installation in front of it.

**jitsi/jibri** — Jitsi BRoadcasting Infrastructure

- Repository: https://github.com/jitsi/jibri
- Stars: 668 · Forks: 327
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/jitsi-jibri

## A browser in a virtual framebuffer, encoded by ffmpeg

Jibri provides services for recording or streaming a Jitsi Meet conference, and the mechanism is described in two sentences: it works by launching a Chrome instance rendered in a virtual framebuffer and capturing and encoding the output with ffmpeg.

There is no screen capture of a real display and no virtual camera. The browser renders into a framebuffer, ffmpeg reads from that framebuffer through the x11 capture support in ffmpeg, and the audio is routed through an ALSA loopback device. Chrome is driven by chromedriver, so the joining of the conference, the muted state, the start of the recording and the file handling are all done by an automated browser session rather than by a native client.

That design is what makes the isolation requirement sensible. The documentation states that Jibri is intended to be run on a separate machine, or a VM, with no other applications using the display or audio devices, and that only one recording at a time is supported on a single Jibri.

So the operational model is a dedicated recorder node, not a service you scale horizontally without thinking. One machine, one recording. If you need more, you add machines.

There is also a hard dependency worth stating up front. The README notes that Jibri currently only works with a full-fledged Jitsi Meet installation, and that using a different frontend will not work. This is not a standalone screen recorder that connects to an arbitrary meeting service; it is the recording arm of the Jitsi stack.

The primary language is Kotlin, the licence is Apache-2.0, and the repository carries a debian/ directory, a pom.xml, src/, lib/, resources/ and doc/, which is the shape of a project that ships as an operating system package rather than a library. The last push was on 2026-09-30 and the repository has no GitHub releases.

## The ALSA loopback module is the audio path, and it is set up by hand

The first prerequisite section is the audio one, and the instruction is explicit that this is done as the root user.

The ALSA loopback module has to be available, and the extra modules including ALSA loopback are installed on Ubuntu with the package name linux-image-extra-virtual. Three commands then do the work: the module is set up to be loaded on boot, it is loaded into the running kernel, and you check that it is already loaded.

```bash
echo "snd_aloop" >> /etc/modules
modprobe snd_aloop
lsmod | grep snd_aloop
```

If the output shows the module loaded, the configuration step is complete.

The purpose of the loopback device is to give the audio pipeline somewhere to send the mixed conference output so that ffmpeg has an ALSA source to capture. That is also why the isolation requirement exists: the loopback device is a system-wide resource, and anything else on the machine writing to it would be captured into the recording.

The documentation also notes the age of the instructions, since it refers to Ubuntu 16.04 for the extra modules package, and the installation notes say Jibri was built on Ubuntu 18.04 Bionic and has been tested with the pre-built kernel and extra kernel modules, while any other distribution or kernel configuration may work but has not been tested.

That last clause is the one to plan around. The tested configuration is specific, and a modern distribution with a different kernel packaging will be your own experiment.

## Chrome, chromedriver and a managed policy that hides a warning

The browser side has three parts, and the middle one is the fiddly part.

First, a recent ffmpeg with x11 capture compiled in, which the documentation says comes by default on Ubuntu by installing the ffmpeg package. A backport repository is offered for older distributions.

Second, Google Chrome stable. The manual installation sequence adds the signing key, writes a sources.list entry pointing at the stable channel, installs google-chrome-stable, and then holds the version with apt-mark so an automatic upgrade does not move the browser out from under chromedriver.

```bash
apt-get -y install google-chrome-stable
apt-mark hold google-chrome-stable
```

Third, a managed policies file that sets CommandLineFlagSecurityWarningsEnabled to false, which the documentation says will hide warnings in Chrome. Jibri passes command line flags to Chrome, and Chrome warns about unrecognised flags, and that warning is what gets suppressed.

```bash
mkdir -p /etc/opt/chrome/policies/managed
echo '{ "CommandLineFlagSecurityWarningsEnabled": false }' >>/etc/opt/chrome/policies/managed/managed_policies.json
```

Chromedriver is then installed by resolving the matching version from the Chrome for Testing known-good-versions feed, unzipping it and placing the binary in /usr/local/bin with root ownership.

The version matching is the clever part and the fragile part. The script reads the installed Chrome version out of the dpkg database, truncates it to three components, then queries the known-good-versions JSON and filters for a linux64 chromedriver download whose version contains that string, taking the last match. So the Chrome version and the chromedriver version are tied together, which is why the Chrome package is held rather than upgraded freely.

That is a concrete operational constraint: upgrading Chrome on the Jibri host means re-resolving chromedriver.

## The Jibri package comes from the Jitsi Debian repository

The installation path for Jibri itself is a Debian repository rather than a build, and the sequence is short.

The key is imported and dearmoured into the keyrings directory.

```bash
curl https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
```

A sources.list.d file is then written for the stable repository, the package list is updated, and the package is installed.

```bash
echo 'deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/' | sudo tee /etc/apt/sources.list.d/jitsi-stable.list > /dev/null
```

```bash
sudo apt-get install jibri
```

The service runs as a regular system user, and the documentation is explicit that this is the intended model, using the name jibri for both user and group as an example, with any user name doing. It also notes this has not been tested with the root user.

The group membership is the part that matters operationally. The jibri user needs to be in the groups that grant access to the audio and video devices, and the example given is adm, audio, video and plugdev.

```bash
sudo usermod -aG adm,audio,video,plugdev jibri
```

Logging defaults to a directory under /var/log/jitsi/jibri, and the documentation notes that if you do not install via the Debian package you have to make sure that directory exists, or change the location by editing the logging configuration in lib/logging.properties.

## jibri.conf carries the XMPP credentials for three different logins

The configuration file is where the complexity of the Jitsi stack shows through, and it is worth reading before anything else.

The file is installed to /etc/jitsi/jibri/jibri.conf, and the reference.conf file in src/main/resources holds the default values and an example. The guidance is to only override the values you want to change from their defaults.

The shape of the configuration is a jibri block containing an api block with an xmpp block, and inside that a list of environments, each with a name, the XMPP server hosts, the XMPP domain, and three separate login blocks.

```
jibri {
    .....
    api {
        xmpp {
            environments = [
                {
                    name = "yourdomain.com"
                    xmpp-server-hosts = ["1.2.3.4"],
                    xmpp-domain = "yourdomain.com"
                    control-login {
                        domain = "auth.yourdomain.com"
                        username = "jibri"
                        password = "jibriauthpass"
                        port = 5222
                    }
                    control-muc {
                        domain = "internal.auth.yourdomain.com"
                        room-name = "JibriBrewery"
                        nickname = "myjibri-1-2-3-4"
                    }
                    call-login {
                        domain = "recorder.yourdomain.com"
                        username = "recorder"
                        password = "jibrirecorderpass"
                    }
                    strip-from-room-domain = "conference."
                    trust-all-xmpp-certs = true
                    usage-timeout = 0
                }
            ]
        }
    }
    .....
}
```

Three identities appear, and they map onto three roles in the Jitsi architecture. The control login is the account Jibri uses to connect to the XMPP control component and to discover the conference. The control MUC entry is the internal room, named JibriBrewery in the example, where the Jibri clients become discoverable to Jicofo, with a nickname that identifies the individual instance. The call login is the account that actually joins the conference as a participant, on a separate domain, recorder.yourdomain.com in the example.

Three settings deserve attention. strip-from-room-domain removes the conference. prefix from the room name before joining, and the internal MUC lives on a domain that regular users cannot reach. trust-all-xmpp-certs set to true disables certificate validation for the XMPP connections, which is convenient in a lab and is a decision you should make deliberately. usage-timeout set to 0 means no usage limit.

The environment list is a list, which is what makes a single Jibri service able to target several Jitsi deployments.

## The Jitsi side needs Prosody, config.js and jicofo.conf changes too

The last part of the setup is the one that is easy to miss, because it happens on the Jitsi Meet side rather than on the Jibri machine.

The documentation states that Jibri requires some settings to be enabled within a Jitsi Meet configuration, and names them: virtualhosts and accounts in Prosody, settings for the jitsi meet web within config.js, and jicofo.conf.

For Prosody, the requirement is an internal MUC component entry, and the reason given is that it is required so that the Jibri clients can be discovered by Jicofo in a MUC that is not externally accessible by Jitsi Meet users. The change goes into /etc/prosody/prosody.cfg.lua.

So the architecture is a closed loop of components. Prosody hosts the internal MUC where Jibri instances register, Jicofo discovers them there and hands them conferences to join, and the Jibri instance joins the actual conference through the call login on a separate domain, then renders the conference in Chrome and encodes the framebuffer and the loopback audio.

That is the part that makes the deployment a project rather than an install. The Jibri host has the browser, the framebuffer, the audio loopback and the encoder; the Jitsi host has the signalling, the MUC component and the conference focus logic. Both halves have to agree, and a misconfigured jicofo.conf or a missing internal virtualhost produces a Jibri that never gets a job.

The documentation also names a Discord for support, and the repository carries a SECURITY.md and a CLAUDE.md alongside the source, so the security reporting path is documented even if the README does not repeat it.

## Where Jibri is the wrong tool

The first wrong-tool case is a deployment that is not a full Jitsi Meet installation. The documentation says it directly: Jibri currently only works with a full-fledged Jitsi Meet installation, and using a different frontend will not work. There is no generic meeting recorder here.

The second case is a shared host. The requirement that Jibri run on a separate machine or VM with no other applications using the display or audio devices is not a caution, it is a precondition. On a host where anything else writes to the ALSA loopback or opens a display, the recording captures it.

The third case is a workload that needs more than one recording at a time. Only one recording at a time is supported on a single Jibri, so scaling out means adding machines, each with a browser, a framebuffer and its own XMPP identities, and each of which has to be able to reach the Jitsi signalling layer.

There is also a maintenance obligation that comes with the design. The Chrome version and the chromedriver version are tied together through a resolution step, and the Chrome package is deliberately held with apt-mark so an automatic upgrade does not break the pairing. Any host management system that upgrades Chrome on a schedule will break Jibri until chromedriver is re-resolved, and the documentation does not describe a mechanism for keeping the two in step automatically.

The age of the instructions is the other caution. The tested configuration is Ubuntu 18.04 Bionic with the pre-built kernel and extra modules, and the ALSA instructions refer to Ubuntu 16.04 package names. Any other distribution or kernel configuration may work but has not been tested, so a modern base is a porting exercise rather than an installation.

What you get in exchange is conference recording and streaming that integrates with the Jitsi stack rather than being bolted on, and the closed loop between the Jibri node and the Jitsi signalling is what makes that integration real.

## Conclusion

Jibri suits a team that already runs Jitsi Meet and needs a recording or live stream of it, and who can dedicate a machine with no other audio or video use to that job. It does not suit a team that only wants a lightweight screen share, and it does not suit a deployment that is not a full Jitsi Meet installation, since the documentation states that a different frontend will not work. Before deploying, plan the dedicated host with the ALSA loopback module and a modern ffmpeg built with x11 capture, and read the Prosody, jitsi meet config.js and jicofo.conf changes, because the recording side is only half of the work.

## FAQ

### What is Jibri?

Jibri is the Jitsi BRoadcasting Infrastructure, providing services for recording or streaming a Jitsi Meet conference. It launches a Chrome instance rendered in a virtual framebuffer and captures and encodes the output with ffmpeg, and it is intended to run on a separate machine or VM with no other applications using the display or audio devices.

### How do I install the Jibri Debian package?

Import the Jitsi repository key into the keyrings directory, write a sources.list.d file for the stable repository, update the package list and then install the package with sudo apt-get install jibri. The service is meant to run as a regular system user in the adm, audio, video and plugdev groups.

### What does the ALSA loopback setup do for Jibri?

It gives the audio pipeline a device to route the mixed conference output through, so ffmpeg has an ALSA source to capture. The module is installed with the linux-image-extra-virtual package, added to /etc/modules, loaded with modprobe snd_aloop and verified with lsmod.

### Which XMPP accounts does a Jibri configuration need?

Three: a control login used to connect to the XMPP control component, a control MUC entry where Jibri clients are discovered by Jicofo in an internal MUC, and a call login on a separate domain that actually joins the conference. The environment block in jibri.conf also sets strip-from-room-domain, trust-all-xmpp-certs and usage-timeout.

### What license is Jibri released under?

Jibri is licensed under the Apache 2.0 license, with the LICENSE file at the root of the repository. The primary language is Kotlin, the project ships a debian package, and the last push to the repository was on 2026-09-30.

## Sources

- [Issues](https://github.com/jitsi/jibri/issues)
- [jitsi/jibri on GitHub](https://github.com/jitsi/jibri)
- [License: Apache-2.0](https://github.com/jitsi/jibri/blob/master/LICENSE)
- [README](https://github.com/jitsi/jibri/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jitsi-jibri
