Jump to content
From ArchWiki

Jitsi is a set of open-source projects that allows you to easily build and deploy secure videoconferencing solutions. At the heart of Jitsi are Jitsi Videobridge and Jitsi Meet, which let you have conferences on the internet, while other projects from the community enable other features such as audio, dial-in, recording, and simulcasting.

## Installation

Jitsi-meet consists of severals components:

- `jitsi-meet`: the files for the webinterface, accessed via files served by a webserver
- `jitsi-meet-prosody`: the prosody plugins for jitsi
- `jitsi-meet-turnserver`: the configs example to run a stun/turn server
- `jitsi-videobridge`: the video bridging service providing video streams to all participants
- `jicofo`: the Jitsi conference focus determining who is speaking
- Prosody: a free XMPP server serving as the base of the setup

A graphical overview of the interfaces to the user and towards each other is given here.

You can either use the git versions, the nightly version or the stable versions.

It is possible to install them at the same time, but you will need to use separate port and several instances of prosody (the plugins cannot be scope by virtual host).

You need to choose between the normal or the bin version. The bin one conflicts with the normal version (i.e. nightly and nightly-bin can not be installed at the same time, but stable and nightly can be).

Try to stick with only one of them:

- stable
- nightly
- git

Some packages install configuration examples in `/usr/share/doc`, ensure to comment this line in `/etc/pacman.conf`:

    #NoExtract = usr/share/gtk-doc/html/* usr/share/doc/*

You need those optionals packages to run a standalone server:

- nginx
- coturn
- prosody
- lua52
- lua52-sec
- lua52-zlib
- lua52-eventAUR

## Configuration

Note: This configuration yields an open server for everyone to connect. Refer to the Jitsi philosophy for rationale. See #Tips and tricks for authentication.

If your server name is `example.com` then a common choice for your jitsi will be `meet.example.com`, but you can choose freely. It is however strongly encouraged from security standpoint to host webapps on their own subdomain. You will need to update DNS record for your server with an entry of your chosen subdomain, in the above example `meet`. The remainder assumes that you have done this.

Also you should have SSL/TLS certificates for your `meet.example.com` domain, on how to obtain free certificates see certbot.

In the following, the following placeholders are used:

- `JITSIFQDN`: your `jitsi-meet` domain, e.g. `meet.example.com`
- `SECRET_JVB_USER`: password for the videobridge
- `SECRET_FOCUS_USER`: password for the authenticator

Passwords should be obtained in a safe way, e.g. via `mktemp -u XXXXXXXX` or via `pwgen`. Make sure to use different and safe passwords!

### Configuration paths

Package | Configuration path
--- | ---
Stable
jitsi-meetAUR jitsi-meet-binAUR | `/etc/webapps/jitsi-meet`
jitsi-meet-prosodyAUR jitsi-meet-prosody-binAUR | `/usr/lib/jitsi-meet-prosody`
jitsi-meet-turnserverAUR jitsi-meet-turnserver-binAUR | `/usr/share/doc/jitsi-meet-turnserver`
jicofoAUR jicofo-binAUR | `/etc/jicofo`
jitsi-videobridgeAUR jitsi-videobridge-binAUR | `/etc/jitsi-videobridge`
Nightly
jitsi-meet-nightlyAUR jitsi-meet-nightly-binAUR | `/etc/webapps/jitsi-meet-nightly`
jitsi-meet-prosody-nightlyAUR jitsi-meet-prosody-nightly-binAUR | `/usr/lib/jitsi-meet-prosody-nightly`
jitsi-meet-turnserver-nightlyAUR jitsi-meet-turnserver-nightly-binAUR | `/usr/share/doc/jitsi-meet-turnserver-nightly`
jicofo-nightlyAUR jicofo-nightly-binAUR | `/etc/jicofo-nightly`
jitsi-videobridge-nightlyAUR jitsi-videobridge-nightly-binAUR | `/etc/jitsi-videobridge-nightly`
Git
jitsi-meet-gitAUR | `/etc/webapps/jitsi-meet-git`
jitsi-meet-prosody-gitAUR | `/usr/lib/jitsi-meet-prosody-git`
jitsi-meet-turnserver-gitAUR | `/usr/share/doc/jitsi-meet-turnserver-git`
jicofo-gitAUR | `/etc/jicofo-git`
jitsi-videobridge-gitAUR | `/etc/jitsi-videobridge-git`

### Loopback

Let us jitsi-meet components reach each other with local ip. It works even if your domain is behind a proxy like Cloudflare which does not return the real ip of the server.

In `/etc/hosts`:

    127.0.0.1 JITSIFQDN auth.JITSIFQDN
    ::1 JITSIFQDN auth.JITSIFQDN

### Configure prosody

