Browse Source

jibri: add jibri service

netaskd 5 năm trước cách đây
mục cha
commit
ffa017b74d

+ 1 - 1
Makefile

@@ -2,7 +2,7 @@ FORCE_REBUILD ?= 0
 JITSI_RELEASE ?= stable
 JITSI_BUILD ?= latest
 JITSI_REPO ?= jitsi
-JITSI_SERVICES ?= base base-java web prosody jicofo jvb jigasi etherpad
+JITSI_SERVICES ?= base base-java web prosody jicofo jvb jigasi etherpad jibri
 
 BUILD_ARGS := --build-arg JITSI_REPO=$(JITSI_REPO)
 ifeq ($(FORCE_REBUILD), 1)

+ 111 - 1
README.md

@@ -43,6 +43,10 @@ and then run Docker Compose as follows: ``docker-compose -f docker-compose.yml -
 If you want to enable document sharing via [Etherpad], configure it and run Docker Compose as
 follows: ``docker-compose -f docker-compose.yml -f etherpad.yml up``
 
+If you want to use jibri too, first configure host as described in JItsi BRoadcasting Infrastructure configuration section
+and then run Docker Compose as follows: ``docker-compose -f docker-compose.yml -f jibri.yml up -d``
+or to use jigasi too: ``docker-compose -f docker-compose.yml -f jigasi.yml -f jibri.yml up -d``
+
 ## Architecture
 
 A Jitsi Meet installation can be broken down into the following components:
@@ -52,6 +56,7 @@ A Jitsi Meet installation can be broken down into the following components:
 * A conference focus component
 * A video router (could be more than one)
 * A SIP gateway for audio calls
+* A Broadcasting Infrastructure for recording or streaming a conference.
 
 ![](resources/docker-jitsi-meet.png)
 
@@ -70,6 +75,7 @@ several container images are provided.
 * **jvb**: [Jitsi Videobridge], the video router.
 * **jigasi**: [Jigasi], the SIP (audio only) gateway.
 * **etherpad**: [Etherpad], shared document editing addon.
+* **jibri**: [Jibri], the brooadcasting infrastructure.
 
 ### Design considerations
 
@@ -127,6 +133,110 @@ Variable | Description | Example
 `JIGASI_SIP_PORT` | SIP server port | 5060
 `JIGASI_SIP_TRANSPORT` | SIP transport | UDP
 
