tuto:linux_divers:jitsi

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
tuto:linux_divers:jitsi [24/04/2020 13:06]
dani
tuto:linux_divers:jitsi [28/05/2020 11:22] (Version actuelle)
dani [Install Jitsi on CentOS 7]
Ligne 1: Ligne 1:
 ====== Install Jitsi on CentOS 7 ====== ====== Install Jitsi on CentOS 7 ======
  
-This page give needed steps to install and configure Jitsi on a CentOS server. If like me, you're not a big Docker fan, and you're happier with EL based systems instead of Debian, it might be useful to you. In this guide, you'll learn :+This page gives the needed steps to install and configure Jitsi on a CentOS server. If like me, you're not a big Docker fan, and you're happier with EL based systems, it might be useful to you. In this guide, you'll learn :
   * How to build latest versions of all components   * How to build latest versions of all components
   * Get a working install with prosody, jicofo, meet, videobridge   * Get a working install with prosody, jicofo, meet, videobridge
Ligne 8: Ligne 8:
  
 <note tip>We deploy all this with ansible, see [[https://git.fws.fr/fws/ansible-roles/src/branch/master/roles/prosody|prosody]] [[https://git.fws.fr/fws/ansible-roles/src/branch/master/roles/jitsi|jitsi]] and [[https://git.fws.fr/fws/ansible-roles/src/branch/master/roles/jitsi_videobridge|jitsi videobridge]] <note tip>We deploy all this with ansible, see [[https://git.fws.fr/fws/ansible-roles/src/branch/master/roles/prosody|prosody]] [[https://git.fws.fr/fws/ansible-roles/src/branch/master/roles/jitsi|jitsi]] and [[https://git.fws.fr/fws/ansible-roles/src/branch/master/roles/jitsi_videobridge|jitsi videobridge]]
-This page are just some notes to help you setting this up if you don't want to play with ansible. It might be out of date though+This page are just some notes to help you setting this up if you don't want to play with ansible. But ansible is our recommanded way to deploy it
 </note> </note>
  
 Jitsi is composed of several components, and also relies on 3rd party ones. Here is a quick overview of which are using for what : Jitsi is composed of several components, and also relies on 3rd party ones. Here is a quick overview of which are using for what :
  
-  * An XMPP server is needed to route messages between all those components. We will use prosody for this+  * An XMPP server is needed to route messages between all the components. We will use prosody for this
   * Videobridge is the SFU((Selective Forwarding Unit)). It will receive all the video and audio streams, and handle relay to the other participants   * Videobridge is the SFU((Selective Forwarding Unit)). It will receive all the video and audio streams, and handle relay to the other participants
   * Jicofo is the component which will handle stream negociation and room management   * Jicofo is the component which will handle stream negociation and room management
Ligne 20: Ligne 20:
   * ConferenceMapper API is a small daemon needed for inbound calls to work. It'll associate a PIN to each Jitsi room and is needed so that a phone call can be routed to the correct Jitsi room   * ConferenceMapper API is a small daemon needed for inbound calls to work. It'll associate a PIN to each Jitsi room and is needed so that a phone call can be routed to the correct Jitsi room
  
-In this example, will use visio.fws.fr as jitsi domain name. You'll need to adapt this+In this example, we will use visio.fws.fr as jitsi domain name. You'll need to adapt this
  
 <note tip>This how to assume you already have a valid SSL cert in /etc/prosody/certs/jitsi.crt with its private key /etc/prosody/certs/jitsi.key.</note> <note tip>This how to assume you already have a valid SSL cert in /etc/prosody/certs/jitsi.crt with its private key /etc/prosody/certs/jitsi.key.</note>
Ligne 56: Ligne 56:
 </code> </code>
  
-Now, lets configure it+Now, lets configure it. Edit /etc/prosody/prosody.cfg.lua
  
-<code bash> +<file prosody.cfg.lua lua>
-cat <<_EOF > /etc/prosody.cfg.lua+
  
 plugin_paths = { "/opt/prosody/modules" } plugin_paths = { "/opt/prosody/modules" }
Ligne 122: Ligne 121:
  
 Include "conf.d/*.cfg.lua" Include "conf.d/*.cfg.lua"
 +</file>
  
-_EOF +Now edit **/etc/prosody/conf.d/jitsi.cfg.lua**
- +
-cat <<_EOF > /etc/prosody/conf.d/jitsi.cfg.lua+
  
 +<file jitsi.cfg.lua lua>
 muc_mapper_domain_base = "visio.fws.fr"; muc_mapper_domain_base = "visio.fws.fr";
 admins = { "focus@auth.visio.fws.fr" } admins = { "focus@auth.visio.fws.fr" }
Ligne 196: Ligne 195:
   muc_component = "conference.visio.fws.fr"   muc_component = "conference.visio.fws.fr"
  
-_EOF +</file>
-</code>+
  
 Now we can start and enable the daemon Now we can start and enable the daemon
Ligne 499: Ligne 497:
   deny all;   deny all;
 } }
 +</file>
 +</hidden>
 +
 +You also have to edit /opt/jitsi/meet/config.js and adapt it to your needs.
 +<hidden Here's a example of config.js>
 +<file config.js js>
 +var config = {
 +    "bosh": "//visio.fws.fr/http-bind",
 +    "channelLastN": -1,
 +    "clientNode": "http://jitsi.org/jitsimeet",
 +    "desktopSharingChromeExtId": null,
 +    "desktopSharingChromeMinExtVersion": 0.1,
 +    "desktopSharingChromeSources": [
 +        "screen",
 +        "window",
 +        "tab"
 +    ],
 +    "dialInConfCodeUrl": "https://visio.fws.fr/conferenceMapper",
 +    "dialInNumbersUrl": "https://visio.fws.fr/phoneNumberList",
 +    "disableAudioLevels": true,
 +    "disableThirdPartyRequests": true,
 +    "enableCalendarIntegration": false,
 +    "enableLayerSuspension": true,
 +    "enableNoAudioDetection": true,
 +    "enableNoisyMicDetection": false,
 +    "enableWelcomePage": true,
 +    // Uncomment to enable Etherpad integration
 +    //"etherpad_base": "https://etherpad.fws.fr/p/",
 +    "focusUserJid": "focus@auth.visio.fws.fr",
 +    "hosts": {
 +        "domain": "visio.fws.fr",
 +        "muc": "conference.visio.fws.fr"
 +    },
 +    "localRecording": {
 +        "enabled": true
 +    },
 +    "p2p": {
 +        "enabled": true,
 +        "preferH264": true,
 +        "useStunTurn": true
 +    },
 +    "requireDisplayName": false,
 +    "resolution": 480,
 +    "testing": {
 +        "p2pTestMode": false
 +    },
 +    "useStunTurn": true,
 +    "websocket": "wss://visio.fws.fr/xmpp-websocket"
 +};
 </file> </file>
 </hidden> </hidden>
