commit 95d8cb57c94ebe4bce672801374c5db3b8acd536 Author: Julien Malik Date: Wed Jan 14 10:55:14 2015 +0100 [enh] first working version diff --git a/README.md b/README.md new file mode 100644 index 0000000..509bd24 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +Jitsi Meet for YunoHost +------------------------- + +https://jitsi.org/Projects/JitMeet diff --git a/conf/jitsi-jicofo.init b/conf/jitsi-jicofo.init new file mode 100644 index 0000000..5707727 --- /dev/null +++ b/conf/jitsi-jicofo.init @@ -0,0 +1,113 @@ +#! /bin/sh +# +# INIT script for Jitsi Conference Focus +# Version: 1.0 4-Dec-2014 pawel.domas@jitsi.org +# +### BEGIN INIT INFO +# Provides: jicofo +# Required-Start: $local_fs $remote_fs +# Required-Stop: $local_fs $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Jitsi conference Focus +# Description: Conference focus for Jitsi Meet application. +### END INIT INFO + +. /lib/lsb/init-functions + +# Include jicofo defaults if available +if [ -f /etc/default/jicofo ]; then + . /etc/default/jicofo +fi + +# Assign default host if not configured +if [ ! $JICOFO_HOST ]; then + JICOFO_HOST=localhost +fi + +PATH=/usr/lib/jvm/java-7-openjdk-amd64/jre/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/opt/yunohost/jicofo/jicofo.sh +DEAMON_DIR=/opt/yunohost/jicofo/ +NAME=jicofo +USER=jicofo +PIDFILE=/var/run/jicofo.pid +LOGFILE=/var/log/jitsi/jicofo.log +DESC=jicofo +DAEMON_OPTS=" --host=$JICOFO_HOST --domain=$JICOFO_HOSTNAME --port=$JICOFO_PORT --secret=$JICOFO_SECRET --user_domain=$JICOFO_AUTH_DOMAIN --user_password=$JICOFO_AUTH_PASSWORD $JICOFO_OPTS" + +test -x $DAEMON || exit 0 + +set -e + +killParentPid() { + PARENT_PPID=$(ps -o pid --no-headers --ppid $1 || true) + if [ $PARENT_PPID ]; then + kill $PARENT_PPID + fi +} + +stop() { + if [ -f $PIDFILE ]; then + PID=$(cat $PIDFILE) + fi + echo -n "Stopping $DESC: " + if [ $PID ]; then + killParentPid $PID + rm $PIDFILE || true + echo "$NAME stopped." + elif [ $(ps -C jicofo.sh --no-headers -o pid) ]; then + kill $(ps -o pid --no-headers --ppid $(ps -C jicofo.sh --no-headers -o pid)) + rm $PIDFILE || true + echo "$NAME stopped." + else + echo "$NAME doesn't seem to be running." + fi +} + +start() { + if [ -f $PIDFILE ]; then + echo "$DESC seems to be already running, we found pidfile $PIDFILE." + exit 1 + fi + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --background --chuid $USER --make-pidfile --pidfile $PIDFILE \ + --exec /bin/bash -- -c "cd $DEAMON_DIR; exec $DAEMON $DAEMON_OPTS < /dev/null >> $LOGFILE 2>&1" + echo "$NAME started." +} + +reload() { + echo 'Not yet implemented.' +} + +status() { + echo 'Not yet implemented.' +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + reload) + reload + ;; + force-reload) + reload + ;; + status) + status + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/conf/jitsi-videobridge.init b/conf/jitsi-videobridge.init new file mode 100644 index 0000000..97ff826 --- /dev/null +++ b/conf/jitsi-videobridge.init @@ -0,0 +1,110 @@ +#! /bin/sh +# +# INIT script for Jitsi Videobridge +# Version: 1.0 01-May-2014 yasen@bluejimp.com +# +### BEGIN INIT INFO +# Provides: jitsi-videobridge +# Required-Start: $local_fs $remote_fs +# Required-Stop: $local_fs $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Jitsi Videobridge +# Description: WebRTC compatible Selective Forwarding Unit (SFU) +### END INIT INFO + +. /lib/lsb/init-functions + +# Include videobridge defaults if available +if [ -f /etc/default/jitsi-videobridge ]; then + . /etc/default/jitsi-videobridge +fi + +PATH=/usr/lib/jvm/java-7-openjdk-amd64/jre/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/opt/yunohost/jitsi-videobridge/jvb.sh +NAME=jvb +USER=jvb +PIDFILE=/var/run/jitsi-videobridge.pid +LOGFILE=/var/log/jitsi/jvb.log +DESC=jitsi-videobridge +if [ ! $JVB_HOST ]; then + JVB_HOST=localhost +fi +DAEMON_OPTS=" --host=$JVB_HOST --domain=$JVB_HOSTNAME --port=$JVB_PORT --secret=$JVB_SECRET $JVB_OPTS" + +test -x $DAEMON || exit 0 + +set -e + +killParentPid() { + PARENT_PID=$(ps -o pid --no-headers --ppid $1 || true) + if [ $PARENT_PID ]; then + kill $PARENT_PID + fi +} + +stop() { + if [ -f $PIDFILE ]; then + PID=$(cat $PIDFILE) + fi + echo -n "Stopping $DESC: " + if [ $PID ]; then + killParentPid $PID + rm $PIDFILE || true + echo "$NAME stopped." + elif [ $(ps -C jvb.sh --no-headers -o pid) ]; then + kill $(ps -o pid --no-headers --ppid $(ps -C jvb.sh --no-headers -o pid)) + rm $PIDFILE || true + echo "$NAME stopped." + else + echo "$NAME doesn't seem to be running." + fi +} + +start() { + if [ -f $PIDFILE ]; then + echo "$DESC seems to be already running, we found pidfile $PIDFILE." + exit 1 + fi + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --background --chuid $USER --make-pidfile --pidfile $PIDFILE \ + --exec /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS < /dev/null >> $LOGFILE 2>&1" + echo "$NAME started." +} + +reload() { + echo 'Not yet implemented.' +} + +status() { + echo 'Not yet implemented.' +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + reload) + reload + ;; + force-reload) + reload + ;; + status) + status + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/conf/jitsimeet-config.js b/conf/jitsimeet-config.js new file mode 100644 index 0000000..065b683 --- /dev/null +++ b/conf/jitsimeet-config.js @@ -0,0 +1,36 @@ +var config = { + hosts: { + domain: 'YNH_JITSI_XMPP_HOST', + //anonymousdomain: 'guest.example.com', + muc: 'conference.YNH_JITSI_XMPP_HOST', // FIXME: use XEP-0030 + bridge: 'jitsi-videobridge.YNH_JITSI_XMPP_HOST', // FIXME: use XEP-0030 + //jirecon: 'jirecon.YNH_JITSI_XMPP_HOST', + //call_control: 'callcontrol.YNH_JITSI_XMPP_HOST', + focus: 'focus.YNH_JITSI_XMPP_HOST' - defaults to 'focus.YNH_JITSI_XMPP_HOST' + }, + //getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; }, + //useStunTurn: true, // use XEP-0215 to fetch STUN and TURN server + //useIPv6: true, // ipv6 support. use at your own risk + useNicks: false, + bosh: '//YNH_JITSI_XMPP_HOST/http-bind', // FIXME: use xep-0156 for that + clientNode: 'http://jitsi.org/jitsimeet', // The name of client node advertised in XEP-0115 'c' stanza + focusUserJid: 'focus@auth.YNH_JITSI_XMPP_HOST', // The real JID of focus participant - can be overridden here + //defaultSipNumber: '', // Default SIP number + desktopSharing: false, // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable. + chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension + desktopSharingSources: ['screen', 'window'], + minChromeExtVersion: '0.1', // Required version of Chrome extension + enableRtpStats: true, // Enables RTP stats processing + openSctp: true, // Toggle to enable/disable SCTP channels + channelLastN: -1, // The default value of the channel attribute last-n. + adaptiveLastN: false, + adaptiveSimulcast: false, + useRtcpMux: true, + useBundle: true, + enableRecording: false, + enableWelcomePage: true, + enableSimulcast: false, + enableFirefoxSupport: false, //firefox support is still experimental, only one-to-one conferences with chrome focus + // will work when simulcast, bundle, mux, lastN and SCTP are disabled. + logStats: true // Enable logging of PeerConnection stats via the focus +}; diff --git a/conf/jvb.version b/conf/jvb.version new file mode 100644 index 0000000..e45b99e --- /dev/null +++ b/conf/jvb.version @@ -0,0 +1 @@ +384 diff --git a/conf/metronome.conf b/conf/metronome.conf new file mode 100644 index 0000000..f6af44c --- /dev/null +++ b/conf/metronome.conf @@ -0,0 +1,30 @@ +VirtualHost "YNH_JITSI_XMPP_HOST" + c2s_require_encryption = false + authentication = "anonymous" + ssl = { + key = "/var/lib/metronome/YNH_JITSI_XMPP_HOST.key"; + certificate = "/var/lib/metronome/YNH_JITSI_XMPP_HOST.crt"; + } + + -- turncredentials_secret = "YNH_SECRET4"; + -- turncredentials = { + -- { type = "turn", host = "turn.host.name", port = 3478, transport = "tcp" } + -- } + +Component "conference.YNH_JITSI_XMPP_HOST" "muc" + +Component "jitsi-videobridge.YNH_JITSI_XMPP_HOST" + component_secret = "YNH_YOURSECRET1" + +VirtualHost "auth.YNH_JITSI_XMPP_HOST" + c2s_require_encryption = false + authentication = "internal_plain" + ssl = { + key = "/var/lib/metronome/YNH_JITSI_XMPP_HOST.key"; + certificate = "/var/lib/metronome/YNH_JITSI_XMPP_HOST.crt"; + } + admins = { "focus@auth.YNH_JITSI_XMPP_HOST" } + +Component "focus.YNH_JITSI_XMPP_HOST" + component_secret = "YNH_YOURSECRET2" + diff --git a/conf/nginx.conf b/conf/nginx.conf new file mode 100644 index 0000000..1cd962f --- /dev/null +++ b/conf/nginx.conf @@ -0,0 +1,18 @@ +location YNH_LOCATION/ { + alias /var/www/jitsi/; + index index.html; + ssi on; +} + +location ~ ^YNH_LOCATION/([a-zA-Z0-9]+)$ { + rewrite ^YNH_LOCATION/(.*)$ YNH_LOCATION/ break; +} + +location YNH_LOCATION/http-bind { + proxy_pass http://localhost:5290/http-bind; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $http_host; + proxy_buffering off; + tcp_nodelay on; + access_log off; +} diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..9f29dce --- /dev/null +++ b/manifest.json @@ -0,0 +1,37 @@ +{ + "name": "Jitsi Meet", + "id": "jitsi", + "description": { + "en": "Video conferencing web application", + "fr": "Application web de conférence vidéo" + }, + "url": "https://jitsi.org/Projects/JitMeet", + "maintainer": { + "name": "ju", + "email": "julien.malik@paraiso.me" + }, + "multi_instance": "false", + "arguments": { + "install": [ + { + "name": "domain", + "type": "domain", + "ask": { + "en": "Choose a domain for Jitsi Meet", + "fr": "Choisissez un domaine pour Jitsi Meet" + }, + "example": "domain.org" + }, + { + "name": "path", + "type": "path", + "ask": { + "en": "Choose a path for Jitsi Meet", + "fr": "Choisissez un chemin pour Jitsi Meet" + }, + "example": "/", + "default": "/" + } + ] + } +} diff --git a/scripts/install b/scripts/install new file mode 100644 index 0000000..9ab4790 --- /dev/null +++ b/scripts/install @@ -0,0 +1,176 @@ +#!/bin/bash + +# Retrieve arguments +domain=$1 +path=$2 + +# TODO : if arch != x86 or amd64 => unsupported +arch=$(uname -m) +if [[ "$arch" != "i686" ]] && [[ "$arch" != "x86_64" ]] ; then + echo "Currently supported only on i686 or x86_64." + echo "ARM platforms are NOT supported right now." + exit 1 +fi + +if [[ "$path" != "/" ]] ; then + echo "Only '/' is supported as path for the moment." + exit 1 +fi + +sudo yunohost app checkurl $domain$path -a jitsi +if [[ ! $? -eq 0 ]]; then + exit 1 +fi + +sudo apt-get update +sudo apt-get install openjdk-7-jre ant openjdk-6-jdk -y + +# TODO do we really need this ??? +#sudo apt-get install lua-dbi-sqlite3 -y + +#git clone https://github.com/andyet/otalk-server ../src/otalk-server +# TODO mam,websocket(s) already available in default metronome +#cp -r ../src/otalk-server/mod_{smacks,carbons,mam,websocket,turncredentials} /usr/lib/metronome/modules + +YNH_YOURSECRET1=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d 'A-Za-z0-9' | sed -n 's/\(.\{24\}\).*/\1/p') +YNH_YOURSECRET2=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d 'A-Za-z0-9' | sed -n 's/\(.\{24\}\).*/\1/p') +YNH_YOURSECRET3=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d 'A-Za-z0-9' | sed -n 's/\(.\{24\}\).*/\1/p') +YNH_YOURSECRET4=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d 'A-Za-z0-9' | sed -n 's/\(.\{24\}\).*/\1/p') + +jitsi_domain="jitsi.${domain}" +# TODO verify $jitsi_domain is not already used somehow... + +sudo groupadd jitsi + + +#--- Install Jitsi videobridge --- +jvb_buildnum=$(cat ../conf/jvb.version) +if [[ "$arch" == "i686" ]] ; then + jvb_arch="x86" +else + jvb_arch="x64" +fi +mkdir ../src +wget -O ../src/jitsi-videobridge.zip https://download.jitsi.org/jitsi-videobridge/linux/jitsi-videobridge-linux-$jvb_arch-$jvb_buildnum.zip +unzip ../src/jitsi-videobridge.zip -d ../src/jitsi-videobridge +jvb_root=/opt/yunohost/jitsi-videobridge +sudo mkdir -p $jvb_root +sudo cp -ar ../src/jitsi-videobridge/jitsi-videobridge-linux-$jvb_arch-$jvb_buildnum/* $jvb_root +sudo useradd -r -g jitsi -d $jvb_root --shell /bin/bash jvb +sudo chown -R jvb:jitsi $jvb_root +sudo mkdir -p /var/log/jitsi +sudo chown jvb:jitsi /var/log/jitsi +sudo chmod 770 /var/log/jitsi + +cat << EOF > ../src/jvb_options +JVB_HOSTNAME=$jitsi_domain +JVB_PORT=5347 +JVB_SECRET=$YNH_YOURSECRET1 +JVB_OPTS="" +EOF + +sudo mv ../src/jvb_options /etc/default/jitsi-videobridge +sudo cp ../conf/jitsi-videobridge.init /etc/init.d/jitsi-videobridge +sudo chmod +x /etc/init.d/jitsi-videobridge +sudo update-rc.d jitsi-videobridge defaults +sudo yunohost service add jitsi-videobridge -l /var/log/jitsi/jvb.log + +# TODO : install java7 +# TODO : create .sip-communicator to handle videobridge behind NAT +# TODO : avoid error in logs Failed to load class "org.slf4j.impl.StaticLoggerBinder" +# See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. +# TODO : logrotate +# TODO : hook to monit +# TODO : enable jitsi stats : what wan we do with it ? + +#--- Install Jicofo --- +wget -O ../src/jicofo.zip https://github.com/jitsi/jicofo/archive/master.zip +unzip ../src/jicofo.zip -d ../src/jicofo +if [[ "$arch" == "i686" ]] ; then + jicofo_target="lin" + jicofo_arch="x86" +else + jicofo_target="lin64" + jicofo_arch="x64" +fi +bash -c "cd ../src/jicofo/jicofo-master; ant dist.$jicofo_target" +jicofo_dist_zip=$(ls ../src/jicofo/jicofo-master/dist/linux/*.zip) +unzip $jicofo_dist_zip -d ../src/jicofo_dist + +jicofo_root=/opt/yunohost/jicofo +sudo mkdir -p $jicofo_root +sudo cp -ar ../src/jicofo_dist/$(basename "$jicofo_dist_zip" .zip)/* $jicofo_root +sudo useradd -r -g jitsi -d $jicofo_root --shell /bin/bash jicofo +sudo chown -R jicofo:jitsi $jicofo_root + +cat << EOF > ../src/jicofo_options +# Jitsi Conference Focus settings +JICOFO_HOST=localhost +JICOFO_HOSTNAME=$jitsi_domain +JICOFO_SECRET=$YNH_YOURSECRET2 +JICOFO_PORT=5347 +JICOFO_AUTH_DOMAIN=auth.$jitsi_domain +JICOFO_AUTH_USER=focus +JICOFO_AUTH_PASSWORD=$YNH_YOURSECRET3 +JICOFO_OPTS="" +EOF + +sudo mv ../src/jicofo_options /etc/default/jicofo +sudo cp ../conf/jitsi-jicofo.init /etc/init.d/jicofo +sudo chmod +x /etc/init.d/jicofo +sudo update-rc.d jicofo defaults +sudo yunohost service add jicofo -l /var/log/jitsi/jvb.log + +# TODO : build with java7, since java6 outputs more warnings +# TODO : logrotate +# TODO : hook to monit + + +#--- Install Jireco daemon --- +# TODO for later... + +#--- Install Jitsi-meet --- +wget -O ../src/jitsi-meet.zip https://github.com/jitsi/jitsi-meet/archive/master.zip +unzip ../src/jitsi-meet.zip -d ../src/jitsi-meet +jitsimeet_path=/var/www/jitsi +sudo mkdir -p $jitsimeet_path +sudo cp -ar ../src/jitsi-meet/jitsi-meet-master/* $jitsimeet_path + +sed -i "s@YNH_JITSI_XMPP_HOST@$jitsi_domain@g" ../conf/jitsimeet-config.js +sudo cp ../conf/jitsimeet-config.js $jitsimeet_path/config.js + +sudo chown -R root: $jitsimeet_path +sudo find $jitsimeet_path -type f | xargs sudo chmod 644 +sudo find $jitsimeet_path -type d | xargs sudo chmod 755 + +# TODO : remove tracking +# TODO : remove GoogleAnalytics + +#--- Configure metronome --- +sed -i "s@YNH_JITSI_XMPP_HOST@$jitsi_domain@g" ../conf/metronome.conf +sed -i "s@YNH_YOURSECRET1@$YNH_YOURSECRET1@g" ../conf/metronome.conf +sed -i "s@YNH_YOURSECRET2@$YNH_YOURSECRET2@g" ../conf/metronome.conf +sed -i "s@YNH_YOURSECRET4@$YNH_YOURSECRET4@g" ../conf/metronome.conf + +sudo cp ../conf/metronome.conf /etc/metronome/conf.d/$jitsi_domain.cfg.lua +sudo chown metronome: /etc/metronome/conf.d/$jitsi_domain.cfg.lua + +sudo openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj \ + "/O=$domain/OU=$domain/CN=$jitsi_domain/emailAddress=webmaster@$domain" \ + -keyout /var/lib/metronome/$jitsi_domain.key \ + -out /var/lib/metronome/$jitsi_domain.crt + + +# sudo metronomectl register focus auth.$jitsi_domain $YNH_YOURSECRET3 + + +#--- Configure Nginx --- +# remove trailing '/'. this leaves '/something' untouched, but changes '/' to '' +path=${path%/} +sed -i "s@YNH_LOCATION@$path@g" ../conf/nginx.conf +sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/jitsi.conf + +sudo service metronome reload +sudo service jitsi-videobridge restart +sudo service jicofo restart +sudo service nginx reload diff --git a/scripts/remove b/scripts/remove new file mode 100644 index 0000000..021551a --- /dev/null +++ b/scripts/remove @@ -0,0 +1,34 @@ +#!/bin/bash + +domain=$(sudo yunohost app setting jitsi domain) + +sudo service jitsi-videobridge stop +sudo service jicofo stop + +sudo rm -rf /opt/yunohost/jicofo +sudo rm -rf /opt/yunohost/jitsi-videobridge +sudo rm /etc/default/jitsi-videobridge +sudo rm /etc/default/jicofo + +sudo update-rc.d jitsi-videobridge remove +sudo rm /etc/init.d/jitsi-videobridge +sudo yunohost service remove jitsi-videobridge + +sudo update-rc.d jicofo remove +sudo rm /etc/init.d/jicofo +sudo yunohost service remove jicofo + +jitsi_domain=jitsi.$domain +sudo rm /etc/metronome/conf.d/$jitsi_domain.cfg.lua +sudo service metronome restart + +sudo rm /etc/nginx/conf.d/$domain.d/jitsi.conf +sudo service nginx reload +sudo yunohost app ssowatconf + +sudo rm -rf /var/log/jitsi + +sudo userdel jvb +sudo userdel jicofo +sudo groupdel jitsi + diff --git a/scripts/upgrade b/scripts/upgrade new file mode 100644 index 0000000..cc13ede --- /dev/null +++ b/scripts/upgrade @@ -0,0 +1,14 @@ +#!/bin/bash + +# Retrieve arguments +domain=$(sudo yunohost app setting jitsi domain) +path=$(sudo yunohost app setting jitsi path) + +# Remove trailing "/" for next commands +path=${path%/} + +# Configure Nginx and reload +sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf +sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/jitsi.conf +sudo service nginx reload +sudo service jitsi reload