+### JItsi BRoadcasting Infrastructure configuration
+
+Before running Jibri, you need to setup an ALSA loopback device on the host:
+
+For CentOS 7, the module is already compiled with the kernel, so just run:
+
+```
+# configure 5 capture/playback interfaces
+echo "options snd-aloop enable=1,1,1,1,1 index=0,1,2,3,4" > /etc/modprobe.d/alsa-loopback.conf
+# setup autoload the module
+echo "snd_aloop" > /etc/modules-load.d/snd_aloop.conf
+# load the module
+modprobe snd-aloop
+# check that the module is loaded
+lsmod | grep snd_aloop
+```
+
+For Ubuntu:
+
+```
+# install the module
+apt update && apt install linux-image-extra-virtual
+# configure 5 capture/playback interfaces
+echo "options snd-aloop enable=1,1,1,1,1 index=0,1,2,3,4" > /etc/modprobe.d/alsa-loopback.conf
+# setup autoload the module
+echo "snd-aloop" >> /etc/modules
+# check that the module is loaded
+lsmod | grep snd_aloop
+```
+
+NOTE: if you are running on AWS you may need to reboot your machine to ue the generic kernel instead
+of the "aws" kernel.
+
+If you want to enable Jibri these options are required:
+
+Variable | Description | Example
+--- | --- | ---
+`ENABLE_RECORDING` | Enable recording conference to local disk | 1
+
+Extended Jibri configuration:
+
+Variable | Description | Example
+--- | --- | ---
+`JIBRI_RECORDER_USER` | Internal recorder user for Jibri client connections | recorder
+`JIBRI_RECORDER_PASSWORD` | Internal recorder password for Jibri client connections | passw0rd
+`JIBRI_RECORDING_DIR` | Directory for recordings inside Jibri container | /config/recordings
+`JIBRI_FINALIZE_RECORDING_SCRIPT_PATH` | The finalizing script. Will run after recording is complete | /config/finalize.sh
+`JIBRI_XMPP_USER` | Internal user for Jibri client connections. | jibri
+`JIBRI_RECORDER_PASSWORD` | Internal user for Jibri client connections | passw0rd
+`JIBRI_STRIP_DOMAIN_JID` | Prefix domain for strip inside Jibri (please see env.example for details) | muc
+`JIBRI_BREWERY_MUC` | MUC name for the Jibri pool | jibribrewery
+`JIBRI_PENDING_TIMEOUT` | MUC connection timeout | 90
+`JIBRI_LOGS_DIR` | Directory for logs inside Jibri container | /config/logs
+
+For using multiple Jibri instances, you have to select different loopback interfces for each instance manually.
+
+<details>
+  <summary>Set interface you can in file `/home/jibri/.asoundrc` inside a docker container.</summary>
+
+  Default the first instance has:
+
+  ```
+  ...
+  slave.pcm "hw:Loopback,0,0"
+  ...
+  slave.pcm "hw:Loopback,0,1"
+  ...
+  slave.pcm "hw:Loopback,1,1"
+  ...
+  slave.pcm "hw:Loopback,1,0"
+  ...
+  ```
+
+  For setup the second instance, run container with changed `/home/jibri/.asoundrc`:
+
+  ```
+  ...
+  slave.pcm "hw:Loopback_1,0,0"
+  ...
+  slave.pcm "hw:Loopback_1,0,1"
+  ...
+  slave.pcm "hw:Loopback_1,1,1"
+  ...
+  slave.pcm "hw:Loopback_1,1,0"
+  ...
+  ```
+
+  Also you can use numbering id for set loopback interface. The third instance will have `.asoundrc` that looks like:
+
+  ```
+  ...
+  slave.pcm "hw:2,0,0"
+  ...
+  slave.pcm "hw:2,0,1"
+  ...
+  slave.pcm "hw:2,1,1"
+  ...
+  slave.pcm "hw:2,1,0"
+  ...
+
+  ```
+
+</details>
+
 ### Authentication
 
 Authentication can be controlled with the environment variables below. If guest
@@ -246,6 +356,7 @@ Variable | Description | Default value
 `XMPP_MUC_DOMAIN` | XMPP domain for the MUC | muc.meet.jitsi
 `XMPP_INTERNAL_MUC_DOMAIN` | XMPP domain for the internal MUC | internal-muc.meet.jitsi
 `XMPP_GUEST_DOMAIN` | XMPP domain for unauthenticated users | guest.meet.jitsi
+`XMPP_RECORDER_DOMAIN` | Domain for the jibri recorder | recorder.meet.jitsi
 `XMPP_MODULES` | Custom Prosody modules for XMPP_DOMAIN (comma separated) | info,alert
 `XMPP_MUC_MODULES` | Custom Prosody modules for MUC component (comma separated) | info,alert
 `XMPP_INTERNAL_MUC_MODULES` | Custom Prosody modules for internal MUC component (comma separated) | info,alert
@@ -293,7 +404,6 @@ option.
 * Support container replicas (where applicable).
 * Docker Swarm mode.
 * More services:
-  * Jibri.
   * TURN server.
 
 [Jitsi]: https://jitsi.org/

+ 17 - 0
docker-compose.yml

@@ -27,10 +27,20 @@ services:
             - XMPP_BOSH_URL_BASE
             - XMPP_GUEST_DOMAIN
             - XMPP_MUC_DOMAIN
+            - XMPP_RECORDER_DOMAIN
             - ETHERPAD_URL_BASE
             - TZ
+            - JIBRI_BREWERY_MUC
+            - JIBRI_PENDING_TIMEOUT
+            - JIBRI_XMPP_USER
+            - JIBRI_XMPP_PASSWORD
+            - JIBRI_RECORDER_USER
+            - JIBRI_RECORDER_PASSWORD
+            - ENABLE_RECORDING
         networks:
             meet.jitsi:
+                aliases:
+                    - ${XMPP_DOMAIN}
 
     # XMPP server
     prosody:
