#!/usr/bin/env bash cript_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/${script_name%%.*}.conf" LOCK_DIR="/tmp/$(basename $0).$$.LOCK" log_file="${LOCK_DIR}/${script_name%%.*}.log" DIST="ubuntu" DIST_RELEASE="xenial" GREENLIGTH_DIR="/usr/local/greenlight" FQDN_HOSTNAME="bbb.oopen.de" HOSTNAME=" ${FQDN_HOSTNAME%%.*}" # ---------- # Base Function(s) # ---------- clean_up() { # Perform program exit housekeeping rm -rf "$LOCK_DIR" blank_line exit $1 } echononl(){ if $terminal ; then echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n " $*\\c" 1>&2 else echo -e -n " $*" 1>&2 fi rm /tmp/shprompt$$ fi } fatal(){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mFatal\033[m ] $*" else echo -e " [ Fatal ] $*" fi echo "" if $terminal ; then echo -e " \033[1mScript terminated\033[m.." else echo -e " Script terminated.." fi echo "" rm -rf $LOCK_DIR exit 1 } error (){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ] $*" else echo " [ Error ] $*" fi echo "" } info () { if $terminal ; then echo "" echo -e " [ \033[32m\033[1mInfo\033[m ] $*" echo "" fi } note () { if $terminal ; then echo "" echo -e " [ \033[33m\033[1mNote\033[m ] $*" echo "" fi } echo_ok() { if $terminal ; then echo -e "\033[85G[ \033[32mok\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[85G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[85G[ \033[37m\033[1mskipped\033[m ]" fi } echo_wait(){ if $terminal ; then echo -en "\033[85G[ \033[5m\033[1m..\033[m ]" fi } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } blank_line() { if $terminal ; then echo "" fi } # ---------- # - Jobhandling # ---------- # - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM # - trap clean_up SIGHUP SIGINT SIGTERM # - Create lock directory '$LOCK_DIR" # mkdir "$LOCK_DIR" # ---------- # - Some checks .. # ---------- # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else fatal "Script must run in a terminal." fi # ========== # - Begin Main Script # ========== # ---------- # - Headline # ---------- if $terminal ; then echo "" echo -e "\033[1m----------\033[m" echo -e "\033[32m\033[1mRunning script \033[m\033[1m$script_name\033[32m .. \033[m" echo -e "\033[1m----------\033[m" fi blank_line # Remove old versions of Docker # echononl "Remove old versions of Docker .." apt-get remove -y docker docker-engine docker.io containerd runc > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi # Stop Service if started # echononl "Stop Greenlight Service.." if $(ps ax | grep -v grep | grep -q /usr/bin/docker-proxy ) ; then cd $GREENLIGTH_DIR && docker-compose down > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi else echo_skipped fi # Install packages to allow apt to use a repository over HTTPS # echononl "Install packages to allow apt to use a repository over HTTPS .." apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common -y > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi blank_line # Add Docker’s official GPG key # echononl "Add Docker’s official GPG key .." curl -fsSL https://download.docker.com/linux/ubuntu/gpg 2> "$log_file" | sudo apt-key add - >> "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi # Add Dockers stable repository # echononl "Add Dockers stable repositor .." cat < /etc/apt/sources.list.d/docker.list 2> "$log_file" deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable EOF if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi # Update the apt package index. # echononl "Update the apt package index. .." apt-get update > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi # Install the latest version of Docker Engine - Community and containerd # echononl "Install the latest version of Docker Engine - Community and containerd .." DEBIAN_FRONTEND=noninteractive apt-get -y install docker-ce docker-ce-cli containerd.io > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi blank_line # Deinstall apparmor # # Needed if docker is running in a LX Conatiner # echononl "Deinstall apparmor - Needed because docker is running in a LX-Container .." DEBIAN_FRONTEND=noninteractive apt-get -y remove apparmor > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi blank_line # Create the Greenlight directory for its configuration to live in. # echononl "Create the Greenlight directory for its configuration to live in. .." if [[ -d "$GREENLIGTH_DIR" ]] ; then echo_skipped else mkdir "$GREENLIGTH_DIR" > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi fi echononl "Enter Greenlight directory .." cd "$GREENLIGTH_DIR" > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi # Greenlight will read its environment configuration from the .env file. To generate this # file and install the Greenlight Docker image, run (inside greenlight directory): # # docker run --rm bigbluebutton/greenlight:v2 cat ./sample.env > .env # _new_env=false echononl "Generate environment configuration and install Greenlight Docker image .." if [[ -s ${GREENLIGTH_DIR}/.env ]]; then echo_skipped else docker run --rm bigbluebutton/greenlight:v2 cat ./sample.env > .env 2> "$log_file" if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok _new_env=true fi fi # Greenlight needs a secret key in order to run in production. To generate this, run: # # docker run --rm bigbluebutton/greenlight:v2 bundle exec rake secret # _secret_key_found=false echononl "Generating a Secret Key (in order to run in production).." if [[ -z "$(grep -E "^\s*SECRET_KEY_BASE\s*=" ${GREENLIGTH_DIR}/.env 2> /dev/null | cut -d '=' -f2)" ]] ; then _greenlight_secret="$(docker run --rm bigbluebutton/greenlight:v2 bundle exec rake secret 2> "$log_file")" if [[ -s "$log_file" ]] ; then echo_failed error "$(cat "$log_file")" else echo_ok fi else echo_skipped _secret_key_found=true fi # Set 'SECRET_KEY_BASE' with generated Secret Key # _key="SECRET_KEY_BASE" _val="$_greenlight_secret" echononl "Set 'SECRET_KEY_BASE' env with generated Secret Key at file '.env'.." if $_secret_key_found ; then echo_skipped else perl -i -n -p -e "s/^(\s*${_key}\s*=.*)/##! \1\n${_key}=${_val}/" \ ${GREENLIGTH_DIR}/.env > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi fi # Get BigBlueButtons secret .. # echononl "Get BigBlueButtons secret .." _bbb_secret="$(bbb-conf --secret 2> $log_file | grep -i -E "^\s*Secret" 2> $log_file | awk '{print$2}' 2> $log_file)" if [[ -s "$log_file" ]] ; then echo_failed error "$(cat "$log_file")" else echo_ok fi # Set 'BIGBLUEBUTTON_SECRET' with generated Secret Key # _key="BIGBLUEBUTTON_SECRET" _val="$_bbb_secret" echononl "Set 'BIGBLUEBUTTON_SECRET' env with BBB's Secret Key at file '.env'.." if $(grep -E -q "^\s*${_key}\s*=\s*${_val}" ${GREENLIGTH_DIR}/.env 2> /dev/null) ; then echo_skipped else perl -i -n -p -e "s/^(\s*${_key}\s*=.*)/##! \1\n${_key}=${_val}/" \ ${GREENLIGTH_DIR}/.env > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi fi # Get BigBlueButtons url .. # echononl "Get BigBlueButtons URL .." _bbb_url="$(bbb-conf --secret 2> $log_file | grep -i -E "^\s*URL" 2> $log_file | awk '{print$2}' 2> $log_file)" if [[ -s "$log_file" ]] ; then echo_failed error "$(cat "$log_file")" else echo_ok fi # Set 'BIGBLUEBUTTON_ENDPOINT' with generated Secret Key # _key="BIGBLUEBUTTON_ENDPOINT" _val="$_bbb_url" echononl "Set 'BIGBLUEBUTTON_ENDPOINT' env with BBB's Secret Key at file '.env'.." if $(grep -E -q "^\s*${_key}\s*=\s*${_val}" ${GREENLIGTH_DIR}/.env 2> /dev/null) ; then echo_skipped else perl -i -n -p -e "s#^(\s*${_key}\s*=.*)#\#\#! \1\n${_key}=${_val}#" \ ${GREENLIGTH_DIR}/.env > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi fi # Set ALLOW_GREENLIGHT_ACCOUNTS # _key="ALLOW_GREENLIGHT_ACCOUNTS" _val="false" echononl "Set 'ALLOW_GREENLIGHT_ACCOUNTS' to false (file .env).." if $(grep -E -q "^\s*${_key}\s*=\s*${_val}" ${GREENLIGTH_DIR}/.env 2> /dev/null) ; then echo_skipped else perl -i -n -p -e "s#^(\s*${_key}\s*=.*)#\#\#! \1\n${_key}=${_val}#" \ ${GREENLIGTH_DIR}/.env > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi fi blank_line # randomly generate a password for the PostgreSQL database and replace the entries # in the .env and docker-compose.yml # # export pass=$(openssl rand -hex 8) # sed -i 's/POSTGRES_PASSWORD=password/POSTGRES_PASSWORD='$_postgresql_pass'/g' docker-compose.yml # sed -i 's/DB_PASSWORD=password/DB_PASSWORD='$_postgresql_pass'/g' .env # _postgresql_pass="" _pass_generated=false echononl "Generate password for the PostgreSQL database.." if $_new_env ; then _postgresql_pass="$(openssl rand -hex 8 2> $log_file)" if [[ -s "$log_file" ]] ; then echo_failed error "$(cat "$log_file")" else echo_ok _pass_generated=true fi else echo_skipped fi # Set DB_PASSWORD' # _key="DB_PASSWORD" _val="$_postgresql_pass" echononl "Set DB_PASSWORD (file .env).." if $_pass_generated ; then perl -i -n -p -e "s#^(\s*${_key}\s*=.*)#\#\#! \1\n${_key}=${_val}#" \ ${GREENLIGTH_DIR}/.env > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi else echo_skipped fi blank_line echononl "Verify the configuration settings (.env file).." cd "${GREENLIGTH_DIR}" \ && docker run --rm --env-file .env bigbluebutton/greenlight:v2 bundle exec rake conf:check > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi blank_line # Greenlight will be configured to deploy at the /b subdirectory. This is necessary so # it doesn’t conflict with the other BigBlueButton components. The Nginx configuration # for this subdirectory is stored in the Greenlight image. To add this configuration file # to your BigBlueButton server, run: # # docker run --rm bigbluebutton/greenlight:v2 cat ./greenlight.nginx | sudo tee /etc/bigbluebutton/nginx/greenlight.nginx # echononl "Add nginx configuration to BigBlueButton's service .." if [[ -f "/etc/bigbluebutton/nginx/greenlight.nginx" ]] ; then echo_skipped else docker run --rm bigbluebutton/greenlight:v2 cat ./greenlight.nginx \ > /etc/bigbluebutton/nginx/greenlight.nginx 2> $log_file if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi fi blank_line # Download the current stable release of Docker Compose: # echononl "Download the current stable release (v 1.25.4) of Docker Compose .." curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" \ -o /usr/local/bin/docker-compose > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi echononl "Set executable bit to 'docker-compose'.." chmod +x /usr/local/bin/docker-compose > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi info "To install a different version of Compose, substitute 1.25.4 with the version of Compose you want to use." echononl "Create cronjob to start Greenlight service after booting the system.." if $(crontab -l 2>/dev/null | grep -q -E "^@reboot\s+.*\s+docker-compose up -d" 2> /dev/null) ; then echo_skipped else _crontab_tmp_file="${LOCK_DIR}/crontab_root.$$" crontab -l > $_crontab_tmp_file 2> /dev/null if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo "" >> $_crontab_tmp_file echo "# Start greenlight service (docker)" >> $_crontab_tmp_file echo "#" >> $_crontab_tmp_file echo "@reboot cd \"$GREENLIGTH_DIR\" && docker-compose up -d" >> $_crontab_tmp_file crontab $_crontab_tmp_file > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi fi fi blank_line echononl "Copy the docker-compose.yml file from the Greenlight image in to greenlight directory.." cd ${GREENLIGTH_DIR} \ && docker run --rm bigbluebutton/greenlight:v2 cat ./docker-compose.yml > docker-compose.yml 2> $log_file if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi echononl "Set 'POSTGRES_PASSWORD' (file docker-compose.yml).." if $_pass_generated ; then sed -i 's/POSTGRES_PASSWORD=password/POSTGRES_PASSWORD='$_postgresql_pass'/g' \ ${GREENLIGTH_DIR}/docker-compose.yml > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi else echo_skipped fi echononl "Start Greenlight service (vi docker).." cd ${GREENLIGTH_DIR} && docker-compose up -d > $log_file 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi echononl "Restart nginx service.." systemctl restart nginx > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat "$log_file")" else echo_ok fi blank_line note "To create an Administrator account with the default values, in the Greenlight directory, run the following command: # cd $GREENLIGTH_DIR # \033[1mdocker exec greenlight-v2 bundle exec rake admin:create\033[m If you would like to configure the name, email, or password of the Administrator account, replace the previous command with this: # cd $GREENLIGTH_DIR # \033[1mdocker exec greenlight-v2 bundle exec rake user:create[\"name\",\"email\",\"password\",\"admin\"]\033[m Once the command has finished it will print the account’s email and password." note "Optionally, if you wish to have the default landing page at the root of your BigBlueButton server redirect to Greenlight, add the following entry to the bottom of /etc/nginx/sites-available/bigbluebutton just before the last } character. \033[33mlocation = / { return 307 /b; }\033[m To have this change take effect, you must once again restart Nginx." clean_up 0