prosody is a prerequisite and you will need to add a configuration to it for your Jitsi services. If you do not already have a prosody server set up, install prosody and lua52-sec now. The rest of the prosody configuration assumes you have a local install of prosody.

The package jitsi-meet-prosodyAUR provides a configuration you can easily customize:

    # cd /etc/prosody
    # mkdir conf.d
    # cp /usr/share/doc/jitsi-meet-prosody/prosody.cfg.lua-jvb.example conf.d/jitsi.cfg.lua

Then add this at the end of:

    /etc/prosody/prosody.cfg.lua

    Include "conf.d/*.cfg.lua"

Customize your configuration:

    /etc/prosody/conf.d/jitsi.cfg.lua

    -- replace all occurences of jitmeet.example.com by JITSIFQDN
    -- replace all occurences of focusUser by focus
    -- then add or update those section

    VirtualHost "JITSIFQDN"
        ssl = {
            key = "/etc/prosody/certs/JITSIFQDN.key";
            certificate = "/etc/prosody/certs/JITSIFQDN.crt";
        }

    VirtualHost "auth.JITSIFQDN"
        ssl = {
            key = "/etc/prosody/certs/auth.JITSIFQDN.key";
            certificate = "/etc/prosody/certs/auth.JITSIFQDN.crt";
        }
        authentication = "internal_hashed"

    /etc/prosody/conf.d/jitsi.cfg.lua

    -- Proxy to jicofo's user JID, so that it does not have to register as a component.
    Component "focus.JITSIFQDN" "client_proxy"
        target_address = "focus@auth.JITSIFQDN"

You need now to generate the certificate for JITSIFQDN and auth.JITSIFQDN.

If you use certbot, you can import the certificate with:

    # prosodyctl --root cert import /etc/letsencrypt/live

If you want to use self generated certs, you can use:

    # sudo -u prosody prosodyctl cert generate JITSIFQDN
    # sudo -u prosody prosodyctl cert generate auth.JITSIFQDN
    # mv /var/lib/prosody/*.{crt,cnf,key} /etc/prosody/certs/
    # trust anchor /etc/prosody/certs/JITSIFQDN.crt
    # trust anchor /etc/prosody/certs/auth.JITSIFQDN.crt
    # update-ca-trust

Let us register the users jvb and focus:

    # prosodyctl register jvb auth.JITSIFQDN SECRET_JVB_USER
    # prosodyctl register focus auth.JITSIFQDN SECRET_FOCUS_USER
    # prosodyctl mod_roster_command subscribe focus.JITSIFQDN focus@auth.JITSIFQDN

Then restart `prosody.service` (or start/enable it if it was just installed).

### Configure jitsi-videobridge

The configuration for jitsi-videobridge. Add -nightly or -git to /etc/jitsi-videobridge for nightly and git version.

For MUC_NICKNAME, use uuidgen command:

    /etc/jitsi-videobridge/sip-communicator.properties

    org.jitsi.videobridge.xmpp.user.shard.DOMAIN=auth.JITSIFQDN
    org.jitsi.videobridge.xmpp.user.shard.PASSWORD=SECRET_JVB_USER
    org.jitsi.videobridge.xmpp.user.shard.MUC_JIDS=JvbBrewery@internal.auth.JITSIFQDN
    org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAME=UUIDGEN_RESULT

Then start/enable `jitsi-videobridge.service`.

### Configure jicofo

The configuration for jicofo. Add -nightly or -git to /etc/jitsi-videobridge for nightly and git version.

    /etc/jicofo/jicofo.conf

    jicofo {
      xmpp: {
        client: {
          client-proxy: "focus.JITSIFQDN"
          xmpp-domain: "JITSIFQDN"
          domain: "auth.JITSIFQDN"
          username: "focus"
          password: "SECRET_FOCUS_USER"
          conference-muc-jid = conference.JITSIFQDN
        }
        trusted-domains: [ "recorder.JITSIFQDN" ]
      }
      bridge: {
        brewery-jid: "JvbBrewery@internal.auth.JITSIFQDN"
      }
    }

Then start/enable `jicofo.service`.

### Configure jitsi-meet

The configuration for jitsi-meet webapps. Add -nightly or -git to /etc/jitsi-videobridge for nightly and git version.

    /etc/webapps/jitsi-meet/config.js

    var config = {
      hosts: {
        domain: 'JITSIFQDN',
        // ...
        muc: 'conference.JITSIFQDN'
      },
      bosh: '//JITSIFQDN/http-bind',
      // ...
    }

### Configure nginx

Configure nginx with TLS as described in nginx#TLS.

Let us copy the provided example.

    # cd /etc/nginx
    # mkdir sites
    # cp /usr/share/doc/jitsi-meet/jitsi-meet.example sites/jitsi.conf