Ligne 575: Ligne 622:
 net.java.sip.communicator.impl.protocol.jabber.acc=acc net.java.sip.communicator.impl.protocol.jabber.acc=acc
 net.java.sip.communicator.impl.protocol.jabber.acc.ACCOUNT_UID=Jabber:jigasi@auth.visio.fws.fr net.java.sip.communicator.impl.protocol.jabber.acc.ACCOUNT_UID=Jabber:jigasi@auth.visio.fws.fr
-net.java.sip.communicator.impl.protocol.jabber.acc.USER_ID=jigasi@auth.conf.fws.fr+net.java.sip.communicator.impl.protocol.jabber.acc.USER_ID=jigasi@auth.visio.fws.fr
 net.java.sip.communicator.impl.protocol.jabber.acc.IS_SERVER_OVERRIDDEN=true net.java.sip.communicator.impl.protocol.jabber.acc.IS_SERVER_OVERRIDDEN=true
 net.java.sip.communicator.impl.protocol.jabber.acc.SERVER_ADDRESS=jitsi.fws.fr net.java.sip.communicator.impl.protocol.jabber.acc.SERVER_ADDRESS=jitsi.fws.fr
Ligne 633: Ligne 680:
 </code> </code>
  
 +Jigasi is now running, but it's not yet ready to be used.
  
 ===== Install confmapper daemon ===== ===== Install confmapper daemon =====
  