@@ -67,6 +77,7 @@ services:
             - XMPP_MODULES
             - XMPP_MUC_MODULES
             - XMPP_INTERNAL_MUC_MODULES
+            - XMPP_RECORDER_DOMAIN
             - JICOFO_COMPONENT_SECRET
             - JICOFO_AUTH_USER
             - JICOFO_AUTH_PASSWORD
@@ -74,6 +85,10 @@ services:
             - JVB_AUTH_PASSWORD
             - JIGASI_XMPP_USER
             - JIGASI_XMPP_PASSWORD
+            - JIBRI_XMPP_USER
+            - JIBRI_XMPP_PASSWORD
+            - JIBRI_RECORDER_USER
+            - JIBRI_RECORDER_PASSWORD
             - JWT_APP_ID
             - JWT_APP_SECRET
             - JWT_ACCEPTED_ISSUERS
@@ -105,6 +120,8 @@ services:
             - JICOFO_AUTH_PASSWORD
             - JVB_BREWERY_MUC
             - JIGASI_BREWERY_MUC
+            - JIBRI_BREWERY_MUC
+            - JIBRI_PENDING_TIMEOUT
             - TZ
         depends_on:
             - prosody

+ 43 - 0
env.example

@@ -246,6 +246,49 @@ JIGASI_PORT_MAX=20050
 # the docker host to ${CONFIG}/jigasi/key.json and to enable this setting:
 #GOOGLE_APPLICATION_CREDENTIALS=/config/key.json
 
+# Enable recording
+#ENABLE_RECORDING=1
+
+# XMPP domain for the jibri recorder
+XMPP_RECORDER_DOMAIN=recorder.meet.jitsi
+
+# XMPP recorder user for Jibri client connections.
+JIBRI_RECORDER_USER=recorder
+
+# XMPP recorder password for Jibri client connections.
+JIBRI_RECORDER_PASSWORD=passw0rd
+
+# Directory for recordings inside Jibri container.
+JIBRI_RECORDING_DIR=/config/recordings
+
+# The finalizing script. Will run after recording is complete.
+JIBRI_FINALIZE_RECORDING_SCRIPT_PATH=/config/finalize.sh
+
+# XMPP user for Jibri client connections.
+JIBRI_XMPP_USER=jibri
+
+# XMPP password for Jibri client connections.
+JIBRI_XMPP_PASSWORD=passw0rd
+
+# MUC name for the Jibri pool.
+JIBRI_BREWERY_MUC=jibribrewery
+
+# MUC connection timeout
+JIBRI_PENDING_TIMEOUT=90
+
+# When jibri gets a request to start a service for a room, the room
+# jid will look like: roomName@optional.prefixes.subdomain.xmpp_domain
+# We'll build the url for the call by transforming that into:
+# https://xmpp_domain/subdomain/roomName
+# So if there are any prefixes in the jid (like jitsi meet, which
+# has its participants join a muc at conference.xmpp_domain) then
+# list that prefix here so it can be stripped out to generate
+# the call url correctly.
+JIBRI_STRIP_DOMAIN_JID=muc
+
+# Directory for logs inside Jibri container.
+JIBRI_LOGS_DIR=/config/logs
+
 # Disable HTTPS. This can be useful if TLS connections are going to be handled outside of this setup.
 #DISABLE_HTTPS=1
 

+ 33 - 0
jibri.yml

@@ -0,0 +1,33 @@
+version: '3'
+
+services:
+    jibri:
+        image: jitsi/jibri
+        volumes:
+            - ${CONFIG}/jibri:/config
+            - /dev/shm:/dev/shm
+        cap_add:
+            - SYS_ADMIN
+            - NET_BIND_SERVICE
+        devices:
+            - /dev/snd:/dev/snd
+        environment:
+            - XMPP_AUTH_DOMAIN
+            - XMPP_INTERNAL_MUC_DOMAIN
+            - XMPP_RECORDER_DOMAIN
+            - XMPP_SERVER
+            - XMPP_DOMAIN
+            - JIBRI_XMPP_USER
+            - JIBRI_XMPP_PASSWORD
+            - JIBRI_BREWERY_MUC
+            - JIBRI_RECORDER_USER
+            - JIBRI_RECORDER_PASSWORD
+            - JIBRI_RECORDING_DIR
+            - JIBRI_FINALIZE_RECORDING_SCRIPT_PATH
+            - JIBRI_STRIP_DOMAIN_JID
+            - JIBRI_LOGS_DIR
+            - DISPLAY=:0
+            - TZ
+        networks:
+            meet.jitsi:
+