Then include it in your main configuration:

    /etc/nginx/nginx.conf

    http {
        // ...
        // this should be placed near to the close bracket of the http block
        include sites/*.conf;
    }

Then changes the jitsi configuration with yours:

    /etc/nginx/sites/jitsi.conf

    server {
      # ...
      server_name JITSIFQDN;

      # ...
      # use prosody path directly
      ssl_certificate /etc/prosody/certs/JITSIFQDN.crt;
      ssl_certificate_key /etc/prosody/certs/JITSIFQDN.key;
      # or use letencrypt path
      ssl_certificate /etc/letsencrypt/live/JITSIFQDN/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/JITSIFQDN/privkey.pem;

      # set the config path
      # replace alias /etc/jitsi/meet/jitmeet.example.com-config.js by
      location = /config.js {
        alias /etc/webapps/jitsi-meet/config.js;
      }
      # ...
      location ~ ^/([^/?&:'"]+)/config.js$
      {
        set $subdomain "$1.";
        set $subdir "$1/";
        alias /etc/webapps/jitsi-meet/config.js;
      }
    }

Then restart `nginx.service`.

## Tips and tricks

### Running the server behind a NAT

The following ports need to be forwarded to your server:

HTTPS:

- TCP/443

Jitsi Videobridge:

- UDP/10000

### Jitsi gateway to SIP (Jigasi)

To interface the Jitsi-meet meetings with traditional SIP install jigasiAUR or jigasi-gitAUR and edit the prosody config:

    /etc/prosody/prosody.cfg.lua

    Component "callcontrol.JITSIFQDN"
        component_secret = "SECRET_JIGASI_USER"

fill the SIP access credentials (`SIPUSER` `SIPSERVER` and `SIPPASSWORD`)

    /opt/jigasi/jigasi-home/sip-communicator.properties

    net.java.sip.communicator.impl.protocol.sip.acc1403273890647.ACCOUNT_UID=SIP\:"SIPUSER@SIPSERVER"
    net.java.sip.communicator.impl.protocol.sip.acc1403273890647.PASSWORD=SIPPASSWORD
    net.java.sip.communicator.impl.protocol.sip.acc1403273890647.SERVER_ADDRESS=SIPSERVER
    net.java.sip.communicator.impl.protocol.sip.acc1403273890647.USER_ID=SIPUSER

To change the default room name SIP is connecting to, change `org.jitsi.jigasi.DEFAULT_JVB_ROOM_NAME` in the above config.

Then edit the jigasi configuration

    /etc/jitsi/jigasi/config

    JIGASI_HOST=callcontrol.JITSIFQDN
    JIGASI_HOSTNAME=jitsi-videobridge.JITSIFQDN
    JIGASI_SECRET=SECRET_JIGASI_USER
    JIGASI_OPTS=""
    LOGFILE=/var/log/jitsi/jigasi.log

    /opt/jitsi-meet/config.js

    hosts.call_control = 'callcontrol.meet.jit.si'

and then start/enable `jigasi.service`.

### Access restrictions for room creation

To restrict video conference room creation to authenticated users, you can do the following steps. Note that participants to the meeting are still not authenticated!

Add authentication to the jitsi domain in prosody and add a new virtual host for guests:

    /etc/prosody/conf.d/jitsi.cfg.lua

    -- change authentification of your domain
    VirtualHost "JITSIFQDN"
        authentification = "internal_plain"

    -- add guest virtual host to allow anonymous user to join your room
    VirtualHost "guest.JITSIFQDN"
        authentication = "jitsi-anonymous"
        c2s_require_encryption = false
        modules_enabled = {
            -- copy the content of the modules_enabled
            -- of the VirtualHost "JITSIFQDN"
            -- remove only the module "muc_lobby_rooms" of the list
            -- example:
            "bosh";
            "pubsub";
            "ping"; -- Enable mod_ping
            "speakerstats";
            "external_services";
            "conference_duration";
        }

Edit the configuration file for `jitsi-meet`:

    /etc/webapps/jitsi-meet/config.js

    var config = {
      host: {
        // anonymous users need to use a dedicated muc without authentication
        anonymousdomain: 'guest.JITSIFQDN',
      },
    }

Add authentication for `jicofo`:

    /etc/jicofo/jicofo.conf

    jicofo {
      authentication {
        enabled = true
        type = XMPP
        login-url = JITSIFQDN
        enable-auto-login = true
      }
    }

Then create the desired users via

    # prosodyctl register <username> JITSIFQDN <password>

Only if you are using `jigasi` (if you do not know, you do not) edit the SIP interface to not allow anonymous authentication:

    /etc/jitsi/jigasi/sip-communicator.properties

    org.jitsi.jigasi.xmpp.acc.ANONYMOUS_AUTH=false

These steps are taken from this guide.

### Access restrictions with JWT token

To restrict video conference room creation to users authenticate with a JWT token (external service for authentication), you can do the following steps. Note that participants to the meeting are still not authenticated!

Install those dependencies:

- lua52-base64AUR
- lua52-basexx
- lua52-cjsonAUR
- lua52-jwtjitsiAUR
- lua52-luaossl

Add authentication to the jitsi domain in prosody and add a new virtual host for guests:

    /etc/prosody/conf.d/jitsi.cfg.lua

    -- change authentification of your domain
    VirtualHost "JITSIFQDN"
        authentification = "token"
        app_id = "APP_ID"
        app_secret = "APP_SECRET"
        allow_empty_token = false
        modules_enabled = {
            -- keep existing modules and add
            "presence_identity";
        }
        c2s_require_encryption = false

    -- add guest virtual host to allow anonymous user to join your room
    VirtualHost "guest.JITSIFQDN"
        authentication = "jitsi-anonymous"
        c2s_require_encryption = false
        modules_enabled = {
            -- copy the content of the modules_enabled
            -- of the VirtualHost "JITSIFQDN"
            -- remove only the module "muc_lobby_rooms" of the list
            -- example:
            "bosh";
            "pubsub";
            "ping"; -- Enable mod_ping
            "speakerstats";
            "external_services";
            "conference_duration";
            "presence_identity";
        }

    Component "conference.JITSIFQDN" "muc"
        modules_enabled = {
            -- add this to the modules_enabled
            "token_verification";
        }

Edit the configuration file for `jitsi-meet`:

    /etc/webapps/jitsi-meet/config.js

    var config = {
      host: {
        // anonymous users need to use a dedicated muc without authentication
        anonymousdomain: 'guest.JITSIFQDN',
      },
    }

Add authentication for `jicofo`:

    /etc/jicofo/jicofo.conf

    jicofo {
      authentication {
        enabled = true
        type = JWT
        login-url = JITSIFQDN
        enable-auto-login = true
      }
    }

Then restart `prosody.service` (or start/enable it if it was just installed). And restart `jicofo.service` (or start/enable it if it was just installed).

Now you can use a JWT token to authenticate an user.

You can read the spec here: Jitsi Meet Tokens

Here an quick example in nodejs:

    const jwt = require('jsonwebtoken')
    const crypto = require('crypto');
    const words = require('random-words')
    const yourDomain = "JITSIFQDN"
    const appId = "APP_ID"
    const appSecret = "APP_SECRET"
    const userName = "YOUR_USERNAME"
    const userEmail = "YOUR_EMAIL"

    function getBody(domain, appId, name, email, room) {
        const md5Email = crypto.createHash('md5').update(email).digest("hex");
        const id = crypto.createHash('sha1').update(`${name}:${email}`).digest("hex")

        return {
            context: {
                user: {
                    avatar: `https:/gravatar.com/avatar/${md5Email}`,
                    name,
                    email,
                    id,
                },
                group: 'users'
            },
            "aud": "jitsi",
            "iss": appId,
            "sub": domain,
            room,
        }
    }

    const room = process.argv[2] || words({exactly: 3, join: '-'})

    const data = getBody(
        yourDomain,
        appId,
        userName,
        userEmail,
        room,
    )

    const options = {
        algorithm: 'HS256',
        expiresIn: '2h',
    }

    const jwtToken = jwt.sign(data, appSecret, options)

    console.log(`https://${yourDomain}/${room}?jwt=${jwtToken}`)

### Log evaluation

For a publicly available IP address the above configuration leads to a public video conference server. To monitor server use one can use journalctl to get an at least vague idea of the usage:

    # journalctl --unit=jicofo.service --grep="created new conference" --output cat

shows all events of new chat room creation and

    # journalctl --unit=jicofo.service --grep="Stopped" --output cat

shows all events of chat room destruction.

Grepping for 'member' also gives you (anonymous!) information on the participants.

### Running own STUN server

By default, Jitsi Meet uses STUN servers from jitsi.org. You can easily run your own STUN server using coturn and setting it in jitsi-meet's config.

## Troubleshooting

### Check your logs

You can stop all service units (i.e., `prosody.service`, `jitsi-videobridge.service`, and `jicofo.service`), start them one at a time, and follow new messages in the journal for each service unit to see if something is wrong. Most problems are due to password or configuration issues.

If you have an upgrade from a very different version, or you mess up with your config, start other. It will be faster than trying to findout which part is wrong.

### Ask help on Matrix rooms

You can join matrix rooms and ask help there:

- Jitsi Meet help and testing

## See also

- Project homepage
- Help community
- Official documentation
- Arch Linux tutorial with more details

Categories:

- Telephony
- Voice over IP