-===== Integrate with Etherpad =====+The confmapper daemon is a small tool to register Jitsi room name <-> PIN. We'll use https://github.com/gronke/jitsi-conferencemapper-api as it's a simple and lightweigt daemon in python, using an SQLite database to store the mappings 
 + 
 +<code bash> 
 +yum install python3 
 +</code> 
 +<code bash> 
 +mkdir -p /opt/jitsi/{data,confmapper} 
 +chown jitsi:jitsi /opt/jitsi/data 
 +chmod 700 /opt/jitsi/data 
 +wget -P /opt/jitsi/confmapper/
 +  https://raw.githubusercontent.com/gronke/jitsi-conferencemapper-api/master/daemon.py 
 +chmod 755 /opt/jitsi/confmapper/daemon.py 
 +</code> 
 + 
 +Now, lets configure it 
 +<code bash> 
 +cat <<_EOF > /opt/jitsi/confmapper/config.json 
 +
 +    "db_file": "/opt/jitsi/data/confmapper.sqlite", 
 +    "expire_seconds": 86400, 
 +    "host": "0.0.0.0", 
 +    "id_max_length": 4, 
 +    "numbers":
 +        "FR":
 +            "0510101010" 
 +        ] 
 +    }, 
 +    "port": 8823 
 +
 +_EOF 
 +</code> 
 + 
 +Here : 
 +    * The daemon listens on 0.0.0.0:8823. You should configure a reverse proxy to make it accessible over HTTPS. The sample nginx configuration does it 
 +    * Room mappings will be kept for 1 day 
 +    * PIN will be created with 4 digits 
 +    * The number 0510101010 is dedicated and will be announced in Jitsi interface. You can set several numbers, including different numbers for different countries 
 + 
 +In any case, make sure requests to https://visio.fws.fr/conferenceMapper and https://visio.fws.fr/phoneNumberList are routed to this daemon (because those are the URL configured in Jitsi meet 
 + 
 +Now, we can create a systemd unit and start the service 
 + 
 +<code bash> 
 +cat <<_EOF > /etc/systemd/system/jitsi-confmapper.service 
 +[Unit] 
 +Description=Jitsi Conference Mapper 
 +After=network.target 
 + 
 +[Service] 
 +Type=simple 
 +User=jitsi 
 +Group=jitsi 
 +PrivateTmp=true 
 +PrivateDevices=true 
 +ProtectHome=true 
 +ProtectSystem=full 
 +Restart=on-failure 
 +StartLimitInterval=
 +RestartSec=30 
 +ExecStart=/opt/jitsi/confmapper/daemon.py 
 + 
 +[Install] 
 +WantedBy=multi-user.target 
 +_EOF 
 +systemctl daemon-reload 
 +systemctl enable --now jitsi-confmapper 
 +</code>
  
 ===== Configure Asterisk/FreePBX ===== ===== Configure Asterisk/FreePBX =====
 +==== Create a SIP extension ====
 +Now, we have to configure Asterisk. First step is to create an SIP extension for Jigasi. So we create a PJSIP extension, with ID **304** and secret **SIP_SECRET** (this is what we've configured in jigasi). In the advanced tab of the extension, there's a few things we can change
 +
 +  * You might want to change the Outbound CID to advertize the 0510101010 number
 +  * You might change the context to **outbound-allroutes** if you don't want conference user to be able to call internal numbers. The default context is **from-internal**
 +  * Restrict codecs to alaw and ulaw (I had sound issues with opus and g722, so better to restrict this to known working codecs). For this, type **all** in the **Disallowed Codecs** field, and **alaw&ulaw** in the **Allowed Codec** field
 +  * You should also disable the **Direct Media** option
 +
 +==== Create a custom IVR ====
 +
 +Now, we have to create a custom IVR which will ask callers the PIN of the room they want to join. you can put it in **/etc/asterisk/extension_custom.conf**
 +
 +<code>
 +[jitsi-ivr]
 +exten => s,1,Answer
 +exten => s,n,Set(IVR_MSG=conf-getpin)
 +exten => s,n,Set(TIMEOUT(digit)=3)
 +exten => s,n,Read(JITSI_PIN,${IVR_MSG})
 +
 +; Fetch the conf name from the PIN entered
 +exten => s,n,AGI(jitsi_conf_pin,"https://visio.fws.fr/conferenceMapper",${JITSI_PIN}
 +
 +; If we got a result, dial JIGASI SIP account, else, loop and ask again
 +exten => s,n,GotoIf($["${JITSI_ROOM}" != "error"]?jitsi,1)
 +exten => s,n(error),Playback(conf-invalid)
 +exten => s,n,Goto(s,1)
 +
 +; We got a result, lets join jitsi room
 +exten => jitsi,1,Verbose(PIN ${JITSI_PIN} maps to Jitsi room ${JITSI_ROOM})
 +exten => jitsi,n,Dial(PJSIP/304,,b(jitsi-conference-room-header^addheader^1(${JITSI_ROOM})))
 +</code>
 +
 +==== Create an AGI script to lookup roomname from their PIN ====
 +
 +We have to create an AGI script so that asterisk can query the confmapper daemon to get the name of a room from the PIN. For this, create the script **/usr/share/asterisk/agi-bin/jitsi_conf_pin** with the following content :
 +
 +<code perl>
 +#!/usr/bin/perl
 +
 +use warnings;
 +use strict;
 +use LWP::UserAgent;
 +use JSON;
 +
 +my $ret = 'error';
 +
 +my $url = $ARGV[0] . '?id=' . $ARGV[1];
 +my $ua = LWP::UserAgent->new(timeout => 10);
 +$ua->env_proxy;
 +
 +my $response = $ua->get($url);
 +if ($response->is_success){
 +  my $json = from_json($response->content);
 +  if (defined $json and defined $json->{conference}){
 +    $ret = $json->{conference};
 +    $ret =~ s/@.*//;
 +  }
 +}
 +
 +print "SET VARIABLE JITSI_ROOM $ret\n";
 +</code>
 +
 +The script must be executable
 +<code bash>
 +chmod +x /usr/share/asterisk/agi-bin/jitsi_conf_pin
 +</code>
 +
 +==== Create a Custom Destination pointing on your custom IVR ====
 +OK, now we need to way to route calls to our new custom IVR. For this, we'll create a **Custom Destination** in FreePBX. Just set the target to **jitsi-ivr,s,1**
 +
 +{{ :tuto:linux_divers:jitsi_custom_dest.png |}}
 +
 +This **Custom Destination** make the IVR available in all the FreePBX routing logic.
 +
 +==== Assign an internal number to the IVR to test ====
 +We can assign it an internal number to test it with a new **Misc Application** :
 +
 +{{ :tuto:linux_divers:jitsi_misc_app.png |}}
 +
 +You can now try it. Create a new room in Jitsi, and if you click on the small **i** button (bottom right), you should see a popup with the number to dial and the PIN
 +
 +{{ :tuto:linux_divers:jitsi_conf_ping.png |}}
 +
 +So, this conf has PIN 4845
 +
 +Now, call your internal test number, which points on the custom IVR (381 in the previous screenshot). You should be prompted to enter a PIN. Once typed, asterisk will lookup on the confmapper daemon to find to which room this PIN maps. If found, you'll join the conference right away. If a wrong PI is entered, you'll be prompted again to enter the PIN.
 +
 +Now, all you have to do is to define a new **Inbound Route** which points on the same **Custom Destination**
 +
 +{{ :tuto:linux_divers:jitsi_inbound_route.png |}}
 +
 +
 +===== Integrate with Etherpad =====
 +
 +Deploying an Etherpad instance is out of scope for this guide (but we also have an [[https://git.fws.fr/fws/ansible-roles/src/branch/master/roles/etherpad|ansible role]] for this). But, say you have it available at https://etherpad.fws.fr. All you have to do is to indicate it in **/opt/jitsi/meet/config.js** 
 +
 +<code>
 +[...]
 +      "etherpad_base": "https://etherpad.fws.fr/p/",
 +[...]
 +</code>
  
 +<note tip>The trailing **/** is important</note>
  
 +===== Note on reverse proxy and Content-Security-Policy =====
 +We use a reverse proxy to serve all the web resources, and this reverse proxy insert CSP headers to response. In this case, we have to allow a few things to get everything working :
 +  * In img-src you have to add https://img.youtube.com and https://i.ytimg.com
 +  * In script-src you have to add https://www.youtube.com and https://s.ytimg.com
 +  * In frame-src you have to add https://etherpad.fws.fr wss://etherpad.fws.fr and https://www.youtube.com
 +  * In connect-src you have to add https://storage.googleapis.com
  • tuto/linux_divers/jitsi.1587726380.txt.gz
  • Dernière modification: 24/04/2020 13:06
  • de dani