+ 48 - 0
jibri/Dockerfile

@@ -0,0 +1,48 @@
+ARG JITSI_REPO=jitsi
+FROM ${JITSI_REPO}/base-java
+
+ARG CHROME_RELEASE=latest
+ARG CHROMEDRIVER_MAJOR_RELEASE=latest
+
+RUN \
+	apt-dpkg-wrap apt-get update \
+	&& apt-dpkg-wrap apt-get install -y jibri \
+	&& apt-cleanup
+
+RUN \
+	[ "${CHROME_RELEASE}" = "latest" ] \
+	&& curl -4s 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-dpkg-wrap apt-get update \
+	&& apt-dpkg-wrap apt-get install -y google-chrome-stable \
+	&& apt-cleanup \
+	|| true
+
+RUN \
+        [ "${CHROME_RELEASE}" != "latest" ] \
+        && curl -4so /tmp/google-chrome-stable_${CHROME_RELEASE}_amd64.deb http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_RELEASE}_amd64.deb \
+	&& apt-dpkg-wrap apt-get update \
+        && apt-dpkg-wrap apt-get install -y /tmp/google-chrome-stable_${CHROME_RELEASE}_amd64.deb \
+	&& apt-cleanup \
+	|| true
+
+RUN \
+	[ "${CHROMEDRIVER_MAJOR_RELEASE}" = "latest" ] \
+	&& CHROMEDRIVER_RELEASE="$(curl -4Ls https://chromedriver.storage.googleapis.com/LATEST_RELEASE)" \
+	|| CHROMEDRIVER_RELEASE="$(curl -4Ls https://chromedriver.storage.googleapis.com/LATEST_RELEASE_${CHROMEDRIVER_MAJOR_RELEASE})" \
+	&& curl -4Ls https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_RELEASE}/chromedriver_linux64.zip \
+	| zcat >> /usr/bin/chromedriver \
+	&& chmod +x /usr/bin/chromedriver \
+	&& chromedriver --version
+
+RUN \
+        [ "$JITSI_RELEASE" = "unstable" ] \
+        && apt-dpkg-wrap apt-get update \
+        && apt-dpkg-wrap apt-get install -y jitsi-upload-integrations \
+        && apt-cleanup \
+        || true
+
+COPY rootfs/ /
+
+VOLUME /config
+

+ 4 - 0
jibri/Makefile

@@ -0,0 +1,4 @@
+build:
+	docker build $(BUILD_ARGS) -t $(JITSI_REPO)/jibri .
+
+.PHONY: build

+ 58 - 0
jibri/rootfs/defaults/config.json

