From 62e0f4cb94ba4fe0c73bf36b033298842b04c3c0 Mon Sep 17 00:00:00 2001 From: "benedikt.wismans@sdw.systems" Date: Sat, 25 Nov 2023 14:32:17 +0100 Subject: [PATCH] Update Ansible BBB auf Version BBB 2.7 --- bbb_install.yml | 9 + bootstrapRoot.yml | 6 + host_vars/bbb.bfwbb-lernen.de | 36 + host_vars/bbb.xitq.de | 25 +- host_vars/bbb0.sdw.systems | 36 + host_vars/bbb1.open-diakonie.de | 36 + host_vars/bbb2.open-diakonie.de | 36 + hosts | 7 +- requirements.yml | 2 + roles/bbb_install/files/bbb-install-2.5.sh | 1115 ++++++++++ roles/bbb_install/files/bbb-install-2.7.sh | 1889 +++++++++++++++++ roles/bbb_install/files/blankDefault.pdf | Bin 0 -> 1897 bytes roles/bbb_install/files/ext_sipgate.xml | 11 + roles/bbb_install/files/install | 1 + roles/bbb_install/files/pub_sipgate.xml | 20 + roles/bbb_install/files/rudiDefault.pdf | Bin 0 -> 33195 bytes roles/bbb_install/files/taillog | 2 + .../files/turn-stun-servers.xml.konfiguriert | 39 + roles/bbb_install/files/update | 21 + roles/bbb_install/files/xitDefault.pdf | Bin 0 -> 113472 bytes roles/bbb_install/tasks/config_bbb.yml | 36 + roles/bbb_install/tasks/dialin_bbb.yml | 43 + roles/bbb_install/tasks/install_bbb.yml | 21 + roles/bbb_install/tasks/main.yml | 9 + roles/bbb_install/tasks/packages.yml | 11 + roles/bbb_install/tasks/setup_bbb.yml | 48 + roles/bs_scripte/addVirtualBackground | 8 + .../files/RD_Logo_Vielfalt_1280x960.jpg | Bin 0 -> 112712 bytes roles/bs_scripte/files/bashlib | 47 + roles/bs_scripte/tasks/main.yml | 29 +- roles/bs_snmp/files/snmpd.conf | 5 +- roles/bs_snmp/tasks/main.yml | 4 +- roles/bs_users/files/authorized_keys_core | 4 +- roles/bs_users/files/authorized_keys_root | 1 + roles/install_image/tasks/main.yml | 2 +- roles/kvm_install/files/vhost_getIPv4 | 2 +- roles/kvm_install/tasks/packages_install.yml | 1 + roles/kvm_installvm/tasks/main.yml | 7 +- roles/kvm_installvm/tasks/virtnet_config.yml | 20 + 39 files changed, 3573 insertions(+), 16 deletions(-) create mode 100644 bbb_install.yml create mode 100644 host_vars/bbb.bfwbb-lernen.de create mode 100644 host_vars/bbb0.sdw.systems create mode 100644 host_vars/bbb1.open-diakonie.de create mode 100644 host_vars/bbb2.open-diakonie.de create mode 100644 requirements.yml create mode 100644 roles/bbb_install/files/bbb-install-2.5.sh create mode 100644 roles/bbb_install/files/bbb-install-2.7.sh create mode 100644 roles/bbb_install/files/blankDefault.pdf create mode 100644 roles/bbb_install/files/ext_sipgate.xml create mode 100644 roles/bbb_install/files/install create mode 100644 roles/bbb_install/files/pub_sipgate.xml create mode 100644 roles/bbb_install/files/rudiDefault.pdf create mode 100644 roles/bbb_install/files/taillog create mode 100644 roles/bbb_install/files/turn-stun-servers.xml.konfiguriert create mode 100644 roles/bbb_install/files/update create mode 100644 roles/bbb_install/files/xitDefault.pdf create mode 100644 roles/bbb_install/tasks/config_bbb.yml create mode 100644 roles/bbb_install/tasks/dialin_bbb.yml create mode 100644 roles/bbb_install/tasks/install_bbb.yml create mode 100644 roles/bbb_install/tasks/main.yml create mode 100644 roles/bbb_install/tasks/packages.yml create mode 100644 roles/bbb_install/tasks/setup_bbb.yml create mode 100644 roles/bs_scripte/addVirtualBackground create mode 100644 roles/bs_scripte/files/RD_Logo_Vielfalt_1280x960.jpg create mode 100644 roles/kvm_installvm/tasks/virtnet_config.yml diff --git a/bbb_install.yml b/bbb_install.yml new file mode 100644 index 0000000..40db637 --- /dev/null +++ b/bbb_install.yml @@ -0,0 +1,9 @@ +--- +- hosts: "{{ target }}" + remote_user: core + become: yes + roles: + - kwoodson.yedit + - bbb_install + +... \ No newline at end of file diff --git a/bootstrapRoot.yml b/bootstrapRoot.yml index c268e57..d91a951 100644 --- a/bootstrapRoot.yml +++ b/bootstrapRoot.yml @@ -1,12 +1,18 @@ --- - hosts: "{{ target }}" remote_user: root + become: yes roles: - apt_upgrade - bs_hostnames - bs_users - bs_sshd +# Falls failed to lock apt for exclusive operation Fehler geworfen wird: +#sudo rm -rf /var/lib/apt/lists/* +#sudo apt-get clean +#sudo apt-get update + # sshd schließt den root user von ssh aus, danach läuft das Playbook nicht mehr als root # Weiter geht's mit bootstrapCore ... \ No newline at end of file diff --git a/host_vars/bbb.bfwbb-lernen.de b/host_vars/bbb.bfwbb-lernen.de new file mode 100644 index 0000000..f707bcc --- /dev/null +++ b/host_vars/bbb.bfwbb-lernen.de @@ -0,0 +1,36 @@ +--- +install_image: + path: /root/.oldroot/nfs/install/installimage + raid: yes -l 1 + image: /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar.gz + drives: sda,sdb + +passwordless_sudo: true + +# bobby $6$A7Sw5gku7$0WqY/Z4Ei0axG.mZwDQlFJfK8Rtx6H0eKuP8CW23V5f/5j9sXendknLtXexQfgDzA4Ri55ZqhJnpf05MJV71J0 +# Passwort für root ist bobby, muss hier im Klartext angegeben werden +password: bobby + +# root hat kein keypair, nur ein .ssh Verzeichnis mit hohgeladener authorized_keys Datei +# ssh_key_root: /root/.ssh/id_rsa.pub + +ssh_key_core: /home/core/.ssh/id_rsa.pub + +default_presentation: rudiDefault.pdf + + +# BBB-Settings + +# bigbluebutton.properties +defaultWelcomeMessage: defaultWelcomeMessage=Willkommen zu %%CONFNAME%% +defaultWelcomeMessageFooter: defaultWelcomeMessageFooter=BigBlueButton +learningDashboardEnabled: learningDashboardEnabled=false +defaultDialAccessNumber: defaultDialAccessNumber=095129909624 +# defaultDialAccessNumber: defaultDialAccessNumber=613-555-1234 + +disableRecordingDefault: disableRecordingDefault=false +webcamsOnlyForModerator: webcamsOnlyForModerator=false +learningDashboardCleanupDelayInMinutes: learningDashboardCleanupDelayInMinutes=0 +bigbluebutton_web_logoutURL: bigbluebutton.web.logoutURL=https://open-diakonie.de + +# settings.yml \ No newline at end of file diff --git a/host_vars/bbb.xitq.de b/host_vars/bbb.xitq.de index 40bdc31..c6ada3a 100644 --- a/host_vars/bbb.xitq.de +++ b/host_vars/bbb.xitq.de @@ -7,6 +7,28 @@ install_image: passwordless_sudo: true +default_presentation: xitDefault.pdf + + +# BBB-Settings + +# bigbluebutton.properties +defaultWelcomeMessage: defaultWelcomeMessage=Willkommen zu %%CONFNAME%% +defaultWelcomeMessageFooter: defaultWelcomeMessageFooter=BigBlueButton +learningDashboardEnabled: learningDashboardEnabled=false +# defaultDialAccessNumber: defaultDialAccessNumber=095129909624 +defaultDialAccessNumber: defaultDialAccessNumber=613-555-1234 + +disableRecordingDefault: disableRecordingDefault=false +webcamsOnlyForModerator: webcamsOnlyForModerator=false +learningDashboardCleanupDelayInMinutes: learningDashboardCleanupDelayInMinutes=0 +bigbluebutton_web_logoutURL: bigbluebutton.web.logoutURL=https://open-diakonie.de + +# settings.yml + + + + #install_vm: # osvariant: ubuntu20.04 # image: /home/core/tmp/ubuntu-22.04.1-live-server-amd64.iso @@ -29,7 +51,8 @@ password: bobby # ssh_key_root: /root/.ssh/id_rsa.pub ssh_key_core: /home/core/.ssh/id_rsa.pub -vm_name: vhosttst2 +vm_name: vhosttst +vm_ip: 192.168.122.10 vm_vcpus: 2 vm_ram_mb: 4096 vm_net: default diff --git a/host_vars/bbb0.sdw.systems b/host_vars/bbb0.sdw.systems new file mode 100644 index 0000000..940b718 --- /dev/null +++ b/host_vars/bbb0.sdw.systems @@ -0,0 +1,36 @@ +--- +install_image: + path: /root/.oldroot/nfs/install/installimage + raid: yes -l 1 + image: /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar.gz + drives: nvme0n1,nvme1n1 + +passwordless_sudo: true + +# bobby $6$A7Sw5gku7$0WqY/Z4Ei0axG.mZwDQlFJfK8Rtx6H0eKuP8CW23V5f/5j9sXendknLtXexQfgDzA4Ri55ZqhJnpf05MJV71J0 +# Passwort für root ist bobby, muss hier im Klartext angegeben werden +password: bobby + +# root hat kein keypair, nur ein .ssh Verzeichnis mit hohgeladener authorized_keys Datei +# ssh_key_root: /root/.ssh/id_rsa.pub + +ssh_key_core: /home/core/.ssh/id_rsa.pub + +default_presentation: blankDefault.pdf + + +# BBB-Settings + +# bigbluebutton.properties +defaultWelcomeMessage: defaultWelcomeMessage=Willkommen zu %%CONFNAME%% +defaultWelcomeMessageFooter: defaultWelcomeMessageFooter=BigBlueButton +learningDashboardEnabled: learningDashboardEnabled=false +# defaultDialAccessNumber: defaultDialAccessNumber=095129909624 +defaultDialAccessNumber: defaultDialAccessNumber=613-555-1234 + +disableRecordingDefault: disableRecordingDefault=false +webcamsOnlyForModerator: webcamsOnlyForModerator=false +learningDashboardCleanupDelayInMinutes: learningDashboardCleanupDelayInMinutes=0 +bigbluebutton_web_logoutURL: bigbluebutton.web.logoutURL=https://www.wikipedia.de/ + +# settings.yml \ No newline at end of file diff --git a/host_vars/bbb1.open-diakonie.de b/host_vars/bbb1.open-diakonie.de new file mode 100644 index 0000000..8313334 --- /dev/null +++ b/host_vars/bbb1.open-diakonie.de @@ -0,0 +1,36 @@ +--- +install_image: + path: /root/.oldroot/nfs/install/installimage + raid: yes -l 1 + image: /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar.gz + drives: sda,sdb + +passwordless_sudo: true + +# bobby $6$A7Sw5gku7$0WqY/Z4Ei0axG.mZwDQlFJfK8Rtx6H0eKuP8CW23V5f/5j9sXendknLtXexQfgDzA4Ri55ZqhJnpf05MJV71J0 +# Passwort für root ist bobby, muss hier im Klartext angegeben werden +password: bobby + +# root hat kein keypair, nur ein .ssh Verzeichnis mit hohgeladener authorized_keys Datei +# ssh_key_root: /root/.ssh/id_rsa.pub + +ssh_key_core: /home/core/.ssh/id_rsa.pub + +default_presentation: rudiDefault.pdf + + +# BBB-Settings + +# bigbluebutton.properties +defaultWelcomeMessage: defaultWelcomeMessage=Willkommen zu %%CONFNAME%% +defaultWelcomeMessageFooter: defaultWelcomeMessageFooter=BigBlueButton +learningDashboardEnabled: learningDashboardEnabled=false +# defaultDialAccessNumber: defaultDialAccessNumber=095129909624 +defaultDialAccessNumber: defaultDialAccessNumber=613-555-1234 + +disableRecordingDefault: disableRecordingDefault=false +webcamsOnlyForModerator: webcamsOnlyForModerator=false +learningDashboardCleanupDelayInMinutes: learningDashboardCleanupDelayInMinutes=0 +bigbluebutton_web_logoutURL: bigbluebutton.web.logoutURL=https://open-diakonie.de + +# settings.yml \ No newline at end of file diff --git a/host_vars/bbb2.open-diakonie.de b/host_vars/bbb2.open-diakonie.de new file mode 100644 index 0000000..3138007 --- /dev/null +++ b/host_vars/bbb2.open-diakonie.de @@ -0,0 +1,36 @@ +--- +install_image: + path: /root/.oldroot/nfs/install/installimage + raid: yes -l 1 + image: /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar.gz + drives: nvme0n1,nvme1n1 + +passwordless_sudo: true + +# bobby $6$A7Sw5gku7$0WqY/Z4Ei0axG.mZwDQlFJfK8Rtx6H0eKuP8CW23V5f/5j9sXendknLtXexQfgDzA4Ri55ZqhJnpf05MJV71J0 +# Passwort für root ist bobby, muss hier im Klartext angegeben werden +password: bobby + +# root hat kein keypair, nur ein .ssh Verzeichnis mit hohgeladener authorized_keys Datei +# ssh_key_root: /root/.ssh/id_rsa.pub + +ssh_key_core: /home/core/.ssh/id_rsa.pub + +default_presentation: rudiDefault.pdf + + +# BBB-Settings + +# bigbluebutton.properties +defaultWelcomeMessage: defaultWelcomeMessage=Willkommen zu %%CONFNAME%% +defaultWelcomeMessageFooter: defaultWelcomeMessageFooter=BigBlueButton +learningDashboardEnabled: learningDashboardEnabled=false +# defaultDialAccessNumber: defaultDialAccessNumber=095129909624 +defaultDialAccessNumber: defaultDialAccessNumber=613-555-1234 + +disableRecordingDefault: disableRecordingDefault=false +webcamsOnlyForModerator: webcamsOnlyForModerator=false +learningDashboardCleanupDelayInMinutes: learningDashboardCleanupDelayInMinutes=0 +bigbluebutton_web_logoutURL: bigbluebutton.web.logoutURL=https://open-diakonie.de + +# settings.yml \ No newline at end of file diff --git a/hosts b/hosts index 4e77df1..b9b5405 100644 --- a/hosts +++ b/hosts @@ -1,2 +1,5 @@ -bbb.xitq.de -# bbb.xit +# bbb.xitq.de +# bbb1.open-diakonie.d# +# bbb2.open-diakonie.de +# bbb.bfwbb-lernen.de +bbb0.sdw.systems \ No newline at end of file diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..75bf100 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,2 @@ +--- +- src: kwoodson.yedit \ No newline at end of file diff --git a/roles/bbb_install/files/bbb-install-2.5.sh b/roles/bbb_install/files/bbb-install-2.5.sh new file mode 100644 index 0000000..b140f86 --- /dev/null +++ b/roles/bbb_install/files/bbb-install-2.5.sh @@ -0,0 +1,1115 @@ +#!/bin/bash -e + +# Copyright (c) 2022 BigBlueButton Inc. +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +# BigBlueButton is an open source conferencing system. For more information see +# https://www.bigbluebutton.org/. +# +# This bbb-install-2.5.sh script automates many of the installation and configuration +# steps at +# https://docs.bigbluebutton.org/2.5/install.html +# +# +# Examples +# +# Install BigBlueButton 2.5.x with a SSL certificate from Let's Encrypt using hostname bbb.example.com +# and email address info@example.com and apply a basic firewall +# +# wget -qO- https://ubuntu.bigbluebutton.org/bbb-install-2.5.sh | bash -s -- -w -v focal-250 -s bbb.example.com -e info@example.com +# +# Same as above but also install the API examples for testing. +# +# wget -qO- https://ubuntu.bigbluebutton.org/bbb-install-2.5.sh | bash -s -- -w -a -v focal-250 -s bbb.example.com -e info@example.com +# +# Install BigBlueButton with SSL + Greenlight +# +# wget -qO- https://ubuntu.bigbluebutton.org/bbb-install-2.5.sh | bash -s -- -w -v focal-250 -s bbb.example.com -e info@example.com -g +# + +usage() { + set +x + cat 1>&2 < Install given version of BigBlueButton (e.g. 'focal-250') (required) + + -s Configure server with + -e Email for Let's Encrypt certbot + + -x Use Let's Encrypt certbot with manual dns challenges + + -a Install BBB API demos + -g Install Greenlight + -c : Configure with coturn server at using + + -m Create a Symbolic link from /var/bigbluebutton to + + -p [:] Use apt-get proxy at (default port 3142) + -r Use alternative apt repository (such as packages-eu.bigbluebutton.org) + + -d Skip SSL certificates request (use provided certificates from mounted volume) in /local/certs/ + -w Install UFW firewall (recommended) + + -j Allows the installation of BigBlueButton to proceed even if not all requirements [for production use] are met. + Note that not all requirements can be ignored. This is useful in development / testing / ci scenarios. + + -i Allows the installation of BigBlueButton to proceed even if Apache webserver is installed. + + -h Print help + +OPTIONS (install coturn only): + + -c : Setup a coturn server with and (required) + -e Configure email for Let's Encrypt certbot (required) + +OPTIONS (install Let's Encrypt certificate only): + + -s Configure server with (required) + -e Configure email for Let's Encrypt certbot (required) + -l Only install Let's Encrypt certificate (not BigBlueButton) + -x Use Let's Encrypt certbot with manual dns challenges (optional) + + +EXAMPLES: + +Sample options for setup a BigBlueButton server + + -v focal-250 -s bbb.example.com -e info@example.com + -v focal-250 -s bbb.example.com -e info@example.com -g + -v focal-250 -s bbb.example.com -e info@example.com -g -c turn.example.com:1234324 + +Sample options for setup of a coturn server (on a Ubuntu 20.04) + + -c turn.example.com:1234324 -e info@example.com + +SUPPORT: + Community: https://bigbluebutton.org/support + Docs: https://github.com/bigbluebutton/bbb-install + +HERE +} + +main() { + export DEBIAN_FRONTEND=noninteractive + PACKAGE_REPOSITORY=ubuntu.bigbluebutton.org + LETS_ENCRYPT_OPTIONS="--webroot --non-interactive" + SOURCES_FETCHED=false + CR_TMPFILE=$(mktemp /tmp/carriage-return.XXXXXX) + echo "\n" > $CR_TMPFILE + + need_x64 + + while builtin getopts "hs:r:c:v:e:p:m:lxgadwji" opt "${@}"; do + + case $opt in + h) + usage + exit 0 + ;; + + s) + HOST=$OPTARG + if [ "$HOST" == "bbb.example.com" ]; then + err "You must specify a valid hostname (not the hostname given in the docs)." + fi + ;; + r) + PACKAGE_REPOSITORY=$OPTARG + ;; + e) + EMAIL=$OPTARG + if [ "$EMAIL" == "info@example.com" ]; then + err "You must specify a valid email address (not the email in the docs)." + fi + ;; + x) + LETS_ENCRYPT_OPTIONS="--manual --preferred-challenges dns" + ;; + c) + COTURN=$OPTARG + check_coturn "$COTURN" + ;; + v) + VERSION=$OPTARG + ;; + + p) + PROXY=$OPTARG + if [ -n "$PROXY" ]; then + if [[ "$PROXY" =~ : ]]; then + echo "Acquire::http::Proxy \"http://$PROXY\";" > /etc/apt/apt.conf.d/01proxy + else + echo "Acquire::http::Proxy \"http://$PROXY:3142\";" > /etc/apt/apt.conf.d/01proxy + fi + fi + ;; + + l) + LETS_ENCRYPT_ONLY=true + ;; + g) + GREENLIGHT=true + ;; + a) + API_DEMOS=true + ;; + m) + LINK_PATH=$OPTARG + ;; + d) + PROVIDED_CERTIFICATE=true + ;; + w) + SSH_PORT=$(grep Port /etc/ssh/ssh_config | grep -v \# | sed 's/[^0-9]*//g') + if [[ -n "$SSH_PORT" && "$SSH_PORT" != "22" ]]; then + err "Detected sshd not listening to standard port 22 -- unable to install default UFW firewall rules. See https://docs.bigbluebutton.org/2.2/customize.html#secure-your-system--restrict-access-to-specific-ports" + fi + UFW=true + ;; + j) + SKIP_MIN_SERVER_REQUIREMENTS_CHECK=true + ;; + i) + SKIP_APACHE_INSTALLED_CHECK=true + ;; + :) + err "Missing option argument for -$OPTARG" + exit 1 + ;; + + \?) + err "Invalid option: -$OPTARG" >&2 + usage + ;; + esac + done + + if [ -n "$HOST" ]; then + check_host "$HOST" + fi + + if [ -n "$VERSION" ]; then + check_version "$VERSION" + fi + + if [ "$SKIP_APACHE_INSTALLED_CHECK" != true ]; then + check_apache2 + fi + + # Check if we're installing coturn (need an e-mail address for Let's Encrypt) + if [ -z "$VERSION" ] && [ -n "$COTURN" ]; then + if [ -z "$EMAIL" ]; then err "Installing coturn needs an e-mail address for Let's Encrypt"; fi + check_ubuntu 20.04 + + install_coturn + exit 0 + fi + + if [ -z "$VERSION" ]; then + usage + exit 0 + fi + + # We're installing BigBlueButton + env + + if [ "$DISTRO" == "focal" ]; then + check_ubuntu 20.04 + TOMCAT_USER=tomcat9 + fi + check_mem + check_cpus + + need_pkg software-properties-common # needed for add-apt-repository + sudo add-apt-repository universe + need_pkg wget curl gpg-agent dirmngr + + # need_pkg xmlstarlet + get_IP "$HOST" + + if [ "$DISTRO" == "focal" ]; then + need_pkg ca-certificates + + # yq version 3 is provided by ppa:bigbluebutton/support + # Uncomment the following to enable yq 4 after bigbluebutton/bigbluebutton#14511 is resolved + #need_ppa rmescandon-ubuntu-yq-bionic.list ppa:rmescandon/yq CC86BB64 # Edit yaml files with yq + + #need_ppa libreoffice-ubuntu-ppa-focal.list ppa:libreoffice/ppa 1378B444 # Latest version of libreoffice + need_ppa bigbluebutton-ubuntu-support-focal.list ppa:bigbluebutton/support E95B94BC # Needed for libopusenc0 + if ! apt-key list 5AFA7A83 | grep -q -E "1024|4096"; then # Add Kurento package + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83 + fi + + rm -rf /etc/apt/sources.list.d/kurento.list # Kurento 6.15 now packaged with 2.3 + + if grep -q 12 /etc/apt/sources.list.d/nodesource.list ; then # Node 12 might be installed, previously used in BigBlueButton + sudo apt-get purge nodejs + sudo rm -r /etc/apt/sources.list.d/nodesource.list + fi + if [ ! -f /etc/apt/sources.list.d/nodesource.list ]; then + curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash - + fi + if ! apt-cache madison nodejs | grep -q node_16; then + err "Did not detect nodejs 16.x candidate for installation" + fi + if ! apt-key list MongoDB | grep -q 4.4; then + wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add - + fi + echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list + rm -f /etc/apt/sources.list.d/mongodb-org-4.2.list + + touch /root/.rnd + MONGODB=mongodb-org + install_docker # needed for bbb-libreoffice-docker + + need_pkg ruby + + BBB_WEB_ETC_CONFIG=/etc/bigbluebutton/bbb-web.properties # Override file for local settings + + need_pkg openjdk-11-jre java-common + update-java-alternatives -s java-1.11.0-openjdk-amd64 + fi + + apt-get update + apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" dist-upgrade + + need_pkg nodejs $MONGODB apt-transport-https haveged + need_pkg bigbluebutton + need_pkg bbb-html5 + + if [ -f /usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties ]; then + SERVLET_DIR=/usr/share/bbb-web + TURN_XML=$SERVLET_DIR/WEB-INF/classes/spring/turn-stun-servers.xml + fi + + while [ ! -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; do sleep 1; echo -n '.'; done + + check_lxc + check_nat + check_LimitNOFILE + + configure_HTML5 + + if [ -n "$API_DEMOS" ]; then + need_pkg bbb-demo + while [ ! -f /var/lib/$TOMCAT_USER/webapps/demo/bbb_api_conf.jsp ]; do sleep 1; echo -n '.'; done + fi + + if [ -n "$LINK_PATH" ]; then + ln -s "$LINK_PATH" "/var/bigbluebutton" + fi + + if [ -n "$PROVIDED_CERTIFICATE" ] ; then + install_ssl + elif [ -n "$HOST" ] && [ -n "$EMAIL" ] ; then + install_ssl + fi + + if [ -n "$GREENLIGHT" ]; then + install_greenlight + fi + + if [ -n "$COTURN" ]; then + configure_coturn + fi + + apt-get auto-remove -y + + if systemctl status freeswitch.service | grep -q SETSCHEDULER; then + sed -i "s/^CPUSchedulingPolicy=rr/#CPUSchedulingPolicy=rr/g" /lib/systemd/system/freeswitch.service + systemctl daemon-reload + fi + + systemctl restart systemd-journald + + if [ -n "$UFW" ]; then + setup_ufw + fi + + if [ -n "$HOST" ]; then + bbb-conf --setip "$HOST" + else + bbb-conf --setip "$IP" + fi + + if ! systemctl show-environment | grep LANG= | grep -q UTF-8; then + sudo systemctl set-environment LANG=C.UTF-8 + fi + + bbb-conf --check +} + +say() { + echo "bbb-install: $1" +} + +err() { + say "$1" >&2 + exit 1 +} + +check_root() { + if [ $EUID != 0 ]; then err "You must run this command as root."; fi +} + +check_mem() { + if awk '$1~/MemTotal/ {exit !($2<3940000)}' /proc/meminfo; then + echo "Your server needs to have (at least) 4G of memory." + if [ "$SKIP_MIN_SERVER_REQUIREMENTS_CHECK" != true ]; then + exit 1 + fi + fi +} + +check_cpus() { + if [ "$(nproc --all)" -lt 4 ]; then + echo "Your server needs to have (at least) 4 CPUs (8 recommended for production)." + if [ "$SKIP_MIN_SERVER_REQUIREMENTS_CHECK" != true ]; then + exit 1 + fi + fi +} + +check_ubuntu(){ + RELEASE=$(lsb_release -r | sed 's/^[^0-9]*//g') + if [ "$RELEASE" != "$1" ]; then err "You must run this command on Ubuntu $1 server."; fi +} + +need_x64() { + UNAME=`uname -m` + if [ "$UNAME" != "x86_64" ]; then err "You must run this command on a 64-bit server."; fi +} + +wait_443() { + echo "Waiting for port 443 to clear " + # ss fields 4 and 6 are Local Address and State + while ss -ant | awk '{print $4, $6}' | grep TIME_WAIT | grep -q ":443"; do sleep 1; echo -n '.'; done + echo +} + +get_IP() { + if [ -n "$IP" ]; then return 0; fi + + # Determine local IP + if [ -e "/sys/class/net/venet0:0" ]; then + # IP detection for OpenVZ environment + _dev="venet0:0" + else + _dev=$(awk '$2 == 00000000 { print $1 }' /proc/net/route | head -1) + fi + _ips=$(LANG=C ip -4 -br address show dev "$_dev" | awk '{ $1=$2=""; print $0 }') + _ips=${_ips/127.0.0.1\/8/} + read -r IP _ <<< "$_ips" + IP=${IP/\/*} # strip subnet provided by ip address + if [ -z "$IP" ]; then + read -r IP _ <<< "$(hostname -I)" + fi + + + # Determine external IP + if grep -sqi ^ec2 /sys/devices/virtual/dmi/id/product_uuid; then + # EC2 + local external_ip=$(wget -qO- http://169.254.169.254/latest/meta-data/public-ipv4) + elif [ -f /var/lib/dhcp/dhclient.eth0.leases ] && grep -q unknown-245 /var/lib/dhcp/dhclient.eth0.leases; then + # Azure + local external_ip=$(curl -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-08-01&format=text") + elif [ -f /run/scw-metadata.cache ]; then + # Scaleway + local external_ip=$(grep "PUBLIC_IP_ADDRESS" /run/scw-metadata.cache | cut -d '=' -f 2) + elif which dmidecode > /dev/null && dmidecode -s bios-vendor | grep -q Google; then + # Google Compute Cloud + local external_ip=$(wget -O - -q "http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" --header 'Metadata-Flavor: Google') + elif [ -n "$1" ]; then + # Try and determine the external IP from the given hostname + need_pkg dnsutils + local external_ip=$(dig +short "$1" @resolver1.opendns.com | grep '^[.0-9]*$' | tail -n1) + fi + + # Check if the external IP reaches the internal IP + if [ -n "$external_ip" ] && [ "$IP" != "$external_ip" ]; then + if which nginx; then + systemctl stop nginx + fi + + need_pkg netcat-openbsd + + wait_443 + + nc -l -p 443 > /dev/null 2>&1 & + nc_PID=$! + sleep 1 + + # Check if we can reach the server through it's external IP address + if nc -zvw3 "$external_ip" 443 > /dev/null 2>&1; then + INTERNAL_IP=$IP + IP=$external_ip + echo + echo " Detected this server has an internal/external IP address." + echo + echo " INTERNAL_IP: $INTERNAL_IP" + echo " (external) IP: $IP" + echo + fi + + kill $nc_PID > /dev/null 2>&1; + + if which nginx; then + systemctl start nginx + fi + fi + + if [ -z "$IP" ]; then err "Unable to determine local IP address."; fi +} + +need_pkg() { + check_root + while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do echo "Sleeping for 1 second because of dpkg lock"; sleep 1; done + + if [ ! "$SOURCES_FETCHED" = true ]; then + apt-get update + SOURCES_FETCHED=true + fi + + if ! dpkg -s ${@:1} >/dev/null 2>&1; then + LC_CTYPE=C.UTF-8 apt-get install -yq ${@:1} + fi + while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do echo "Sleeping for 1 second because of dpkg lock"; sleep 1; done +} + +need_ppa() { + need_pkg software-properties-common + if [ ! -f "/etc/apt/sources.list.d/$1" ]; then + LC_CTYPE=C.UTF-8 add-apt-repository -y "$2" + fi + if ! apt-key list "$3" | grep -q -E "1024|4096"; then # Let's try it a second time + LC_CTYPE=C.UTF-8 add-apt-repository "$2" -y + if ! apt-key list "$3" | grep -q -E "1024|4096"; then + err "Unable to setup PPA for $2" + fi + fi +} + +check_version() { + if ! echo "$1" | grep -Eq "focal"; then err "This script can only install BigBlueButton 2.5 (or later) and is meant to be run on Ubuntu 20.04 (focal) server."; fi + DISTRO=$(echo "$1" | sed 's/-.*//g') + if ! wget -qS --spider "https://$PACKAGE_REPOSITORY/$1/dists/bigbluebutton-$DISTRO/Release.gpg" > /dev/null 2>&1; then + err "Unable to locate packages for $1 at $PACKAGE_REPOSITORY." + fi + check_root + need_pkg apt-transport-https + if ! apt-key list | grep -q "BigBlueButton apt-get"; then + wget "https://$PACKAGE_REPOSITORY/repo/bigbluebutton.asc" -O- | apt-key add - + fi + + echo "deb https://$PACKAGE_REPOSITORY/$VERSION bigbluebutton-$DISTRO main" > /etc/apt/sources.list.d/bigbluebutton.list +} + +check_host() { + if [ -z "$PROVIDED_CERTIFICATE" ] && [ -z "$HOST" ]; then + need_pkg dnsutils apt-transport-https + DIG_IP=$(dig +short "$1" | grep '^[.0-9]*$' | tail -n1) + if [ -z "$DIG_IP" ]; then err "Unable to resolve $1 to an IP address using DNS lookup."; fi + get_IP "$1" + if [ "$DIG_IP" != "$IP" ]; then err "DNS lookup for $1 resolved to $DIG_IP but didn't match local $IP."; fi + fi +} + +check_coturn() { + if ! echo "$1" | grep -q ':'; then err "Option for coturn must be :"; fi + + COTURN_HOST=$(echo "$OPTARG" | cut -d':' -f1) + COTURN_SECRET=$(echo "$OPTARG" | cut -d':' -f2) + + if [ -z "$COTURN_HOST" ]; then err "-c option must contain "; fi + if [ -z "$COTURN_SECRET" ]; then err "-c option must contain "; fi + + if [ "$COTURN_HOST" == "turn.example.com" ]; then + err "You must specify a valid hostname (not the example given in the docs)" + fi + if [ "$COTURN_SECRET" == "1234abcd" ]; then + err "You must specify a new password (not the example given in the docs)." + fi + + check_host "$COTURN_HOST" +} + +check_apache2() { + if dpkg -l | grep -q apache2-bin; then + echo "You must uninstall the Apache2 server first" + if [ "$SKIP_APACHE_INSTALLED_CHECK" != true ]; then + exit 1 + fi + fi +} + +# If running under LXC, then modify the FreeSWITCH systemctl service so it does not use realtime scheduler +check_lxc() { + if grep -qa container=lxc /proc/1/environ; then + if grep IOSchedulingClass /lib/systemd/system/freeswitch.service > /dev/null; then + cat > /lib/systemd/system/freeswitch.service << HERE +[Unit] +Description=freeswitch +After=syslog.target network.target local-fs.target + +[Service] +Type=forking +PIDFile=/opt/freeswitch/var/run/freeswitch/freeswitch.pid +Environment="DAEMON_OPTS=-nonat" +EnvironmentFile=-/etc/default/freeswitch +ExecStart=/opt/freeswitch/bin/freeswitch -u freeswitch -g daemon -ncwait \$DAEMON_OPTS +TimeoutSec=45s +Restart=always +WorkingDirectory=/opt/freeswitch +User=freeswitch +Group=daemon + +LimitCORE=infinity +LimitNOFILE=100000 +LimitNPROC=60000 +LimitSTACK=250000 +LimitRTPRIO=infinity +LimitRTTIME=7000000 +#IOSchedulingClass=realtime +#IOSchedulingPriority=2 +#CPUSchedulingPolicy=rr +#CPUSchedulingPriority=89 + +[Install] +WantedBy=multi-user.target +HERE + + systemctl daemon-reload + fi +fi +} + +# Check if running externally with internal/external IP addresses +check_nat() { + xmlstarlet edit --inplace --update '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_rtp_ip=")]/@data' --value "external_rtp_ip=$IP" /opt/freeswitch/conf/vars.xml + xmlstarlet edit --inplace --update '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_sip_ip=")]/@data' --value "external_sip_ip=$IP" /opt/freeswitch/conf/vars.xml + + if [ -n "$INTERNAL_IP" ]; then + xmlstarlet edit --inplace --update '//param[@name="ext-rtp-ip"]/@value' --value "\$\${external_rtp_ip}" /opt/freeswitch/conf/sip_profiles/external.xml + xmlstarlet edit --inplace --update '//param[@name="ext-sip-ip"]/@value' --value "\$\${external_sip_ip}" /opt/freeswitch/conf/sip_profiles/external.xml + + sed -i "s/$INTERNAL_IP:/$IP:/g" /usr/share/bigbluebutton/nginx/sip.nginx + ip addr add "$IP" dev lo + + # If dummy NIC is not in dummy-nic.service (or the file does not exist), update/create it + if ! grep -q "$IP" /lib/systemd/system/dummy-nic.service > /dev/null 2>&1; then + if [ -f /lib/systemd/system/dummy-nic.service ]; then + DAEMON_RELOAD=true; + fi + + cat > /lib/systemd/system/dummy-nic.service << HERE +[Unit] +Description=Configure dummy NIC for FreeSWITCH +Before=freeswitch.service +After=network.target + +[Service] +ExecStart=/sbin/ip addr add $IP dev lo + +[Install] +WantedBy=multi-user.target +HERE + + if [ "$DAEMON_RELOAD" == "true" ]; then + systemctl daemon-reload + systemctl restart dummy-nic + else + systemctl enable dummy-nic + systemctl start dummy-nic + fi + fi + fi +} + +check_LimitNOFILE() { + CPU=$(nproc --all) + + if [ "$CPU" -ge 8 ]; then + if [ -f /lib/systemd/system/bbb-web.service ]; then + # Let's create an override file to increase the number of LimitNOFILE + mkdir -p /etc/systemd/system/bbb-web.service.d/ + cat > /etc/systemd/system/bbb-web.service.d/override.conf << HERE +[Service] +LimitNOFILE=8192 +HERE + systemctl daemon-reload + fi + fi +} + +configure_HTML5() { + # Use Google's default STUN server + if [ -n "$INTERNAL_IP" ]; then + sed -i "s/[;]*externalIPv4=.*/externalIPv4=$IP/g" /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini + sed -i "s/[;]*iceTcp=.*/iceTcp=0/g" /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini + fi +} + +install_greenlight(){ + install_docker + + docker pull bigbluebutton/greenlight:v2 # Ensure the current version of greenlight is pulled + + # Purge older docker compose + if dpkg -l | grep -q docker-compose; then + apt-get purge -y docker-compose + fi + + if [ ! -x /usr/local/bin/docker-compose ]; then + curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + fi + + if [ ! -d ~/greenlight ]; then + mkdir -p ~/greenlight + fi + + # This will trigger the download of Greenlight docker image (if needed) + SECRET_KEY_BASE=$(docker run --rm bigbluebutton/greenlight:v2 bundle exec rake secret) + + if [ ! -f ~/greenlight/.env ]; then + docker run --rm bigbluebutton/greenlight:v2 cat ./sample.env > ~/greenlight/.env + fi + + BIGBLUEBUTTON_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties $CR_TMPFILE $BBB_WEB_ETC_CONFIG | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | tail -n 1 )/bigbluebutton/ + BIGBLUEBUTTON_SECRET=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties $CR_TMPFILE $BBB_WEB_ETC_CONFIG | grep -v '#' | grep ^securitySalt | tail -n 1 | cut -d= -f2) + SAFE_HOSTS=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties $CR_TMPFILE $BBB_WEB_ETC_CONFIG | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | tail -n 1 | sed 's/https\?:\/\///') + + # Update Greenlight configuration file in ~/greenlight/env + sed -i "s|SECRET_KEY_BASE=.*|SECRET_KEY_BASE=$SECRET_KEY_BASE|" ~/greenlight/.env + sed -i "s|.*BIGBLUEBUTTON_ENDPOINT=.*|BIGBLUEBUTTON_ENDPOINT=$BIGBLUEBUTTON_URL|" ~/greenlight/.env + sed -i "s|.*BIGBLUEBUTTON_SECRET=.*|BIGBLUEBUTTON_SECRET=$BIGBLUEBUTTON_SECRET|" ~/greenlight/.env + sed -i "s|SAFE_HOSTS=.*|SAFE_HOSTS=$SAFE_HOSTS|" ~/greenlight/.env + + # need_pkg bbb-webhooks + + if [ ! -f /usr/share/bigbluebutton/nginx/greenlight.nginx ]; then + docker run --rm bigbluebutton/greenlight:v2 cat ./greenlight.nginx | tee /usr/share/bigbluebutton/nginx/greenlight.nginx + cat > /usr/share/bigbluebutton/nginx/greenlight-redirect.nginx << HERE +location = / { + return 307 /b; +} +HERE + systemctl restart nginx + fi + + if ! gem list | grep -q java_properties; then + gem install jwt java_properties + fi + + if [ ! -f ~/greenlight/docker-compose.yml ]; then + docker run --rm bigbluebutton/greenlight:v2 cat ./docker-compose.yml > ~/greenlight/docker-compose.yml + fi + + # change the default passwords + PGPASSWORD=$(openssl rand -base64 24) + sed -i "s,^\([ \t-]*POSTGRES_PASSWORD\)\(=password\),\1=$PGPASSWORD,g" ~/greenlight/docker-compose.yml + sed -i "s,^\([ \t]*DB_PASSWORD\)\(=password\),\1=$PGPASSWORD,g" ~/greenlight/.env + + # Remove old containers + if docker ps | grep -q greenlight_db_1; then + docker rm -f greenlight_db_1 + fi + if docker ps | grep -q greenlight-v2; then + docker rm -f greenlight-v2 + fi + + if ! docker ps | grep -q greenlight; then + docker-compose -f ~/greenlight/docker-compose.yml up -d + sleep 5 + fi +} + + +install_docker() { + need_pkg apt-transport-https ca-certificates curl gnupg-agent software-properties-common openssl + + # Install Docker + if ! apt-key list | grep -q Docker; then + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - + fi + + if ! dpkg -l | grep -q docker-ce; then + add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) \ + stable" + + apt-get update + need_pkg docker-ce docker-ce-cli containerd.io + fi + if ! which docker; then err "Docker did not install"; fi + + # Remove Docker Compose + if dpkg -l | grep -q docker-compose; then + apt-get purge -y docker-compose + fi +} + + +install_ssl() { + if ! grep -q "$HOST" /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml; then + bbb-conf --setip "$HOST" + fi + + mkdir -p /etc/nginx/ssl + + if [ -z "$PROVIDED_CERTIFICATE" ]; then + add-apt-repository universe + apt-get update + need_pkg certbot + fi + + if [ ! -f /etc/nginx/ssl/dhp-4096.pem ]; then + openssl dhparam -dsaparam -out /etc/nginx/ssl/dhp-4096.pem 4096 + fi + + if [ ! -f "/etc/letsencrypt/live/$HOST/fullchain.pem" ]; then + rm -f /tmp/bigbluebutton.bak + if ! grep -q "$HOST" /etc/nginx/sites-available/bigbluebutton; then # make sure we can do the challenge + if [ -f /etc/nginx/sites-available/bigbluebutton ]; then + cp /etc/nginx/sites-available/bigbluebutton /tmp/bigbluebutton.bak + fi + cat < /etc/nginx/sites-available/bigbluebutton +server_tokens off; +server { + listen 80; + listen [::]:80; + server_name $HOST; + + access_log /var/log/nginx/bigbluebutton.access.log; + + # BigBlueButton landing page. + location / { + root /var/www/bigbluebutton-default; + index index.html index.htm; + expires 1m; + } +} +HERE + systemctl restart nginx + fi + + if [ -z "$PROVIDED_CERTIFICATE" ]; then + if ! certbot --email "$EMAIL" --agree-tos --rsa-key-size 4096 -w /var/www/bigbluebutton-default/ \ + -d "$HOST" --deploy-hook "systemctl reload nginx" $LETS_ENCRYPT_OPTIONS certonly; then + systemctl restart nginx + err "Let's Encrypt SSL request for $HOST did not succeed - exiting" + fi + else + # Place your fullchain.pem and privkey.pem files in /local/certs/ and bbb-install-2.5.sh will deal with the rest. + mkdir -p "/etc/letsencrypt/live/$HOST/" + ln -s /local/certs/fullchain.pem "/etc/letsencrypt/live/$HOST/fullchain.pem" + ln -s /local/certs/privkey.pem "/etc/letsencrypt/live/$HOST/privkey.pem" + fi + fi + + cat < /etc/nginx/sites-available/bigbluebutton +server_tokens off; + +server { + listen 80; + listen [::]:80; + server_name $HOST; + + return 301 https://\$server_name\$request_uri; #redirect HTTP to HTTPS + +} +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name $HOST; + + ssl_certificate /etc/letsencrypt/live/$HOST/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/$HOST/privkey.pem; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_dhparam /etc/nginx/ssl/dhp-4096.pem; + + # HSTS (comment out to enable) + #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + access_log /var/log/nginx/bigbluebutton.access.log; + + # BigBlueButton landing page. + location / { + root /var/www/bigbluebutton-default; + index index.html index.htm; + expires 1m; + } + + # Include specific rules for record and playback + include /usr/share/bigbluebutton/nginx/*.nginx; + include /etc/bigbluebutton/nginx/*.nginx; # possible overrides +} +HERE + + # Configure rest of BigBlueButton Configuration for SSL + xmlstarlet edit --inplace --update '//param[@name="wss-binding"]/@value' --value "$IP:7443" /opt/freeswitch/conf/sip_profiles/external.xml + + source /etc/bigbluebutton/bigbluebutton-release + if [ -n "$(echo "$BIGBLUEBUTTON_RELEASE" | grep '2.2')" ] && [ "$(echo "$BIGBLUEBUTTON_RELEASE" | cut -d\. -f3)" -lt 29 ]; then + sed -i "s/proxy_pass .*/proxy_pass https:\/\/$IP:7443;/g" /usr/share/bigbluebutton/nginx/sip.nginx + else + # Use nginx as proxy for WSS -> WS (see https://github.com/bigbluebutton/bigbluebutton/issues/9667) + yq w -i /usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml public.media.sipjsHackViaWs true + sed -i "s/proxy_pass .*/proxy_pass http:\/\/$IP:5066;/g" /usr/share/bigbluebutton/nginx/sip.nginx + xmlstarlet edit --inplace --update '//param[@name="ws-binding"]/@value' --value "$IP:5066" /opt/freeswitch/conf/sip_profiles/external.xml + fi + + sed -i 's/^bigbluebutton.web.serverURL=http:/bigbluebutton.web.serverURL=https:/g' $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties + if [ -f $BBB_WEB_ETC_CONFIG ]; then + sed -i 's/^bigbluebutton.web.serverURL=http:/bigbluebutton.web.serverURL=https:/g' $BBB_WEB_ETC_CONFIG + fi + + yq w -i /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml playback_protocol https + chmod 644 /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml + + if [ -f /var/lib/$TOMCAT_USER/webapps/demo/bbb_api_conf.jsp ]; then + sed -i 's/String BigBlueButtonURL = "http:/String BigBlueButtonURL = "https:/g' /var/lib/$TOMCAT_USER/webapps/demo/bbb_api_conf.jsp + fi + + if [ -f /usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml ]; then + yq w -i /usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml public.note.url "https://$HOST/pad" + fi + + # Update Greenlight (if installed) to use SSL + if [ -f ~/greenlight/.env ]; then + if ! grep ^BIGBLUEBUTTON_ENDPOINT ~/greenlight/.env | grep -q https; then + BIGBLUEBUTTON_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties $CR_TMPFILE $BBB_WEB_ETC_CONFIG | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | tail -n 1 )/bigbluebutton/ + sed -i "s|.*BIGBLUEBUTTON_ENDPOINT=.*|BIGBLUEBUTTON_ENDPOINT=$BIGBLUEBUTTON_URL|" ~/greenlight/.env + docker-compose -f ~/greenlight/docker-compose.yml down + docker-compose -f ~/greenlight/docker-compose.yml up -d + fi + fi + + TARGET=/usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml + if [ -f $TARGET ]; then + if grep -q kurentoIp $TARGET; then + # 2.0 + yq w -i $TARGET kurentoIp "$IP" + else + # 2.2 + yq w -i $TARGET kurento[0].ip "$IP" + yq w -i $TARGET freeswitch.ip "$IP" + + if [ -n "$(echo "$BIGBLUEBUTTON_RELEASE" | grep '2.2')" ] && [ "$(echo "$BIGBLUEBUTTON_RELEASE" | cut -d\. -f3)" -lt 29 ]; then + if [ -n "$INTERNAL_IP" ]; then + yq w -i $TARGET freeswitch.sip_ip "$INTERNAL_IP" + else + yq w -i $TARGET freeswitch.sip_ip "$IP" + fi + else + # Use nginx as proxy for WSS -> WS (see https://github.com/bigbluebutton/bigbluebutton/issues/9667) + yq w -i $TARGET freeswitch.sip_ip "$IP" + fi + fi + chown bigbluebutton:bigbluebutton $TARGET + chmod 644 $TARGET + fi + + mkdir -p /etc/bigbluebutton/bbb-webrtc-sfu + TARGET=/etc/bigbluebutton/bbb-webrtc-sfu/production.yml + touch $TARGET + + # Configure mediasoup IPs, reference: https://raw.githubusercontent.com/bigbluebutton/bbb-webrtc-sfu/v2.7.2/docs/mediasoup.md + # mediasoup IPs: WebRTC + yq w -i "$TARGET" mediasoup.webrtc.listenIps[0].ip "0.0.0.0" + yq w -i "$TARGET" mediasoup.webrtc.listenIps[0].announcedIp "$IP" + + # mediasoup IPs: plain RTP (internal comms, FS <-> mediasoup) + yq w -i "$TARGET" mediasoup.plainRtp.listenIp.ip "0.0.0.0" + yq w -i "$TARGET" mediasoup.plainRtp.listenIp.announcedIp "$IP" +} + +configure_coturn() { + cat < $TURN_XML + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +HERE +} + + +install_coturn() { + apt-get update + apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" dist-upgrade + + need_pkg software-properties-common certbot + + if ! certbot certonly --standalone --non-interactive --preferred-challenges http \ + -d "$COTURN_HOST" --email "$EMAIL" --agree-tos -n ; then + err "Let's Encrypt SSL request for $COTURN_HOST did not succeed - exiting" + fi + + need_pkg coturn + + if [ -n "$INTERNAL_IP" ]; then + EXTERNAL_IP="external-ip=$IP/$INTERNAL_IP" + fi + + cat < /etc/turnserver.conf +listening-port=3478 +tls-listening-port=443 + +listening-ip=$IP +relay-ip=$IP +$EXTERNAL_IP + +min-port=32769 +max-port=65535 +verbose + +fingerprint +lt-cred-mech +use-auth-secret +static-auth-secret=$COTURN_SECRET +realm=$(echo "$COTURN_HOST" | cut -d'.' -f2-) + +cert=/etc/turnserver/fullchain.pem +pkey=/etc/turnserver/privkey.pem +# From https://ssl-config.mozilla.org/ Intermediate, openssl 1.1.0g, 2020-01 +cipher-list="ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384" +dh-file=/etc/turnserver/dhp.pem + +keep-address-family + +no-cli +no-tlsv1 +no-tlsv1_1 +HERE + + mkdir -p /etc/turnserver + if [ ! -f /etc/turnserver/dhp.pem ]; then + openssl dhparam -dsaparam -out /etc/turnserver/dhp.pem 2048 + fi + + mkdir -p /var/log/turnserver + chown turnserver:turnserver /var/log/turnserver + + cat < /etc/logrotate.d/coturn +/var/log/turnserver/*.log +{ + rotate 7 + daily + missingok + notifempty + compress + postrotate + /bin/systemctl kill -s HUP coturn.service + endscript +} +HERE + + # Eanble coturn to bind to port 443 with CAP_NET_BIND_SERVICE + mkdir -p /etc/systemd/system/coturn.service.d + rm -rf /etc/systemd/system/coturn.service.d/ansible.conf # Remove previous file + cat > /etc/systemd/system/coturn.service.d/override.conf < /etc/letsencrypt/renewal-hooks/deploy/coturn < /etc/bigbluebutton/bbb-conf/apply-config.sh << HERE +#!/bin/bash + +# Pull in the helper functions for configuring BigBlueButton +source /etc/bigbluebutton/bbb-conf/apply-lib.sh + +enableUFWRules +HERE + chmod +x /etc/bigbluebutton/bbb-conf/apply-config.sh + fi +} + +main "$@" || exit 1 + diff --git a/roles/bbb_install/files/bbb-install-2.7.sh b/roles/bbb_install/files/bbb-install-2.7.sh new file mode 100644 index 0000000..4d41f1c --- /dev/null +++ b/roles/bbb_install/files/bbb-install-2.7.sh @@ -0,0 +1,1889 @@ +#!/bin/bash -e + +# Copyright (c) 2023 BigBlueButton Inc. +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +# BigBlueButton is an open source conferencing system. For more information see +# https://www.bigbluebutton.org/. +# +# This bbb-install.sh script automates many of the installation and configuration +# steps at https://docs.bigbluebutton.org/2.7/administration/install +# +# +# Examples +# +# Install BigBlueButton 2.7.x with a SSL certificate from Let's Encrypt using hostname bbb.example.com +# and email address info@example.com and apply a basic firewall +# +# wget -qO- https://raw.githubusercontent.com/bigbluebutton/bbb-install/v2.7.x-release/bbb-install.sh | bash -s -- -w -v focal-270 -s bbb.example.com -e info@example.com +# +# Install BigBlueButton with SSL + Greenlight +# +# wget -qO- https://raw.githubusercontent.com/bigbluebutton/bbb-install/v2.7.x-release/bbb-install.sh | bash -s -- -w -v focal-270 -s bbb.example.com -e info@example.com -g +# + +usage() { + set +x + cat 1>&2 < Install given version of BigBlueButton (e.g. 'focal-270') (required) + + -s Configure server with + -e Email for Let's Encrypt certbot + + -x Use Let's Encrypt certbot with manual DNS challenges + + -g Install Greenlight version 3 + -k Install Keycloak version 20 + + -t : Install BigBlueButton LTI framework tools and add/update LTI consumer credentials : + + -c : Configure with external coturn server at using (instead of built-in TURN server) + + -m Create a Symbolic link from /var/bigbluebutton to + + -p [:] Use apt-get proxy at (default port 3142) + -r Use alternative apt repository (such as packages-eu.bigbluebutton.org) + + -d Skip SSL certificates request (use provided certificates from mounted volume) in /local/certs/ + -w Install UFW firewall (recommended) + + -j Allows the installation of BigBlueButton to proceed even if not all requirements [for production use] are met. + Note that not all requirements can be ignored. This is useful in development / testing / ci scenarios. + + -i Allows the installation of BigBlueButton to proceed even if Apache webserver is installed. + + -h Print help + +OPTIONS (install Let's Encrypt certificate only): + + -s Configure server with (required) + -e Configure email for Let's Encrypt certbot (required) + -l Only install Let's Encrypt certificate (not BigBlueButton) + -x Use Let's Encrypt certbot with manual dns challenges (optional) + +OPTIONS (install Greenlight only): + + -g Install Greenlight version 3 (required) + -k Install Keycloak version 20 (optional) + +OPTIONS (install BigBlueButton LTI framework only): + + -t : Install BigBlueButton LTI framework tools and add/update LTI consumer credentials : (required) + +VARIABLES (configure Greenlight only): + GL_PATH Configure Greenlight relative URL root path (Optional) + * Use this when deploying Greenlight behind a reverse proxy on a path other than the default '/' e.g. '/gl'. + + +EXAMPLES: + +Sample options for setup a BigBlueButton 2.7 server + + -v focal-270 -s bbb.example.com -e info@example.com + +Sample options for setup a BigBlueButton 2.7 server with Greenlight 3 and optionally Keycloak + + -v focal-270 -s bbb.example.com -e info@example.com -g [-k] + +Sample options for setup a BigBlueButton 2.7 server with LTI framework while managing LTI consumer credentials MY_KEY:MY_SECRET + + -v focal-270 -s bbb.example.com -e info@example.com -t MY_KEY:MY_SECRET + +SUPPORT: + Community: https://bigbluebutton.org/support + Docs: https://github.com/bigbluebutton/bbb-install + https://docs.bigbluebutton.org/administration/install/#minimum-server-requirements + +HERE +} + +main() { + export DEBIAN_FRONTEND=noninteractive + PACKAGE_REPOSITORY=ubuntu.bigbluebutton.org + LETS_ENCRYPT_OPTIONS=(--webroot --non-interactive) + SOURCES_FETCHED=false + GL3_DIR=~/greenlight-v3 + LTI_DIR=~/bbb-lti + NGINX_FILES_DEST=/usr/share/bigbluebutton/nginx + CR_TMPFILE=$(mktemp /tmp/carriage-return.XXXXXX) + printf '\n' > "$CR_TMPFILE" + + need_x64 + + while builtin getopts "hs:r:c:v:e:p:m:t:xgadwjik" opt "${@}"; do + + case $opt in + h) + usage + exit 0 + ;; + + s) + HOST=$OPTARG + if [ "$HOST" == "bbb.example.com" ]; then + err "You must specify a valid hostname (not the hostname given in the docs)." + fi + ;; + r) + PACKAGE_REPOSITORY=$OPTARG + ;; + e) + EMAIL=$OPTARG + if [ "$EMAIL" == "info@example.com" ]; then + err "You must specify a valid email address (not the email in the docs)." + fi + ;; + x) + LETS_ENCRYPT_OPTIONS=(--manual --preferred-challenges dns) + ;; + c) + COTURN=$OPTARG + check_coturn "$COTURN" + ;; + v) + VERSION=$OPTARG + ;; + + p) + PROXY=$OPTARG + if [ -n "$PROXY" ]; then + if [[ "$PROXY" =~ : ]]; then + echo "Acquire::http::Proxy \"http://$PROXY\";" > /etc/apt/apt.conf.d/01proxy + else + echo "Acquire::http::Proxy \"http://$PROXY:3142\";" > /etc/apt/apt.conf.d/01proxy + fi + fi + ;; + + g) + GREENLIGHT=true + GL_DEFAULT_PATH=/ + + if [ -n "$GL_PATH" ] && [ "$GL_PATH" != "$GL_DEFAULT_PATH" ]; then + if [[ ! $GL_PATH =~ ^/.*[^/]$ ]]; then + err "\$GL_PATH ENV is set to '$GL_PATH' which is invalid, Greenlight relative URL root path must start but not end with '/'." + fi + fi + ;; + k) + INSTALL_KC=true + ;; + t) + LTI_CREDS_STR=$OPTARG + + if [ "$LTI_CREDS_STR" == "MY_KEY:MY_SECRET" ]; then + err "You must use a valid complex credentials for your LTI setup (not the ones in the example)." + fi + + if [[ ! $LTI_CREDS_STR == *:* ]]; then + err "You must respect the format : when specifying your LTI credentials." + fi + + # Making LTI_CREDS an array, first element is the LTI TC key and the second is the LTI TC secret. + IFS=: read -ra LTI_CREDS <<<"${LTI_CREDS_STR}" + ;; + a) + err "Error: bbb-demo (API demos, '-a' option) were deprecated in BigBlueButton 2.6. Please use Greenlight or API MATE" + ;; + m) + LINK_PATH=$OPTARG + ;; + d) + PROVIDED_CERTIFICATE=true + ;; + w) + SSH_PORT=$(grep Port /etc/ssh/ssh_config | grep -v \# | sed 's/[^0-9]*//g') + if [[ -n "$SSH_PORT" && "$SSH_PORT" != "22" ]]; then + err "Detected sshd not listening to standard port 22 -- unable to install default UFW firewall rules. See https://docs.bigbluebutton.org/2.2/customize.html#secure-your-system--restrict-access-to-specific-ports" + fi + UFW=true + ;; + j) + SKIP_MIN_SERVER_REQUIREMENTS_CHECK=true + ;; + i) + SKIP_APACHE_INSTALLED_CHECK=true + ;; + :) + err "Missing option argument for -$OPTARG" + ;; + + \?) + usage_err "Invalid option: -$OPTARG" >&2 + ;; + esac + done + + if [ -n "$HOST" ]; then + check_host "$HOST" + fi + + if [ -n "$VERSION" ]; then + check_version "$VERSION" + fi + + if [ "$SKIP_APACHE_INSTALLED_CHECK" != true ]; then + check_apache2 + fi + + # Check if we're installing coturn (need an e-mail address for Let's Encrypt) + if [ -z "$VERSION" ] && [ -n "$COTURN" ]; then + if [ -z "$EMAIL" ]; then err "Installing coturn needs an e-mail address for Let's Encrypt"; fi + check_ubuntu 20.04 + + install_coturn + exit 0 + fi + + if [ -z "$VERSION" ]; then + usage + exit 0 + fi + + if [ -n "$INSTALL_KC" ] && [ -z "$GREENLIGHT" ]; then + err "Keycloak cannot be installed without Greenlight." + fi + + # We're installing BigBlueButton + env + + check_mem + check_cpus + check_ipv6 + + need_pkg software-properties-common # needed for add-apt-repository + sudo add-apt-repository universe + need_pkg wget curl gpg-agent dirmngr apparmor-utils + + # need_pkg xmlstarlet + get_IP "$HOST" + + if [ "$DISTRO" == "focal" ]; then + need_pkg ca-certificates + + # yq version 3 is provided by ppa:bigbluebutton/support + # Uncomment the following to enable yq 4 after bigbluebutton/bigbluebutton#14511 is resolved + #need_ppa rmescandon-ubuntu-yq-bionic.list ppa:rmescandon/yq CC86BB64 # Edit yaml files with yq + + #need_ppa libreoffice-ubuntu-ppa-focal.list ppa:libreoffice/ppa 1378B444 # Latest version of libreoffice + need_ppa bigbluebutton-ubuntu-support-focal.list ppa:bigbluebutton/support 2E1B01D0E95B94BC # Needed for libopusenc0 + need_ppa martin-uni-mainz-ubuntu-coturn-focal.list ppa:martin-uni-mainz/coturn 4B77C2225D3BBDB3 # Coturn + + if ! apt-key list 5AFA7A83 | grep -q -E "1024|4096"; then # Add Kurento package + sudo apt-key adv --keyserver https://keyserver.ubuntu.com --recv-keys 5AFA7A83 + fi + + rm -rf /etc/apt/sources.list.d/kurento.list # Kurento 6.15 now packaged with 2.3 + + if [ -f /etc/apt/sources.list.d/nodesource.list ] && grep -q 16 /etc/apt/sources.list.d/nodesource.list; then + # Node 16 might be installed, previously used in BigBlueButton + # Remove the repository config. This will cause the repository to get + # re-added using the current nodejs version, and nodejs will be upgraded. + sudo rm -r /etc/apt/sources.list.d/nodesource.list + fi + if [ ! -f /etc/apt/sources.list.d/nodesource.list ]; then + sudo mkdir -p /etc/apt/keyrings + curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg + NODE_MAJOR=18 + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list + fi + if ! apt-key list MongoDB | grep -q 4.4; then + wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add - + fi + echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list + rm -f /etc/apt/sources.list.d/mongodb-org-4.2.list + + touch /root/.rnd + MONGODB=mongodb-org + install_docker # needed for bbb-libreoffice-docker + need_pkg ruby + + BBB_WEB_ETC_CONFIG=/etc/bigbluebutton/bbb-web.properties # Override file for local settings + + need_pkg openjdk-17-jre + update-java-alternatives -s java-1.17.0-openjdk-amd64 + + # Remove old bbb-demo if installed from a previous 2.5 setup + if dpkg -s bbb-demo > /dev/null 2>&1; then + apt purge -y bbb-demo tomcat9 + rm -rf /var/lib/tomcat9 + fi + fi + + apt-get update + apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" dist-upgrade + + need_pkg nodejs "$MONGODB" apt-transport-https haveged + need_pkg bigbluebutton + need_pkg bbb-html5 + + if [ -f /usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties ]; then + SERVLET_DIR=/usr/share/bbb-web + fi + + while [ ! -f "$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties" ]; do sleep 1; echo -n '.'; done + + check_cap_sys_nice + check_nat + check_LimitNOFILE + + configure_HTML5 + + if [ -n "$LINK_PATH" ]; then + ln -s "$LINK_PATH" "/var/bigbluebutton" + fi + + if [ -n "$PROVIDED_CERTIFICATE" ] ; then + install_ssl + elif [ -n "$HOST" ] && [ -n "$EMAIL" ] ; then + install_ssl + fi + + if [ -n "$COTURN" ]; then + configure_coturn + + if systemctl is-active --quiet haproxy.service; then + systemctl disable --now haproxy.service + fi + else + install_coturn + install_haproxy + systemctl enable --now haproxy.service # In case we had previously disabled (see above) + + # The turn server will always try to connect to the BBB server's public IP address, + # so if NAT is in use, add an iptables rule to adjust the destination IP address + # of UDP packets sent from the turn server to FreeSWITCH. + if [ -n "$INTERNAL_IP" ]; then + need_pkg iptables-persistent + iptables -t nat -A OUTPUT -p udp -s "$INTERNAL_IP" -d "$IP" -j DNAT --to-destination "$INTERNAL_IP" + netfilter-persistent save + fi + fi + + apt-get auto-remove -y + + systemctl restart systemd-journald + + if [ -n "$UFW" ]; then + setup_ufw + fi + + if [ -n "$HOST" ]; then + bbb-conf --setip "$HOST" + else + bbb-conf --setip "$IP" + fi + + if ! systemctl show-environment | grep LANG= | grep -q UTF-8; then + sudo systemctl set-environment LANG=C.UTF-8 + fi + + # BBB ecosystem apps: + if [[ ${#LTI_CREDS[*]} -eq 2 ]]; then + install_lti + fi + + if [ -n "$GREENLIGHT" ]; then + install_greenlight_v3 + fi + + bbb-conf --check +} + +say() { + echo "bbb-install: $1" +} + +err() { + say "$1" >&2 + exit 1 +} + +usage_err() { + say "$1" >&2 + usage + exit 1 +} + +check_root() { + if [ $EUID != 0 ]; then err "You must run this command as root."; fi +} + +check_mem() { + if awk '$1~/MemTotal/ {exit !($2<3940000)}' /proc/meminfo; then + echo "Your server needs to have (at least) 4G of memory." + if [ "$SKIP_MIN_SERVER_REQUIREMENTS_CHECK" != true ]; then + exit 1 + fi + fi +} + +check_ipv6() { + if [ ! -f /proc/net/if_inet6 ]; then + echo "Your server does not support IPV6" + if [ "$SKIP_MIN_SERVER_REQUIREMENTS_CHECK" != true ]; then + exit 1 + fi + fi +} + +check_cpus() { + if [ "$(nproc --all)" -lt 4 ]; then + echo "Your server needs to have (at least) 4 CPUs (8 recommended for production)." + if [ "$SKIP_MIN_SERVER_REQUIREMENTS_CHECK" != true ]; then + exit 1 + fi + fi +} + +check_ubuntu(){ + RELEASE=$(lsb_release -r | sed 's/^[^0-9]*//g') + if [ "$RELEASE" != "$1" ]; then err "You must run this command on Ubuntu $1 server."; fi +} + +need_x64() { + UNAME=$(uname -m) + if [ "$UNAME" != "x86_64" ]; then err "You must run this command on a 64-bit server."; fi +} + +wait_443() { + echo "Waiting for port 443 to clear " + # ss fields 4 and 6 are Local Address and State + while ss -ant | awk '{print $4, $6}' | grep TIME_WAIT | grep -q ":443"; do sleep 1; echo -n '.'; done + echo +} + +get_IP() { + if [ -n "$IP" ]; then return 0; fi + + # Determine local IP + if [ -e "/sys/class/net/venet0:0" ]; then + # IP detection for OpenVZ environment + _dev="venet0:0" + else + _dev=$(awk '$2 == 00000000 { print $1 }' /proc/net/route | head -1) + fi + _ips=$(LANG=C ip -4 -br address show dev "$_dev" | awk '{ $1=$2=""; print $0 }') + _ips=${_ips/127.0.0.1\/8/} + read -r IP _ <<< "$_ips" + IP=${IP/\/*} # strip subnet provided by ip address + if [ -z "$IP" ]; then + read -r IP _ <<< "$(hostname -I)" + fi + + + local external_ip + # Determine external IP + if grep -sqi ^ec2 /sys/devices/virtual/dmi/id/product_uuid; then + # EC2 + external_ip=$(wget -qO- http://169.254.169.254/latest/meta-data/public-ipv4) + elif [ -f /var/lib/dhcp/dhclient.eth0.leases ] && grep -q unknown-245 /var/lib/dhcp/dhclient.eth0.leases; then + # Azure + external_ip=$(curl -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-08-01&format=text") + elif [ -f /run/scw-metadata.cache ]; then + # Scaleway + external_ip=$(grep "PUBLIC_IP_ADDRESS" /run/scw-metadata.cache | cut -d '=' -f 2) + elif which dmidecode > /dev/null && dmidecode -s bios-vendor | grep -q Google; then + # Google Compute Cloud + external_ip=$(wget -O - -q "http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" --header 'Metadata-Flavor: Google') + elif [ -n "$1" ]; then + # Try and determine the external IP from the given hostname + need_pkg dnsutils + external_ip=$(dig +short "$1" @resolver1.opendns.com | grep '^[.0-9]*$' | tail -n1) + fi + + # Check if the external IP reaches the internal IP + if [ -n "$external_ip" ] && [ "$IP" != "$external_ip" ]; then + if which nginx; then + systemctl stop nginx + fi + + need_pkg netcat-openbsd + + wait_443 + + nc -l -p 443 > /dev/null 2>&1 & + nc_PID=$! + sleep 1 + + # Check if we can reach the server through it's external IP address + if nc -zvw3 "$external_ip" 443 > /dev/null 2>&1; then + INTERNAL_IP=$IP + IP=$external_ip + echo + echo " Detected this server has an internal/external IP address." + echo + echo " INTERNAL_IP: $INTERNAL_IP" + echo " (external) IP: $IP" + echo + fi + + kill $nc_PID > /dev/null 2>&1; + + if which nginx; then + systemctl start nginx + fi + fi + + if [ -z "$IP" ]; then err "Unable to determine local IP address."; fi +} + +need_pkg() { + check_root + while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do echo "Sleeping for 1 second because of dpkg lock"; sleep 1; done + + if [ ! "$SOURCES_FETCHED" = true ]; then + apt-get update + SOURCES_FETCHED=true + fi + + if ! dpkg -s "${@}" >/dev/null 2>&1; then + LC_CTYPE=C.UTF-8 apt-get install -yq "${@}" + fi + while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do echo "Sleeping for 1 second because of dpkg lock"; sleep 1; done +} + +need_ppa() { + need_pkg software-properties-common + if [ ! -f "/etc/apt/sources.list.d/$1" ]; then + LC_CTYPE=C.UTF-8 add-apt-repository -y "$2" + fi + if ! apt-key list "$3" | grep -q -E "1024|4096"; then # Let's try it a second time + LC_CTYPE=C.UTF-8 add-apt-repository "$2" -y + if ! apt-key list "$3" | grep -q -E "1024|4096"; then + err "Unable to setup PPA for $2" + fi + fi +} + +check_version() { + if ! echo "$1" | grep -Eq "focal-27"; then err "This script can only install BigBlueButton 2.7 and is meant to be run on Ubuntu 20.04 (focal) server."; fi + DISTRO=${1%%-*} + if ! wget -qS --spider "https://$PACKAGE_REPOSITORY/$1/dists/bigbluebutton-$DISTRO/Release.gpg" > /dev/null 2>&1; then + err "Unable to locate packages for $1 at $PACKAGE_REPOSITORY." + fi + check_root + need_pkg apt-transport-https + if ! apt-key list | grep -q "BigBlueButton apt-get"; then + wget "https://$PACKAGE_REPOSITORY/repo/bigbluebutton.asc" -O- | apt-key add - + fi + + echo "deb https://$PACKAGE_REPOSITORY/$VERSION bigbluebutton-$DISTRO main" > /etc/apt/sources.list.d/bigbluebutton.list +} + +check_host() { + if [ -z "$PROVIDED_CERTIFICATE" ] && [ -z "$HOST" ]; then + need_pkg dnsutils apt-transport-https + DIG_IP=$(dig +short "$1" | grep '^[.0-9]*$' | tail -n1) + if [ -z "$DIG_IP" ]; then err "Unable to resolve $1 to an IP address using DNS lookup."; fi + get_IP "$1" + if [ "$DIG_IP" != "$IP" ]; then err "DNS lookup for $1 resolved to $DIG_IP but didn't match local $IP."; fi + fi +} + +check_coturn() { + if ! echo "$1" | grep -q ':'; then err "Option for coturn must be :"; fi + + COTURN_HOST=$(echo "$OPTARG" | cut -d':' -f1) + COTURN_SECRET=$(echo "$OPTARG" | cut -d':' -f2) + + if [ -z "$COTURN_HOST" ]; then err "-c option must contain "; fi + if [ -z "$COTURN_SECRET" ]; then err "-c option must contain "; fi + + if [ "$COTURN_HOST" == "turn.example.com" ]; then + err "You must specify a valid hostname (not the example given in the docs)" + fi + if [ "$COTURN_SECRET" == "1234abcd" ]; then + err "You must specify a new password (not the example given in the docs)." + fi + + check_host "$COTURN_HOST" +} + +check_apache2() { + if dpkg -l | grep -q apache2-bin; then + echo "You must uninstall the Apache2 server first" + if [ "$SKIP_APACHE_INSTALLED_CHECK" != true ]; then + exit 1 + fi + fi +} + +# If CAP_SYS_NICE is not available, then the FreeSWITCH systemctl service +# will fail to start, with an error message like "status=214/SETSCHEDULER". +# In this case we need to modify this service so that it does not require a realtime scheduler. +# A similar modification needs to be done to a couple of other services as well, +# like: bbb-html5-frontend@.service, bbb-html5-backend@.service and bbb-webrtc-sfu.service +check_cap_sys_nice() { + # if we don't detect a SETSCHEDULER error message in the status of the service, + # then there is nothing to be modified/customized + { systemctl status freeswitch | grep -q SETSCHEDULER; } || return + + # override /lib/systemd/system/freeswitch.service so that it does not use realtime scheduler + mkdir -p /etc/systemd/system/freeswitch.service.d + cat < /etc/systemd/system/freeswitch.service.d/override.conf +[Service] +IOSchedulingClass= +IOSchedulingPriority= +CPUSchedulingPolicy= +CPUSchedulingPriority= +HERE + + # override /usr/lib/systemd/system/bbb-html5-frontend@.service + mkdir -p /etc/systemd/system/bbb-html5-frontend@.service.d + cat < /etc/systemd/system/bbb-html5-frontend@.service.d/override.conf +[Service] +CPUSchedulingPolicy= +HERE + + # override /usr/lib/systemd/system/bbb-html5-backend@.service + mkdir -p /etc/systemd/system/bbb-html5-backend@.service.d + cat < /etc/systemd/system/bbb-html5-backend@.service.d/override.conf +[Service] +CPUSchedulingPolicy= +HERE + + # override /usr/lib/systemd/system/bbb-webrtc-sfu.service + mkdir -p /etc/systemd/system/bbb-webrtc-sfu.service.d + cat < /etc/systemd/system/bbb-webrtc-sfu.service.d/override.conf +[Service] +CPUSchedulingPolicy= +HERE + + systemctl daemon-reload +} + +# Check if running externally with internal/external IP addresses +check_nat() { + xmlstarlet edit --inplace --update '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_rtp_ip=")]/@data' --value "external_rtp_ip=$IP" /opt/freeswitch/conf/vars.xml + xmlstarlet edit --inplace --update '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_sip_ip=")]/@data' --value "external_sip_ip=$IP" /opt/freeswitch/conf/vars.xml + + if [ -n "$INTERNAL_IP" ]; then + xmlstarlet edit --inplace --update '//param[@name="ext-rtp-ip"]/@value' --value "\$\${external_rtp_ip}" /opt/freeswitch/conf/sip_profiles/external.xml + xmlstarlet edit --inplace --update '//param[@name="ext-sip-ip"]/@value' --value "\$\${external_sip_ip}" /opt/freeswitch/conf/sip_profiles/external.xml + + sed -i "s/$INTERNAL_IP:/$IP:/g" /usr/share/bigbluebutton/nginx/sip.nginx + ip addr add "$IP" dev lo + + # If dummy NIC is not in dummy-nic.service (or the file does not exist), update/create it + if ! grep -q "$IP" /lib/systemd/system/dummy-nic.service > /dev/null 2>&1; then + if [ -f /lib/systemd/system/dummy-nic.service ]; then + DAEMON_RELOAD=true; + fi + + cat > /lib/systemd/system/dummy-nic.service << HERE +[Unit] +Description=Configure dummy NIC for FreeSWITCH +Before=freeswitch.service +After=network.target + +[Service] +ExecStart=/sbin/ip addr add $IP dev lo + +[Install] +WantedBy=multi-user.target +HERE + + if [ "$DAEMON_RELOAD" == "true" ]; then + systemctl daemon-reload + systemctl restart dummy-nic + else + systemctl enable dummy-nic + systemctl start dummy-nic + fi + fi + fi +} + +check_LimitNOFILE() { + CPU=$(nproc --all) + + if [ "$CPU" -ge 8 ]; then + if [ -f /lib/systemd/system/bbb-web.service ]; then + # Let's create an override file to increase the number of LimitNOFILE + mkdir -p /etc/systemd/system/bbb-web.service.d/ + cat > /etc/systemd/system/bbb-web.service.d/override.conf << HERE +[Service] +LimitNOFILE=8192 +HERE + systemctl daemon-reload + fi + fi +} + +configure_HTML5() { + # Use Google's default STUN server + if [ -n "$INTERNAL_IP" ]; then + sed -i "s/[;]*externalIPv4=.*/externalIPv4=$IP/g" /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini + sed -i "s/[;]*iceTcp=.*/iceTcp=0/g" /etc/kurento/modules/kurento/WebRtcEndpoint.conf.ini + fi +} + +install_haproxy() { + need_pkg haproxy + if [ -n "$INTERNAL_IP" ]; then + TURN_IP="$INTERNAL_IP" + else + TURN_IP="$IP" + fi + HAPROXY_CFG=/etc/haproxy/haproxy.cfg + cat > "$HAPROXY_CFG" < /etc/haproxy/protocolmap + chmod 0644 /etc/haproxy/protocolmap + + # cert renewal + mkdir -p /etc/letsencrypt/renewal-hooks/deploy + cat > /etc/letsencrypt/renewal-hooks/deploy/haproxy < /etc/haproxy/certbundle.pem.new +chown root:haproxy /etc/haproxy/certbundle.pem.new +mv /etc/haproxy/certbundle.pem.new /etc/haproxy/certbundle.pem +systemctl reload haproxy +HERE + chmod 0755 /etc/letsencrypt/renewal-hooks/deploy/haproxy + /etc/letsencrypt/renewal-hooks/deploy/haproxy +} + +# This function will install the latest official version of greenlight-v3 and set it as the hosting Bigbluebutton default frontend or update greenlight-v3 if installed. +# Greenlight is a simple to use Bigbluebutton room manager that offers a set of features useful to online workloads especially virtual schooling. +# https://docs.bigbluebutton.org/greenlight/gl-overview.html +install_greenlight_v3(){ + # This function depends on the following files existing on their expected location so an eager check is done asserting that. + if [[ -z $SERVLET_DIR || ! -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties || ! -f $CR_TMPFILE || ! -f $BBB_WEB_ETC_CONFIG ]]; then + err "greenlight-v3 failed to install/update due to unmet requirements, have you followed the recommended steps to install Bigbluebutton?" + fi + + check_root + install_docker + + # Preparing and checking the enviroment. + say "preparing and checking the enviroment to install/update greelight-v3..." + + if [ ! -d $GL3_DIR ]; then + mkdir -p $GL3_DIR && say "created $GL3_DIR" + fi + + local GL_IMG_REPO=bigbluebutton/greenlight:v3 + + say "pulling latest $GL_IMG_REPO image..." + docker pull $GL_IMG_REPO + + if [ ! -s $GL3_DIR/docker-compose.yml ]; then + docker run --rm --entrypoint sh $GL_IMG_REPO -c 'cat docker-compose.yml' > $GL3_DIR/docker-compose.yml + + if [ ! -s $GL3_DIR/docker-compose.yml ]; then + err "failed to create docker compose file - is docker running?" + fi + + say "greenlight-v3 docker compose file was created" + fi + + # Configuring Greenlight v3. + say "checking the configuration of greenlight-v3..." + + local ROOT_URL BIGBLUEBUTTON_URL BIGBLUEBUTTON_SECRET + ROOT_URL=$(cat "$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties" "$CR_TMPFILE" "$BBB_WEB_ETC_CONFIG" | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | tail -n 1 ) + BIGBLUEBUTTON_URL=$ROOT_URL/bigbluebutton/ + BIGBLUEBUTTON_SECRET=$(cat "$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties" "$CR_TMPFILE" "$BBB_WEB_ETC_CONFIG" | grep -v '#' | grep ^securitySalt | tail -n 1 | cut -d= -f2) + + # Configuring Greenlight v3 docker-compose.yml (if configured no side effect will happen). + sed -i "s|^\([ \t-]*POSTGRES_PASSWORD\)\(=[ \t]*\)$|\1=$(openssl rand -hex 24)|g" $GL3_DIR/docker-compose.yml # Do not overwrite the value if not empty. + + local PGUSER=postgres # Postgres db user to be used by greenlight-v3. + local PGTXADDR=postgres:5432 # Postgres DB transport address (pair of (@ip:@port)). + local RSTXADDR=redis:6379 # Redis DB transport address (pair of (@ip:@port)). + local PGPASSWORD + PGPASSWORD=$(sed -ne "s/^\([ \t-]*POSTGRES_PASSWORD=\)\(.*\)$/\2/p" $GL3_DIR/docker-compose.yml) # Extract generated Postgres password. + + if [ -z "$PGPASSWORD" ]; then + err "failed to retrieve greenlight-v3 DB password - retry to resolve." + fi + + local DATABASE_URL_ROOT="postgres://$PGUSER:$PGPASSWORD@$PGTXADDR" + local REDIS_URL_ROOT="redis://$RSTXADDR" + + local PGDBNAME=greenlight-v3-production + local SECRET_KEY_BASE + SECRET_KEY_BASE=$(docker run --rm --entrypoint bundle $GL_IMG_REPO exec rails secret) + + if [ -z "$SECRET_KEY_BASE" ]; then + err "failed to generate greenlight-v3 secret key base - is docker running?" + fi + + if [ ! -s $GL3_DIR/.env ]; then + docker run --rm --entrypoint sh $GL_IMG_REPO -c 'cat sample.env' > $GL3_DIR/.env + + if [ ! -s $GL3_DIR/.env ]; then + err "failed to create greenlight-v3 .env file - is docker running?" + fi + + say "greenlight-v3 .env file was created" + fi + + # A note for future maintainers: + # The following configuration operations were made idempotent, meaning that playing these actions will have an outcome on the system (configure it) only once. + # Replaying these steps are a safe and an expected operation, this gurantees the seemless simple installation and upgrade of Greenlight v3. + # A simple change can impact that property and therefore render the upgrading functionnality unoperationnal or impact the running system. + + # Configuring Greenlight v3 .env file (if already configured this will only update the BBB endpoint and secret). + cp -v $GL3_DIR/.env $GL3_DIR/.env.old && say "old .env file can be retrieved at $GL3_DIR/.env.old" #Backup + + sed -i "s|^[# \t]*BIGBLUEBUTTON_ENDPOINT=.*|BIGBLUEBUTTON_ENDPOINT=$BIGBLUEBUTTON_URL|" $GL3_DIR/.env + sed -i "s|^[# \t]*BIGBLUEBUTTON_SECRET=.*|BIGBLUEBUTTON_SECRET=$BIGBLUEBUTTON_SECRET|" $GL3_DIR/.env + sed -i "s|^[# \t]*SECRET_KEY_BASE=[ \t]*$|SECRET_KEY_BASE=$SECRET_KEY_BASE|" $GL3_DIR/.env # Do not overwrite the value if not empty. + sed -i "s|^[# \t]*DATABASE_URL=[ \t]*$|DATABASE_URL=$DATABASE_URL_ROOT/$PGDBNAME|" $GL3_DIR/.env # Do not overwrite the value if not empty. + sed -i "s|^[# \t]*REDIS_URL=[ \t]*$|REDIS_URL=$REDIS_URL_ROOT/|" $GL3_DIR/.env # Do not overwrite the value if not empty. + + # Placing greenlight-v3 nginx file, this will enable greenlight-v3 as your Bigbluebutton frontend (bbb-fe). + cp -v $NGINX_FILES_DEST/greenlight-v3.nginx $NGINX_FILES_DEST/greenlight-v3.nginx.old && say "old greenlight-v3 nginx config can be retrieved at $NGINX_FILES_DEST/greenlight-v3.nginx.old" #Backup + docker run --rm --entrypoint sh $GL_IMG_REPO -c 'cat greenlight-v3.nginx' > $NGINX_FILES_DEST/greenlight-v3.nginx && say "added greenlight-v3 nginx file" + + # For backward compatibility with deployments running greenlight-v2 and haven't picked the patch from COMMIT (583f868). + # Move any nginx files from greenlight-v2 to the expected location. + if [ -s /etc/bigbluebutton/nginx/greenlight.nginx ]; then + mv /etc/bigbluebutton/nginx/greenlight.nginx $NGINX_FILES_DEST/greenlight.nginx && say "found /etc/bigbluebutton/nginx/greenlight.nginx and moved to expected location." + fi + + if [ -s /etc/bigbluebutton/nginx/greenlight-redirect.nginx ]; then + mv /etc/bigbluebutton/nginx/greenlight-redirect.nginx $NGINX_FILES_DEST/greenlight-redirect.nginx && say "found /etc/bigbluebutton/nginx/greenlight-redirect.nginx and moved to expected location." + fi + + if [ -z "$COTURN" ]; then + # When NGINX is the frontend reverse proxy, 'X-Forwarded-Proto' proxy header will dynamically match the $scheme of the received client request. + # In case a builtin turn server is installed, then HAPROXY is introduced and it becomes the frontend reverse proxy. + # NGINX will then act as a backend reverse proxy residing behind of it. + # HTTPS traffic from the client then is terminated at HAPROXY and plain HTTP traffic is proxied to NGINX. + # Therefore the 'X-Forwarded-Proto' proxy header needs to correctly indicate that HTTPS traffic was proxied in such scenario. + # shellcheck disable=SC2016 + sed -i '/X-Forwarded-Proto/s/$scheme/"https"/' $NGINX_FILES_DEST/greenlight-v3.nginx + + if [ -s $NGINX_FILES_DEST/greenlight.nginx ]; then + # For backward compatibility with deployments running greenlight-v2 and haven't picked the patch from PR (#579). + # shellcheck disable=SC2016 + sed -i '/X-Forwarded-Proto/s/$scheme/"https"/' $NGINX_FILES_DEST/greenlight.nginx + fi + fi + + # For backward compatibility, any already installed greenlight-v2 application will remain but it will not be the default frontend for BigBluebutton. + # To access greelight-v2 an explicit /b relative root needs to be indicated, otherwise greelight-v3 will be served by default. + + # Disabling the greenlight-v2 redirection rule. + disable_nginx_site greenlight-redirect.nginx && say "found greelight-v2 redirection rule and disabled it!" + + # Disabling the Bigbluebutton default Welcome page frontend. + disable_nginx_site default-fe.nginx && say "found default bbb-fe 'Welcome' and disabled it!" + + # Adding Keycloak + if [ -n "$INSTALL_KC" ]; then + # When attepmting to install/update Keycloak let us attempt to create the database to resolve any issues caused by postgres false negatives. + docker-compose -f $GL3_DIR/docker-compose.yml up -d postgres && say "started postgres" + wait_postgres_start + docker-compose -f $GL3_DIR/docker-compose.yml exec -T postgres psql -U postgres -c 'CREATE DATABASE keycloakdb;' + fi + + if ! grep -q 'keycloak:' $GL3_DIR/docker-compose.yml; then + # The following logic is expected to run only once when adding Keycloak. + # Keycloak isn't installed + if [ -n "$INSTALL_KC" ]; then + # Add Keycloak + say "Adding Keycloak..." + + docker-compose -f $GL3_DIR/docker-compose.yml down + cp -v $GL3_DIR/docker-compose.yml $GL3_DIR/docker-compose.base.yml # Persist working base compose file for admins as a Backup. + + docker run --rm --entrypoint sh $GL_IMG_REPO -c 'cat docker-compose.kc.yml' >> $GL3_DIR/docker-compose.yml + + if ! grep -q 'keycloak:' $GL3_DIR/docker-compose.yml; then + err "failed to add Keycloak service to greenlight-v3 compose file - is docker running?" + fi + say "added Keycloak to compose file" + + KCPASSWORD=$(openssl rand -hex 12) # Keycloak admin password. + sed -i "s|^\([ \t-]*KEYCLOAK_ADMIN_PASSWORD\)\(=[ \t]*\)$|\1=$KCPASSWORD|g" $GL3_DIR/docker-compose.yml # Do not overwrite the value if not empty. + sed -i "s|^\([ \t-]*KC_DB_PASSWORD\)\(=[ \t]*\)$|\1=$PGPASSWORD|g" $GL3_DIR/docker-compose.yml # Do not overwrite the value if not empty. + + # Updating Keycloak nginx file. + cp -v $NGINX_FILES_DEST/keycloak.nginx $NGINX_FILES_DEST/keycloak.nginx.old && say "old Keycloak nginx config can be retrieved at $NGINX_FILES_DEST/keycloak.nginx.old" + docker run --rm --entrypoint sh $GL_IMG_REPO -c 'cat keycloak.nginx' > $NGINX_FILES_DEST/keycloak.nginx && say "added Keycloak nginx file" + fi + + else + # Update Keycloak nginx file only. + cp -v $NGINX_FILES_DEST/keycloak.nginx $NGINX_FILES_DEST/keycloak.nginx.old && say "old Keycloak nginx config can be retrieved at $NGINX_FILES_DEST/keycloak.nginx.old" + docker run --rm --entrypoint sh $GL_IMG_REPO -c 'cat keycloak.nginx' > $NGINX_FILES_DEST/keycloak.nginx && say "added Keycloak nginx file" + fi + + if [ -z "$COTURN" ] && [ -s $NGINX_FILES_DEST/keycloak.nginx ]; then + # shellcheck disable=SC2016 + sed -i '/X-Forwarded-Proto/s/$scheme/"https"/' $NGINX_FILES_DEST/keycloak.nginx + fi + + # Update .env file catching new configurations: + if ! grep -q 'RELATIVE_URL_ROOT=' $GL3_DIR/.env; then + cat <> $GL3_DIR/.env +#RELATIVE_URL_ROOT=/gl + +HERE + fi + + if [ -n "$GL_PATH" ]; then + sed -i "s|^[# \t]*RELATIVE_URL_ROOT=.*|RELATIVE_URL_ROOT=$GL_PATH|" $GL3_DIR/.env + fi + + local GL_RELATIVE_URL_ROOT + GL_RELATIVE_URL_ROOT=$(sed -ne "s/^\([ \t]*RELATIVE_URL_ROOT=\)\(.*\)$/\2/p" $GL3_DIR/.env) # Extract relative URL root path. + say "Deploying Greenlight on the '${GL_RELATIVE_URL_ROOT:-$GL_DEFAULT_PATH}' path..." + + if [ -n "$GL_RELATIVE_URL_ROOT" ] && [ "$GL_RELATIVE_URL_ROOT" != "$GL_DEFAULT_PATH" ]; then + sed -i "s|^\([ \t]*location\)[ \t]*\(.*/cable\)[ \t]*\({\)$|\1 $GL_RELATIVE_URL_ROOT/cable \3|" $NGINX_FILES_DEST/greenlight-v3.nginx + sed -i "s|^\([ \t]*location\)[ \t]*\(@bbb-fe\)[ \t]*\({\)$|\1 $GL_RELATIVE_URL_ROOT \3|" $NGINX_FILES_DEST/greenlight-v3.nginx + fi + + nginx -qt || err 'greenlight-v3 failed to install/update due to nginx tests failing to pass - if using the official image then please contact the maintainers.' + nginx -qs reload && say 'greenlight-v3 was successfully configured' + + # Eager pulling images. + say "pulling latest greenlight-v3 services images..." + docker-compose -f $GL3_DIR/docker-compose.yml pull + + if check_container_running greenlight-v3; then + # Restarting Greenlight-v3 services after updates. + say "greenlight-v3 is updating..." + say "shutting down greenlight-v3..." + docker-compose -f $GL3_DIR/docker-compose.yml down + fi + + say "starting greenlight-v3..." + docker-compose -f $GL3_DIR/docker-compose.yml up -d + sleep 5 + say "greenlight-v3 is now installed and accessible on: https://$HOST${GL_RELATIVE_URL_ROOT:-$GL_DEFAULT_PATH}" + say "To create Greenlight administrator account, see: https://docs.bigbluebutton.org/greenlight/v3/install#creating-an-admin-account" + + + if grep -q 'keycloak:' $GL3_DIR/docker-compose.yml; then + say "Keycloak is installed, up to date and accessible for configuration on: https://$HOST/keycloak/" + if [ -n "$KCPASSWORD" ];then + say "Use the following credentials when accessing the admin console:" + say " admin" + say " $KCPASSWORD" + fi + + say "To complete the configuration of Keycloak, see: https://docs.bigbluebutton.org/greenlight/v3/external-authentication#configuring-keycloak" + fi + + return 0; +} + +# This function will install and update to the latest official version of BigBlueButton LTI framework. +# BigBlueButton LTI tools framewrok provides a simple interface to integrate Bigbluebutton features into any LTI certified LMS. +install_lti(){ + # This function depends on the following files existing on their expected location so an eager check is done asserting that. + if [[ -z $SERVLET_DIR || ! -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties || ! -f $CR_TMPFILE || ! -f $BBB_WEB_ETC_CONFIG ]]; then + err "BBB LTI framework failed to install/update due to unmet requirements, have you followed the recommended steps to install Bigbluebutton?" + fi + + check_root + install_docker + + # Preparing and checking the enviroment. + say "preparing and checking the enviroment to install/update BBB LTI framework..." + + if [ ! -d $LTI_DIR ]; then + mkdir -p $LTI_DIR && say "created $LTI_DIR" + fi + + BROKER_IMG_REPO=bigbluebutton/bbb-lti-broker + + # Installing/Updating the LTI broker. + say "pulling latest $BROKER_IMG_REPO image..." + docker pull $BROKER_IMG_REPO + + if [ ! -s $LTI_DIR/docker-compose.yml ]; then + docker run --rm --entrypoint sh $BROKER_IMG_REPO -c 'cat docker-compose.yml' > $LTI_DIR/docker-compose.yml + + if [ ! -s $LTI_DIR/docker-compose.yml ]; then + err "failed to create docker compose file - is docker running?" + fi + + say "LTI framework docker compose file was created" + fi + + # Configuring BBB LTI. + say "prepping the configuration of BBB LTI framework..." + + local ROOT_URL + ROOT_URL=$(cat "$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties" "$CR_TMPFILE" "$BBB_WEB_ETC_CONFIG" | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | tail -n 1 ) + BIGBLUEBUTTON_URL=$ROOT_URL/bigbluebutton/ + BIGBLUEBUTTON_SECRET=$(cat "$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties" "$CR_TMPFILE" "$BBB_WEB_ETC_CONFIG" | grep -v '#' | grep ^securitySalt | tail -n 1 | cut -d= -f2) + + # Configuring BBB LTI docker-compose.yml (if configured no side effect will happen). + sed -i "s|^\([ \t-]*POSTGRES_PASSWORD\)\(=[ \t]*\)$|\1=$(openssl rand -hex 24)|g" $LTI_DIR/docker-compose.yml # Do not overwrite the value if not empty. + + say "installing/updating BBB LTI framework Broker and applications..." + local PGUSER=postgres # Postgres db user to be used by bbb-lti. + local PGTXADDR=postgres:5432 # Postgres DB transport address (pair of (@ip:@port)). + local RSTXADDR=redis:6379 # Redis DB transport address (pair of (@ip:@port)). + local PGPASSWORD + PGPASSWORD=$(sed -ne "s/^\([ \t-]*POSTGRES_PASSWORD=\)\(.*\)$/\2/p" $LTI_DIR/docker-compose.yml) # Extract generated Postgres password. + + if [ -z "$PGPASSWORD" ]; then + err "failed to retrieve the LTI framework DB password - retry to resolve." + fi + + DATABASE_URL_ROOT="postgres://$PGUSER:$PGPASSWORD@$PGTXADDR" # Must be global - expected by install_lti_tool. + REDIS_URL_ROOT="redis://$RSTXADDR" # Must be global - expected by install_lti_tool. + BROKER_RELATIVE_URL_ROOT=lti # Must be global - expected by install_lti_tools, will be dynamic in the future. + APPS_RELATIVE_URL_ROOT=apps # Must be global - expected by install_lti_tools, will be dynamic in the future. + + install_lti_tools || err "BBB LTI framework failed to install/update tools!" + + # Updating BBB LTI framework images. + say "pulling latest BBB LTI framework services images..." + docker-compose -f $LTI_DIR/docker-compose.yml pull + + if check_container_running broker; then + # Restarting BBB LTI framework services after updates. + say "BBB LTI framework is updating..." + say "shutting down BBB LTI framework services..." + docker-compose -f $LTI_DIR/docker-compose.yml down + fi + + say "starting BBB LTI framework services..." + docker-compose -f $LTI_DIR/docker-compose.yml up -d + + wait_lti_broker_start + + local LTI_KEY=${LTI_CREDS[0]} + local LTI_SECRET=${LTI_CREDS[1]} + + say "Setting/updating LTI credentials for LTI KEY: $LTI_KEY..." + + if ! docker-compose -f $LTI_DIR/docker-compose.yml exec -T broker bundle exec rake db:keys:update["$LTI_KEY","$LTI_SECRET"] \ + 2> /dev/null 1>&2; then + docker-compose -f $LTI_DIR/docker-compose.yml exec -T broker bundle exec rake db:keys:add["$LTI_KEY","$LTI_SECRET"] \ + 2> /dev/null 1>&2 || err "failed to set LTI credentials $LTI_KEY:$LTI_SECRET." + + say "New LTI credentials for LTI KEY: $LTI_KEY were added!" + else + say "LTI credentials for LTI KEY: $LTI_KEY were updated!" + fi + + say "BBB LTI framework is installed, up to date and accessible on: https://$HOST/$BROKER_RELATIVE_URL_ROOT" + say "You can refer to your LMS documentation on how to add a LTI application." + say " The LTI launch links for all of the installed BBB LTI framework applications can be found in https://$HOST/$BROKER_RELATIVE_URL_ROOT." + + return 0; +} + +install_lti_tools() { + # BBB LTI FRAMEWORK COMPONENTS + if [[ -z $BROKER_IMG_REPO || -z $DATABASE_URL_ROOT || -z $REDIS_URL_ROOT || -z $BROKER_RELATIVE_URL_ROOT || -z $APPS_RELATIVE_URL_ROOT ]]; then + err "BBB LTI tools installation/update failed due to unmet requirements!" + fi + + # BBB LTI BROKER setup ↓ + say "installing/updating BBB LTI framework broker..." + LTI_APP_DIR=$LTI_DIR/broker APP_IMG_REPO=$BROKER_IMG_REPO LOG_NAME='LTI Broker' RELATIVE_URL_ROOT=$BROKER_RELATIVE_URL_ROOT \ + NGINX_NAME=bbb-lti-broker PGDBNAME=bbb_lti_broker install_lti_tool || return 1 + + say "BBB LTI Broker is installed, configured and up to date!" + # BBB LTI TOOLS setup ↓ + say "installing/updating BBB LTI framework apps..." + LTI_APP_DIR=$LTI_DIR/rooms APP_IMG_REPO=bigbluebutton/bbb-app-rooms LOG_NAME='LTI Rooms' RELATIVE_URL_ROOT=$APPS_RELATIVE_URL_ROOT \ + NGINX_NAME=bbb-app-rooms PGDBNAME=bbb_app_rooms install_lti_tool || return 1 + + say "All BBB LTI apps are installed, configured and up to date!" + # BBB LTI TOOLS registration ↓ + register_lti_tools || return 1 + + say "All BBB LTI apps are registered to the LTI framework!" + + return 0; +} + +install_lti_tool() { + # Preparing and checking the enviroment. + if [[ -z $LTI_APP_DIR || -z $APP_IMG_REPO || -z $LOG_NAME || -z $RELATIVE_URL_ROOT || -z $NGINX_NAME || -z $PGDBNAME ]]; then + err "$LOG_NAME installation/update failed due to unmet requirements!" + fi + + say "preparing and checking the enviroment to install/update $LOG_NAME..." + + if [ ! -d "$LTI_APP_DIR" ]; then + mkdir -p "$LTI_APP_DIR" && say "created $LTI_APP_DIR" + fi + + # Installing/Updating the LTI broker. + say "pulling latest $APP_IMG_REPO image..." + docker pull "$APP_IMG_REPO" + + # Configuring BBB LTI. + say "checking/updating the configuration of $LOG_NAME..." + + local SECRET_KEY_BASE + SECRET_KEY_BASE=$(docker run --rm --entrypoint bundle "$APP_IMG_REPO" exec rake secret) + + if [ -z "$SECRET_KEY_BASE" ]; then + err "failed to generate $LOG_NAME secret key base - is docker running?" + fi + + if [ ! -s "$LTI_APP_DIR"/.env ]; then + docker run --rm --entrypoint sh "$APP_IMG_REPO" -c 'cat dotenv' > "$LTI_APP_DIR"/.env + + if [ ! -s "$LTI_APP_DIR"/.env ]; then + err "failed to create $LOG_NAME .env file - is docker running?" + fi + + say "$LOG_NAME .env file was created" + fi + + # A note for future maintainers: + # The following configuration operations were made idempotent, meaning that playing these actions will have an outcome on the system (configure it) only once. + # Replaying these steps are a safe and an expected operation, this gurantees the seemless simple installation and upgrade of BBB LTI framework. + # A simple change can impact that property and therefore render the upgrading functionnality unoperationnal or impact the running system. + + # Configuring BBB LTI .env file (if already configured this will only update some expected or safe to change variables). + cp -v "$LTI_APP_DIR"/.env "$LTI_APP_DIR"/.env.old && say "old $LOG_NAME .env file can be retrieved at $LTI_APP_DIR/.env.old" #Backup + + sed -i "s|^[# \t]*SECRET_KEY_BASE=[ \t]*$|SECRET_KEY_BASE=$SECRET_KEY_BASE|" "$LTI_APP_DIR"/.env # Do not overwrite the value if not empty. + sed -i "s|^[# \t]*BIGBLUEBUTTON_ENDPOINT=.*|BIGBLUEBUTTON_ENDPOINT=$BIGBLUEBUTTON_URL|" "$LTI_APP_DIR"/.env + sed -i "s|^[# \t]*BIGBLUEBUTTON_SECRET=.*|BIGBLUEBUTTON_SECRET=$BIGBLUEBUTTON_SECRET|" "$LTI_APP_DIR"/.env + sed -i "s|^[# \t]*URL_HOST=.*$|URL_HOST=$HOST|" "$LTI_APP_DIR"/.env + sed -i "s|^[# \t]*RELATIVE_URL_ROOT=.*$|RELATIVE_URL_ROOT=$RELATIVE_URL_ROOT|" "$LTI_APP_DIR"/.env + sed -i "s|^[# \t]*DATABASE_URL=.*myuser:mypass@localhost.*$|DATABASE_URL=$DATABASE_URL_ROOT/$PGDBNAME|" "$LTI_APP_DIR"/.env # Do not overwrite the value if not a default. + sed -i "s|^[# \t]*DATABASE_URL=[ \t]*$|DATABASE_URL=$DATABASE_URL_ROOT/$PGDBNAME|" "$LTI_APP_DIR"/.env # Do not overwrite the value if not empty. + sed -i "s|^[# \t]*REDIS_URL=.*myuser:mypass@localhost.*$|REDIS_URL=$REDIS_URL_ROOT/|" "$LTI_APP_DIR"/.env # Do not overwrite the value if not a default. + sed -i "s|^[# \t]*REDIS_URL=[ \t]*$|REDIS_URL=$REDIS_URL_ROOT/|" "$LTI_APP_DIR"/.env # Do not overwrite the value if not empty. + sed -i "s|^[# \t]*OMNIAUTH_BBBLTIBROKER_SITE=.*|OMNIAUTH_BBBLTIBROKER_SITE=https://$HOST|" "$LTI_APP_DIR"/.env + sed -i "s|^[# \t]*OMNIAUTH_BBBLTIBROKER_ROOT=.*|OMNIAUTH_BBBLTIBROKER_ROOT=$BROKER_RELATIVE_URL_ROOT|" "$LTI_APP_DIR"/.env + sed -i "s|^[# \t]*OMNIAUTH_BBBLTIBROKER_KEY=.*|OMNIAUTH_BBBLTIBROKER_KEY=$(openssl rand -hex 24)|" "$LTI_APP_DIR"/.env # Credentials are rotated on update. + sed -i "s|^[# \t]*OMNIAUTH_BBBLTIBROKER_SECRET=.*|OMNIAUTH_BBBLTIBROKER_SECRET=$(openssl rand -hex 24)|" "$LTI_APP_DIR"/.env # Credentials are rotated on update. + + # Placing application nginx file. + say "configuring nginx for $LOG_NAME..." + + cp -v $NGINX_FILES_DEST/"$NGINX_NAME.nginx" $NGINX_FILES_DEST/"$NGINX_NAME.nginx.old" && say "old $LOG_NAME nginx config can be retrieved at $NGINX_FILES_DEST/$NGINX_NAME.nginx.old" # Backup. + docker run --rm --entrypoint sh "$APP_IMG_REPO" -c 'cat config.nginx' > $NGINX_FILES_DEST/"$NGINX_NAME.nginx" && say "added $LOG_NAME nginx file" + + if [ -z "$COTURN" ]; then + # When NGINX is the frontend reverse proxy, 'X-Forwarded-Proto' proxy header will dynamically match the $scheme of the received client request. + # In case a builtin turn server is installed, then HAPROXY is introduced and it becomes the frontend reverse proxy. + # NGINX will then act as a backend reverse proxy residing behind of it. + # HTTPS traffic from the client then is terminated at HAPROXY and plain HTTP traffic is proxied to NGINX. + # Therefore the 'X-Forwarded-Proto' proxy header needs to correctly indicate that HTTPS traffic was proxied in such scenario. + # shellcheck disable=SC2016 + sed -i '/X-Forwarded-Proto/s/$scheme/"https"/' $NGINX_FILES_DEST/"$NGINX_NAME.nginx" + fi + + nginx -qt || return 1 + nginx -qs reload && say "$LOG_NAME was successfully configured" + + return 0; +} + + +register_lti_tools() { + # Registering/Updating LTI apps. + wait_lti_broker_start + + # BBB LTI TOOLS registration ↓ + say "Registering All BBB LTI framework apps..." + LTI_APP_DIR=$LTI_DIR/rooms LOG_NAME='LTI Rooms' APP_NAME=rooms register_lti_tool || return 1 + + return 0; +} + +wait_lti_broker_start() { + say "Waiting for the LTI broker to start..." + docker-compose -f $LTI_DIR/docker-compose.yml up -d broker || err "failed to register LTI framework apps due to LTI broker failling to start - retry to resolve" + + local tries=0 + while ! docker-compose -f $LTI_DIR/docker-compose.yml exec -T broker bundle exec rake db:version 2> /dev/null 1>&2; do + echo -n . + sleep 3 + if (( ++tries == 3 )); then + err "failed to register LTI framework apps due to reaching LTI broker waiting timeout - retry to resolve" + fi + done + + sleep 3 # Optimistically wait for LTI Broker to become ready. + + say "LTI broker is ready!" + + return 0; +} + +wait_postgres_start() { + say "Waiting for the Postgres DB to start..." + docker-compose -f $GL3_DIR/docker-compose.yml up -d postgres || err "failed to start Postgres service - retry to resolve" + + local tries=0 + while ! docker-compose -f $GL3_DIR/docker-compose.yml exec -T postgres pg_isready 2> /dev/null 1>&2; do + echo -n . + sleep 3 + if (( ++tries == 3 )); then + err "failed to start Postgres due to reaching waiting timeout - retry to resolve" + fi + done + + say "Postgres is ready!" + + return 0; +} + +register_lti_tool() { + # Preparing and checking the enviroment. + if [[ -z $LTI_APP_DIR || -z $APP_NAME || -z $LOG_NAME ]]; then + err "$LOG_NAME registration failed due to unmet requirements!" + fi + + say "Registering $LOG_NAME..." + + local OAUTH_KEY OAUTH_SECRET RELATIVE_URL_ROOT + OAUTH_KEY=$(sed -ne "s/^\([ \t]*OMNIAUTH_BBBLTIBROKER_KEY=\)\(.*\)$/\2/p" "$LTI_APP_DIR"/.env) # Extract the LTI app OAUTH key. + OAUTH_SECRET=$(sed -ne "s/^\([ \t]*OMNIAUTH_BBBLTIBROKER_SECRET=\)\(.*\)$/\2/p" "$LTI_APP_DIR"/.env) # Extract LTI app OAUTH secret. + RELATIVE_URL_ROOT=$(sed -ne "s/^\([ \t]*RELATIVE_URL_ROOT=\)\(.*\)$/\2/p" "$LTI_APP_DIR"/.env) # Extract LTI app realtive URL root path. + + if [ -z "$OAUTH_KEY" ] || [ -z "$OAUTH_SECRET" ] ; then + err "failed to retrieve the $LOG_NAME OAUTH credentials - retry to resolve." + fi + + local CALLBACK_URI_SUFFIX=auth/bbbltibroker/callback + local CALLBACK_URI=https://$HOST/$RELATIVE_URL_ROOT/$APP_NAME/$CALLBACK_URI_SUFFIX + + if ! check_container_running broker; then + err "failed to register $LOG_NAME due to LTI broker not running - retry to resolve." + fi + + if ! docker-compose -f $LTI_DIR/docker-compose.yml exec -T broker bundle exec rake db:apps:show["$APP_NAME"] \ + 2> /dev/null 1>&2; then + docker-compose -f $LTI_DIR/docker-compose.yml exec -T broker bundle exec rake db:apps:add["$APP_NAME","$CALLBACK_URI","$OAUTH_KEY","$OAUTH_SECRET"] \ + 2> /dev/null 1>&2 && say "$LOG_NAME was successfully registered." + else + docker-compose -f $LTI_DIR/docker-compose.yml exec -T broker bundle exec rake db:apps:update["$APP_NAME","$CALLBACK_URI","$OAUTH_KEY","$OAUTH_SECRET"] \ + 2> /dev/null 1>&2 && say "$LOG_NAME was successfully updated." + fi + + return 0; +} + +# Given a container name as $1, this function will check if there's a match for that name in the list of running docker containers on the system. +# The result will be binded to $?. +check_container_running() { + docker ps | grep -q "$1" || return 1; + + return 0; +} + +# Given a filename as $1, if file exists under $sites_dir then the file will be suffixed with '.disabled'. +# sites_dir points to Bigbluebutton nginx sites, when suffixed with '.disabled' nginx will not include the site on reload/restart thus disabling it. +disable_nginx_site() { + local site_path="$1" + + if [ -z "$site_path" ]; then + return 1; + fi + + if [ -f $NGINX_FILES_DEST/"$site_path" ]; then + mv $NGINX_FILES_DEST/"$site_path" $NGINX_FILES_DEST/"$site_path.disabled" && return 0; + fi + + return 1; +} + +install_docker() { + need_pkg apt-transport-https ca-certificates curl gnupg-agent software-properties-common openssl + + # Install Docker + if ! apt-key list | grep -q Docker; then + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - + fi + + if ! dpkg -l | grep -q docker-ce; then + echo "deb [ arch=amd64 ] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list + + add-apt-repository --remove\ + "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) \ + stable" + + apt-get update + need_pkg docker-ce docker-ce-cli containerd.io + fi + if ! which docker; then err "Docker did not install"; fi + + # Purge older docker compose if exists. + if dpkg -l | grep -q docker-compose; then + apt-get purge -y docker-compose + fi + + if [ ! -x /usr/local/bin/docker-compose ]; then + curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + fi + + # Ensuring docker is running + if ! docker version > /dev/null ; then + # Attempting to auto resolve by restarting docker socket and engine. + systemctl restart docker.socket docker.service + sleep 5 + + docker version > /dev/null || err "docker is failing to restart, something is wrong retry to resolve - exiting" + say "docker is running!" + fi + +} + + +install_ssl() { + if ! grep -q "$HOST" /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml; then + bbb-conf --setip "$HOST" + fi + + mkdir -p /etc/nginx/ssl + + if [ -z "$PROVIDED_CERTIFICATE" ]; then + add-apt-repository universe + apt-get update + need_pkg certbot + + if [[ -f "/etc/letsencrypt/live/$HOST/fullchain.pem" ]] && [[ -f "/etc/letsencrypt/renewal/$HOST.conf" ]] \ + && ! grep -q '/var/www/bigbluebutton-default/assets' "/etc/letsencrypt/renewal/$HOST.conf"; then + sed -i -e 's#/var/www/bigbluebutton-default#/var/www/bigbluebutton-default/assets#' "/etc/letsencrypt/renewal/$HOST.conf" + if ! certbot renew; then + err "Let's Encrypt SSL renewal request for $HOST did not succeed - exiting" + fi + fi + fi + + if [ ! -f "/etc/letsencrypt/live/$HOST/fullchain.pem" ]; then + rm -f /tmp/bigbluebutton.bak + if ! grep -q "$HOST" /etc/nginx/sites-available/bigbluebutton; then # make sure we can do the challenge + if [ -f /etc/nginx/sites-available/bigbluebutton ]; then + cp /etc/nginx/sites-available/bigbluebutton /tmp/bigbluebutton.bak + fi + cat < /etc/nginx/sites-available/bigbluebutton +server_tokens off; +server { + listen 80; + listen [::]:80; + server_name $HOST; + + access_log /var/log/nginx/bigbluebutton.access.log; + + # BigBlueButton landing page. + location / { + root /var/www/bigbluebutton-default/assets; + try_files \$uri @bbb-fe; + } +} +HERE + systemctl restart nginx + fi + + if [ -z "$PROVIDED_CERTIFICATE" ]; then + if ! certbot --email "$EMAIL" --agree-tos --rsa-key-size 4096 -w /var/www/bigbluebutton-default/assets/ \ + -d "$HOST" --deploy-hook "systemctl reload nginx" "${LETS_ENCRYPT_OPTIONS[@]}" certonly; then + systemctl restart nginx + err "Let's Encrypt SSL request for $HOST did not succeed - exiting" + fi + else + # Place your fullchain.pem and privkey.pem files in /local/certs/ and bbb-install.sh will deal with the rest. + mkdir -p "/etc/letsencrypt/live/$HOST/" + ln -s /local/certs/fullchain.pem "/etc/letsencrypt/live/$HOST/fullchain.pem" + ln -s /local/certs/privkey.pem "/etc/letsencrypt/live/$HOST/privkey.pem" + fi + fi + + if [ -z "$COTURN" ]; then + # No COTURN credentials provided, setup a local TURN server + cat < /etc/nginx/sites-available/bigbluebutton +server_tokens off; + +server { + listen 80; + listen [::]:80; + server_name $HOST; + + location ^~ / { + return 301 https://\$server_name\$request_uri; #redirect HTTP to HTTPS + } + + location ^~ /.well-known/acme-challenge/ { + allow all; + default_type "text/plain"; + root /var/www/bigbluebutton-default/assets; + } + + location = /.well-known/acme-challenge/ { + return 404; + } +} + +set_real_ip_from 127.0.0.1; +real_ip_header proxy_protocol; +real_ip_recursive on; +server { + # this double listenting is intended. We terminate SSL on haproxy. HTTP2 is a + # binary protocol. haproxy has to decide which protocol is spoken. This is + # negotiated by ALPN. + # + # Depending on the ALPN value traffic is redirected to either port 82 (HTTP2, + # ALPN value h2) or 81 (HTTP 1.0 or HTTP 1.1, ALPN value http/1.1 or no value) + + listen 127.0.0.1:82 http2 proxy_protocol; + listen [::1]:82 http2; + listen 127.0.0.1:81 proxy_protocol; + listen [::1]:81; + server_name $HOST; + + # nginx does not know its external port/protocol behind haproxy, so use relative redirects. + absolute_redirect off; + + # HSTS (uncomment to enable) + #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + access_log /var/log/nginx/bigbluebutton.access.log; + + # This variable is used instead of \$scheme by bigbluebutton nginx include + # files, so \$scheme can be overridden in reverse-proxy configurations. + set \$real_scheme "https"; + + # BigBlueButton landing page. + location / { + root /var/www/bigbluebutton-default/assets; + try_files \$uri @bbb-fe; + } + + # Include specific rules for record and playback + include /etc/bigbluebutton/nginx/*.nginx; +} +HERE + else + # We've been given COTURN credentials, so HAPROXY is not installed for local TURN server + cat < /etc/nginx/sites-available/bigbluebutton +server_tokens off; + +server { + listen 80; + listen [::]:80; + server_name $HOST; + + location ^~ / { + return 301 https://\$server_name\$request_uri; #redirect HTTP to HTTPS + } + + location ^~ /.well-known/acme-challenge/ { + allow all; + default_type "text/plain"; + root /var/www/bigbluebutton-default/assets; + } + + location = /.well-known/acme-challenge/ { + return 404; + } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name $HOST; + + ssl_certificate /etc/letsencrypt/live/$HOST/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/$HOST/privkey.pem; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_dhparam /etc/nginx/ssl/ffdhe2048.pem; + + # HSTS (comment out to enable) + #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + access_log /var/log/nginx/bigbluebutton.access.log; + + # This variable is used instead of \$scheme by bigbluebutton nginx include + # files, so \$scheme can be overridden in reverse-proxy configurations. + set \$real_scheme \$scheme; + + # BigBlueButton landing page. + location / { + root /var/www/bigbluebutton-default/assets; + try_files \$uri @bbb-fe; + } + + # Include specific rules for record and playback + include /etc/bigbluebutton/nginx/*.nginx; +} +HERE + + if [[ ! -f /etc/nginx/ssl/ffdhe2048.pem ]]; then + cat >/etc/nginx/ssl/ffdhe2048.pem <<"HERE" +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== +-----END DH PARAMETERS----- +HERE + fi + if [[ -f /etc/nginx/ssl/dhp-4096.pem ]]; then + rm /etc/nginx/ssl/dhp-4096.pem + fi + fi +# Create the default Welcome page Bigbluebutton Frontend unless it exists. +if [[ ! -f /usr/share/bigbluebutton/nginx/default-fe.nginx && ! -f /usr/share/bigbluebutton/nginx/default-fe.nginx.disabled ]]; then +cat < /usr/share/bigbluebutton/nginx/default-fe.nginx +# Default Bigbluebutton Landing page. + +location @bbb-fe { + index index.html index.htm; + expires 1m; +} + +HERE +fi + + # Configure rest of BigBlueButton Configuration for SSL + xmlstarlet edit --inplace --update '//param[@name="wss-binding"]/@value' --value "$IP:7443" /opt/freeswitch/conf/sip_profiles/external.xml + + # shellcheck disable=SC1091 + eval "$(source /etc/bigbluebutton/bigbluebutton-release && declare -p BIGBLUEBUTTON_RELEASE)" + if [[ $BIGBLUEBUTTON_RELEASE == 2.2.* ]] && [[ ${BIGBLUEBUTTON_RELEASE#*.*.} -lt 29 ]]; then + sed -i "s/proxy_pass .*/proxy_pass https:\/\/$IP:7443;/g" /usr/share/bigbluebutton/nginx/sip.nginx + else + # Use nginx as proxy for WSS -> WS (see https://github.com/bigbluebutton/bigbluebutton/issues/9667) + yq w -i /usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml public.media.sipjsHackViaWs true + sed -i "s/proxy_pass .*/proxy_pass http:\/\/$IP:5066;/g" /usr/share/bigbluebutton/nginx/sip.nginx + xmlstarlet edit --inplace --update '//param[@name="ws-binding"]/@value' --value "$IP:5066" /opt/freeswitch/conf/sip_profiles/external.xml + fi + + sed -i 's/^bigbluebutton.web.serverURL=http:/bigbluebutton.web.serverURL=https:/g' "$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties" + if [ -f "$BBB_WEB_ETC_CONFIG" ]; then + sed -i 's/^bigbluebutton.web.serverURL=http:/bigbluebutton.web.serverURL=https:/g' "$BBB_WEB_ETC_CONFIG" + fi + + yq w -i /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml playback_protocol https + chmod 644 /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml + + # Update Greenlight (if installed) to use SSL + for gl_dir in ~/greenlight $GL3_DIR;do + if [ -f "$gl_dir"/.env ]; then + if ! grep ^BIGBLUEBUTTON_ENDPOINT "$gl_dir"/.env | grep -q https; then + if [[ -z $BIGBLUEBUTTON_URL ]]; then + BIGBLUEBUTTON_URL=$(cat "$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties" "$CR_TMPFILE" "$BBB_WEB_ETC_CONFIG" | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | tail -n 1 )/bigbluebutton/ + fi + + sed -i "s|.*BIGBLUEBUTTON_ENDPOINT=.*|BIGBLUEBUTTON_ENDPOINT=$BIGBLUEBUTTON_URL|" ~/greenlight/.env + docker-compose -f "$gl_dir"/docker-compose.yml down + docker-compose -f "$gl_dir"/docker-compose.yml up -d + fi + fi + done + + TARGET=/usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml + if [ -f $TARGET ]; then + if grep -q kurentoIp $TARGET; then + # 2.0 + yq w -i $TARGET kurentoIp "$IP" + else + # 2.2 + yq w -i $TARGET kurento[0].ip "$IP" + yq w -i $TARGET freeswitch.ip "$IP" + + if [[ $BIGBLUEBUTTON_RELEASE == 2.2.* ]] && [[ ${BIGBLUEBUTTON_RELEASE#*.*.} -lt 29 ]]; then + if [ -n "$INTERNAL_IP" ]; then + yq w -i $TARGET freeswitch.sip_ip "$INTERNAL_IP" + else + yq w -i $TARGET freeswitch.sip_ip "$IP" + fi + else + # Use nginx as proxy for WSS -> WS (see https://github.com/bigbluebutton/bigbluebutton/issues/9667) + yq w -i $TARGET freeswitch.sip_ip "$IP" + fi + fi + chown bigbluebutton:bigbluebutton $TARGET + chmod 644 $TARGET + fi + + mkdir -p /etc/bigbluebutton/bbb-webrtc-sfu + TARGET=/etc/bigbluebutton/bbb-webrtc-sfu/production.yml + touch $TARGET + + # Configure mediasoup IPs, reference: https://raw.githubusercontent.com/bigbluebutton/bbb-webrtc-sfu/v2.7.2/docs/mediasoup.md + # mediasoup IPs: WebRTC + yq w -i "$TARGET" mediasoup.webrtc.listenIps[0].ip "0.0.0.0" + yq w -i "$TARGET" mediasoup.webrtc.listenIps[0].announcedIp "$IP" + + # mediasoup IPs: plain RTP (internal comms, FS <-> mediasoup) + yq w -i "$TARGET" mediasoup.plainRtp.listenIp.ip "0.0.0.0" + yq w -i "$TARGET" mediasoup.plainRtp.listenIp.announcedIp "$IP" + + systemctl reload nginx +} + +configure_coturn() { + TURN_XML=/etc/bigbluebutton/turn-stun-servers.xml + + if [ -z "$COTURN" ]; then + # the user didn't pass '-c', so use the local TURN server's host + COTURN_HOST=$HOST + fi + + cat < $TURN_XML + + + + + + + + + + + + + + + + + + + + + + + + + + + + +HERE + + chown root:bigbluebutton "$TURN_XML" + chmod 640 "$TURN_XML" +} + + +install_coturn() { + apt-get update + apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" dist-upgrade + + need_pkg software-properties-common certbot + + need_pkg coturn + + if [ -n "$INTERNAL_IP" ]; then + SECOND_ALLOWED_PEER_IP="allowed-peer-ip=$INTERNAL_IP" + fi + # check if this is still the default coturn config file. Replace it in this case. + if grep "#static-auth-secret=north" /etc/turnserver.conf > /dev/null ; then + COTURN_SECRET="$(openssl rand -base64 32)" + cat < /etc/turnserver.conf +listening-port=3478 + +listening-ip=${INTERNAL_IP:-$IP} +relay-ip=${INTERNAL_IP:-$IP} + +min-port=32769 +max-port=65535 +verbose + +fingerprint +lt-cred-mech +use-auth-secret +static-auth-secret=$COTURN_SECRET +realm=$HOST + +keep-address-family + +no-cli +no-tlsv1 +no-tlsv1_1 + +# Block connections to IP ranges which shouldn't be reachable +no-loopback-peers +no-multicast-peers + + +# we only need to allow peer connections from the machine itself (from mediasoup or freeswitch). +denied-peer-ip=0.0.0.0-255.255.255.255 +denied-peer-ip=::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +allowed-peer-ip=$IP +$SECOND_ALLOWED_PEER_IP + +HERE + chown root:turnserver /etc/turnserver.conf + chmod 640 /etc/turnserver.conf + else + # fetch secret for later setting up in BBB turn config + COTURN_SECRET="$(grep static-auth-secret= /etc/turnserver.conf |cut -d = -f 2-)" + fi + + mkdir -p /var/log/turnserver + chown turnserver:turnserver /var/log/turnserver + + cat < /etc/logrotate.d/coturn +/var/log/turnserver/*.log +{ + rotate 7 + daily + missingok + notifempty + compress + postrotate + /bin/systemctl kill -s HUP coturn.service + endscript +} +HERE + + # Eanble coturn to bind to port 443 with CAP_NET_BIND_SERVICE + mkdir -p /etc/systemd/system/coturn.service.d + rm -rf /etc/systemd/system/coturn.service.d/ansible.conf # Remove previous file + cat > /etc/systemd/system/coturn.service.d/override.conf < /etc/bigbluebutton/bbb-conf/apply-config.sh << HERE +#!/bin/bash + +# Pull in the helper functions for configuring BigBlueButton +source /etc/bigbluebutton/bbb-conf/apply-lib.sh + +enableUFWRules +HERE + chmod +x /etc/bigbluebutton/bbb-conf/apply-config.sh + fi +} + +main "$@" || exit 1 + diff --git a/roles/bbb_install/files/blankDefault.pdf b/roles/bbb_install/files/blankDefault.pdf new file mode 100644 index 0000000000000000000000000000000000000000..02e8b9cc06ca82dac413c149503c14ca45c3f125 GIT binary patch literal 1897 zcmcIl%Wm5+5Y(Ap!ApSTkdV~dL6Af2rVUy*t{tESj2tM5vXxk(E7671Q@_0Jt}NNE zl|F!=1_ThxS#oz~mOdH{u2038ONpSI>ga)7To5*rGgVO=B4fhto|cNTzBF>7XXNsd zs3JiiZnp^=Or1v9+bpT*lscGB?+NScRbi;uOU12jD&AWvfHoJ8Ri#&D43%I_pKhZE z6&qMnc9U}&*2hCRY*gxaq73!7k)cX5d8OBM${`lIHuZWQR#NKab75T=xVNG%o&X)s zS9wGQGBVz)8h6{O->G6|=G1E;l_{0X$>*9zPBE3!I45nbzVNR@q^FLid6gR*zI{*kKJrcuz~uL#p-n_pSFAZp8Zd)G{uXJ zC;w7?jrz6xJ*)4;60MbXZMJ4WtN)XJL-{iO_W68P#J2N#tk7wH(oMA1-F38QQ+Ah` zg`&sbe^`;Vu%uO3kJhQRv`R}^6?}zdAZo14(y+Epa8#8vnJxy>K;q!s<~HZH2u0v| zt_^^pPJX)wFG8}4!Pv)XwovDcu~k*FY7Wl}OLWXKoGAFR`0>;~jdh;ug3V37U|Er< z^%*Wt_J(U+s+7P~hlFo`)b~8cqbc3S(5m>O#V+Q7p$}q0z^op`9LVa#!e?T=Zm#P9 z_Xp>>96h zqe=D^o*Q^pZi-Y>fxd!wXRI|mNt^Y}fKD%D>UjZAJqae^Q6SSGjAiOZalobT^OPs4 uCzNYPGVO`PO_UeejvXe7tI$c(_>#W-i2Kc)$kNo75e}4nboA=>n*0Rw3HbW} literal 0 HcmV?d00001 diff --git a/roles/bbb_install/files/ext_sipgate.xml b/roles/bbb_install/files/ext_sipgate.xml new file mode 100644 index 0000000..3b68157 --- /dev/null +++ b/roles/bbb_install/files/ext_sipgate.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/roles/bbb_install/files/install b/roles/bbb_install/files/install new file mode 100644 index 0000000..e315150 --- /dev/null +++ b/roles/bbb_install/files/install @@ -0,0 +1 @@ +./bbb-install-2.5.sh -v focal-250 -s bbb.xitq.de -e benedikt.wismans@sdw.systems -c service.sdw.systems:3ef948d61ff4bcf3e87f068dfecbbbe6 diff --git a/roles/bbb_install/files/pub_sipgate.xml b/roles/bbb_install/files/pub_sipgate.xml new file mode 100644 index 0000000..a2e3a9f --- /dev/null +++ b/roles/bbb_install/files/pub_sipgate.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/roles/bbb_install/files/rudiDefault.pdf b/roles/bbb_install/files/rudiDefault.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8f2b1de2097a577d574c007489dd26922bcdfef4 GIT binary patch literal 33195 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/roles/bbb_install/files/update b/roles/bbb_install/files/update new file mode 100644 index 0000000..343777d --- /dev/null +++ b/roles/bbb_install/files/update @@ -0,0 +1,21 @@ +#!/bin/bash + +echo Working on host `hostname` +sudo apt-get update && yes Y | sudo apt-get upgrade && yes Y | sudo apt-get dist-upgrade && yes Y | sudo apt autoremove + +sudo cp ~/Scripte/turn-stun-servers.xml.konfiguriert /usr/share/bbb-web/WEB-INF/classes/spring/turn-stun-servers.xml + +sudo cp ~/Scripte/customerDefault.pdf /var/www/bigbluebutton-default/default.pdf + +sudo bbb-conf --setip `hostname` + +exit 0 + +vhosts=( vhost ) + +for i in "${vhosts[@]}"; do +echo Working on vhost $i + ssh $i sudo apt-get update && yes Y | sudo apt-get upgrade && yes Y | sudo apt-get dist-upgrade && yes Y | sudo apt autoremove +done + +exit 0 diff --git a/roles/bbb_install/files/xitDefault.pdf b/roles/bbb_install/files/xitDefault.pdf new file mode 100644 index 0000000000000000000000000000000000000000..09754000c368cc5b4a49f9e31365e72e4c97cdc4 GIT binary patch literal 113472 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 z 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 fc653!L7%MMv|eig^&4BgZ4eJ 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 AwEzGB literal 0 HcmV?d00001 diff --git a/roles/bbb_install/tasks/config_bbb.yml b/roles/bbb_install/tasks/config_bbb.yml new file mode 100644 index 0000000..18e4a92 --- /dev/null +++ b/roles/bbb_install/tasks/config_bbb.yml @@ -0,0 +1,36 @@ +--- + +- name: Set default values in settings.yml + yedit: + src: /home/core/Scripte/settings.yml + edits: + - key: public.kurento.pagination.mobilePageSizes.moderator + value: 6 + - key: public.kurento.pagination.mobilePageSizes.viewer + value: 4 + +- name: Set default values in file bigbluebutton.properties + ansible.builtin.lineinfile: + path: /home/core/Scripte/bigbluebutton.properties + ### line to be searched & matched + regexp: '{{ item.From }}' + ### line to be in placed + line: '{{ item.To }}' + state: present + backrefs: yes + backup: yes + + with_items: + - { From: '^defaultWelcomeMessage=(.*)$', To: '{{ defaultWelcomeMessage }}'} + - { From: '^defaultWelcomeMessageFooter=(.*)$', To: '{{ defaultWelcomeMessageFooter }}'} + - { From: '^learningDashboardEnabled=(.*)$', To: '{{ learningDashboardEnabled }}'} + - { From: '^disableRecordingDefault=(.*)$', To: '{{ disableRecordingDefault }}'} + - { From: '^webcamsOnlyForModerator=(.*)$', To: '{{ webcamsOnlyForModerator }}'} + - { From: '^learningDashboardCleanupDelayInMinutes=(.*)$', To: '{{ learningDashboardCleanupDelayInMinutes }}'} + - { From: '^bigbluebutton\.web\.logoutURL=(.*)$', To: '{{ bigbluebutton_web_logoutURL }}'} + +- name: Configure turn and stun service and default presentation using update script and restart BBB + command: + cmd: "/home/core/Scripte/update" + chdir: /home/core/Scripte +... \ No newline at end of file diff --git a/roles/bbb_install/tasks/dialin_bbb.yml b/roles/bbb_install/tasks/dialin_bbb.yml new file mode 100644 index 0000000..5a45f99 --- /dev/null +++ b/roles/bbb_install/tasks/dialin_bbb.yml @@ -0,0 +1,43 @@ +--- + +- name: Ensure /opt/freeswitch/etc/freeswitch/sip_profiles/external dir exists + file: + path: "/opt/freeswitch/etc/freeswitch/sip_profiles/external" + state: directory + +- name: Upload ext_sipgate.xml config to /opt/freeswitch/etc/freeswitch/sip_profiles/external/sipgate.xml + copy: + src: ext_sipgate.xml + dest: /opt/freeswitch/etc/freeswitch/sip_profiles/external/sipgate.xml + owner: root + group: root + mode: 0644 + +- name: Ensure /opt/freeswitch/etc/freeswitch/dialplan/public dir exists + file: + path: "/opt/freeswitch/etc/freeswitch/dialplan/public" + state: directory + +- name: Upload pub_sipgate.xml config to /opt/freeswitch/etc/freeswitch/dialplan/public/sipgate.xml + copy: + src: pub_sipgate.xml + dest: /opt/freeswitch/etc/freeswitch/dialplan/public/sipgate.xml + owner: freeswitch + group: daemon + mode: 0644 + +- name: Set defaultDialAccessNumber number in file bigbluebutton.properties + ansible.builtin.lineinfile: + path: /home/core/Scripte/bigbluebutton.properties + ### line to be searched & matched + regexp: '{{ item.From }}' + ### line to be in placed + line: '{{ item.To }}' + state: present + backrefs: yes + backup: yes + + with_items: + - { From: '^defaultDialAccessNumber=(.*)$', To: '{{ defaultDialAccessNumber }}'} + +... \ No newline at end of file diff --git a/roles/bbb_install/tasks/install_bbb.yml b/roles/bbb_install/tasks/install_bbb.yml new file mode 100644 index 0000000..f334a23 --- /dev/null +++ b/roles/bbb_install/tasks/install_bbb.yml @@ -0,0 +1,21 @@ +--- + +- name: Upload bbb-install script to /root + copy: + src: bbb-install-2.7.sh + dest: /root + owner: root + group: root + mode: 0755 + +- name: Execute bbb-install script only if /usr/share/bigbluebutton/license.txt does not exist + command: + cmd: "/root/bbb-install-2.7.sh -v focal-270 -s {{ inventory_hostname }} -e benedikt.wismans@sdw.systems -c service.sdw.systems:3ef948d61ff4bcf3e87f068dfecbbbe6" + chdir: /root + creates: /usr/share/bigbluebutton/license.txt + +- name: Install bbb webhooks package + apt: + name: bbb-webhooks + state: present +... \ No newline at end of file diff --git a/roles/bbb_install/tasks/main.yml b/roles/bbb_install/tasks/main.yml new file mode 100644 index 0000000..3a36061 --- /dev/null +++ b/roles/bbb_install/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- import_tasks: packages.yml +- import_tasks: install_bbb.yml +- import_tasks: setup_bbb.yml +- import_tasks: config_bbb.yml +# - import_tasks: dialin_bbb.yml + +... + diff --git a/roles/bbb_install/tasks/packages.yml b/roles/bbb_install/tasks/packages.yml new file mode 100644 index 0000000..06c8683 --- /dev/null +++ b/roles/bbb_install/tasks/packages.yml @@ -0,0 +1,11 @@ +--- + +- name: Install apparmor required by new version of docker + apt: + name: + - apparmor-utils + - apparmor-profiles + - apparmor-profiles-extra + - vim-addon-manager + +... \ No newline at end of file diff --git a/roles/bbb_install/tasks/setup_bbb.yml b/roles/bbb_install/tasks/setup_bbb.yml new file mode 100644 index 0000000..94d9f9e --- /dev/null +++ b/roles/bbb_install/tasks/setup_bbb.yml @@ -0,0 +1,48 @@ +--- + +- name: Create or recreate symlinks for bbb config files in script-directory + shell: | + cd /home/core/Scripte + ln -sf /usr/local/bigbluebutton/bbb-webhooks + ln -sf /etc/bigbluebutton + ln -sf /var/www/bigbluebutton-default + ln -sf /usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties + ln -sf /usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml + ln -sf /usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml + ln -sf /usr/share/meteor/bundle/systemd_start.sh + ln -sf /usr/share/bbb-web/WEB-INF/classes/spring/turn-stun-servers.xml + ln -sf /usr/share/bigbluebutton/nginx/sip.nginx + +- name: Upload turn-stun-config to core's Scripte directory + copy: + src: turn-stun-servers.xml.konfiguriert + dest: /home/core/Scripte + owner: core + group: users + mode: 0644 + +- name: Upload update script to core's Scripte directory + copy: + src: update + dest: /home/core/Scripte + owner: core + group: users + mode: 0755 + +- name: Install core user's crontab update-Script before at 3.00 before rebooting at 4 AM + ansible.builtin.cron: + name: run update Script at 3:00 + user: core + minute: "0" + hour: "3" + job: "/home/core/Scripte/update" + +- name: Upload default presantation to core's Scripte directory + copy: + src: "{{ default_presentation }}" + dest: /home/core/Scripte/customerDefault.pdf + owner: core + group: users + mode: 0644 + +... \ No newline at end of file diff --git a/roles/bs_scripte/addVirtualBackground b/roles/bs_scripte/addVirtualBackground new file mode 100644 index 0000000..72754ec --- /dev/null +++ b/roles/bs_scripte/addVirtualBackground @@ -0,0 +1,8 @@ +#!/bin/bash + +source /home/core/Scripte/bashlib + +echo $1 + +addVBackground $1 + diff --git a/roles/bs_scripte/files/RD_Logo_Vielfalt_1280x960.jpg b/roles/bs_scripte/files/RD_Logo_Vielfalt_1280x960.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6621e4ebaf246e639f96840466bfe03024421e2e GIT binary patch literal 112712 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 literal 0 HcmV?d00001 diff --git a/roles/bs_scripte/files/bashlib b/roles/bs_scripte/files/bashlib index 493c953..2dbccd1 100644 --- a/roles/bs_scripte/files/bashlib +++ b/roles/bs_scripte/files/bashlib @@ -17,3 +17,50 @@ adddate() { getnic() { echo `ip link show | grep "state UP" | grep -v "LOOPBACK" | grep -v virbr | awk '{print $2}' | sed 's/://g'` } + +#Method removes all BBB Virtual Webcam Backgrounds (except the blur thumbnail) +removeAllVBackgrounds() { + + HTML5_CONFIG=/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml + + cat /usr/share/meteor/bundle/programs/web.browser/program.json | jq '.manifest|=map(select( (.path|contains("virtual-backgrounds")) and (.path|contains("blur.jpg")|not) |not))' | sponge /usr/share/meteor/bundle/programs/web.browser/program.json >/dev/null + yq d -i $HTML5_CONFIG public.virtualBackgrounds.fileNames +} + +#Adds a new Virtual Background image. Paramter: full path to background image +# If a file thumbnails/ exists in the original location this thumbnail is used. Otherwise a scaled down image of the original is made +addVBackground() { + PROGRAMJSON=/usr/share/meteor/bundle/programs/web.browser/program.json + if [ ! -f $1 ]; then + echo "Could not find file $1 - not adding as Virtual Background" + return 1 + fi + FILENAME=$(basename $1) + DIRECTORY=$(dirname $1) + + HTML5_CONFIG=/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml + + #Copy Files + cp $1 /usr/share/meteor/bundle/programs/web.browser/app/resources/images/virtual-backgrounds + if [ -f $DIRECTORY/thumbnails/$FILENAME ]; then + cp $DIRECTORY/thumbnails/$FILENAME /usr/share/meteor/bundle/programs/web.browser/app/resources/images/virtual-backgrounds/thumbnails + else + convert $1 -scale 50 /usr/share/meteor/bundle/programs/web.browser/app/resources/images/virtual-backgrounds/thumbnails/$FILENAME + fi + + #Get SHA-1 Checksums + CHKSUM=$(sha1sum $1|cut -d" " -f1) + CHKSUM_TN=$(sha1sum /usr/share/meteor/bundle/programs/web.browser/app/resources/images/virtual-backgrounds/thumbnails/$FILENAME|cut -d" " -f1) + + #Get File Sizes + SIZE=$(stat --printf="%s" $1) + SIZE_TN=$(stat --printf="%s" /usr/share/meteor/bundle/programs/web.browser/app/resources/images/virtual-backgrounds/thumbnails/$FILENAME) + + #Generate JSON-Snippet to add to program.json + JSON="{ \"path\" : \"app/resources/images/virtual-backgrounds/$FILENAME\", \"where\" : \"client\", \"type\" : \"asset\", \"cacheable\": false, \"url\": \"/resources/images/virtual-backgrounds/$FILENAME\", \"size\": \"$SIZE\", \"hash\": \"$CHKSUM\", \"sri\": null }" + JSON_TN="{ \"path\" : \"app/resources/images/virtual-backgrounds/thumbnails/$FILENAME\", \"where\" : \"client\", \"type\" : \"asset\", \"cacheable\": false, \"url\": \"/resources/images/virtual-backgrounds/thumbnails/$FILENAME\", \"size\": \"$SIZE_TN\", \"hash\": \"$CHKSUM_TN\", \"sri\": null }" + + #Append Metadata to program.json + cat $PROGRAMJSON |jq ".manifest += [$JSON] + [$JSON_TN]" |sponge $PROGRAMJSON + yq w -i $HTML5_CONFIG public.virtualBackgrounds.fileNames[+] "$FILENAME" +} diff --git a/roles/bs_scripte/tasks/main.yml b/roles/bs_scripte/tasks/main.yml index 3e8faf8..7db90ce 100644 --- a/roles/bs_scripte/tasks/main.yml +++ b/roles/bs_scripte/tasks/main.yml @@ -37,14 +37,39 @@ - sysstat - ifstat -- name: Upload update to core's Scripte directory +- name: Install moreutis soak up standard input and write to a file) und jq (The jq is a command line based JSON processor) for custom background installation script in bashlib + apt: + name: + - moreutils + - jq + +- name: Upload addVirtualBackground Script to core's Scripte directory copy: - src: update + src: addVirtualBackground dest: /home/core/Scripte/ owner: core group: users mode: 0755 +- name: Upload VirtualBackground to core's Scripte directory + copy: + src: RD_Logo_Vielfalt_1280x960.jpg + dest: /home/core/Scripte/ + owner: core + group: users + mode: 0644 + + + +# Das update-Script beisst sich mit dem aus BBB +#- name: Upload update to core's Scripte directory +# copy: +# src: update +# dest: /home/core/Scripte/ +# owner: core +# group: users +# mode: 0755 + - name: Install vim for script editing apt: diff --git a/roles/bs_snmp/files/snmpd.conf b/roles/bs_snmp/files/snmpd.conf index 6ffa2ae..8bcba1d 100644 --- a/roles/bs_snmp/files/snmpd.conf +++ b/roles/bs_snmp/files/snmpd.conf @@ -13,6 +13,7 @@ rocommunity SDW 88.99.138.96 #root4.sdw.systems rocommunity SDW 94.130.135.216 #root5.sdw.systems rocommunity SDW 178.15.59.28 #core-open-diakonie.de +rocommunity SDW 178.15.152.60 #core-open-diaknoie.de behind reverse proxy # Default access to basic system info rocommunity public default -V systemonly @@ -84,7 +85,3 @@ load 12 10 5 # Remember to activate the 'createUser' lines above iquerySecName internalUser rouser internalUser - # generate traps on UCD error conditions -defaultMonitors yes - # generate traps on linkUp/Down -linkUpDownNotifications yes diff --git a/roles/bs_snmp/tasks/main.yml b/roles/bs_snmp/tasks/main.yml index dab3c0e..874d560 100644 --- a/roles/bs_snmp/tasks/main.yml +++ b/roles/bs_snmp/tasks/main.yml @@ -4,11 +4,13 @@ apt: name: - snmpd + - snmp + - snmp-mibs-downloader - name: Upload snnmpd configuration file snmpd.conf to /etc/snmp copy: src: snmpd.conf - dest: /etc/snmpd/ + dest: /etc/snmp/ owner: root group: root mode: 0600 diff --git a/roles/bs_users/files/authorized_keys_core b/roles/bs_users/files/authorized_keys_core index cb534f2..d087ebb 100644 --- a/roles/bs_users/files/authorized_keys_core +++ b/roles/bs_users/files/authorized_keys_core @@ -1,4 +1,6 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLGR3klHdPzj5rOwoce8JdvkMGXoTSXdp66JhYYO4t5hWQRB+DZjvhpSBjvtKZZH07wHS0Ya69baDmwHiOhzhNwcs3hwi/I2k/ABSjmjRNNAMlxauHvaRviFYtx5/h7ZayKW9gpxU4e22/9k0F9XAaWkN8Mc7PgvagUy9POpP19gyBBS35kjFIKjOMrz1nQ+9jwUza7lARryctnDoaiUd7DHsLfvSa8Q1fVNUka+k0H1YtRxfsdU8CdMrQf+bDtUTjJupyT5xFphXEle31E49+WAsYGwXkpmQA4zM6E1gOJ0rgnmm/DFJeJ/DYaYP79XzwjvJxNSVMRAg6t5P5z93x benediktwismans@macmini ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSqGfwbqDQdkjG8s/iCVYlsXcVzScjm/D5xZ11AnWWTZ2rL4BitjYgTNx+3SRoM6K8mUYHFi5tTw3X5ZWcjIj+4UXqONA0pCfkVSo24obIqiCXa7+ZyI7MEW/lGmt4u02fJYCrrzxZCfHd3qR3hFAfv1b188ebEMDYpDORAek0PtMoKHVpNZDK9EBNotT7v92WGFngNSLd4qqnUexEd89zsv9mDlttQe6Z5oIHeFIpu0VsaOQiKXQHcKdwwsXdoTG7q989jJ9kRb3lC/Bs+fpzKd8Q/rPGLSkpJUA4RN6f7ZXJ7fQ86zNGZ7MsskcHJyQCdFPV/ESXNV9rabE6DX73 benediktwismans@acer ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDdvEW4c8+OqO3bdc+5JonpEADbR304X5zXI5j9cOROK0XmK0BQVBrmimlcguEcBPinFRC7XaWgxH70bzPBcwTNVCQOzcAAF3zyuDFfLE5Kv5+vxp0g41AERYLC27Smwo8hQ/ckO+RSxFgM5FKTLErSqXdbtGMlFqA0b/auZhXDHXE+7ft8TSVFnTusrlYovNqwK3wuGHB2xs6gEqlVw5DVwhRsO/hq6pdoSx35GygQYWWPwY8vCSXaqrKbakG9GA0u4TqLE8StpnItEPfvQ3Fe/8AptC4u4JgYuucYZjFOQqzJdv0KHqKOriy7RdO01HxS6Ts7VnbvAc5aL8jZF9bl benediktwismans@intel -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSU++o+8yN2V9ojFnnHgkj7QgciurCxcK5b0Yei/I9BmwE8uAWgQR4DJw3iAkV+NSVJ0dsiqGwc6I9f8e9IsTStfcSlwYA8VENuFSelVu0Xph0CY8jPKV8h6gEM8+AQd4iYUgJeROtEkNZhh3D/ZC68ap5VxfF4PrHeDu0jE0C1fG6MGJ5btgI7IWAoaAkSAtoxC9latnFDhFBNmnJmq+d0DNNPBKoB5DG9wQvVxpeuuKzSZyDv87N3/28Uo8JqLm3r4ftBU0sWctymRS0Z5EDqHlLNFQdqQeSzPtQeNh5QOEKH+aa9aAsjINOaEpI2uIe0EYAmBOMjyzvi5BRy6AJ benediktwismans@vhostbbb \ No newline at end of file +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSU++o+8yN2V9ojFnnHgkj7QgciurCxcK5b0Yei/I9BmwE8uAWgQR4DJw3iAkV+NSVJ0dsiqGwc6I9f8e9IsTStfcSlwYA8VENuFSelVu0Xph0CY8jPKV8h6gEM8+AQd4iYUgJeROtEkNZhh3D/ZC68ap5VxfF4PrHeDu0jE0C1fG6MGJ5btgI7IWAoaAkSAtoxC9latnFDhFBNmnJmq+d0DNNPBKoB5DG9wQvVxpeuuKzSZyDv87N3/28Uo8JqLm3r4ftBU0sWctymRS0Z5EDqHlLNFQdqQeSzPtQeNh5QOEKH+aa9aAsjINOaEpI2uIe0EYAmBOMjyzvi5BRy6AJ benediktwismans@vhostbbb +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC8g5FOIInITmq8oOSy/CUmIWhOWFnqpBHhNweohK1SWHRjg8/kySZo4PwS2sKCGkZpTelnJjoVY3rBaZBb75HEn0BSRhZ2FPIviD3+ymXLvGgA9ewkms2s78jvhmr3iZSOH+PXZ0vhobrzzh2e2ZuyqsP/cTdc8KQOV3HFzkXfi7sLbGbKSuXwHqEwImj6KJ5Z0g0e1YxPQtkhpwtKkMhC7kgzK5HTEE7xh7DePG6i5gD9E/XXEGxKMPcDAff6YM31MVy0n+2LQ2fz7rFdmceHtYY9f6XijYuOBiNlNmvtD+zcO2Q44nUipkDkFBUYZeTXxfE8xf3rbmpBX5f3WNprUrNmnG1elgsWOa6yxoAL0ZGCfdSboS68JxTG9JxM2lKOv/jUc/0zwkiKkOX24ZnCAmBBh+zT4rNlJbA2dYVTl0+B5PNA2JlXbpkOJgGlvt6gT7N5fvHfVhvVPWbGRPUksk8aP+0jSZWIWN0tF3aXTagOi+5fwx1pNQcZQobQThk= core@px-core4five-p1.rummelsberger.local +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCV4amm6qrzqUfdjXftZCg37875duFRpJYkexQjtHpFRSR5Jk+m01MtQEwns4Ou6qlLhXUUZDhxGaktg5Bme8tMzp/AQ8mcKO4LfXVV+yAqbkJCYNHuAGJpNOaC9H8RdjuvN0wFq8lLiE4vGIbc2L5NPDzGYzoNTU8ubpqzvLldLqm46yL6uTdTOCCDNQuJV1oW6qj28R7AU5eKqYYib040RDdLkPZeTxGaEo+yy1vbR8dO0fU1HtT6gNay2F9nKsfPCXOk3ZU8ra5qA+ri9LK1GHCg8wM4FrJF22njrEJN/WBbjR7BXii4uqmrx+3RcYQrtJsAHjW3pUjkaROgBWjonlxSTkL7hcJmSBhXw3Uop8wVY7y8ntUbS6kBMhaZkYRfs2tekDoR5NmhcBAZtDmyI+MqVDUeg0biIRLDtCA5+pXpiBxgLf3NEf/E5kHPdrW+Na/ioO3b+aHO0124XfCTWjYPasw80hkLKRl1sHR/G7ZIMwVPk/6BzkwV8V95Fms= benediktwismans@sdwmacair diff --git a/roles/bs_users/files/authorized_keys_root b/roles/bs_users/files/authorized_keys_root index dbb4273..2d5874b 100644 --- a/roles/bs_users/files/authorized_keys_root +++ b/roles/bs_users/files/authorized_keys_root @@ -1,3 +1,4 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLGR3klHdPzj5rOwoce8JdvkMGXoTSXdp66JhYYO4t5hWQRB+DZjvhpSBjvtKZZH07wHS0Ya69baDmwHiOhzhNwcs3hwi/I2k/ABSjmjRNNAMlxauHvaRviFYtx5/h7ZayKW9gpxU4e22/9k0F9XAaWkN8Mc7PgvagUy9POpP19gyBBS35kjFIKjOMrz1nQ+9jwUza7lARryctnDoaiUd7DHsLfvSa8Q1fVNUka+k0H1YtRxfsdU8CdMrQf+bDtUTjJupyT5xFphXEle31E49+WAsYGwXkpmQA4zM6E1gOJ0rgnmm/DFJeJ/DYaYP79XzwjvJxNSVMRAg6t5P5z93x benediktwismans@macmini ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSqGfwbqDQdkjG8s/iCVYlsXcVzScjm/D5xZ11AnWWTZ2rL4BitjYgTNx+3SRoM6K8mUYHFi5tTw3X5ZWcjIj+4UXqONA0pCfkVSo24obIqiCXa7+ZyI7MEW/lGmt4u02fJYCrrzxZCfHd3qR3hFAfv1b188ebEMDYpDORAek0PtMoKHVpNZDK9EBNotT7v92WGFngNSLd4qqnUexEd89zsv9mDlttQe6Z5oIHeFIpu0VsaOQiKXQHcKdwwsXdoTG7q989jJ9kRb3lC/Bs+fpzKd8Q/rPGLSkpJUA4RN6f7ZXJ7fQ86zNGZ7MsskcHJyQCdFPV/ESXNV9rabE6DX73 benediktwismans@acer ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDdvEW4c8+OqO3bdc+5JonpEADbR304X5zXI5j9cOROK0XmK0BQVBrmimlcguEcBPinFRC7XaWgxH70bzPBcwTNVCQOzcAAF3zyuDFfLE5Kv5+vxp0g41AERYLC27Smwo8hQ/ckO+RSxFgM5FKTLErSqXdbtGMlFqA0b/auZhXDHXE+7ft8TSVFnTusrlYovNqwK3wuGHB2xs6gEqlVw5DVwhRsO/hq6pdoSx35GygQYWWPwY8vCSXaqrKbakG9GA0u4TqLE8StpnItEPfvQ3Fe/8AptC4u4JgYuucYZjFOQqzJdv0KHqKOriy7RdO01HxS6Ts7VnbvAc5aL8jZF9bl benediktwismans@intel +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCV4amm6qrzqUfdjXftZCg37875duFRpJYkexQjtHpFRSR5Jk+m01MtQEwns4Ou6qlLhXUUZDhxGaktg5Bme8tMzp/AQ8mcKO4LfXVV+yAqbkJCYNHuAGJpNOaC9H8RdjuvN0wFq8lLiE4vGIbc2L5NPDzGYzoNTU8ubpqzvLldLqm46yL6uTdTOCCDNQuJV1oW6qj28R7AU5eKqYYib040RDdLkPZeTxGaEo+yy1vbR8dO0fU1HtT6gNay2F9nKsfPCXOk3ZU8ra5qA+ri9LK1GHCg8wM4FrJF22njrEJN/WBbjR7BXii4uqmrx+3RcYQrtJsAHjW3pUjkaROgBWjonlxSTkL7hcJmSBhXw3Uop8wVY7y8ntUbS6kBMhaZkYRfs2tekDoR5NmhcBAZtDmyI+MqVDUeg0biIRLDtCA5+pXpiBxgLf3NEf/E5kHPdrW+Na/ioO3b+aHO0124XfCTWjYPasw80hkLKRl1sHR/G7ZIMwVPk/6BzkwV8V95Fms= benediktwismans@sdwmacair \ No newline at end of file diff --git a/roles/install_image/tasks/main.yml b/roles/install_image/tasks/main.yml index 7351c67..7327856 100644 --- a/roles/install_image/tasks/main.yml +++ b/roles/install_image/tasks/main.yml @@ -11,7 +11,7 @@ when: stat_result.stat.exists == false - name: Execute installimage - shell: "{{ install_image.path }} -a -n {{ inventory_hostname }} -b grub -r {{ install_image.raid }} -i {{ install_image.image }} -p /boot:ext3:512M,/:ext4:all -d {{ install_image.drives }}" + shell: "{{ install_image.path }} -a -n {{ inventory_hostname }} -b grub -r {{ install_image.raid }} -i {{ install_image.image }} -p /boot:ext3:512M,swap:swap:32G,/:ext4:all -d {{ install_image.drives }}" - name: Rebooting... shell: reboot diff --git a/roles/kvm_install/files/vhost_getIPv4 b/roles/kvm_install/files/vhost_getIPv4 index 0357166..f56eec6 100644 --- a/roles/kvm_install/files/vhost_getIPv4 +++ b/roles/kvm_install/files/vhost_getIPv4 @@ -13,7 +13,7 @@ buf=`/usr/sbin/arp -an | grep $mac` #echo arp reports ipv4 config for MAC $mac is:$buf # Die IPv4-Adresse steht in der Ausgabe von arp in runden Klammern. -# Das sind auch die einziegen runden Klammern in der Asugabe. +# Das sind auch die einzigen runden Klammern in der Ausgabe. buf=${buf#*(} buf=${buf%)*} diff --git a/roles/kvm_install/tasks/packages_install.yml b/roles/kvm_install/tasks/packages_install.yml index ad7c9b0..4c8426a 100644 --- a/roles/kvm_install/tasks/packages_install.yml +++ b/roles/kvm_install/tasks/packages_install.yml @@ -14,6 +14,7 @@ - virt-manager - dnsmasq - python3-libvirt + - python3-lxml - libguestfs-tools - name: Check KVM ok diff --git a/roles/kvm_installvm/tasks/main.yml b/roles/kvm_installvm/tasks/main.yml index 47b7407..7d80a12 100644 --- a/roles/kvm_installvm/tasks/main.yml +++ b/roles/kvm_installvm/tasks/main.yml @@ -1,6 +1,7 @@ --- -- import_tasks: template_upload.yml -- import_tasks: vm_create.yml -- import_tasks: hosts_vm2ip.yml +#- import_tasks: template_upload.yml +#- import_tasks: vm_create.yml +#- import_tasks: hosts_vm2ip.yml +- import_tasks: virtnet_config.yml ... \ No newline at end of file diff --git a/roles/kvm_installvm/tasks/virtnet_config.yml b/roles/kvm_installvm/tasks/virtnet_config.yml new file mode 100644 index 0000000..fb6d810 --- /dev/null +++ b/roles/kvm_installvm/tasks/virtnet_config.yml @@ -0,0 +1,20 @@ +--- + +# +- name: Retrieve MAC-address + shell: /home/core/Scripte/vhost_getMAC "{{ vm_name }}" + register: vm_mac + changed_when: "False" + + +- name: Debug MAC-address + debug: msg={{ vm_mac["stdout"] }} + changed_when: "False" + +- name: Add a new host in the dhcp pool + community.libvirt.virt_net: + name: br_nat + command: modify + xml: "" + +... \ No newline at end of file