Running Jitsi-Meet in a FreeBSD Jail
Introduction
Due to the situation with COVID-19 that also lead to people being confined to their homes in South Africa as well, we decided to provide a (freely usable of course) Jitsi Meet instance to the community being hosted in South Africa on our FreeBSD environment.
That way, communities in South Africa and beyond have a free alternative to the commercial conferencing solutions with sometimes dubious security and privacy histories and at the same time improved user experience due to the lower latency of local hosting.
Our instance is available at jitsi.honeyguide.net for those wanting to try it out.
This tutorial will show you how to set up your own Jitsi Meet from scratch on FreeBSD.
Initial Set Up
We first of all initialise the jail which we will use (we use iocage for jail management):
$ iocage create -n jitsi ip4_addr="igb0|10.10.0.1/24" -r 11.3-RELEASE boot="on"
Then we connect to the jail and prepare pkg and ports (some ports are so new that we need to build them ourselves):
$ iocage console jitsi
...
$ pkg
...
$ portsnap fetch
...
$ portsnap extract
...
Installing All Packages and Ports
jitsi-meet
and jitsi-videobridge
are built from ports:
$ cd /usr/ports/www/jitsi-meet
$ make install clean
...
$ cd /usr/ports/net-im/jitsi-videobridge
$ make install clean
...
nginx
, acme.sh
for SSL certificate management and prosody
can be installed from packages:
$ pkg install nginx
...
$ pkg install prosody
...
$ pkg install acme.sh
If you run into problems with your setup, we recommend you compare your configuration with https://github.com/jitsi/jitsi-meet/blob/master/doc/manual-install.md.
Setting Up prosody
The prosody
configuration is located in /usr/local/etc/prosody/prosody.cfg.lua
.
The log files are located in /var/db/prosody
.
First of all, we need to create and register the certificates:
$ prosodyctl cert generate jitsi.honeyguide.net
...
$ prosodyctl cert generate auth.jitsi.honeyguide.net
...
$ prosodyctl register focus auth.jitsi.honeyguide.net KEYUSEDINCONFIG
Replace KEYUSEDINCONFIG
with a key that you will need to use in the config files.
In /usr/local/etc/prosody/prosody.cfg.lua
, we added the following lines at the end (otherwise, the default configuration works fine):
VirtualHost "jitsi.honeyguide.net"
authentication = "anonymous"
ssl = {
key = "/var/db/prosody/jitsi.honeyguide.net.key";
certificate = "/var/db/prosody/jitsi.honeyguide.net.crt";
}
modules_enabled = {
"bosh";
"pubsub";
}
c2s_require_encryption = false
VirtualHost "auth.jitsi.honeyguide.net"
ssl = {
key = "/var/db/prosody/auth.jitsi.honeyguide.net.key";
certificate = "/var/db/prosody/auth.jitsi.honeyguide.net.crt";
}
authentication = "internal_plain"
admins = { "focus@auth.jitsi.honeyguide.net" }
Component "conference.jitsi.honeyguide.net" "muc"
Component "jitsi-videobridge.jitsi.honeyguide.net"
component_secret = "KEYUSEDINCONFIG"
Component "focus.jitsi.honeyguide.net"
component_secret = "KEYUSEDINCONFIG"
Setting up jitsi-videobridge
The jitsi-videobridge
configuration is located in /usr/local/etc/jitsi/videobridge/jitsi-videobridge.conf
and /usr/local/etc/jitsi/videobridge/sip-communicator.properties
.
There is one minor problem though: /usr/local/etc/jitsi/videobridge/jitsi-videobridge.conf
is currently ignored, the /usr/local/etc/rc.d/jitsi-videobridge
startup script does not read the environment file correctly.
Being pragmatic, we adjusted the startup script (and saved the original file in jitsi-videobridge.orig). Since also the additional flags from /etc/rc.conf
are ignored, we also added –apis=rest,xmpp for the telegraf
set up (for the grafana
dashboard, see our separate blog post) there:
...
jitsi_videobridge_start()
{
daemon -p ${pidfile} -o /var/log/jitsi-videobridge.log ${command} -Xmx3072m \
-XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/tmp \
-Djava.util.logging.config.file=${jitsi_videobridge_logging_config} \
-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/usr/local/etc/jitsi \
-Dnet.java.sip.communicator.SC_HOME_DIR_NAME=videobridge \
-Dnet.java.sip.communicator.SC_LOG_DIR_LOCATION=/var/log/ \
-cp ${jitsi_videobridge_jar} \
org.jitsi.videobridge.Main \
--host=localhost \
--domain=jitsi.honeyguide.net \
--port=5347 \
--secret=KEYUSEDINCONFIG --apis=rest,xmpp ${jitsi_videobridge_flags}
echo "Started"
}
...
Please note that if you want to use the restart command for the service, you also need to adjust the jitsi_videobridge_restart()
function similarly.
As soon as reading from the config file is fixed, our config file will look like this:
JVB_XMPP_HOST=localhost
JVB_XMPP_DOMAIN=jitsi.honeyguide.net
JVB_XMPP_PORT=5347
JVB_XMPP_SECRET=KEYUSEDINCONFIG
VIDEOBRIDGE_MAX_MEMORY=3072m
# VIDEOBRIDGE_DEBUG_OPTIONS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000"
We also need to adjust /usr/local/etc/jitsi/videobridge/sip-communicator.properties
(this file also already is prepared for the grafana
dashboard, but you need to adjust the IP address in any case if your jail does not use the public IP address because e.g. you have 1:1 NAT):
# The videobridge uses 443 by default with 4443 as a fallback, but since we're already
# running nginx on 443 in this example doc, we specify 4443 manually to avoid a race condition
org.jitsi.videobridge.TCP_HARVESTER_PORT=4443
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=10.10.0.1
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=197.155.21.68
# 197.155.21.68 is the address assigned to jitsi.honeyguide.net
#
# For Grafana dashboard
#
# the callstats credentials
io.callstats.sdk.CallStats.appId="hgstats"
io.callstats.sdk.CallStats.keyId="GRAFANAKEY"
##io.callstats.sdk.CallStats.keyPath=
##io.callstats.sdk.CallStats.appSecret=
# the id of the videobridge
#io.callstats.sdk.CallStats.bridgeId=jitsi-videobridge.jitsi.honeyguide.net
#io.callstats.sdk.CallStats.conferenceIDPrefix=conference.jitsi.honeyguide.net
# enable statistics and callstats statistics and the report interval
org.jitsi.videobridge.ENABLE_STATISTICS=true
org.jitsi.videobridge.STATISTICS_INTERVAL.callstats.io=30000
org.jitsi.videobridge.STATISTICS_TRANSPORT=callstats.io
Setting up jicofo
The jicofo
startup script /usr/local/etc/rc.d/jicofo
expects a /usr/local/etc/ssl/java.pem
, so we create it:
$ keytool -noprompt -keystore /usr/local/etc/ssl/java.pem -importcert -alias prosody -file /var/db/prosody/auth.jitsi.honeyguide.net.crt
Remember your keystore password for later on.
The jicofo
config file is in /usr/local/etc/jitsi/jicofo/jicofo.conf
but it is currently ignored as well.
So we also adjusted /usr/local/etc/rc.d/jicofo
and saved the original file as jicofo.orig:
...
jicofo_start()
{
daemon -p ${pidfile} -o /var/log/${name}.log ${command} -Xmx3072m \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/tmp \
-Djava.util.logging.config.file=${jicofo_logging_config} \
-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/usr/local/etc/jitsi \
-Dnet.java.sip.communicator.SC_HOME_DIR_NAME=jicofo \
-Dnet.java.sip.communicator.SC_LOG_DIR_LOCATION=/var/log/ \
-Djavax.net.ssl.trustStore=/usr/local/etc/ssl/java.pem \
-cp ${jicofo_jar} \
org.jitsi.jicofo.Main \
--host=localhost \
--domain=jitsi.honeyguide.net \
--port=5347 \
--secret=3r8wer8DH \
--user_domain=auth.jitsi.honeyguide.net \
--user_name=focus \
--user_password=KEYUSEDINCONFIG ${jicofo_flags}
echo "Started"
}
...
Here, the restart command works as it has been implemented more elegantly in the startup script already.
For later on, when the startup script reads the config file correctly, here is our /usr/local/etc/jitsi/jicofo/jicofo.conf
:
JVB_XMPP_HOST=localhost
JVB_XMPP_DOMAIN=jitsi.honeyguide.net
JVB_XMPP_PORT=5347
JVB_XMPP_SECRET=KEYUSEDINCONFIG
JVB_XMPP_USER_DOMAIN=auth.jitsi.honeyguide.net
JVB_XMPP_USER_NAME=focus
JVB_XMPP_USER_SECRET=KEYUSEDINCONFIG
MAX_MEMORY=3072m
Setting up nginx
The nginx
configuration is in /usr/local/etc/nginx/nginx.conf
. Of course it might be done differently, but we set up everything in this one file as it is not complicated.
We only need to add two server
entries:
...
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 0.0.0.0:443 ssl http2;
ssl_certificate /usr/local/etc/ssl/jitsi.honeyguide.net.cer;
ssl_certificate_key /usr/local/etc/ssl/jitsi.honeyguide.net.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
server_name jitsi.honeyguide.net;
# set the root
root /usr/local/www/jitsi-meet;
index index.html;
location ~ ^/([a-zA-Z0-9=\?]+)$ {
rewrite ^/(.*)$ / break;
}
location / {
ssi on;
}
# BOSH, Bidirectional-streams Over Synchronous HTTP
# https://en.wikipedia.org/wiki/BOSH_(protocol)
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
# external_api.js must be accessible from the root of the
# installation for the electron version of Jitsi Meet to work
# https://github.com/jitsi/jitsi-meet-electron
location /external_api.js {
alias /srv/jitsi-meet/libs/external_api.min.js;
}
}
...
An easy way to maintain Let’s Encrypt SSL certificates is acme.sh
stand alone mode:
$ /usr/local/etc/rc.d/nginx stop
...
$ cd
$ acme.sh --force --issue -d jitsi.honeyguide.net --standalone
...
$ cd /root/.acme.sh/jitsi.honeyguide.net/
$ mv * /usr/local/etc/ssl/
$ /usr/local/etc/rc.d/nginx start
Setting up jitsi-meet
The jitsi-meet
configuration is located in /usr/local/www/jitsi-meet/config.js
.
Most of the values there can remain as they are (though you might want to customise them depending on your needs), but you need to change the first lines of the file to reflect your domain:
var config = {
// Connection
//
hosts: {
// XMPP domain.
domain: 'jitsi.honeyguide.net',
// When using authentication, domain for guest users.
// anonymousdomain: 'guest.example.com',
// Domain for authenticated users. Defaults to <domain>.
// authdomain: 'jitsi-meet.example.com',
// Jirecon recording component domain.
// jirecon: 'jirecon.jitsi-meet.example.com',
// Call control component (Jigasi).
// call_control: 'callcontrol.jitsi-meet.example.com',
bridge: 'jitsi-videobridge.jitsi.honeyguide.net',
// Focus component domain. Defaults to focus.<domain>.
focus: 'focus.jitsi.honeyguide.net',
// XMPP MUC domain. FIXME: use XEP-0030 to discover it.
muc: 'conference.jitsi.honeyguide.net'
},
...
If you want to adjust the frontend and look and feel, look at the content in the directories static
, images
and at interface_config.js
.
Finishing Up
To make sure everything is started automatically, add the services to /etc/rc.conf
:
...
jitsi_videobridge_enable="YES"
jisti_videobridge_flags="--apis=rest,xmpp"
nginx_enable="YES"
prosody_enable="YES"
jicofo_enable="YES"
...