@@ -0,0 +1,58 @@
+{
+    "recording_directory":"{{ .Env.JIBRI_RECORDING_DIR }}",
+    // The path to the script which will be run on completed recordings
+    "finalize_recording_script_path": "{{ .Env.JIBRI_FINALIZE_RECORDING_SCRIPT_PATH }}",
+    "xmpp_environments": [
+        {
+            // A friendly name for this environment which can be used
+            //  for logging, stats, etc.
+            "name": "prod environment",
+            // The hosts of the XMPP servers to connect to as part of
+            //  this environment
+            "xmpp_server_hosts": [
+                "{{ .Env.XMPP_SERVER }}"
+            ],
+            "xmpp_domain": "{{ .Env.XMPP_DOMAIN }}",
+            // Jibri will login to the xmpp server as a privileged user 
+            "control_login": {
+                "domain": "{{ .Env.XMPP_AUTH_DOMAIN }}",
+                // The credentials for logging in
+                "username": "{{ .Env.JIBRI_XMPP_USER }}",
+                "password": "{{ .Env.JIBRI_XMPP_PASSWORD }}"
+            },
+            // Using the control_login information above, Jibri will join 
+            //  a control muc as a means of announcing its availability 
+            //  to provide services for a given environment
+            "control_muc": {
+                "domain": "{{ .Env.XMPP_INTERNAL_MUC_DOMAIN }}",
+                "room_name": "{{ .Env.JIBRI_BREWERY_MUC }}",
+		// MUST be unic for every instanse
+                "nickname": "jibri-instanse-{{ .Env.JIBRI_INSTANCE_ID }}"
+            },
+            // All participants in a call join a muc so they can exchange
+            //  information.  Jibri can be instructed to join a special muc
+            //  with credentials to give it special abilities (e.g. not being
+            //  displayed to other users like a normal participant)
+            "call_login": {
+                "domain": "{{ .Env.XMPP_RECORDER_DOMAIN }}",
+                "username": "{{ .Env.JIBRI_RECORDER_USER }}",
+                "password": "{{ .Env.JIBRI_RECORDER_PASSWORD }}"
+            },
+            // When jibri gets a request to start a service for a room, the room
+            //  jid will look like:
+            //  roomName@optional.prefixes.subdomain.xmpp_domain
+            // We'll build the url for the call by transforming that into:
+            //  https://xmpp_domain/subdomain/roomName
+            // So if there are any prefixes in the jid (like jitsi meet, which
+            //  has its participants join a muc at conference.xmpp_domain) then
+            //  list that prefix here so it can be stripped out to generate
+            //  the call url correctly
+            "room_jid_domain_string_to_strip_from_start": "{{ .Env.JIBRI_STRIP_DOMAIN_JID }}.",
+            // The amount of time, in minutes, a service is allowed to continue.
+            //  Once a service has been running for this long, it will be
+            //  stopped (cleanly).  A value of 0 means an indefinite amount
+            //  of time is allowed
+            "usage_timeout": "0"
+        }
+    ]
+}

+ 33 - 0
jibri/rootfs/defaults/logging.properties

@@ -0,0 +1,33 @@
+handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
+
+java.util.logging.FileHandler.level = FINE
+java.util.logging.FileHandler.pattern   = {{ .Env.JIBRI_LOGS_DIR }}/log.%g.txt
+java.util.logging.FileHandler.formatter = net.java.sip.communicator.util.ScLogFormatter
+java.util.logging.FileHandler.count = 10
+java.util.logging.FileHandler.limit = 10000000
+
+org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.level = FINE
+org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.pattern   = {{ .Env.JIBRI_LOGS_DIR }}/ffmpeg.%g.txt
+org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.formatter = net.java.sip.communicator.util.ScLogFormatter
+org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.count = 10
+org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.limit = 10000000
+
+org.jitsi.jibri.sipgateway.pjsua.util.PjsuaFileHandler.level = FINE
+org.jitsi.jibri.sipgateway.pjsua.util.PjsuaFileHandler.pattern   = {{ .Env.JIBRI_LOGS_DIR }}/pjsua.%g.txt
+org.jitsi.jibri.sipgateway.pjsua.util.PjsuaFileHandler.formatter = net.java.sip.communicator.util.ScLogFormatter
+org.jitsi.jibri.sipgateway.pjsua.util.PjsuaFileHandler.count = 10
+org.jitsi.jibri.sipgateway.pjsua.util.PjsuaFileHandler.limit = 10000000
+
+org.jitsi.jibri.selenium.util.BrowserFileHandler.level = FINE
+org.jitsi.jibri.selenium.util.BrowserFileHandler.pattern   = {{ .Env.JIBRI_LOGS_DIR }}/browser.%g.txt
+org.jitsi.jibri.selenium.util.BrowserFileHandler.formatter = net.java.sip.communicator.util.ScLogFormatter
+org.jitsi.jibri.selenium.util.BrowserFileHandler.count = 10
+org.jitsi.jibri.selenium.util.BrowserFileHandler.limit = 10000000
+
+java.util.logging.ConsoleHandler.level = FINE
+java.util.logging.ConsoleHandler.formatter = net.java.sip.communicator.util.ScLogFormatter
+
+org.jitsi.level = FINE
+
+org.glassfish.level = INFO
+org.osgi.level = INFO

+ 38 - 0
jibri/rootfs/etc/cont-init.d/10-config

@@ -0,0 +1,38 @@
+#!/usr/bin/with-contenv bash
+
+# DISPLAY is necessary for start
+[ -z "${DISPLAY}" ] \
+&& ( echo -e "\e[31mERROR: Please set DISPLAY variable.\e[39m"; kill 1; exit 1 )
+
+# check loaded snd_aloop module and exit if is not loaded on the host
+[ -z "$(lsmod | grep -om1 snd_aloop)" ] \
+&& ( echo -e "\e[31mERROR: Please load snd-aloop module on the docker host.\e[39m"; kill 1; exit 1 )
+
+# get host's audio group id
+host_audio_group="$(stat -c %g /dev/snd/pcmC0D0p)"
+# try to create group with this id. If group with the id already exists, just skip
+groupadd -g ${host_audio_group} jibri-audio >/dev/null 2>&1
+# include user to the group by id
+usermod -aG ${host_audio_group} jibri
+
+# script for finalizing must have executing bit.
+[ ! -z "${JIBRI_FINALIZE_RECORDING_SCRIPT_PATH}" ] \
+&& [ ! -x "${JIBRI_FINALIZE_RECORDING_SCRIPT_PATH}" ] \
+&& chmod +x ${JIBRI_FINALIZE_RECORDING_SCRIPT_PATH}
+
+# set rundom jibri nickname for the instance if is not set
+[ -z "${JIBRI_INSTANCE_ID}" ] && export JIBRI_INSTANCE_ID=$(date +%N)
+
+# always recreate configs
+tpl /defaults/config.json > /etc/jitsi/jibri/config.json
+tpl /defaults/logging.properties > /etc/jitsi/jibri/logging.properties
+
+# make recording dir
+[ -z "${JIBRI_RECORDING_DIR}" ] && export JIBRI_RECORDING_DIR=/config/recordings
+mkdir -p ${JIBRI_RECORDING_DIR}
+chown -R jibri ${JIBRI_RECORDING_DIR}
+
+# make logs dir
+[ -z "${JIBRI_LOGS_DIR}" ] && export JIBRI_LOGS_DIR=/config/logs
+mkdir -p ${JIBRI_LOGS_DIR}
+chown -R jibri ${JIBRI_LOGS_DIR}

+ 4 - 0
jibri/rootfs/etc/opt/chrome/policies/managed/managed_policies.json

@@ -0,0 +1,4 @@
+{
+  "CommandLineFlagSecurityWarningsEnabled": false
+}
+

+ 5 - 0
jibri/rootfs/etc/services.d/10-xorg/run

@@ -0,0 +1,5 @@
+#!/usr/bin/with-contenv bash
+
+DAEMON="/usr/bin/Xorg -nocursor -noreset  +extension RANDR +extension RENDER -logfile /tmp/xorg.log  -config /etc/jitsi/jibri/xorg-video-dummy.conf ${DISPLAY}"
+exec s6-setuidgid jibri /bin/bash -c "exec $DAEMON"
+

+ 5 - 0
jibri/rootfs/etc/services.d/20-icewm/run

@@ -0,0 +1,5 @@
+#!/usr/bin/with-contenv bash
+
+DAEMON="/usr/bin/icewm-session"
+exec s6-setuidgid jibri /bin/bash -c "exec $DAEMON"
+

+ 8 - 0
jibri/rootfs/etc/services.d/30-jibri/run

@@ -0,0 +1,8 @@
+#!/usr/bin/with-contenv bash
+
+# we have to set it, otherwise chrome won't find ~/.asoundrc file
+HOME=/home/jibri
+
+DAEMON=/opt/jitsi/jibri/launch.sh
+exec s6-setuidgid jibri /bin/bash -c "exec $DAEMON"
+

+ 5 - 0
jicofo/rootfs/defaults/sip-communicator.properties

@@ -1,6 +1,11 @@
 org.jitsi.jicofo.ALWAYS_TRUST_MODE_ENABLED=true
 org.jitsi.jicofo.BRIDGE_MUC={{ .Env.JVB_BREWERY_MUC }}@{{ .Env.XMPP_INTERNAL_MUC_DOMAIN }}
 
+{{ if and .Env.JIBRI_BREWERY_MUC .Env.JIBRI_PENDING_TIMEOUT }}
+org.jitsi.jicofo.jibri.BREWERY={{ .Env.JIBRI_BREWERY_MUC}}@{{ .Env.XMPP_INTERNAL_MUC_DOMAIN }}
+org.jitsi.jicofo.jibri.PENDING_TIMEOUT={{ .Env.JIBRI_PENDING_TIMEOUT }}
+{{ end }}
+
 {{ if .Env.JIGASI_BREWERY_MUC }}
 org.jitsi.jicofo.jigasi.BREWERY={{ .Env.JIGASI_BREWERY_MUC}}@{{ .Env.XMPP_INTERNAL_MUC_DOMAIN }}
 {{ end }}

+ 8 - 0
prosody/rootfs/defaults/conf.d/jitsi-meet.cfg.lua

@@ -69,6 +69,14 @@ VirtualHost "{{ .Env.XMPP_AUTH_DOMAIN }}"
     }
     authentication = "internal_plain"
 
+{{ if .Env.XMPP_RECORDER_DOMAIN }}
+VirtualHost "{{ .Env.XMPP_RECORDER_DOMAIN }}"
+    modules_enabled = {
+      "ping";
+    }
+    authentication = "internal_plain"
+{{ end }}
+
 Component "{{ .Env.XMPP_INTERNAL_MUC_DOMAIN }}" "muc"
     modules_enabled = {
         "ping";

+ 8 - 0
prosody/rootfs/etc/cont-init.d/10-config

@@ -37,6 +37,14 @@ if [[ ! -f $PROSODY_CFG ]]; then
     prosodyctl --config $PROSODY_CFG register $JICOFO_AUTH_USER $XMPP_AUTH_DOMAIN $JICOFO_AUTH_PASSWORD
     prosodyctl --config $PROSODY_CFG register $JVB_AUTH_USER $XMPP_AUTH_DOMAIN $JVB_AUTH_PASSWORD
 
+    if [[ ! -z $JIBRI_XMPP_USER ]] && [[ ! -z $JIBRI_XMPP_PASSWORD ]]; then
+        prosodyctl --config $PROSODY_CFG register $JIBRI_XMPP_USER $XMPP_AUTH_DOMAIN $JIBRI_XMPP_PASSWORD
+    fi
+
+    if [[ ! -z $JIBRI_RECORDER_USER ]] && [[ ! -z $JIBRI_RECORDER_PASSWORD ]]; then
+        prosodyctl --config $PROSODY_CFG register $JIBRI_RECORDER_USER $XMPP_RECORDER_DOMAIN $JIBRI_RECORDER_PASSWORD
+    fi
+
     if [[ ! -z $JIGASI_XMPP_USER ]] && [[ ! -z $JIGASI_XMPP_PASSWORD ]]; then
         prosodyctl --config $PROSODY_CFG register $JIGASI_XMPP_USER $XMPP_AUTH_DOMAIN $JIGASI_XMPP_PASSWORD
     fi

+ 8 - 0
web/rootfs/etc/cont-init.d/10-config

@@ -61,6 +61,14 @@ if [[ ! -f /config/config.js ]]; then
         -e "s#// focusUserJid:.*#focusUserJid: '${JICOFO_AUTH_USER}@${XMPP_AUTH_DOMAIN}',#" \
         /config/config.js
 
+    if [[ $ENABLE_RECORDING -eq 1 || x$ENABLE_RECORDING == xtrue ]]; then
+        sed -i \
+            -e "/\/\/ Recording.*/a hiddenDomain: '$XMPP_RECORDER_DOMAIN'," \
+            -e "s#// fileRecordingsEnabled:.*#fileRecordingsEnabled: true,#" \
+            -e "s#// liveStreamingEnabled:.*#liveStreamingEnabled: true,#" \
+        /config/config.js
+    fi
+
     if [[ $ENABLE_AUTH -eq 1 ]]; then
         if [[ $ENABLE_GUESTS -eq 1 ]]; then
             sed -i \