Compare commits
12
Commits
d95618dce9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ea53f6372 | ||
|
|
da911ff607 | ||
|
|
1ce47febbf | ||
|
|
37cab43f2c | ||
|
|
c7ce9f50ac | ||
|
|
26965815c7 | ||
|
|
497ea263fd | ||
|
|
21020f182e | ||
|
|
a6abb8021d | ||
|
|
aab211ea3b | ||
|
|
8b571ebb88 | ||
|
|
1fb0829979 |
Executable
+2102
File diff suppressed because it is too large
Load Diff
Executable
+788
@@ -0,0 +1,788 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
script_name="$(basename $(realpath $0))"
|
||||
working_dir="$(dirname $(realpath $0))"
|
||||
|
||||
#conf_file="${working_dir}/conf/${script_name%%.*}.conf"
|
||||
conf_file="${working_dir}/conf/mattermost.conf"
|
||||
|
||||
LOCK_DIR="/tmp/$(basename $0).$$.LOCK"
|
||||
log_file="${LOCK_DIR}/${script_name%%.*}.log"
|
||||
|
||||
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||
|
||||
|
||||
# ----------
|
||||
# Base Function(s)
|
||||
# ----------
|
||||
|
||||
clean_up() {
|
||||
|
||||
if [[ -f "$_backup_crontab_file" ]]; then
|
||||
|
||||
echononl "(Re)Install previously saved crontab from '$_backup_crontab_file'.."
|
||||
|
||||
crontab $_backup_crontab_file >> $log_file 2>&1
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
error "$(cat $log_file)"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# 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 ""
|
||||
}
|
||||
|
||||
warn (){
|
||||
echo ""
|
||||
if $terminal ; then
|
||||
echo -e " [ \033[33m\033[1mWarning\033[m ] $*"
|
||||
else
|
||||
echo " [ Warning ] $*"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
info (){
|
||||
if $terminal ; then
|
||||
echo ""
|
||||
if $terminal ; then
|
||||
echo -e " [ \033[32m\033[1mInfo\033[m ] $*"
|
||||
else
|
||||
echo " [ Info ] $*"
|
||||
fi
|
||||
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[33m\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
|
||||
}
|
||||
|
||||
detect_os () {
|
||||
|
||||
if $(which lsb_release > /dev/null 2>&1) ; then
|
||||
|
||||
DIST="$(lsb_release -i | awk '{print tolower($3)}')"
|
||||
DIST_VERSION="$(lsb_release -r | awk '{print tolower($2)}')"
|
||||
DIST_CODENAME="$(lsb_release -c | awk '{print tolower($2)}')"
|
||||
|
||||
if [[ "$DIST" = "debian" ]]; then
|
||||
if $(echo "$DIST_VERSION" | grep -q '\.') ; then
|
||||
DIST_VERSION=$(echo "$DIST_VERSION" | cut --delimiter='.' -f1)
|
||||
fi
|
||||
fi
|
||||
|
||||
elif [[ -e "/etc/os-release" ]]; then
|
||||
|
||||
. /etc/os-release
|
||||
|
||||
DIST=$ID
|
||||
DIST_VERSION=${VERSION_ID}
|
||||
|
||||
fi
|
||||
|
||||
# remove whitespace from DIST and DIST_VERSION
|
||||
DIST="${DIST// /}"
|
||||
DIST_VERSION="${DIST_VERSION// /}"
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
# ----------
|
||||
# - 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
|
||||
|
||||
|
||||
# ----------
|
||||
# Read Configurations from $conf_file
|
||||
# ----------
|
||||
|
||||
# - Give your default values here
|
||||
# -
|
||||
DEFAULT_FQHN_HOSTNAME="$(hostname -f)"
|
||||
|
||||
DEFAULT_MATTERMOST_USER="mattermost"
|
||||
DEFAULT_MATTERMOST_GROUP="mattermost"
|
||||
|
||||
DEFAULT_DB_TYPE="pgsql"
|
||||
|
||||
DEFAULT_MATTERMOST_BASE_INSTALL_PATH="/opt"
|
||||
DEFAULT_MATTERMOST_TMP_DIR="/tmp"
|
||||
|
||||
if [[ -f "$conf_file" ]]; then
|
||||
source "$conf_file"
|
||||
else
|
||||
fatal "No configuration file '$conf_file' present.\n
|
||||
|
||||
In upgrade mode a configuration file is required!"
|
||||
fi
|
||||
|
||||
[[ -n "$FQHN_HOSTNAME" ]] && DEFAULT_FQHN_HOSTNAME="$FQHN_HOSTNAME"
|
||||
|
||||
if [[ -z "$DB_TYPE" ]] ; then
|
||||
fatal "Missing database type (DB_TYPE)!"
|
||||
fi
|
||||
if [[ -z "$DB_NAME" ]] ; then
|
||||
fatal "Missing database name (DB_NAME)!"
|
||||
fi
|
||||
if [[ -z "$DB_USER" ]] ; then
|
||||
fatal "Missing database user (DB_USER)!"
|
||||
fi
|
||||
if [[ -z "$DB_PASS" ]] ; then
|
||||
fatal "Missing database password (DB_PASS)!"
|
||||
fi
|
||||
|
||||
[[ -n "$MATTERMOST_BASE_INSTALL_PATH" ]] && DEFAULT_MATTERMOST_BASE_INSTALL_PATH="$MATTERMOST_BASE_INSTALL_PATH"
|
||||
[[ -n "$MATTERMOST_TMP_DIR" ]] && DEFAULT_MATTERMOST_TMP_DIR="$MATTERMOST_TMP_DIR"
|
||||
|
||||
[[ -n "$MATTERMOST_USER" ]] && DEFAULT_MATTERMOST_USER="$MATTERMOST_USER"
|
||||
if [[ -n "$MATTERMOST_GROUP" ]]; then
|
||||
DEFAULT_MATTERMOST_GROUP="$MATTERMOST_GROUP"
|
||||
else
|
||||
DEFAULT_MATTERMOST_GROUP="$DEFAULT_MATTERMOST_USER"
|
||||
fi
|
||||
|
||||
|
||||
echo -e "\033[32m--\033[m"
|
||||
echo ""
|
||||
echo "Version to upgrade Mattermost Server"
|
||||
echo ""
|
||||
echo " see: https://mattermost.com/download/"
|
||||
echo ""
|
||||
echo ""
|
||||
MM_NEW_VERSION=
|
||||
while [ "X$MM_NEW_VERSION" = "X" ]
|
||||
do
|
||||
echononl "New Mattermost Server Version: "
|
||||
read MM_NEW_VERSION
|
||||
if [ "X$MM_NEW_VERSION" = "X" ]; then
|
||||
echo -e "\n\t\033[33m\033[1mA Version number is required!\033[m\n"
|
||||
fi
|
||||
done
|
||||
DOWNLOAD_ARCHIVE="mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz"
|
||||
DOWNLOAD_URL="https://releases.mattermost.com/${MM_NEW_VERSION}/${DOWNLOAD_ARCHIVE}"
|
||||
|
||||
|
||||
|
||||
echo -e "\033[32m--\033[m"
|
||||
echo ""
|
||||
echo "Base path of current mattermost installation."
|
||||
echo ""
|
||||
echo -e " The install directory is everything before the first occurrence "
|
||||
echo -e " of the string \e[3m/mattermost\e[0m."
|
||||
echo ""
|
||||
echo ""
|
||||
MATTERMOST_BASE_INSTALL_PATH=
|
||||
if [[ -n "$DEFAULT_MATTERMOST_BASE_INSTALL_PATH" ]]; then
|
||||
while [[ "X${MATTERMOST_BASE_INSTALL_PATH}" = "X" ]]; do
|
||||
echononl "Base installation path [${DEFAULT_MATTERMOST_BASE_INSTALL_PATH}]: "
|
||||
read MATTERMOST_BASE_INSTALL_PATH
|
||||
if [[ "X${MATTERMOST_BASE_INSTALL_PATH}" = "X" ]]; then
|
||||
MATTERMOST_BASE_INSTALL_PATH=$DEFAULT_MATTERMOST_BASE_INSTALL_PATH
|
||||
fi
|
||||
if [[ ! -d "${MATTERMOST_BASE_INSTALL_PATH}/mattermost" ]]; then
|
||||
echo -e "\n\tGiven Path does not contain a mattermost installation"
|
||||
MATTERMOST_BASE_INSTALL_PATH=
|
||||
fi
|
||||
done
|
||||
else
|
||||
while [[ "X${MATTERMOST_BASE_INSTALL_PATH}" = "X" ]]; do
|
||||
echononl "Base installation path: "
|
||||
read MATTERMOST_BASE_INSTALL_PATH
|
||||
if [[ "X${MATTERMOST_BASE_INSTALL_PATH}" = "X" ]]; then
|
||||
echo -e "\n\t\033[33m\033[1mBase installation path of current installation is reqired\033[m\n"
|
||||
fi
|
||||
if [[ ! -d "${MATTERMOST_BASE_INSTALL_PATH}/mattermost" ]]; then
|
||||
echo -e "\n\tGiven Path does not contain a mattermost installation"
|
||||
MATTERMOST_BASE_INSTALL_PATH=
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
MATTERMOST_CURRENT_VERSION="$(${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost version 2> /dev/null | grep -E "^Version:" | cut -d' ' -f2)"
|
||||
MATTERMOST_CURRENT_BUILD_NUMBER="$(${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost version 2> /dev/null | grep -E "^Build Number:" | cut -d' ' -f3)"
|
||||
|
||||
|
||||
|
||||
echo -e "\033[32m--\033[m"
|
||||
echo ""
|
||||
echo "Give TMP directory for Downlaoding and extracting mattermost sources.."
|
||||
echo ""
|
||||
echo ""
|
||||
MATTERMOST_TMP_DIR=
|
||||
if [[ -n "$DEFAULT_MATTERMOST_TMP_DIR" ]]; then
|
||||
while [[ "X${MATTERMOST_TMP_DIR}" = "X" ]]; do
|
||||
echononl "TMP directory [${DEFAULT_MATTERMOST_TMP_DIR}]: "
|
||||
read MATTERMOST_TMP_DIR
|
||||
if [[ "X${MATTERMOST_TMP_DIR}" = "X" ]]; then
|
||||
MATTERMOST_TMP_DIR=$DEFAULT_MATTERMOST_TMP_DIR
|
||||
fi
|
||||
if [[ ! -d "${MATTERMOST_TMP_DIR}" ]]; then
|
||||
echo -e "\n\tnGiven TMP Directory \033[33m\033[1m$MATTERMOST_TMP_DIR\033[m does not exist!\n"
|
||||
MATTERMOST_TMP_DIR=
|
||||
fi
|
||||
done
|
||||
else
|
||||
while [[ "X${MATTERMOST_TMP_DIR}" = "X" ]]; do
|
||||
echononl "TMP directory: "
|
||||
read MATTERMOST_TMP_DIR
|
||||
if [[ "X${MATTERMOST_TMP_DIR}" = "X" ]]; then
|
||||
echo -e "\n\t\033[33m\033[1mA TMP directory is required!\033[m\n"
|
||||
continue
|
||||
fi
|
||||
if [[ ! -d "${MATTERMOST_TMP_DIR}" ]]; then
|
||||
echo -e "\n\tGiven TMP Directory \033[33m\033[1m$MATTERMOST_TMP_DIR\033[m does not exist!\n"
|
||||
MATTERMOST_TMP_DIR=""
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
FQHN_HOSTNAME=
|
||||
echo ""
|
||||
echo -e "\033[32m--\033[m"
|
||||
echo ""
|
||||
echo "Insert full qualified hostname for Mattermost Service"
|
||||
echo ""
|
||||
if [[ -n "$DEFAULT_FQHN_HOSTNAME" ]]; then
|
||||
while [[ "X${FQHN_HOSTNAME}" = "X" ]]; do
|
||||
echononl "Full qualified hostname [${DEFAULT_FQHN_HOSTNAME}]: "
|
||||
read FQHN_HOSTNAME
|
||||
if [[ "X${FQHN_HOSTNAME}" = "X" ]]; then
|
||||
FQHN_HOSTNAME=$DEFAULT_FQHN_HOSTNAME
|
||||
fi
|
||||
if [[ ! $FQHN_HOSTNAME =~ \. ]]; then
|
||||
echo -e "\n\tGiven Host \033[33m\033[1m$FQHN_HOSTNAME\033[m seems not to be a full qualified hostname.\n"
|
||||
FQHN_HOSTNAME=""
|
||||
fi
|
||||
done
|
||||
else
|
||||
while [[ "X${FQHN_HOSTNAME}" = "X" ]]; do
|
||||
echononl "Full qualified hostname: "
|
||||
read FQHN_HOSTNAME
|
||||
if [[ "X${FQHN_HOSTNAME}" = "X" ]]; then
|
||||
echo -e "\n\t\033[33m\033[1mFull qualified hostname is reqired\033[m\n"
|
||||
fi
|
||||
if [[ ! $FQHN_HOSTNAME =~ \. ]]; then
|
||||
echo -e "\n\tGiven Host \033[33m\033[1m$FQHN_HOSTNAME\033[m seems not to be a full qualified hostname.\n"
|
||||
FQHN_HOSTNAME=""
|
||||
fi
|
||||
done
|
||||
fi
|
||||
HOSTNAME="${FQHN_HOSTNAME%%.*}"
|
||||
|
||||
echo ""
|
||||
echo "--"
|
||||
echo ""
|
||||
echo "Enter user and group for Mattermost Service."
|
||||
echo ""
|
||||
MATTERMOST_USER=
|
||||
while [ "X$MATTERMOST_USER" = "X" ]
|
||||
do
|
||||
echononl "Mattermost user [${DEFAULT_MATTERMOST_USER}]: "
|
||||
read MATTERMOST_USER
|
||||
if [ "X$MATTERMOST_USER" = "X" ]; then
|
||||
MATTERMOST_USER=$DEFAULT_MATTERMOST_USER
|
||||
fi
|
||||
done
|
||||
MATTERMOST_GROUP=
|
||||
while [ "X$MATTERMOST_GROUP" = "X" ]
|
||||
do
|
||||
echononl "Mattermost group [$DEFAULT_MATTERMOST_GROUP]: "
|
||||
read MATTERMOST_GROUP
|
||||
if [ "X$MATTERMOST_GROUP" = "X" ]; then
|
||||
MATTERMOST_GROUP=$DEFAULT_MATTERMOST_GROUP
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
if [[ "$DB_TYPE" = "mysql" ]] ; then
|
||||
if [[ -n "$MYSQL_CREDENTIAL_ARGS" ]] ; then
|
||||
if ! $(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e 'quit' > /dev/null 2>&1) ; then
|
||||
fatal "Parameter MYSQL_CREDENTIAL_ARGS is given, but a connection to MySQL Service failed.!"
|
||||
fi
|
||||
USE_MYSQL_CREDENTIAL_ARGS=true
|
||||
else
|
||||
USE_MYSQL_CREDENTIAL_ARGS=false
|
||||
|
||||
_MYSQL_ROOT_PW=""
|
||||
echo ""
|
||||
echo -e "\033[32m--\033[m"
|
||||
echo ""
|
||||
echo "Insert root password of MySQL Database Service"
|
||||
echo ""
|
||||
while [ "X${_MYSQL_ROOT_PW}" = "X" ]; do
|
||||
|
||||
echononl "Passworteingabe: "
|
||||
read -s _MYSQL_ROOT_PW
|
||||
if [ "X${_MYSQL_ROOT_PW}" = "X" ]; then
|
||||
echo -e "\n\t\033[33m\033[1mPassworteingabe erforderlich!\033[m\n"
|
||||
continue
|
||||
fi
|
||||
if $(pgrep mysqld_safe > /dev/null 2>&1) || $(pgrep mysqld > /dev/null 2>&1); then
|
||||
if $(mysql --user="root" --password="$_MYSQL_ROOT_PW" -N -s -e 'quit' > /dev/null 2>&1) ; then
|
||||
MYSQL_ROOT_PW=$_MYSQL_ROOT_PW
|
||||
else
|
||||
echo -e "\n\t\033[33m\033[1mFalsches Passwort\033[m\n"
|
||||
_MYSQL_ROOT_PW=""
|
||||
fi
|
||||
else
|
||||
fatal "MySQL seems not be running. Start MySQL Service and try installing mattermost again."
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
blank_line
|
||||
blank_line
|
||||
echo -e "\033[32mStart upgrade script for Mattermost Server with the following parameters\033[m"
|
||||
echo ""
|
||||
echo -e " Mattermost current Server Version.: $MATTERMOST_CURRENT_VERSION"
|
||||
echo -e " Mattermost current Build Number...: $MATTERMOST_CURRENT_BUILD_NUMBER"
|
||||
echo ""
|
||||
echo -e " Mattermost New Server Version.....: \033[33m\033[1m$MM_NEW_VERSION\033[m"
|
||||
echo ""
|
||||
echo -e " Full qualified Hostname...........: $FQHN_HOSTNAME"
|
||||
echo -e " Hostname..........................: $HOSTNAME"
|
||||
echo ""
|
||||
echo -e " Base path of installation.........: $MATTERMOST_BASE_INSTALL_PATH"
|
||||
echo ""
|
||||
echo -e " TMP directory ....................: $MATTERMOST_TMP_DIR"
|
||||
echo ""
|
||||
echo -e " Mattermost user...................: $MATTERMOST_USER"
|
||||
echo -e " Mattermost group..................: $MATTERMOST_GROUP"
|
||||
echo ""
|
||||
echo ""
|
||||
if [[ "${DB_TYPE}" = "pgsql" ]] ; then
|
||||
echo -e " Database Type.....................: PostgreSQL"
|
||||
else
|
||||
echo -e " Database Type.....................: MySQL"
|
||||
fi
|
||||
echo ""
|
||||
if [[ "${DB_TYPE}" = "mysql" ]]; then
|
||||
if $USE_MYSQL_CREDENTIAL_ARGS ; then
|
||||
echo -e " MYSQL_CREDENTIAL_ARGS.............: $MYSQL_CREDENTIAL_ARGS"
|
||||
else
|
||||
echo -e " Root password MySQL...............: **"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
echo -e " Database Name.....................: $DB_NAME"
|
||||
echo -e " Database User.....................: $DB_USER"
|
||||
echo -e " Database Password.................: $DB_PASS"
|
||||
echo ""
|
||||
echononl "einverstanden (yes/no): "
|
||||
read OK
|
||||
OK=${OK,,}
|
||||
while [ "X$OK" != "Xyes" -a "X$OK" != "Xno" ]; do
|
||||
echononl "Wrong entry! [yes/no]: "
|
||||
read OK
|
||||
OK=${OK,,}
|
||||
done
|
||||
[ $OK = "yes" ] || fatal Repeat with other settings..
|
||||
|
||||
|
||||
blank_line
|
||||
blank_line
|
||||
|
||||
if ! $USE_MYSQL_CREDENTIAL_ARGS ; then
|
||||
MYSQL_CREDENTIAL_ARGS="--user='root' --password=$_MYSQL_ROOT_PW"
|
||||
if ! $(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e 'quit' > /dev/null 2>&1) ; then
|
||||
fatal "Parameter MYSQL_CREDENTIAL_ARGS is given, but a connection to MySQL Service failed.!"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mSome pre-installation stuff..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Download version \033[1m${MM_NEW_VERSION}\033[m of the Mattermost Server.."
|
||||
if [[ ! -f "${working_dir}/mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz" ]]; then
|
||||
wget -P ${working_dir} $DOWNLOAD_URL > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
else
|
||||
echo_skipped
|
||||
fi
|
||||
|
||||
|
||||
# - Deaktiviere Cronjobs
|
||||
# -
|
||||
_backup_crontab_file=/tmp/crontab_root.${backup_date}
|
||||
echononl "Backup Crontab to '$_backup_crontab_file'"
|
||||
crontab -l > $_backup_crontab_file 2> $log_file
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "$(cat $log_file)"
|
||||
fi
|
||||
|
||||
echononl "Remove crontab for root.."
|
||||
crontab -r > $log_file 2>&1
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "$(cat $log_file)"
|
||||
fi
|
||||
|
||||
|
||||
echononl "Extract the Mattermost Server files into TMP directory.."
|
||||
tar -xf ${working_dir}/mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz \
|
||||
-C ${MATTERMOST_TMP_DIR} --transform='s,^[^/]\+,\0-upgrade,'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
echononl "Stop Mattermost Service.."
|
||||
if $(systemctl is-active --quiet service mattermost.service) ; then
|
||||
systemctl stop mattermost.service > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
else
|
||||
echo_skipped
|
||||
fi
|
||||
|
||||
echononl "Backup mattermost database.."
|
||||
if [[ "${DB_TYPE}" = "mysql" ]]; then
|
||||
mysqldump --login-path=local --opt $DB_NAME \
|
||||
> ${MATTERMOST_BASE_INSTALL_PATH}/${DB_NAME}-${backup_date}.sql 2> $log_file
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
else
|
||||
pg_dump -U ${DB_USER} -F p -c ${DB_NAME} -f ${MATTERMOST_BASE_INSTALL_PATH}/${DB_NAME}-${backup_date}.sql 2> $log_file
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
fi
|
||||
|
||||
echononl "Backup mattermost installation directory.."
|
||||
cp -ra ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/ \
|
||||
${MATTERMOST_BASE_INSTALL_PATH}/mattermost-back-${backup_date}/ > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
|
||||
echo
|
||||
echo -e "\033[37m\033[1mUpgrade Mattermost to version $MM_NEW_VERSION ..\033[m"
|
||||
echo
|
||||
|
||||
|
||||
echononl "Remove all files except \e[3mspecial directories\e[0m from within the current mattermost directory."
|
||||
find ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/ ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/ \
|
||||
-mindepth 1 -maxdepth 1 \! \( -type d \( -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/plugins \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/config \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/logs \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/plugins \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/data \) -prune \) | sort | sudo xargs rm -r > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
|
||||
echononl "Change ownership of the new files before copying them.."
|
||||
chown -hR ${MATTERMOST_USER}:${MATTERMOST_GROUP} ${MATTERMOST_TMP_DIR}/mattermost-upgrade/ > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
|
||||
echononl "Copy the new files to your install directory.."
|
||||
cp -an ${MATTERMOST_TMP_DIR}/mattermost-upgrade/. ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/ > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
# Activate the CAP_NET_BIND_SERVICE capability to allow the new Mattermost binary
|
||||
# to bind to low ports.
|
||||
#
|
||||
echononl "Allow the new Mattermost binary to bind to low ports.."
|
||||
setcap cap_net_bind_service=+ep ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mSome post-installation stuff..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Remove the temporary files.."
|
||||
rm -r ${MATTERMOST_TMP_DIR}/mattermost-upgrade/ > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
echononl "Start Mattermost Service"
|
||||
systemctl start mattermost.service > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
clean_up 0
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,691 @@
|
||||
# Mattermost OIDC Mobile Bridge
|
||||
|
||||
## Zweck
|
||||
|
||||
Diese Dokumentation beschreibt die Installation und Konfiguration der `mobile-bridge` aus dem Projekt `mattermost-oidc` für eine native Mattermost-Mobile-App.
|
||||
|
||||
Die Bridge wird benötigt, wenn Mattermost für die Anmeldung das Plugin `mattermost-oidc` verwendet, die native Mobile-App aber den eingebauten Mattermost-OpenID-Endpunkt erwartet. Die Bridge verändert Mattermost selbst nicht. Sie fängt nur zwei HTTP-Endpunkte ab:
|
||||
|
||||
- `/api/v4/config/client`
|
||||
- `/oauth/openid/mobile_login`
|
||||
|
||||
Für die native Mattermost-App wird in der Client-Konfiguration `EnableSignUpWithOpenId=true` signalisiert. Der Mobile-Login wird anschließend zum `mattermost-oidc`-Plugin umgeleitet.
|
||||
|
||||
Web- und Desktop-Clients bleiben unverändert.
|
||||
|
||||
## Versions- und Umgebungsvariablen
|
||||
|
||||
Die Anleitung ist bewusst versionsunabhängig aufgebaut. Vor Beginn werden die für die jeweilige Installation gültigen Versionen, URLs und Pfade einmal in der aktuellen Root-Shell gesetzt. Die nachfolgenden Befehle verwenden diese Variablen.
|
||||
|
||||
```bash
|
||||
export MM_VER="11.7.11"
|
||||
export MM_OIDC_VER="0.6.1"
|
||||
export MM_SITE_URL="https://mm.nd.digital"
|
||||
|
||||
export MM_SRC_BASE="/usr/local/src/mattermost-oidc"
|
||||
export MM_OIDC_REPO="https://github.com/server-camp/mattermost-oidc-plugin.git"
|
||||
export MM_OIDC_SRC="${MM_SRC_BASE}/mattermost-oidc-plugin-${MM_OIDC_VER}"
|
||||
|
||||
export MM_UPSTREAM="http://127.0.0.1:8065"
|
||||
export MM_BRIDGE_LISTEN="127.0.0.1:8066"
|
||||
|
||||
export MM_BRIDGE_BIN_DIR="/usr/local/sbin"
|
||||
export MM_BRIDGE_BIN="${MM_BRIDGE_BIN_DIR}/mattermost-oidc-mobile-bridge-${MM_OIDC_VER}"
|
||||
export MM_BRIDGE_LINK="${MM_BRIDGE_BIN_DIR}/mattermost-oidc-mobile-bridge"
|
||||
```
|
||||
|
||||
`MM_VER` dokumentiert die aktuell eingesetzte Mattermost-Version. Für Download und Build der Bridge ist insbesondere `MM_OIDC_VER` relevant. Bei einer späteren Aktualisierung wird die gewünschte Version im Variablenblock geändert und der Ablauf mit dem neuen Release wiederholt.
|
||||
|
||||
Die hier beschriebene Installation wurde mit den oben beispielhaft eingetragenen Versionen getestet. Weitere Rahmenbedingungen waren Debian 13, nginx als Reverse Proxy, Mattermost auf `127.0.0.1:8065`, die Mobile Bridge auf `127.0.0.1:8066` und Keycloak als OIDC-Provider.
|
||||
|
||||
Die Bridge benötigt **kein eigenes OIDC-Client-Secret**. Client-ID, Client-Secret und Kommunikation mit dem OIDC-Provider bleiben Aufgabe des `mattermost-oidc`-Plugins.
|
||||
|
||||
## Funktionsweise
|
||||
|
||||
Der relevante Ablauf ist:
|
||||
|
||||
```text
|
||||
Mattermost Mobile App
|
||||
|
|
||||
| GET /api/v4/config/client
|
||||
v
|
||||
nginx
|
||||
|
|
||||
+--> mobile-bridge :8066
|
||||
|
|
||||
+--> Mattermost :8065
|
||||
|
|
||||
+--> bei Mobile User-Agent:
|
||||
EnableSignUpWithOpenId=true
|
||||
|
||||
Mobile App
|
||||
|
|
||||
| /oauth/openid/mobile_login?redirect_to=mmauth://callback
|
||||
v
|
||||
nginx
|
||||
|
|
||||
+--> mobile-bridge :8066
|
||||
|
|
||||
+--> 302 /plugins/mattermost-oidc/oauth2/connect
|
||||
?mobile_redirect=mmauth://callback
|
||||
|
|
||||
v
|
||||
Keycloak
|
||||
|
|
||||
v
|
||||
/plugins/mattermost-oidc/oauth2/callback
|
||||
|
|
||||
v
|
||||
mmauth://callback
|
||||
|
|
||||
v
|
||||
Mattermost App
|
||||
```
|
||||
|
||||
Alle anderen Requests, insbesondere REST, WebSocket, Dateien und `/plugins/...`, gehen weiterhin direkt an Mattermost.
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
Vor Installation der Bridge müssen folgende Bedingungen erfüllt sein:
|
||||
|
||||
1. Das Plugin `mattermost-oidc` ist installiert und aktiviert.
|
||||
2. Der normale OIDC-Web-Login funktioniert bereits vollständig.
|
||||
3. Der OIDC-Provider ist korrekt eingerichtet.
|
||||
4. Die bestehende Redirect-URI des Plugins funktioniert:
|
||||
`<SiteURL>/plugins/mattermost-oidc/oauth2/callback`
|
||||
5. nginx leitet die normale Mattermost-Site bereits auf `127.0.0.1:8065` weiter.
|
||||
6. Go ist zum Bauen der Bridge verfügbar.
|
||||
|
||||
Die benötigte Go-Version ist nicht in dieser Anleitung fest verdrahtet. Nach dem Download wird sie direkt aus `mobile-bridge/go.mod` abgelesen. Falls die Debian-Standardversion nicht ausreicht, kann eine passende Go-Version beispielsweise aus den Debian-Backports verwendet werden.
|
||||
|
||||
## 1. Quellcode herunterladen
|
||||
|
||||
Das Repository wird versionsbezogen unter `MM_SRC_BASE` abgelegt. Dadurch können mehrere Release-Stände parallel vorhanden sein und die Herkunft einer installierten Binary bleibt nachvollziehbar.
|
||||
|
||||
Arbeitsverzeichnis anlegen:
|
||||
|
||||
```bash
|
||||
mkdir -p "$MM_SRC_BASE"
|
||||
```
|
||||
|
||||
Gewünschten Release-Tag direkt in ein versionsbezogenes Verzeichnis klonen:
|
||||
|
||||
```bash
|
||||
git clone --branch "v${MM_OIDC_VER}" --depth 1 \
|
||||
"$MM_OIDC_REPO" \
|
||||
"$MM_OIDC_SRC"
|
||||
```
|
||||
|
||||
Ausgecheckten Stand kontrollieren:
|
||||
|
||||
```bash
|
||||
cd "$MM_OIDC_SRC"
|
||||
git status
|
||||
git describe --tags --exact-match
|
||||
```
|
||||
|
||||
Bei einem direkt ausgecheckten Release-Tag ist ein `detached HEAD` normal. `git describe --tags --exact-match` sollte `v${MM_OIDC_VER}` ausgeben.
|
||||
|
||||
Die Mobile Bridge befindet sich anschließend unter:
|
||||
|
||||
```text
|
||||
${MM_OIDC_SRC}/mobile-bridge
|
||||
```
|
||||
|
||||
## 2. Go installieren
|
||||
|
||||
Benötigte Go-Version aus dem Release ermitteln:
|
||||
|
||||
```bash
|
||||
awk '/^go / {print "benötigte Go-Version:", $2}' \
|
||||
"$MM_OIDC_SRC/mobile-bridge/go.mod"
|
||||
```
|
||||
|
||||
Installierte Version prüfen:
|
||||
|
||||
```bash
|
||||
go version
|
||||
```
|
||||
|
||||
Falls die vorhandene Go-Version nicht ausreicht, eine passende Version installieren. Unter Debian 13 kann - sofern `trixie-backports` bereits konfiguriert ist - beispielsweise verwendet werden:
|
||||
|
||||
```bash
|
||||
apt install -t trixie-backports golang-go
|
||||
```
|
||||
|
||||
Danach erneut prüfen:
|
||||
|
||||
```bash
|
||||
go version
|
||||
```
|
||||
|
||||
## 3. Mobile Bridge bauen
|
||||
|
||||
In das Bridge-Verzeichnis wechseln:
|
||||
|
||||
```bash
|
||||
cd "$MM_OIDC_SRC/mobile-bridge"
|
||||
```
|
||||
|
||||
Binary bauen:
|
||||
|
||||
```bash
|
||||
go build -o mobile-bridge .
|
||||
```
|
||||
|
||||
Ergebnis kontrollieren:
|
||||
|
||||
```bash
|
||||
file mobile-bridge
|
||||
ls -lh mobile-bridge
|
||||
```
|
||||
|
||||
## 4. Bridge vor der Installation manuell testen
|
||||
|
||||
Port 8066 sollte zunächst frei sein:
|
||||
|
||||
```bash
|
||||
ss -lntp | grep ':8066'
|
||||
```
|
||||
|
||||
Die Bridge testweise nur auf Loopback starten:
|
||||
|
||||
```bash
|
||||
LISTEN="$MM_BRIDGE_LISTEN" UPSTREAM="$MM_UPSTREAM" ./mobile-bridge
|
||||
```
|
||||
|
||||
Die Bindung an `127.0.0.1` ist beabsichtigt. Die Bridge muss nicht direkt aus dem Internet erreichbar sein; nginx ist der öffentliche Einstiegspunkt.
|
||||
|
||||
### Mobile Client-Konfiguration testen
|
||||
|
||||
In einem zweiten Terminal:
|
||||
|
||||
```bash
|
||||
curl -s -A 'Mattermost Mobile/' \
|
||||
http://127.0.0.1:8066/api/v4/config/client |
|
||||
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
|
||||
```
|
||||
|
||||
Erwartet:
|
||||
|
||||
```text
|
||||
"EnableSignUpWithOpenId":"true"
|
||||
```
|
||||
|
||||
Mit einem Browser-User-Agent:
|
||||
|
||||
```bash
|
||||
curl -s -A 'Mozilla/5.0' \
|
||||
http://127.0.0.1:8066/api/v4/config/client |
|
||||
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
|
||||
```
|
||||
|
||||
Bei der dokumentierten Konfiguration war das Ergebnis:
|
||||
|
||||
```text
|
||||
"EnableSignUpWithOpenId":"false"
|
||||
```
|
||||
|
||||
Damit ist sichergestellt, dass die Änderung nur für die Mobile-App erfolgt.
|
||||
|
||||
### Mobile-Login-Redirect testen
|
||||
|
||||
```bash
|
||||
curl -si \
|
||||
'http://127.0.0.1:8066/oauth/openid/mobile_login?redirect_to=mmauth%3A%2F%2Fcallback' |
|
||||
head -20
|
||||
```
|
||||
|
||||
Erwartet wird HTTP 302 mit einem `Location`-Header in Richtung:
|
||||
|
||||
```text
|
||||
/plugins/mattermost-oidc/oauth2/connect?mobile_redirect=mmauth%3A%2F%2Fcallback
|
||||
```
|
||||
|
||||
Danach den manuellen Prozess mit `Ctrl-C` beenden.
|
||||
|
||||
## 5. Binary versionsbezogen installieren
|
||||
|
||||
Die gebaute Bridge wird mit ihrer Plugin-/Bridge-Version im Dateinamen unter `/usr/local/sbin` installiert. Ein stabiler Symlink ohne Versionsnummer zeigt auf die aktuell aktive Binary. Dadurch kann ein Update oder Rollback durch Umschalten des Symlinks erfolgen, während die systemd-Unit unverändert bleibt.
|
||||
|
||||
Binary installieren:
|
||||
|
||||
```bash
|
||||
install -o root -g root -m 755 \
|
||||
mobile-bridge \
|
||||
"$MM_BRIDGE_BIN"
|
||||
```
|
||||
|
||||
Stabilen Symlink auf diese Version setzen:
|
||||
|
||||
```bash
|
||||
ln -sfn "$(basename "$MM_BRIDGE_BIN")" "$MM_BRIDGE_LINK"
|
||||
```
|
||||
|
||||
Ergebnis kontrollieren:
|
||||
|
||||
```bash
|
||||
ls -l "$MM_BRIDGE_BIN" "$MM_BRIDGE_LINK"
|
||||
readlink -f "$MM_BRIDGE_LINK"
|
||||
```
|
||||
|
||||
Beispiel für Version `0.6.1`:
|
||||
|
||||
```text
|
||||
/usr/local/sbin/mattermost-oidc-mobile-bridge-0.6.1
|
||||
/usr/local/sbin/mattermost-oidc-mobile-bridge -> mattermost-oidc-mobile-bridge-0.6.1
|
||||
```
|
||||
|
||||
## 6. systemd-Service einrichten
|
||||
|
||||
Datei anlegen:
|
||||
|
||||
```text
|
||||
/etc/systemd/system/mattermost-oidc-mobile-bridge.service
|
||||
```
|
||||
|
||||
Inhalt:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Mattermost OIDC Mobile Bridge
|
||||
After=network.target mattermost.service
|
||||
Requires=mattermost.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=mattermost
|
||||
Group=mattermost
|
||||
Environment=LISTEN=127.0.0.1:8066
|
||||
Environment=UPSTREAM=http://127.0.0.1:8065
|
||||
ExecStart=/usr/local/sbin/mattermost-oidc-mobile-bridge
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
`ExecStart` verweist bewusst auf den versionsunabhängigen Symlink. Bei einem Update muss die Unit-Datei deshalb nicht geändert werden.
|
||||
|
||||
Konfiguration laden und prüfen:
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemd-analyze verify /etc/systemd/system/mattermost-oidc-mobile-bridge.service
|
||||
```
|
||||
|
||||
Dienst zunächst nur starten:
|
||||
|
||||
```bash
|
||||
systemctl start mattermost-oidc-mobile-bridge.service
|
||||
```
|
||||
|
||||
Status prüfen:
|
||||
|
||||
```bash
|
||||
systemctl status mattermost-oidc-mobile-bridge.service
|
||||
ss -lntp | grep ':8066'
|
||||
```
|
||||
|
||||
Erwartet wird ein Listener ausschließlich auf:
|
||||
|
||||
```text
|
||||
127.0.0.1:8066
|
||||
```
|
||||
|
||||
Nach erfolgreichem End-to-End-Test den Autostart aktivieren:
|
||||
|
||||
```bash
|
||||
systemctl enable mattermost-oidc-mobile-bridge.service
|
||||
```
|
||||
|
||||
Kontrolle:
|
||||
|
||||
```bash
|
||||
systemctl is-enabled mattermost-oidc-mobile-bridge.service
|
||||
systemctl is-active mattermost-oidc-mobile-bridge.service
|
||||
```
|
||||
|
||||
Erwartet:
|
||||
|
||||
```text
|
||||
enabled
|
||||
active
|
||||
```
|
||||
|
||||
## 7. nginx konfigurieren
|
||||
|
||||
In der dokumentierten Installation ist die aktive Konfiguration:
|
||||
|
||||
```text
|
||||
/etc/nginx/sites-available/mm.nd.digital.conf
|
||||
```
|
||||
|
||||
mit Symlink unter `sites-enabled`.
|
||||
|
||||
Vor der Änderung ein Backup der realen Datei anlegen, nicht nur des Symlinks.
|
||||
|
||||
Vor den allgemeinen Mattermost-`location`-Blöcken werden zwei Exact-Match-Locations eingefügt:
|
||||
|
||||
```nginx
|
||||
# Mattermost OIDC Mobile Bridge
|
||||
location = /api/v4/config/client {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass http://127.0.0.1:8066;
|
||||
}
|
||||
|
||||
location = /oauth/openid/mobile_login {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass http://127.0.0.1:8066;
|
||||
}
|
||||
```
|
||||
|
||||
Die vorhandenen WebSocket- und Catch-all-Locations bleiben unverändert und zeigen weiterhin direkt auf Mattermost.
|
||||
|
||||
Die Exact-Match-Locations sind wichtig: Nur diese beiden Endpunkte sollen über die Bridge laufen.
|
||||
|
||||
Konfiguration prüfen:
|
||||
|
||||
```bash
|
||||
nginx -t
|
||||
```
|
||||
|
||||
Bei erfolgreicher Prüfung:
|
||||
|
||||
```bash
|
||||
systemctl reload nginx
|
||||
```
|
||||
|
||||
## 8. Öffentliche Endpunkte testen
|
||||
|
||||
### Mobile User-Agent
|
||||
|
||||
```bash
|
||||
curl -s -A 'Mattermost Mobile/' \
|
||||
${MM_SITE_URL}/api/v4/config/client |
|
||||
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
|
||||
```
|
||||
|
||||
Erwartet:
|
||||
|
||||
```text
|
||||
"EnableSignUpWithOpenId":"true"
|
||||
```
|
||||
|
||||
### Browser User-Agent
|
||||
|
||||
```bash
|
||||
curl -s -A 'Mozilla/5.0' \
|
||||
${MM_SITE_URL}/api/v4/config/client |
|
||||
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
|
||||
```
|
||||
|
||||
Bei der dokumentierten Installation:
|
||||
|
||||
```text
|
||||
"EnableSignUpWithOpenId":"false"
|
||||
```
|
||||
|
||||
### Mobile Login
|
||||
|
||||
```bash
|
||||
curl -si \
|
||||
"${MM_SITE_URL}/oauth/openid/mobile_login?redirect_to=mmauth%3A%2F%2Fcallback" |
|
||||
head -20
|
||||
```
|
||||
|
||||
Erwartet wird HTTP 302 auf den Connect-Endpunkt des OIDC-Plugins.
|
||||
|
||||
## 9. End-to-End-Test mit der Mattermost-App
|
||||
|
||||
In der nativen Mattermost-App:
|
||||
|
||||
1. Server aus `MM_SITE_URL` hinzufügen (im dokumentierten Beispiel `https://mm.nd.digital`).
|
||||
2. Die App muss zusätzlich zur normalen Anmeldung einen Button **Log in with OIDC** anzeigen.
|
||||
3. OIDC-Login auswählen.
|
||||
4. Bei Keycloak anmelden.
|
||||
5. Nach erfolgreicher Authentifizierung muss die App über `mmauth://callback` zurückkehren.
|
||||
6. Team und Channels müssen anschließend geladen werden.
|
||||
|
||||
## 10. Wichtiger Sonderfall: Default Team und erlaubte E-Mail-Domains
|
||||
|
||||
Das `mattermost-oidc`-Plugin kann neu angelegte OIDC-Benutzer automatisch einem **Default Team** hinzufügen.
|
||||
|
||||
In der dokumentierten Installation ist im Plugin konfiguriert:
|
||||
|
||||
```text
|
||||
Default Team: nd
|
||||
```
|
||||
|
||||
Das Team `nd` erlaubt jedoch nur Benutzer mit einer bestimmten E-Mail-Domain:
|
||||
|
||||
```text
|
||||
nd-online.de
|
||||
```
|
||||
|
||||
Beim Test wurde ein OIDC-Benutzer mit einer anderen Domain erfolgreich angelegt und authentifiziert, konnte aber nicht automatisch dem Team `nd` hinzugefügt werden. Mattermost protokollierte sinngemäß:
|
||||
|
||||
```text
|
||||
Failed to add user to default team
|
||||
The user cannot be added as the domain associated with the account is not permitted.
|
||||
```
|
||||
|
||||
Das Fehlerbild in der Mobile-App war:
|
||||
|
||||
```text
|
||||
Konnte nicht geladen werden
|
||||
```
|
||||
|
||||
Das Profil des angemeldeten Benutzers war trotzdem erreichbar. Ursache war **nicht die Mobile Bridge und nicht der OIDC-Token**, sondern die fehlende Team-Mitgliedschaft.
|
||||
|
||||
### Diagnose
|
||||
|
||||
Team-Domain aus PostgreSQL nur lesend prüfen:
|
||||
|
||||
```bash
|
||||
su - postgres -c \
|
||||
"psql -d mattermost -c \"SELECT name, displayname, type, allowopeninvite, alloweddomains FROM teams WHERE name='nd';\""
|
||||
```
|
||||
|
||||
Alternativ in der System Console:
|
||||
|
||||
```text
|
||||
User Management
|
||||
-> Teams
|
||||
-> ND
|
||||
-> Team Management
|
||||
-> Only specific email domains can join this team
|
||||
```
|
||||
|
||||
Wenn ein Testbenutzer aus einer anderen Domain verwendet wird, sollte die Domain-Beschränkung **nicht dauerhaft aufgeweicht** werden.
|
||||
|
||||
Für den dokumentierten Test wurde die zusätzliche Testdomain kurzzeitig in der kommagetrennten Domainliste zugelassen, der Testbenutzer administrativ zum Team hinzugefügt und die Domainliste anschließend wieder auf den ursprünglichen Wert zurückgesetzt.
|
||||
|
||||
## 11. Logs und Fehlersuche
|
||||
|
||||
### Bridge
|
||||
|
||||
Status:
|
||||
|
||||
```bash
|
||||
systemctl status mattermost-oidc-mobile-bridge.service
|
||||
```
|
||||
|
||||
Journal:
|
||||
|
||||
```bash
|
||||
journalctl -u mattermost-oidc-mobile-bridge.service
|
||||
```
|
||||
|
||||
Für eine gezielte Fehlersuche kann die Bridge mit `DEBUG=1` betrieben werden. Dies sollte nur bei Bedarf aktiviert werden, da dann beobachtete User-Agents protokolliert werden.
|
||||
|
||||
### Mattermost
|
||||
|
||||
```bash
|
||||
journalctl -u mattermost.service
|
||||
```
|
||||
|
||||
Bei OIDC-Problemen insbesondere nach Meldungen mit folgenden Begriffen suchen:
|
||||
|
||||
```text
|
||||
oidc
|
||||
mobile
|
||||
session
|
||||
mattermost-oidc
|
||||
```
|
||||
|
||||
### Typische Fehlerbilder
|
||||
|
||||
**Kein OIDC-Button in der App**
|
||||
|
||||
Prüfen:
|
||||
|
||||
- `mattermost-oidc` ist aktiviert.
|
||||
- Web-OIDC funktioniert.
|
||||
- `/api/v4/config/client` wird für Mobile User-Agents über die Bridge geleitet.
|
||||
- `EnableSignUpWithOpenId` ist für `Mattermost Mobile/` auf `true`.
|
||||
- nginx wurde nach der Änderung erfolgreich neu geladen.
|
||||
|
||||
**OIDC-Button erscheint, Login startet nicht korrekt**
|
||||
|
||||
Prüfen:
|
||||
|
||||
- `/oauth/openid/mobile_login` liefert HTTP 302.
|
||||
- Ziel ist `/plugins/mattermost-oidc/oauth2/connect`.
|
||||
- nginx routet exakt diesen Endpunkt auf Port 8066.
|
||||
|
||||
**Login bei Keycloak erfolgreich, App lädt aber kein Team**
|
||||
|
||||
Prüfen:
|
||||
|
||||
- Wurde der Benutzer in Mattermost angelegt?
|
||||
- Ist der Benutzer Mitglied eines Teams?
|
||||
- Ist im OIDC-Plugin ein `Default Team` konfiguriert?
|
||||
- Verhindert `AllowedDomains` des Teams das automatische Hinzufügen?
|
||||
|
||||
## 12. Umgebungsvariablen der Bridge
|
||||
|
||||
Die Bridge unterstützt laut Projekt-README folgende Variablen:
|
||||
|
||||
| Variable | Standard | Zweck |
|
||||
|---|---|---|
|
||||
| `LISTEN` | `:8066` | Listen-Adresse |
|
||||
| `UPSTREAM` | `http://127.0.0.1:8065` | Mattermost-Upstream |
|
||||
| `PLUGIN_CONNECT_PATH` | `/plugins/mattermost-oidc/oauth2/connect` | Connect-Endpunkt des Plugins |
|
||||
| `PLUGIN_CONFIG_PATH` | `/plugins/mattermost-oidc/api/v1/config` | öffentliche Plugin-Konfiguration |
|
||||
| `MOBILE_UA_MATCH` | `Mattermost Mobile/` | Erkennung der nativen App |
|
||||
| `OPENID_BUTTON_TEXT` | leer / automatisch | optionaler fester Button-Text |
|
||||
| `OPENID_BUTTON_COLOR` | leer / automatisch | optionale feste Button-Farbe |
|
||||
| `DEBUG` | leer | bei `1` User-Agent-Logging |
|
||||
|
||||
In der dokumentierten Installation werden nur `LISTEN` und `UPSTREAM` explizit gesetzt. Die übrigen Werte bleiben auf den Defaults.
|
||||
|
||||
## 13. Update der Bridge
|
||||
|
||||
Für ein Update wird die neue Version zunächst im Variablenblock als `MM_OIDC_VER` gesetzt. `MM_OIDC_SRC` und `MM_BRIDGE_BIN` ergeben sich daraus automatisch. Die bisherige versionsbezogene Binary bleibt zunächst erhalten.
|
||||
|
||||
Beispiel: Variablenblock mit der gewünschten neuen Version erneut setzen und anschließend den Release wie in Abschnitt 1 herunterladen. Danach:
|
||||
|
||||
```bash
|
||||
cd "$MM_OIDC_SRC/mobile-bridge"
|
||||
go build -o mobile-bridge .
|
||||
```
|
||||
|
||||
Neue versionsbezogene Binary installieren:
|
||||
|
||||
```bash
|
||||
install -o root -g root -m 755 \
|
||||
mobile-bridge \
|
||||
"$MM_BRIDGE_BIN"
|
||||
```
|
||||
|
||||
Vor dem Umschalten kontrollieren:
|
||||
|
||||
```bash
|
||||
file "$MM_BRIDGE_BIN"
|
||||
ls -lh "$MM_BRIDGE_BIN"
|
||||
```
|
||||
|
||||
Symlink atomar auf die neue Version umstellen und Dienst neu starten:
|
||||
|
||||
```bash
|
||||
ln -sfn "$(basename "$MM_BRIDGE_BIN")" "$MM_BRIDGE_LINK"
|
||||
systemctl restart mattermost-oidc-mobile-bridge.service
|
||||
systemctl is-active mattermost-oidc-mobile-bridge.service
|
||||
readlink -f "$MM_BRIDGE_LINK"
|
||||
```
|
||||
|
||||
Danach die HTTP-Tests und einen Mobile-Login erneut durchführen. Die alte versionsbezogene Binary sollte erst entfernt werden, wenn der neue Stand erfolgreich getestet wurde.
|
||||
|
||||
## 14. Rollback
|
||||
|
||||
Soll die Bridge wieder entfernt werden:
|
||||
|
||||
1. Die beiden Exact-Match-`location`-Blöcke aus nginx entfernen.
|
||||
2. `nginx -t` ausführen.
|
||||
3. nginx neu laden.
|
||||
4. Bridge stoppen und deaktivieren.
|
||||
5. Optional Unit-Datei und Binary entfernen.
|
||||
|
||||
### Rollback auf eine vorherige Bridge-Version
|
||||
|
||||
Solange die vorherige versionsbezogene Binary noch vorhanden ist, genügt es, den Symlink zurückzusetzen und den Dienst neu zu starten. Beispiel:
|
||||
|
||||
```bash
|
||||
ln -sfn mattermost-oidc-mobile-bridge-<vorherige-version> \
|
||||
/usr/local/sbin/mattermost-oidc-mobile-bridge
|
||||
systemctl restart mattermost-oidc-mobile-bridge.service
|
||||
readlink -f /usr/local/sbin/mattermost-oidc-mobile-bridge
|
||||
```
|
||||
|
||||
### Bridge vollständig entfernen
|
||||
|
||||
```bash
|
||||
systemctl disable --now mattermost-oidc-mobile-bridge.service
|
||||
rm -f /etc/systemd/system/mattermost-oidc-mobile-bridge.service
|
||||
systemctl daemon-reload
|
||||
rm -f /usr/local/sbin/mattermost-oidc-mobile-bridge
|
||||
# Versionsbezogene Binaries bei Bedarf anschließend gezielt entfernen.
|
||||
```
|
||||
|
||||
Das `mattermost-oidc`-Plugin und der normale Web-OIDC-Login können dabei unverändert weiterbetrieben werden.
|
||||
|
||||
## 15. Sicherheitsaspekte
|
||||
|
||||
- Die Bridge nur auf `127.0.0.1:8066` binden.
|
||||
- Port 8066 nicht öffentlich in der Firewall freigeben.
|
||||
- Nur die beiden benötigten Exact-Match-Endpunkte über nginx zur Bridge leiten.
|
||||
- Keine OIDC-Secrets in die systemd-Unit eintragen; die Bridge benötigt keine.
|
||||
- Client Secret und andere Zugangsdaten nicht in Dokumentationen oder Logs übernehmen.
|
||||
- Nach Änderungen an OIDC immer Web- und Mobile-Login testen.
|
||||
- Team-Domain-Beschränkungen nicht nur für einen Test dauerhaft erweitern.
|
||||
|
||||
## 16. Abschlusskontrolle
|
||||
|
||||
Nach einer vollständigen Installation sollten folgende Prüfungen erfolgreich sein:
|
||||
|
||||
```bash
|
||||
systemctl is-enabled mattermost-oidc-mobile-bridge.service
|
||||
systemctl is-active mattermost-oidc-mobile-bridge.service
|
||||
ss -lntp | grep ':8066'
|
||||
nginx -t
|
||||
```
|
||||
|
||||
Zusätzlich:
|
||||
|
||||
```text
|
||||
Mobile UA -> EnableSignUpWithOpenId=true
|
||||
Browser UA -> unveränderte Mattermost-Konfiguration
|
||||
mobile_login -> HTTP 302 zum mattermost-oidc-Plugin
|
||||
Web-OIDC -> funktioniert
|
||||
Mobile-OIDC -> funktioniert
|
||||
Team/Channels -> werden in der App geladen
|
||||
```
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
# Mattermost CLI (mmctl) – Anmeldung & Admin-Nutzerverwaltung
|
||||
|
||||
Diese Anleitung beschreibt, wie du `mmctl` per **Login-Modus** (Variante 2) nutzt, statt über den Local-Socket-Modus. Damit brauchst du kein `sudo` und keine Serverkonfiguration anzupassen.
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Mattermost läuft und ist unter einer URL erreichbar (lokal z. B. `http://localhost:8065`)
|
||||
- Du hast bereits einen bestehenden System-Admin-Account (Username + Passwort)
|
||||
- `mmctl` ist installiert (z. B. unter `/opt/mattermost/bin/mmctl`)
|
||||
|
||||
---
|
||||
|
||||
## 1. Bei mmctl anmelden
|
||||
|
||||
/opt/mattermost/bin/mmctl auth login http://localhost:8065 \
|
||||
--name local-admin \
|
||||
--username <dein-admin-username> \
|
||||
--password <dein-admin-passwort>
|
||||
|
||||
# alternativ: zunächst das passwort in einer Datei speichern und dies dann bei der
|
||||
# Authentifizierung einlesen:
|
||||
#
|
||||
cat << EOF > /tmp/.mm-admin-nd.auth
|
||||
9-ULw6j-RRZsF./p
|
||||
EOF
|
||||
|
||||
/opt/mattermost/bin/mmctl auth login http://localhost:8065 \
|
||||
--name local-admin \
|
||||
--username admin-nd \
|
||||
--password-file /tmp/.mm-admin-nd.auth
|
||||
|
||||
|
||||
**Parameter-Erklärung:**
|
||||
|
||||
| Parameter | Bedeutung
|
||||
|-------------------------|-----------
|
||||
| `http://localhost:8065` | URL deines Mattermost-Servers
|
||||
| `--name local-admin` | Frei wählbarer Name für dieses Login-Profil (wird lokal gespeichert)
|
||||
| `--username` | Dein bestehender Admin-Benutzername
|
||||
| `--password` | Dein bestehendes Admin-Passwort
|
||||
|
||||
Nach erfolgreichem Login speichert `mmctl` die Session lokal (unter `~/.config/mmctl/`), sodass du dich nicht bei jedem Befehl neu anmelden musst.
|
||||
|
||||
**Kein `sudo` nötig** - die Authentifizierung läuft über die normale API, nicht über den geschützten Unix-Socket.
|
||||
|
||||
---
|
||||
|
||||
## 2. Login prüfen (optional)
|
||||
|
||||
/opt/mattermost/bin/mmctl auth list
|
||||
|
||||
Zeigt alle gespeicherten Login-Profile. Das aktive Profil ist markiert.
|
||||
|
||||
Falls du mehrere Profile hast und wechseln willst:
|
||||
|
||||
/opt/mattermost/bin/mmctl auth set local-admin
|
||||
|
||||
---
|
||||
|
||||
## 3. Neuen System-Admin-Nutzer anlegen
|
||||
|
||||
/opt/mattermost/bin/mmctl user create \
|
||||
--email "l.nienhaus@nd-online.de" \
|
||||
--username "admin-nd" \
|
||||
--password "EinSicheresPasswort123!" \
|
||||
--system-admin
|
||||
|
||||
**Parameter-Erklärung:**
|
||||
|
||||
| Parameter | Bedeutung
|
||||
|------------------|----------
|
||||
| `--email` | E-Mail-Adresse des neuen Nutzers
|
||||
| `--username` | Gewünschter Benutzername
|
||||
| `--password` | Startpasswort (sollte sicher sein, Nutzer kann es später ändern)
|
||||
| `--system-admin` | Vergibt sofort die System-Admin-Rolle
|
||||
|
||||
---
|
||||
|
||||
## 4. Bestehenden Nutzer nachträglich zum Admin machen
|
||||
|
||||
Falls der Nutzer schon existiert und nur die Rolle fehlt:
|
||||
|
||||
/opt/mattermost/bin/mmctl roles system_admin <username-oder-email>
|
||||
|
||||
---
|
||||
|
||||
## 5. Kontrolle: Nutzerliste anzeigen
|
||||
|
||||
/opt/mattermost/bin/mmctl user list
|
||||
|
||||
Zeigt alle registrierten Nutzer inkl. E-Mail und Rollen.
|
||||
|
||||
---
|
||||
|
||||
## 6. Abmelden (optional, für saubere Sessions)
|
||||
|
||||
/opt/mattermost/bin/mmctl auth clean
|
||||
|
||||
Löscht alle gespeicherten Login-Profile.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Fehler | Ursache | Lösung |
|
||||
|------------------------------------------------- | ------------------------- |---------------------------
|
||||
| `socket file "/var/tmp/mattermost_local.socket" | mmctl versucht Local Mode | Erst `mmctl auth login`
|
||||
| doesn't exist` | statt Login-Modus | ausführen (siehe Schritt 1)
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
| `Error: You are not logged in` | Session abgelaufen oder | Schritt 1 wiederholen
|
||||
| | nicht angemeldet |
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
| `command not found: mmctl` | mmctl nicht im PATH | Vollen Pfad nutzen, z. B.
|
||||
| | |`/opt/mattermost/bin/mmctl`
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
| Verbindung schlägt fehl (`connection refused`) | Falsche URL oder Server | URL/Port prüfen,
|
||||
| | läuft nicht | `systemctl status mattermost`
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
---
|
||||
|
||||
## Kurzreferenz (Cheat Sheet)
|
||||
|
||||
# Anmelden
|
||||
/opt/mattermost/bin/mmctl auth login http://localhost:8065 --name local-admin --username <user> --password <pass>
|
||||
|
||||
# Neuen Admin anlegen
|
||||
/opt/mattermost/bin/mmctl user create --email "<email>" --username "<user>" --password "<pass>" --system-admin
|
||||
|
||||
# Bestehenden Nutzer zum Admin machen
|
||||
/opt/mattermost/bin/mmctl roles system_admin <username-oder-email>
|
||||
|
||||
# Nutzerliste anzeigen
|
||||
/opt/mattermost/bin/mmctl user list
|
||||
|
||||
# Abmelden / Session löschen
|
||||
/opt/mattermost/bin/mmctl auth clean
|
||||
@@ -0,0 +1,131 @@
|
||||
# Mattermost CLI (mmctl) – Anmeldung & Admin-Nutzerverwaltung
|
||||
|
||||
Diese Anleitung beschreibt, wie du `mmctl` per **Login-Modus** (Variante 2) nutzt, statt über den Local-Socket-Modus. Damit brauchst du kein `sudo` und keine Serverkonfiguration anzupassen.
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Mattermost läuft und ist unter einer URL erreichbar (lokal z. B. `http://localhost:8065`)
|
||||
- Du hast bereits einen bestehenden System-Admin-Account (Username + Passwort)
|
||||
- `mmctl` ist installiert (z. B. unter `/opt/mattermost/bin/mmctl`)
|
||||
|
||||
---
|
||||
|
||||
## 1. Bei mmctl anmelden
|
||||
|
||||
```bash
|
||||
mmctl auth login http://localhost:8065 --name local-admin --username <dein-admin-username> --password <dein-admin-passwort>
|
||||
```
|
||||
|
||||
**Parameter-Erklärung:**
|
||||
|
||||
| Parameter | Bedeutung |
|
||||
|---|---|
|
||||
| `http://localhost:8065` | URL deines Mattermost-Servers |
|
||||
| `--name local-admin` | Frei wählbarer Name für dieses Login-Profil (wird lokal gespeichert) |
|
||||
| `--username` | Dein bestehender Admin-Benutzername |
|
||||
| `--password` | Dein bestehendes Admin-Passwort |
|
||||
|
||||
Nach erfolgreichem Login speichert `mmctl` die Session lokal (unter `~/.config/mmctl/`), sodass du dich nicht bei jedem Befehl neu anmelden musst.
|
||||
|
||||
**Kein `sudo` nötig** – die Authentifizierung läuft über die normale API, nicht über den geschützten Unix-Socket.
|
||||
|
||||
---
|
||||
|
||||
## 2. Login prüfen (optional)
|
||||
|
||||
```bash
|
||||
mmctl auth list
|
||||
```
|
||||
|
||||
Zeigt alle gespeicherten Login-Profile. Das aktive Profil ist markiert.
|
||||
|
||||
Falls du mehrere Profile hast und wechseln willst:
|
||||
|
||||
```bash
|
||||
mmctl auth set local-admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Neuen System-Admin-Nutzer anlegen
|
||||
|
||||
```bash
|
||||
mmctl user create \
|
||||
--email "l.nienhaus@nd-online.de" \
|
||||
--username "admin-nd" \
|
||||
--password "EinSicheresPasswort123!" \
|
||||
--system-admin
|
||||
```
|
||||
|
||||
**Parameter-Erklärung:**
|
||||
|
||||
| Parameter | Bedeutung |
|
||||
|---|---|
|
||||
| `--email` | E-Mail-Adresse des neuen Nutzers |
|
||||
| `--username` | Gewünschter Benutzername |
|
||||
| `--password` | Startpasswort (sollte sicher sein, Nutzer kann es später ändern) |
|
||||
| `--system-admin` | Vergibt sofort die System-Admin-Rolle |
|
||||
|
||||
---
|
||||
|
||||
## 4. Bestehenden Nutzer nachträglich zum Admin machen
|
||||
|
||||
Falls der Nutzer schon existiert und nur die Rolle fehlt:
|
||||
|
||||
```bash
|
||||
mmctl roles system_admin <username-oder-email>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Kontrolle: Nutzerliste anzeigen
|
||||
|
||||
```bash
|
||||
mmctl user list
|
||||
```
|
||||
|
||||
Zeigt alle registrierten Nutzer inkl. E-Mail und Rollen.
|
||||
|
||||
---
|
||||
|
||||
## 6. Abmelden (optional, für saubere Sessions)
|
||||
|
||||
```bash
|
||||
mmctl auth clean
|
||||
```
|
||||
|
||||
Löscht alle gespeicherten Login-Profile.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Fehler | Ursache | Lösung |
|
||||
|---|---|---|
|
||||
| `socket file "/var/tmp/mattermost_local.socket" doesn't exist` | mmctl versucht Local Mode statt Login-Modus | Erst `mmctl auth login` ausführen (siehe Schritt 1) |
|
||||
| `Error: You are not logged in` | Session abgelaufen oder nicht angemeldet | Schritt 1 wiederholen |
|
||||
| `command not found: mmctl` | mmctl nicht im PATH | Vollen Pfad nutzen, z. B. `/opt/mattermost/bin/mmctl` |
|
||||
| Verbindung schlägt fehl (`connection refused`) | Falsche URL oder Server läuft nicht | URL/Port prüfen, `systemctl status mattermost` |
|
||||
|
||||
---
|
||||
|
||||
## Kurzreferenz (Cheat Sheet)
|
||||
|
||||
```bash
|
||||
# Anmelden
|
||||
mmctl auth login http://localhost:8065 --name local-admin --username <user> --password <pass>
|
||||
|
||||
# Neuen Admin anlegen
|
||||
mmctl user create --email "<email>" --username "<user>" --password "<pass>" --system-admin
|
||||
|
||||
# Bestehenden Nutzer zum Admin machen
|
||||
mmctl roles system_admin <username-oder-email>
|
||||
|
||||
# Nutzerliste anzeigen
|
||||
mmctl user list
|
||||
|
||||
# Abmelden / Session löschen
|
||||
mmctl auth clean
|
||||
```
|
||||
@@ -100,6 +100,10 @@ EOF
|
||||
#
|
||||
apt install poppler-utils
|
||||
|
||||
# Install ffmpeg
|
||||
#
|
||||
apt install ffmpeg
|
||||
|
||||
|
||||
# ---
|
||||
# 1.) Install Mattermost Service
|
||||
|
||||
@@ -17,8 +17,9 @@ server {
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
listen 443 ssl ;
|
||||
listen [::]:443 ssl ;
|
||||
http2 on;
|
||||
|
||||
server_name @FQHN_HOSTNAME@;
|
||||
|
||||
@@ -28,8 +29,6 @@ server {
|
||||
#
|
||||
include snippets/letsencrypt-acme-challenge.conf;
|
||||
|
||||
#ssl on;
|
||||
|
||||
ssl_certificate /var/lib/dehydrated/certs/@FQHN_HOSTNAME@/fullchain.pem;
|
||||
ssl_certificate_key /var/lib/dehydrated/certs/@FQHN_HOSTNAME@/privkey.pem;
|
||||
ssl_trusted_certificate /var/lib/dehydrated/certs/@FQHN_HOSTNAME@/chain.pem;
|
||||
@@ -51,15 +50,24 @@ server {
|
||||
# omit TLSv1 TLSv1.1
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
# Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to
|
||||
# prevent replay attacks.
|
||||
#
|
||||
# @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
|
||||
ssl_early_data on;
|
||||
|
||||
# ECDHE better than DHE (faster) ECDHE & DHE GCM better than CBC (attacks on AES)
|
||||
# Everything better than SHA1 (deprecated)
|
||||
#
|
||||
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1:secp384r1;
|
||||
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;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
|
||||
#
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
add_header X-Early-Data $tls1_3_early_data;
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
|
||||
# OCSP Stapling ---
|
||||
# fetch OCSP records from URL in ssl_certificate and cache them
|
||||
@@ -74,7 +82,6 @@ server {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Frame-Options SAMEORIGIN;
|
||||
proxy_buffers 256 16k;
|
||||
proxy_buffer_size 16k;
|
||||
client_body_timeout 60;
|
||||
@@ -93,7 +100,6 @@ server {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Frame-Options SAMEORIGIN;
|
||||
proxy_buffers 256 16k;
|
||||
proxy_buffer_size 16k;
|
||||
proxy_read_timeout 600s;
|
||||
|
||||
+442
-586
File diff suppressed because it is too large
Load Diff
Executable
+977
@@ -0,0 +1,977 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
script_name="$(basename $(realpath $0))"
|
||||
working_dir="$(dirname $(realpath $0))"
|
||||
|
||||
LOCK_DIR="/tmp/$(basename $0).$$.LOCK"
|
||||
log_file="${LOCK_DIR}/${script_name%%.*}.log"
|
||||
|
||||
backup_date="$(date +%Y-%m-%d-%H%M%S)"
|
||||
|
||||
MM_OIDC_REPOSITORY="https://github.com/server-camp/mattermost-oidc-plugin.git"
|
||||
MM_OIDC_RELEASE_BASE="https://github.com/server-camp/mattermost-oidc-plugin/releases/download"
|
||||
MM_OIDC_PLUGIN_ID="mattermost-oidc"
|
||||
MM_SOURCE_BASE="/usr/local/src/mattermost"
|
||||
MM_INSTALL_DIR="/opt/mattermost"
|
||||
MM_BIN="${MM_INSTALL_DIR}/bin/mattermost"
|
||||
MMCTL="${MM_INSTALL_DIR}/bin/mmctl"
|
||||
MM_CONFIG_FILE="${MM_INSTALL_DIR}/config/config.json"
|
||||
MM_LOCAL_SOCKET="/var/tmp/mattermost_local.socket"
|
||||
MM_SERVICE="mattermost.service"
|
||||
MM_USER="mattermost"
|
||||
MM_GROUP="mattermost"
|
||||
|
||||
INSTALLATION_MODE=""
|
||||
MM_CURRENT_VERSION=""
|
||||
MM_NEW_VERSION=""
|
||||
MM_LATEST_VERSION=""
|
||||
MM_MIN_SERVER_VERSION=""
|
||||
MM_SERVER_VERSION=""
|
||||
MM_BUNDLE=""
|
||||
MM_BUNDLE_BACKUP=""
|
||||
|
||||
MM_ROLLBACK_BUNDLE=""
|
||||
MM_PREVIOUS_PLUGIN_ENABLED=false
|
||||
MM_ROLLBACK_REQUIRED=false
|
||||
|
||||
|
||||
# ----------
|
||||
# Base Function(s)
|
||||
# ----------
|
||||
|
||||
clean_up() {
|
||||
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 ""
|
||||
clean_up 1
|
||||
}
|
||||
|
||||
error (){
|
||||
echo ""
|
||||
if $terminal ; then
|
||||
echo -e " [ \033[31m\033[1mError\033[m ] $*"
|
||||
else
|
||||
echo " [ Error ] $*"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
warn (){
|
||||
echo ""
|
||||
if $terminal ; then
|
||||
echo -e " [ \033[33m\033[1mWarning\033[m ] $*"
|
||||
else
|
||||
echo " [ Warning ] $*"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
info (){
|
||||
if $terminal ; then
|
||||
echo ""
|
||||
echo -e " [ \033[32m\033[1mInfo\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[33m\033[1mskipped\033[m ]"
|
||||
fi
|
||||
}
|
||||
|
||||
blank_line() {
|
||||
if $terminal ; then
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
ask_yes_no() {
|
||||
local question="$1"
|
||||
local default_answer="${2:-no}"
|
||||
local answer=""
|
||||
local prompt="[yes/no]"
|
||||
|
||||
if [[ "$default_answer" = "yes" ]]; then
|
||||
prompt="[yes/no, default: yes]"
|
||||
elif [[ "$default_answer" = "no" ]]; then
|
||||
prompt="[yes/no, default: no]"
|
||||
fi
|
||||
|
||||
while true ; do
|
||||
echononl "$question $prompt: "
|
||||
read answer
|
||||
answer="${answer,,}"
|
||||
[[ -z "$answer" ]] && answer="$default_answer"
|
||||
case "$answer" in
|
||||
yes) return 0 ;;
|
||||
no) return 1 ;;
|
||||
*) warn "Wrong entry! Please enter 'yes' or 'no'." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
version_ge() {
|
||||
[[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -1)" = "$2" ]]
|
||||
}
|
||||
|
||||
plugin_state_json() {
|
||||
"$MMCTL" --local --json plugin list 2>> "$log_file"
|
||||
}
|
||||
|
||||
installed_plugin_version() {
|
||||
plugin_state_json | python3 -c '
|
||||
import json, sys
|
||||
plugin_id = sys.argv[1]
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
except Exception:
|
||||
raise SystemExit(1)
|
||||
if isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict):
|
||||
data = data[0]
|
||||
|
||||
def walk(obj):
|
||||
if isinstance(obj, dict):
|
||||
if obj.get("id") == plugin_id and obj.get("version"):
|
||||
print(obj["version"])
|
||||
raise SystemExit(0)
|
||||
for value in obj.values():
|
||||
walk(value)
|
||||
elif isinstance(obj, list):
|
||||
for value in obj:
|
||||
walk(value)
|
||||
|
||||
walk(data)
|
||||
raise SystemExit(2)
|
||||
' "$MM_OIDC_PLUGIN_ID"
|
||||
}
|
||||
|
||||
plugin_is_enabled() {
|
||||
plugin_state_json | python3 -c '
|
||||
import json, sys
|
||||
plugin_id = sys.argv[1]
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
except Exception:
|
||||
raise SystemExit(1)
|
||||
|
||||
if isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict):
|
||||
data = data[0]
|
||||
|
||||
if not isinstance(data, dict):
|
||||
raise SystemExit(1)
|
||||
|
||||
active = data.get("active")
|
||||
inactive = data.get("inactive")
|
||||
|
||||
if not isinstance(active, list) or not isinstance(inactive, list):
|
||||
raise SystemExit(1)
|
||||
|
||||
for plugin in active:
|
||||
if isinstance(plugin, dict) and plugin.get("id") == plugin_id:
|
||||
raise SystemExit(0)
|
||||
|
||||
for plugin in inactive:
|
||||
if isinstance(plugin, dict) and plugin.get("id") == plugin_id:
|
||||
raise SystemExit(2)
|
||||
|
||||
raise SystemExit(1)
|
||||
' "$MM_OIDC_PLUGIN_ID"
|
||||
}
|
||||
|
||||
|
||||
restore_release_bundle() {
|
||||
if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then
|
||||
rm -f "$MM_BUNDLE"
|
||||
if mv "$MM_BUNDLE_BACKUP" "$MM_BUNDLE" > "$log_file" 2>&1 ; then
|
||||
MM_BUNDLE_BACKUP=""
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -f "$MM_BUNDLE"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
cleanup_prepared_bundles() {
|
||||
if [[ -n "$MM_ROLLBACK_BUNDLE" ]]; then
|
||||
rm -f "$MM_ROLLBACK_BUNDLE"
|
||||
fi
|
||||
|
||||
restore_release_bundle
|
||||
}
|
||||
|
||||
|
||||
rollback_plugin() {
|
||||
local rollback_failed=false
|
||||
local restore_command_failed=false
|
||||
local _rollback_version=""
|
||||
local _rollback_rc
|
||||
local _plugin_enabled_rc
|
||||
|
||||
blank_line
|
||||
warn "Mattermost OIDC Plugin installation failed. Trying to restore the previous plugin state."
|
||||
|
||||
if [[ "$INSTALLATION_MODE" = "upgrade" ]]; then
|
||||
echononl "Restore Mattermost OIDC Plugin ${MM_CURRENT_VERSION}.."
|
||||
if [[ -f "$MM_ROLLBACK_BUNDLE" ]] &&
|
||||
"$MMCTL" --local plugin add --force "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_command_failed=true
|
||||
fi
|
||||
|
||||
if $MM_PREVIOUS_PLUGIN_ENABLED ; then
|
||||
echononl "Restore previous plugin state 'enabled'.."
|
||||
if "$MMCTL" --local plugin enable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_command_failed=true
|
||||
fi
|
||||
else
|
||||
echononl "Restore previous plugin state 'disabled'.."
|
||||
if "$MMCTL" --local plugin disable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_command_failed=true
|
||||
fi
|
||||
fi
|
||||
|
||||
echononl "Verify restored plugin version '${MM_CURRENT_VERSION}'.."
|
||||
_rollback_version="$(installed_plugin_version 2>/dev/null)"
|
||||
if [[ "$_rollback_version" = "$MM_CURRENT_VERSION" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
rollback_failed=true
|
||||
fi
|
||||
|
||||
echononl "Verify restored plugin state.."
|
||||
plugin_is_enabled
|
||||
_plugin_enabled_rc=$?
|
||||
if $MM_PREVIOUS_PLUGIN_ENABLED ; then
|
||||
if [[ $_plugin_enabled_rc -eq 0 ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
rollback_failed=true
|
||||
fi
|
||||
else
|
||||
if [[ $_plugin_enabled_rc -eq 2 ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
rollback_failed=true
|
||||
fi
|
||||
fi
|
||||
|
||||
elif [[ "$INSTALLATION_MODE" = "initial-installation" ]]; then
|
||||
installed_plugin_version > /dev/null 2>&1
|
||||
_rollback_rc=$?
|
||||
|
||||
echononl "Remove newly installed Mattermost OIDC Plugin.."
|
||||
if [[ $_rollback_rc -eq 2 ]]; then
|
||||
echo_ok
|
||||
elif [[ $_rollback_rc -eq 0 ]]; then
|
||||
if "$MMCTL" --local plugin delete "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_command_failed=true
|
||||
fi
|
||||
else
|
||||
echo_failed
|
||||
restore_command_failed=true
|
||||
fi
|
||||
|
||||
echononl "Verify Mattermost OIDC Plugin was removed.."
|
||||
installed_plugin_version > /dev/null 2>&1
|
||||
_rollback_rc=$?
|
||||
if [[ $_rollback_rc -eq 2 ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
rollback_failed=true
|
||||
fi
|
||||
else
|
||||
rollback_failed=true
|
||||
fi
|
||||
|
||||
if $rollback_failed ; then
|
||||
error "Automatic plugin rollback could not fully restore the previous state."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if $restore_command_failed ; then
|
||||
warn "One or more rollback commands reported an error, but the previous plugin state was successfully verified."
|
||||
fi
|
||||
|
||||
info "Previous Mattermost OIDC Plugin state was successfully restored."
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
fatal_with_plugin_rollback() {
|
||||
local failure_message="$1"
|
||||
|
||||
if $MM_ROLLBACK_REQUIRED ; then
|
||||
if rollback_plugin ; then
|
||||
MM_ROLLBACK_REQUIRED=false
|
||||
|
||||
if [[ -n "$MM_ROLLBACK_BUNDLE" && -f "$MM_ROLLBACK_BUNDLE" ]]; then
|
||||
echononl "Remove temporary rollback bundle.."
|
||||
if rm -f "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
warn "Plugin rollback was successful, but temporary rollback bundle '${MM_ROLLBACK_BUNDLE}' could not be removed."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then
|
||||
echononl "Remove previous release bundle backup.."
|
||||
if rm -f "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then
|
||||
MM_BUNDLE_BACKUP=""
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
warn "Plugin rollback was successful, but previous release bundle backup '${MM_BUNDLE_BACKUP}' could not be removed."
|
||||
fi
|
||||
fi
|
||||
|
||||
fatal "${failure_message} The previous plugin state was successfully restored."
|
||||
else
|
||||
fatal "${failure_message} Automatic rollback could not fully restore the previous state. Manual intervention is required."
|
||||
fi
|
||||
fi
|
||||
|
||||
fatal "$failure_message"
|
||||
}
|
||||
|
||||
|
||||
handle_signal() {
|
||||
trap - SIGHUP SIGINT SIGTERM
|
||||
|
||||
blank_line
|
||||
warn "Installation interrupted by signal."
|
||||
|
||||
if $MM_ROLLBACK_REQUIRED ; then
|
||||
if rollback_plugin ; then
|
||||
MM_ROLLBACK_REQUIRED=false
|
||||
|
||||
cleanup_prepared_bundles ||
|
||||
warn "Plugin rollback was successful, but previous release bundle state could not be fully restored."
|
||||
else
|
||||
error "Automatic rollback could not fully restore the previous plugin state. Manual intervention is required."
|
||||
fi
|
||||
else
|
||||
cleanup_prepared_bundles ||
|
||||
warn "Could not fully restore previous release bundle state."
|
||||
fi
|
||||
|
||||
clean_up 1
|
||||
}
|
||||
|
||||
|
||||
# ----------
|
||||
# Jobhandling
|
||||
# ----------
|
||||
|
||||
trap 'handle_signal' SIGHUP SIGINT SIGTERM
|
||||
|
||||
if ! mkdir "$LOCK_DIR" 2>/dev/null ; then
|
||||
echo "Cannot create lock directory '$LOCK_DIR'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -t 1 ]] ; then
|
||||
terminal=true
|
||||
else
|
||||
fatal "Script must run in a terminal."
|
||||
fi
|
||||
|
||||
|
||||
# ==========
|
||||
# Begin Main Script
|
||||
# ==========
|
||||
|
||||
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
|
||||
|
||||
# ----------
|
||||
# Some checks
|
||||
# ----------
|
||||
|
||||
echononl "Check if script is running as root.."
|
||||
if [[ "$(id -u)" -eq 0 ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "This script must be run as root."
|
||||
fi
|
||||
|
||||
for _cmd in git curl tar awk grep sed sort python3 systemctl stat uname mv cp mkdir ; do
|
||||
echononl "Check for command '${_cmd}'.."
|
||||
if command -v "$_cmd" > /dev/null 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Required command '${_cmd}' was not found."
|
||||
fi
|
||||
done
|
||||
|
||||
echononl "Check Mattermost binary.."
|
||||
if [[ -x "$MM_BIN" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost binary '${MM_BIN}' was not found."
|
||||
fi
|
||||
|
||||
echononl "Check mmctl binary.."
|
||||
if [[ -x "$MMCTL" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "mmctl binary '${MMCTL}' was not found."
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost service '${MM_SERVICE}'.."
|
||||
if systemctl is-active --quiet "$MM_SERVICE" ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost service '${MM_SERVICE}' is not active."
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost user '${MM_USER}'.."
|
||||
if id "$MM_USER" > /dev/null 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost user '${MM_USER}' does not exist."
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost group '${MM_GROUP}'.."
|
||||
if getent group "$MM_GROUP" > /dev/null 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost group '${MM_GROUP}' does not exist."
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost configuration '${MM_CONFIG_FILE}'.."
|
||||
if [[ -r "$MM_CONFIG_FILE" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost configuration '${MM_CONFIG_FILE}' is not readable."
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost Local Mode configuration.."
|
||||
_local_data="$(python3 - "$MM_CONFIG_FILE" <<'PY_EOF'
|
||||
import json, sys
|
||||
with open(sys.argv[1], encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
s = data.get("ServiceSettings", {})
|
||||
print("true" if s.get("EnableLocalMode") is True else "false")
|
||||
print(s.get("LocalModeSocketLocation") or "/var/tmp/mattermost_local.socket")
|
||||
PY_EOF
|
||||
)" || {
|
||||
echo_failed
|
||||
fatal "Could not parse '${MM_CONFIG_FILE}'."
|
||||
}
|
||||
_local_enabled="$(printf '%s\n' "$_local_data" | sed -n '1p')"
|
||||
_local_socket="$(printf '%s\n' "$_local_data" | sed -n '2p')"
|
||||
if [[ "$_local_enabled" = "true" ]]; then
|
||||
MM_LOCAL_SOCKET="$_local_socket"
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost Local Mode is disabled. Set ServiceSettings.EnableLocalMode to true and restart Mattermost first."
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost Local Mode socket '${MM_LOCAL_SOCKET}'.."
|
||||
if [[ -S "$MM_LOCAL_SOCKET" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost Local Mode socket '${MM_LOCAL_SOCKET}' does not exist."
|
||||
fi
|
||||
|
||||
echononl "Test mmctl Local Mode connection.."
|
||||
if "$MMCTL" --local plugin list > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "mmctl Local Mode connection failed. $(cat "$log_file")"
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost plugin configuration.."
|
||||
_plugin_settings="$(python3 - "$MM_CONFIG_FILE" <<'PY_EOF'
|
||||
import json, sys
|
||||
with open(sys.argv[1], encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
s = data.get("PluginSettings", {})
|
||||
print("true" if s.get("Enable") is True else "false")
|
||||
print("true" if s.get("EnableUploads") is True else "false")
|
||||
PY_EOF
|
||||
)" || {
|
||||
echo_failed
|
||||
fatal "Could not parse Mattermost plugin settings in '${MM_CONFIG_FILE}'."
|
||||
}
|
||||
|
||||
_plugins_enabled="$(printf '%s\n' "$_plugin_settings" | sed -n '1p')"
|
||||
_plugin_uploads_enabled="$(printf '%s\n' "$_plugin_settings" | sed -n '2p')"
|
||||
|
||||
if [[ "$_plugins_enabled" != "true" ]]; then
|
||||
echo_failed
|
||||
fatal "Mattermost plugins are disabled. Set PluginSettings.Enable to true and restart Mattermost first."
|
||||
elif [[ "$_plugin_uploads_enabled" != "true" ]]; then
|
||||
echo_failed
|
||||
fatal "Mattermost plugin uploads are disabled. Set PluginSettings.EnableUploads to true and restart Mattermost first."
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
MM_SERVER_VERSION="$("$MM_BIN" version 2>/dev/null | awk -F': ' '$1 == "Version" {print $2; exit}')"
|
||||
[[ -n "$MM_SERVER_VERSION" ]] || fatal "Could not determine installed Mattermost version."
|
||||
|
||||
|
||||
# ----------
|
||||
# Detect installation mode
|
||||
# ----------
|
||||
|
||||
echononl "Detect existing Mattermost OIDC plugin installation.."
|
||||
MM_CURRENT_VERSION="$(installed_plugin_version 2>/dev/null)"
|
||||
_plugin_version_rc=$?
|
||||
if [[ $_plugin_version_rc -eq 0 && -n "$MM_CURRENT_VERSION" ]]; then
|
||||
INSTALLATION_MODE="upgrade"
|
||||
plugin_is_enabled
|
||||
_plugin_enabled_rc=$?
|
||||
if [[ $_plugin_enabled_rc -eq 0 ]]; then
|
||||
MM_PREVIOUS_PLUGIN_ENABLED=true
|
||||
elif [[ $_plugin_enabled_rc -eq 2 ]]; then
|
||||
MM_PREVIOUS_PLUGIN_ENABLED=false
|
||||
else
|
||||
echo_failed
|
||||
fatal "Could not determine whether Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}' is enabled or disabled."
|
||||
fi
|
||||
echo_ok
|
||||
elif [[ $_plugin_version_rc -eq 2 ]]; then
|
||||
INSTALLATION_MODE="initial-installation"
|
||||
MM_CURRENT_VERSION=""
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Could not determine current Mattermost OIDC plugin state."
|
||||
fi
|
||||
|
||||
|
||||
# ----------
|
||||
# Determine latest stable release
|
||||
# ----------
|
||||
|
||||
echononl "Determine latest stable Mattermost OIDC release.."
|
||||
MM_LATEST_VERSION="$(git ls-remote --tags --refs "$MM_OIDC_REPOSITORY" 2> "$log_file" \
|
||||
| awk '{print $2}' \
|
||||
| sed -nE 's#refs/tags/v([0-9]+\.[0-9]+\.[0-9]+)$#\1#p' \
|
||||
| sort -V \
|
||||
| tail -1)"
|
||||
if [[ -n "$MM_LATEST_VERSION" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Could not determine latest stable release from '${MM_OIDC_REPOSITORY}'. $(cat "$log_file")"
|
||||
fi
|
||||
|
||||
blank_line
|
||||
if [[ "$INSTALLATION_MODE" = "initial-installation" ]]; then
|
||||
echo " Installation mode....................: Initial installation"
|
||||
else
|
||||
echo " Installation mode....................: Upgrade"
|
||||
echo " Currently installed version.........: ${MM_CURRENT_VERSION}"
|
||||
fi
|
||||
echo " Installed Mattermost version........: ${MM_SERVER_VERSION}"
|
||||
echo " Latest stable OIDC version..........: ${MM_LATEST_VERSION}"
|
||||
blank_line
|
||||
|
||||
while true ; do
|
||||
echononl "New Mattermost OIDC Plugin Version [${MM_LATEST_VERSION}]: "
|
||||
read MM_NEW_VERSION
|
||||
MM_NEW_VERSION="${MM_NEW_VERSION#v}"
|
||||
[[ -z "$MM_NEW_VERSION" ]] && MM_NEW_VERSION="$MM_LATEST_VERSION"
|
||||
|
||||
echononl "Check release tag 'v${MM_NEW_VERSION}'.."
|
||||
if git ls-remote --exit-code --tags "$MM_OIDC_REPOSITORY" \
|
||||
"refs/tags/v${MM_NEW_VERSION}" "refs/tags/v${MM_NEW_VERSION}^{}" \
|
||||
> /dev/null 2> "$log_file" ; then
|
||||
echo_ok
|
||||
break
|
||||
else
|
||||
echo_failed
|
||||
warn "Tag 'v${MM_NEW_VERSION}' does not exist in the upstream repository."
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$INSTALLATION_MODE" = "upgrade" && "$MM_NEW_VERSION" = "$MM_CURRENT_VERSION" ]]; then
|
||||
blank_line
|
||||
warn "Mattermost OIDC Plugin ${MM_CURRENT_VERSION} is already installed."
|
||||
if ! ask_yes_no "Reinstall version ${MM_NEW_VERSION}" "no" ; then
|
||||
info "Version ${MM_CURRENT_VERSION} is already installed. Nothing to do."
|
||||
clean_up 0
|
||||
fi
|
||||
fi
|
||||
|
||||
MM_BUNDLE="${MM_SOURCE_BASE}/mattermost-oidc-${MM_NEW_VERSION}.tar.gz"
|
||||
|
||||
|
||||
# ----------
|
||||
# Summary
|
||||
# ----------
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mMattermost OIDC Plugin installation settings:\033[m"
|
||||
blank_line
|
||||
echo " Installation mode....................: ${INSTALLATION_MODE}"
|
||||
[[ -n "$MM_CURRENT_VERSION" ]] && echo " Current plugin version...............: ${MM_CURRENT_VERSION}"
|
||||
echo " New plugin version...................: ${MM_NEW_VERSION}"
|
||||
echo " Latest stable version...............: ${MM_LATEST_VERSION}"
|
||||
echo " Installed Mattermost version........: ${MM_SERVER_VERSION}"
|
||||
echo " Repository...........................: ${MM_OIDC_REPOSITORY}"
|
||||
echo " Release bundle.......................: ${MM_BUNDLE}"
|
||||
echo " Plugin ID............................: ${MM_OIDC_PLUGIN_ID}"
|
||||
echo " Local Mode socket....................: ${MM_LOCAL_SOCKET}"
|
||||
blank_line
|
||||
|
||||
if ! ask_yes_no "einverstanden" "no" ; then
|
||||
fatal "Stopped by user"
|
||||
fi
|
||||
|
||||
|
||||
# ----------
|
||||
# Prepare source directory
|
||||
# ----------
|
||||
|
||||
blank_line
|
||||
|
||||
# ----------
|
||||
# Download release bundle
|
||||
# ----------
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mPrepare Mattermost OIDC Plugin release bundle..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Create source directory '${MM_SOURCE_BASE}'.."
|
||||
if mkdir -p "$MM_SOURCE_BASE" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "$(cat "$log_file")"
|
||||
fi
|
||||
|
||||
if [[ -e "$MM_BUNDLE" ]]; then
|
||||
MM_BUNDLE_BACKUP="${MM_BUNDLE}.${backup_date}"
|
||||
echononl "Backup existing release bundle.."
|
||||
if mv "$MM_BUNDLE" "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "$(cat "$log_file")"
|
||||
fi
|
||||
else
|
||||
echononl "Backup existing release bundle.."
|
||||
echo_skipped
|
||||
fi
|
||||
|
||||
echononl "Download Mattermost OIDC Plugin ${MM_NEW_VERSION}.."
|
||||
_release_url="${MM_OIDC_RELEASE_BASE}/v${MM_NEW_VERSION}/mattermost-oidc-${MM_NEW_VERSION}.tar.gz"
|
||||
if curl -fL --retry 2 --connect-timeout 15 -o "$MM_BUNDLE" "$_release_url" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
_download_error="$(cat "$log_file")"
|
||||
echo_failed
|
||||
restore_release_bundle || warn "Could not restore previous release bundle."
|
||||
fatal "Could not download '${_release_url}'. ${_download_error}"
|
||||
fi
|
||||
|
||||
echononl "Check release bundle archive.."
|
||||
if tar tzf "$MM_BUNDLE" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_release_bundle || warn "Could not restore previous release bundle."
|
||||
fatal "Downloaded release bundle is not a valid gzip-compressed tar archive."
|
||||
fi
|
||||
|
||||
echononl "Read and verify plugin metadata.."
|
||||
_plugin_json="$(tar xOf "$MM_BUNDLE" mattermost-oidc/plugin.json 2> "$log_file")" || {
|
||||
echo_failed
|
||||
restore_release_bundle || warn "Could not restore previous release bundle."
|
||||
fatal "Could not read mattermost-oidc/plugin.json from release bundle."
|
||||
}
|
||||
_metadata="$(printf '%s' "$_plugin_json" | python3 -c '
|
||||
import json, sys
|
||||
expected_id, expected_version = sys.argv[1:3]
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
except Exception:
|
||||
raise SystemExit(1)
|
||||
if data.get("id") != expected_id:
|
||||
raise SystemExit(2)
|
||||
if data.get("version") != expected_version:
|
||||
raise SystemExit(3)
|
||||
print(data.get("min_server_version", ""))
|
||||
' "$MM_OIDC_PLUGIN_ID" "$MM_NEW_VERSION")"
|
||||
_metadata_rc=$?
|
||||
if [[ $_metadata_rc -eq 0 ]]; then
|
||||
MM_MIN_SERVER_VERSION="$_metadata"
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_release_bundle || warn "Could not restore previous release bundle."
|
||||
fatal "Plugin metadata does not match expected ID '${MM_OIDC_PLUGIN_ID}' and version '${MM_NEW_VERSION}'."
|
||||
fi
|
||||
|
||||
if [[ -n "$MM_MIN_SERVER_VERSION" ]]; then
|
||||
echononl "Check Mattermost version (installed: ${MM_SERVER_VERSION}, required: ${MM_MIN_SERVER_VERSION}).."
|
||||
if version_ge "$MM_SERVER_VERSION" "$MM_MIN_SERVER_VERSION" ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_release_bundle || warn "Could not restore previous release bundle."
|
||||
fatal "Mattermost ${MM_NEW_VERSION} requires Mattermost ${MM_MIN_SERVER_VERSION} or newer. Installed version is ${MM_SERVER_VERSION}."
|
||||
fi
|
||||
fi
|
||||
|
||||
_arch="$(uname -m)"
|
||||
case "$_arch" in
|
||||
x86_64|amd64) _bundle_arch="amd64" ;;
|
||||
aarch64|arm64) _bundle_arch="arm64" ;;
|
||||
*)
|
||||
restore_release_bundle || warn "Could not restore previous release bundle."
|
||||
fatal "Unsupported system architecture '${_arch}'."
|
||||
;;
|
||||
esac
|
||||
|
||||
echononl "Check Linux server binary for architecture '${_bundle_arch}'.."
|
||||
if tar tzf "$MM_BUNDLE" | grep -qx "mattermost-oidc/server/dist/plugin-linux-${_bundle_arch}" ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
restore_release_bundle || warn "Could not restore previous release bundle."
|
||||
fatal "Release bundle does not contain plugin-linux-${_bundle_arch}."
|
||||
fi
|
||||
|
||||
|
||||
# ----------
|
||||
# Prepare rollback bundle
|
||||
# ----------
|
||||
|
||||
if [[ "$INSTALLATION_MODE" = "upgrade" ]]; then
|
||||
MM_ROLLBACK_BUNDLE="${MM_SOURCE_BASE}/mattermost-oidc-${MM_CURRENT_VERSION}.rollback-${backup_date}.tar.gz"
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mPrepare Mattermost OIDC Plugin rollback bundle..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Download rollback bundle for Mattermost OIDC Plugin ${MM_CURRENT_VERSION}.."
|
||||
_rollback_url="${MM_OIDC_RELEASE_BASE}/v${MM_CURRENT_VERSION}/mattermost-oidc-${MM_CURRENT_VERSION}.tar.gz"
|
||||
if curl -fL --retry 2 --connect-timeout 15 -o "$MM_ROLLBACK_BUNDLE" "$_rollback_url" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
_rollback_download_error="$(cat "$log_file")"
|
||||
echo_failed
|
||||
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
||||
fatal "Could not prepare rollback bundle '${_rollback_url}'. No changes were made to the installed plugin. ${_rollback_download_error}"
|
||||
fi
|
||||
|
||||
echononl "Check rollback bundle archive.."
|
||||
if tar tzf "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
||||
fatal "Rollback bundle for version '${MM_CURRENT_VERSION}' is not a valid gzip-compressed tar archive."
|
||||
fi
|
||||
|
||||
echononl "Verify rollback bundle metadata.."
|
||||
_rollback_plugin_json="$(tar xOf "$MM_ROLLBACK_BUNDLE" mattermost-oidc/plugin.json 2> "$log_file")" || {
|
||||
echo_failed
|
||||
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
||||
fatal "Could not read plugin metadata from rollback bundle."
|
||||
}
|
||||
|
||||
if printf '%s' "$_rollback_plugin_json" | python3 -c '
|
||||
import json, sys
|
||||
expected_id, expected_version = sys.argv[1:3]
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
except Exception:
|
||||
raise SystemExit(1)
|
||||
if data.get("id") != expected_id or data.get("version") != expected_version:
|
||||
raise SystemExit(1)
|
||||
' "$MM_OIDC_PLUGIN_ID" "$MM_CURRENT_VERSION" ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state."
|
||||
fatal "Rollback bundle metadata does not match plugin '${MM_OIDC_PLUGIN_ID}' version '${MM_CURRENT_VERSION}'."
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# ----------
|
||||
# Install/upgrade plugin
|
||||
# ----------
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mInstall Mattermost OIDC Plugin..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Install Mattermost OIDC Plugin ${MM_NEW_VERSION}.."
|
||||
MM_ROLLBACK_REQUIRED=true
|
||||
if "$MMCTL" --local plugin add --force "$MM_BUNDLE" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
_install_error="$(cat "$log_file")"
|
||||
echo_failed
|
||||
fatal_with_plugin_rollback "Plugin installation failed. ${_install_error}"
|
||||
fi
|
||||
|
||||
echononl "Enable Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}'.."
|
||||
if "$MMCTL" --local plugin enable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
_enable_error="$(cat "$log_file")"
|
||||
echo_failed
|
||||
fatal_with_plugin_rollback "Plugin was installed but could not be enabled. ${_enable_error}"
|
||||
fi
|
||||
|
||||
|
||||
# ----------
|
||||
# Verify installation
|
||||
# ----------
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mVerify Mattermost OIDC Plugin installation..\033[m"
|
||||
blank_line
|
||||
|
||||
sleep 1
|
||||
|
||||
echononl "Verify installed plugin version '${MM_NEW_VERSION}'.."
|
||||
_verified_version="$(installed_plugin_version 2>/dev/null)"
|
||||
if [[ "$_verified_version" = "$MM_NEW_VERSION" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal_with_plugin_rollback "Installed plugin version is '${_verified_version:-unknown}', expected '${MM_NEW_VERSION}'."
|
||||
fi
|
||||
|
||||
echononl "Verify plugin is enabled.."
|
||||
plugin_is_enabled
|
||||
_plugin_enabled_rc=$?
|
||||
if [[ $_plugin_enabled_rc -eq 0 ]]; then
|
||||
echo_ok
|
||||
MM_ROLLBACK_REQUIRED=false
|
||||
elif [[ $_plugin_enabled_rc -eq 2 ]]; then
|
||||
echo_failed
|
||||
fatal_with_plugin_rollback "Plugin '${MM_OIDC_PLUGIN_ID}' is installed but not enabled."
|
||||
else
|
||||
echo_failed
|
||||
fatal_with_plugin_rollback "Could not determine whether Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}' is enabled."
|
||||
fi
|
||||
|
||||
|
||||
if [[ -n "$MM_ROLLBACK_BUNDLE" && -f "$MM_ROLLBACK_BUNDLE" ]]; then
|
||||
echononl "Remove temporary rollback bundle.."
|
||||
if rm -f "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
warn "Mattermost OIDC Plugin was successfully installed, but temporary rollback bundle '${MM_ROLLBACK_BUNDLE}' could not be removed."
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then
|
||||
echononl "Remove previous release bundle backup.."
|
||||
if rm -f "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then
|
||||
MM_BUNDLE_BACKUP=""
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
warn "Mattermost OIDC Plugin was successfully installed, but previous release bundle backup '${MM_BUNDLE_BACKUP}' could not be removed."
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# ----------
|
||||
# Final information
|
||||
# ----------
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mMattermost OIDC Plugin successfully installed.\033[m"
|
||||
blank_line
|
||||
echo " Installed version.....................: ${MM_NEW_VERSION}"
|
||||
echo " Plugin ID.............................: ${MM_OIDC_PLUGIN_ID}"
|
||||
echo " Release bundle........................: ${MM_BUNDLE}"
|
||||
echo " Mattermost version....................: ${MM_SERVER_VERSION}"
|
||||
echo " Minimum Mattermost version............: ${MM_MIN_SERVER_VERSION:-not specified}"
|
||||
echo " Status................................: enabled"
|
||||
blank_line
|
||||
|
||||
clean_up 0
|
||||
Executable
+1353
File diff suppressed because it is too large
Load Diff
+266
-60
@@ -9,7 +9,7 @@ conf_file="${working_dir}/conf/mattermost.conf"
|
||||
LOCK_DIR="/tmp/$(basename $0).$$.LOCK"
|
||||
log_file="${LOCK_DIR}/${script_name%%.*}.log"
|
||||
|
||||
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||
backup_date="$(date +%Y-%m-%d-%H%M%S)"
|
||||
|
||||
|
||||
# ----------
|
||||
@@ -64,8 +64,7 @@ fatal(){
|
||||
echo -e " Script terminated.."
|
||||
fi
|
||||
echo ""
|
||||
rm -rf $LOCK_DIR
|
||||
exit 1
|
||||
clean_up 1
|
||||
}
|
||||
error (){
|
||||
echo ""
|
||||
@@ -136,14 +135,14 @@ blank_line() {
|
||||
|
||||
detect_os () {
|
||||
|
||||
if $(which lsb_release > /dev/null 2>&1) ; then
|
||||
if command -v lsb_release > /dev/null 2>&1 ; then
|
||||
|
||||
DIST="$(lsb_release -i | awk '{print tolower($3)}')"
|
||||
DIST_VERSION="$(lsb_release -r | awk '{print tolower($2)}')"
|
||||
DIST_CODENAME="$(lsb_release -c | awk '{print tolower($2)}')"
|
||||
|
||||
if [[ "$DIST" = "debian" ]]; then
|
||||
if $(echo "$DIST_VERSION" | grep -q '\.') ; then
|
||||
if echo "$DIST_VERSION" | grep -q '\.' ; then
|
||||
DIST_VERSION=$(echo "$DIST_VERSION" | cut --delimiter='.' -f1)
|
||||
fi
|
||||
fi
|
||||
@@ -171,7 +170,7 @@ detect_os () {
|
||||
|
||||
# - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM
|
||||
# -
|
||||
trap clean_up SIGHUP SIGINT SIGTERM
|
||||
trap 'clean_up 1' SIGHUP SIGINT SIGTERM
|
||||
|
||||
# - Create lock directory '$LOCK_DIR"
|
||||
#
|
||||
@@ -273,8 +272,9 @@ do
|
||||
echo -e "\n\t\033[33m\033[1mA Version number is required!\033[m\n"
|
||||
fi
|
||||
done
|
||||
DOWNLOAD_ARCHIVE="mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz"
|
||||
DOWNLOAD_URL="https://releases.mattermost.com/${MM_NEW_VERSION}/${DOWNLOAD_ARCHIVE}"
|
||||
# Download archive is selected after the current installation has been inspected.
|
||||
DOWNLOAD_ARCHIVE=
|
||||
DOWNLOAD_URL=
|
||||
|
||||
|
||||
|
||||
@@ -313,8 +313,93 @@ else
|
||||
done
|
||||
fi
|
||||
|
||||
MATTERMOST_CURRENT_VERSION="$(${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost version 2> /dev/null | grep -E "^Version:" | cut -d' ' -f2)"
|
||||
MATTERMOST_CURRENT_BUILD_NUMBER="$(${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost version 2> /dev/null | grep -E "^Build Number:" | cut -d' ' -f3)"
|
||||
if [[ ! -x "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost" ]]; then
|
||||
fatal "Mattermost binary '${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost' does not exist or is not executable."
|
||||
fi
|
||||
if ! MATTERMOST_VERSION_OUTPUT="$("${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost" version 2> /dev/null)" ; then
|
||||
fatal "Failed to determine the currently installed Mattermost version."
|
||||
fi
|
||||
MATTERMOST_CURRENT_VERSION="$(echo "$MATTERMOST_VERSION_OUTPUT" | grep -E "^Version:" | cut -d' ' -f2)"
|
||||
MATTERMOST_CURRENT_BUILD_NUMBER="$(echo "$MATTERMOST_VERSION_OUTPUT" | grep -E "^Build Number:" | cut -d' ' -f3)"
|
||||
MATTERMOST_CURRENT_ENTERPRISE_READY="$(echo "$MATTERMOST_VERSION_OUTPUT" | grep -E "^Build Enterprise Ready:" | awk '{print $4}')"
|
||||
|
||||
if [[ "${MATTERMOST_CURRENT_ENTERPRISE_READY,,}" = "true" ]]; then
|
||||
MATTERMOST_CURRENT_EDITION="enterprise"
|
||||
MATTERMOST_CURRENT_EDITION_NAME="Enterprise Ready"
|
||||
elif [[ "${MATTERMOST_CURRENT_ENTERPRISE_READY,,}" = "false" ]]; then
|
||||
MATTERMOST_CURRENT_EDITION="team"
|
||||
MATTERMOST_CURRENT_EDITION_NAME="Team Edition"
|
||||
else
|
||||
MATTERMOST_CURRENT_EDITION="unknown"
|
||||
MATTERMOST_CURRENT_EDITION_NAME="Unknown"
|
||||
fi
|
||||
|
||||
echo -e "\033[32m--\033[m"
|
||||
echo ""
|
||||
echo "Choose Mattermost Edition for the upgrade"
|
||||
echo ""
|
||||
if [[ "$MATTERMOST_CURRENT_EDITION" = "enterprise" ]]; then
|
||||
echo -e "\033[3G\033[37m\033[1m[1] Enterprise Ready\033[m"
|
||||
echo -e "\033[3G[2] Team Edition"
|
||||
elif [[ "$MATTERMOST_CURRENT_EDITION" = "team" ]]; then
|
||||
echo -e "\033[3G[1] Enterprise Ready"
|
||||
echo -e "\033[3G\033[37m\033[1m[2] Team Edition\033[m"
|
||||
else
|
||||
echo -e "\033[3G[1] Enterprise Ready"
|
||||
echo -e "\033[3G[2] Team Edition"
|
||||
fi
|
||||
echo ""
|
||||
echo "Current edition: ${MATTERMOST_CURRENT_EDITION_NAME}"
|
||||
echo ""
|
||||
if [[ "$MATTERMOST_CURRENT_EDITION" != "unknown" ]]; then
|
||||
echo "Press <RETURN> to keep the current edition"
|
||||
echo ""
|
||||
fi
|
||||
echononl "Eingabe: "
|
||||
MATTERMOST_EDITION=
|
||||
while [[ "$MATTERMOST_EDITION" != "enterprise" ]] && [[ "$MATTERMOST_EDITION" != "team" ]]; do
|
||||
read OPTION
|
||||
case $OPTION in
|
||||
1)
|
||||
MATTERMOST_EDITION="enterprise"
|
||||
MATTERMOST_EDITION_NAME="Enterprise Ready"
|
||||
DOWNLOAD_ARCHIVE="mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz"
|
||||
;;
|
||||
2)
|
||||
MATTERMOST_EDITION="team"
|
||||
MATTERMOST_EDITION_NAME="Team Edition"
|
||||
DOWNLOAD_ARCHIVE="mattermost-team-${MM_NEW_VERSION}-linux-amd64.tar.gz"
|
||||
;;
|
||||
'')
|
||||
if [[ "$MATTERMOST_CURRENT_EDITION" = "team" ]]; then
|
||||
MATTERMOST_EDITION="team"
|
||||
MATTERMOST_EDITION_NAME="Team Edition"
|
||||
DOWNLOAD_ARCHIVE="mattermost-team-${MM_NEW_VERSION}-linux-amd64.tar.gz"
|
||||
elif [[ "$MATTERMOST_CURRENT_EDITION" = "enterprise" ]]; then
|
||||
MATTERMOST_EDITION="enterprise"
|
||||
MATTERMOST_EDITION_NAME="Enterprise Ready"
|
||||
DOWNLOAD_ARCHIVE="mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz"
|
||||
else
|
||||
echo ""
|
||||
echo -e "\033[3GNo default edition available. Please choose 1 or 2."
|
||||
echo ""
|
||||
echononl "Eingabe: "
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo -e "\033[3GWrong entry! [ 1 = Enterprise Ready ; 2 = Team Edition ]"
|
||||
echo ""
|
||||
echononl "Eingabe: "
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
DOWNLOAD_URL="https://releases.mattermost.com/${MM_NEW_VERSION}/${DOWNLOAD_ARCHIVE}"
|
||||
|
||||
if [[ "$MATTERMOST_CURRENT_EDITION" != "unknown" ]] && [[ "$MATTERMOST_CURRENT_EDITION" != "$MATTERMOST_EDITION" ]]; then
|
||||
warn "You are changing the Mattermost edition from '${MATTERMOST_CURRENT_EDITION_NAME}' to '${MATTERMOST_EDITION_NAME}'."
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -412,7 +497,7 @@ done
|
||||
|
||||
if [[ "$DB_TYPE" = "mysql" ]] ; then
|
||||
if [[ -n "$MYSQL_CREDENTIAL_ARGS" ]] ; then
|
||||
if ! $(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e 'quit' > /dev/null 2>&1) ; then
|
||||
if ! mysql $MYSQL_CREDENTIAL_ARGS -N -s -e 'quit' > /dev/null 2>&1 ; then
|
||||
fatal "Parameter MYSQL_CREDENTIAL_ARGS is given, but a connection to MySQL Service failed.!"
|
||||
fi
|
||||
USE_MYSQL_CREDENTIAL_ARGS=true
|
||||
@@ -433,8 +518,8 @@ if [[ "$DB_TYPE" = "mysql" ]] ; then
|
||||
echo -e "\n\t\033[33m\033[1mPassworteingabe erforderlich!\033[m\n"
|
||||
continue
|
||||
fi
|
||||
if $(pgrep mysqld_safe > /dev/null 2>&1) || $(pgrep mysqld > /dev/null 2>&1); then
|
||||
if $(mysql --user="root" --password="$_MYSQL_ROOT_PW" -N -s -e 'quit' > /dev/null 2>&1) ; then
|
||||
if pgrep mysqld_safe > /dev/null 2>&1 || pgrep mysqld > /dev/null 2>&1; then
|
||||
if mysql --user="root" --password="$_MYSQL_ROOT_PW" -N -s -e 'quit' > /dev/null 2>&1 ; then
|
||||
MYSQL_ROOT_PW=$_MYSQL_ROOT_PW
|
||||
else
|
||||
echo -e "\n\t\033[33m\033[1mFalsches Passwort\033[m\n"
|
||||
@@ -455,8 +540,10 @@ echo -e "\033[32mStart upgrade script for Mattermost Server with the following p
|
||||
echo ""
|
||||
echo -e " Mattermost current Server Version.: $MATTERMOST_CURRENT_VERSION"
|
||||
echo -e " Mattermost current Build Number...: $MATTERMOST_CURRENT_BUILD_NUMBER"
|
||||
echo -e " Mattermost current Edition........: $MATTERMOST_CURRENT_EDITION_NAME"
|
||||
echo ""
|
||||
echo -e " Mattermost New Server Version.....: \033[33m\033[1m$MM_NEW_VERSION\033[m"
|
||||
echo -e " Mattermost New Edition............: \033[33m\033[1m$MATTERMOST_EDITION_NAME\033[m"
|
||||
echo ""
|
||||
echo -e " Full qualified Hostname...........: $FQHN_HOSTNAME"
|
||||
echo -e " Hostname..........................: $HOSTNAME"
|
||||
@@ -477,7 +564,7 @@ fi
|
||||
echo ""
|
||||
if [[ "${DB_TYPE}" = "mysql" ]]; then
|
||||
if $USE_MYSQL_CREDENTIAL_ARGS ; then
|
||||
echo -e " MYSQL_CREDENTIAL_ARGS.............: $MYSQL_CREDENTIAL_ARGS"
|
||||
echo -e " MYSQL_CREDENTIAL_ARGS.............: **"
|
||||
else
|
||||
echo -e " Root password MySQL...............: **"
|
||||
fi
|
||||
@@ -485,7 +572,7 @@ fi
|
||||
echo ""
|
||||
echo -e " Database Name.....................: $DB_NAME"
|
||||
echo -e " Database User.....................: $DB_USER"
|
||||
echo -e " Database Password.................: $DB_PASS"
|
||||
echo -e " Database Password.................: **"
|
||||
echo ""
|
||||
echononl "einverstanden (yes/no): "
|
||||
read OK
|
||||
@@ -501,9 +588,9 @@ done
|
||||
blank_line
|
||||
blank_line
|
||||
|
||||
if ! $USE_MYSQL_CREDENTIAL_ARGS ; then
|
||||
MYSQL_CREDENTIAL_ARGS="--user='root' --password=$_MYSQL_ROOT_PW"
|
||||
if ! $(mysql $MYSQL_CREDENTIAL_ARGS -N -s -e 'quit' > /dev/null 2>&1) ; then
|
||||
if [[ "$DB_TYPE" = "mysql" ]] && ! $USE_MYSQL_CREDENTIAL_ARGS ; then
|
||||
MYSQL_CREDENTIAL_ARGS="--user=root --password=$_MYSQL_ROOT_PW"
|
||||
if ! mysql $MYSQL_CREDENTIAL_ARGS -N -s -e 'quit' > /dev/null 2>&1 ; then
|
||||
fatal "Parameter MYSQL_CREDENTIAL_ARGS is given, but a connection to MySQL Service failed.!"
|
||||
fi
|
||||
fi
|
||||
@@ -514,7 +601,7 @@ echo -e "\033[37m\033[1mSome pre-installation stuff..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Download version \033[1m${MM_NEW_VERSION}\033[m of the Mattermost Server.."
|
||||
if [[ ! -f "${working_dir}/mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz" ]]; then
|
||||
if [[ ! -f "${working_dir}/${DOWNLOAD_ARCHIVE}" ]]; then
|
||||
wget -P ${working_dir} $DOWNLOAD_URL > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
@@ -536,6 +623,17 @@ else
|
||||
echo_skipped
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost Server archive.."
|
||||
if [[ -f "${working_dir}/${DOWNLOAD_ARCHIVE}" ]] \
|
||||
&& tar -tzf "${working_dir}/${DOWNLOAD_ARCHIVE}" > /dev/null 2> "$log_file" ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Mattermost Server archive '${working_dir}/${DOWNLOAD_ARCHIVE}' is missing, invalid or incomplete."
|
||||
fi
|
||||
|
||||
blank_line
|
||||
|
||||
|
||||
# - Deaktiviere Cronjobs
|
||||
# -
|
||||
@@ -559,42 +657,35 @@ else
|
||||
fi
|
||||
|
||||
|
||||
echononl "Remove existing temporary Mattermost upgrade directory.."
|
||||
if [[ -d "${MATTERMOST_TMP_DIR}/mattermost-upgrade" ]]; then
|
||||
rm -rf "${MATTERMOST_TMP_DIR}/mattermost-upgrade" > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
fatal "$(cat "$log_file")"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
else
|
||||
echo_skipped
|
||||
fi
|
||||
|
||||
echononl "Extract the Mattermost Server files into TMP directory.."
|
||||
tar -xf ${working_dir}/mattermost-${MM_NEW_VERSION}-linux-amd64.tar.gz \
|
||||
-C ${MATTERMOST_TMP_DIR} --transform='s,^[^/]\+,\0-upgrade,'
|
||||
tar -xf "${working_dir}/${DOWNLOAD_ARCHIVE}" \
|
||||
-C "${MATTERMOST_TMP_DIR}" --transform='s,^[^/]\+,\0-upgrade,' > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
fatal "$(cat "$log_file")"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
echononl "Stop Mattermost Service.."
|
||||
if $(systemctl is-active --quiet service mattermost.service) ; then
|
||||
if systemctl is-active --quiet mattermost.service ; then
|
||||
systemctl stop mattermost.service > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
echononl "continue anyway [yes/no]: "
|
||||
read OK
|
||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||
echononl "Wrong entry! - repeat [yes/no]: "
|
||||
read OK
|
||||
done
|
||||
[[ $OK = "yes" ]] || fatal "Stopped by user"
|
||||
|
||||
fatal "$(cat "$log_file")"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
@@ -604,8 +695,8 @@ fi
|
||||
|
||||
echononl "Backup mattermost database.."
|
||||
if [[ "${DB_TYPE}" = "mysql" ]]; then
|
||||
mysqldump --login-path=local --opt $DB_NAME \
|
||||
> ${MATTERMOST_BASE_INSTALL_PATH}/${DB_NAME}-${backup_date}.sql 2> $log_file
|
||||
mysqldump $MYSQL_CREDENTIAL_ARGS --opt "$DB_NAME" \
|
||||
> "${MATTERMOST_BASE_INSTALL_PATH}/${DB_NAME}-${backup_date}.sql" 2> "$log_file"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
@@ -641,8 +732,8 @@ else
|
||||
fi
|
||||
|
||||
echononl "Backup mattermost installation directory.."
|
||||
cp -ra ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/ \
|
||||
${MATTERMOST_BASE_INSTALL_PATH}/mattermost-back-${backup_date}/ > "$log_file" 2>&1
|
||||
cp -ra "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/" \
|
||||
"${MATTERMOST_BASE_INSTALL_PATH}/mattermost-back-${backup_date}/" > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
@@ -660,20 +751,89 @@ else
|
||||
fi
|
||||
|
||||
|
||||
# - When switching from Enterprise Ready to Team Edition, remove stale
|
||||
# - Enterprise-only plugin state before installing the Team Edition files.
|
||||
# - Keep Playbooks explicitly disabled so AutomaticPrepackagedPlugins does
|
||||
# - not try to install/activate it again on Team Edition startup.
|
||||
#
|
||||
if [[ "$MATTERMOST_CURRENT_EDITION" = "enterprise" ]] && [[ "$MATTERMOST_EDITION" = "team" ]]; then
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mPrepare Enterprise Ready -> Team Edition switch..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Check for Python 3 (needed to adjust Mattermost plugin configuration).."
|
||||
if command -v python3 > /dev/null 2>&1 ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Python 3 is required for a safe Enterprise Ready -> Team Edition switch."
|
||||
fi
|
||||
|
||||
echononl "Clean Enterprise-only plugin configuration for Team Edition.."
|
||||
MM_CONFIG_FILE="${MATTERMOST_BASE_INSTALL_PATH}/mattermost/config/config.json"
|
||||
python3 - "$MM_CONFIG_FILE" > "$log_file" 2>&1 <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
path = sys.argv[1]
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
plugin_settings = data.setdefault("PluginSettings", {})
|
||||
plugins = plugin_settings.setdefault("Plugins", {})
|
||||
states = plugin_settings.setdefault("PluginStates", {})
|
||||
|
||||
plugins.pop("playbooks", None)
|
||||
states.pop("com.mattermost.nps", None)
|
||||
states["playbooks"] = {"Enable": False}
|
||||
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=4)
|
||||
f.write("\n")
|
||||
PY
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
fatal "Failed to adjust plugin configuration:\n$(cat "$log_file")"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
echononl "Remove installed Playbooks/NPS plugin files.."
|
||||
rm -rf \
|
||||
"${MATTERMOST_BASE_INSTALL_PATH}/mattermost/plugins/playbooks" \
|
||||
"${MATTERMOST_BASE_INSTALL_PATH}/mattermost/plugins/com.mattermost.nps" \
|
||||
"${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/plugins/playbooks" \
|
||||
"${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/plugins/com.mattermost.nps" \
|
||||
> "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
fatal "Failed to remove Enterprise-only plugin files:\n$(cat "$log_file")"
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
echo
|
||||
echo -e "\033[37m\033[1mUpgrade Mattermost to version $MM_NEW_VERSION ..\033[m"
|
||||
echo
|
||||
|
||||
|
||||
echononl "Remove all files except \e[3mspecial directories\e[0m from within the current mattermost directory."
|
||||
find ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/ ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/ \
|
||||
-mindepth 1 -maxdepth 1 \! \( -type d \( -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/plugins \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/config \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/logs \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/plugins \
|
||||
-o -path ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/data \) -prune \) | sort | sudo xargs rm -r > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
set -o pipefail
|
||||
find "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/" "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/" \
|
||||
-mindepth 1 -maxdepth 1 \! \( -type d \( -path "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client" \
|
||||
-o -path "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/client/plugins" \
|
||||
-o -path "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/config" \
|
||||
-o -path "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/logs" \
|
||||
-o -path "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/plugins" \
|
||||
-o -path "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/data" \) -prune \) -print0 \
|
||||
| sort -z | xargs -0 -r rm -r > "$log_file" 2>&1
|
||||
_pipe_status=$?
|
||||
set +o pipefail
|
||||
if [[ $_pipe_status -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
|
||||
@@ -692,7 +852,7 @@ fi
|
||||
|
||||
|
||||
echononl "Change ownership of the new files before copying them.."
|
||||
chown -hR ${MATTERMOST_USER}:${MATTERMOST_GROUP} ${MATTERMOST_TMP_DIR}/mattermost-upgrade/ > "$log_file" 2>&1
|
||||
chown -hR "${MATTERMOST_USER}:${MATTERMOST_GROUP}" "${MATTERMOST_TMP_DIR}/mattermost-upgrade/" > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
@@ -712,7 +872,7 @@ fi
|
||||
|
||||
|
||||
echononl "Copy the new files to your install directory.."
|
||||
cp -an ${MATTERMOST_TMP_DIR}/mattermost-upgrade/. ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/ > "$log_file" 2>&1
|
||||
cp -an "${MATTERMOST_TMP_DIR}/mattermost-upgrade/." "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/" > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
@@ -734,7 +894,7 @@ fi
|
||||
# to bind to low ports.
|
||||
#
|
||||
echononl "Allow the new Mattermost binary to bind to low ports.."
|
||||
setcap cap_net_bind_service=+ep ${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost > "$log_file" 2>&1
|
||||
setcap cap_net_bind_service=+ep "${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost" > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
@@ -752,12 +912,46 @@ else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
echononl "Verify installed Mattermost binary.."
|
||||
if ! INSTALLED_MATTERMOST_VERSION_OUTPUT="$("${MATTERMOST_BASE_INSTALL_PATH}/mattermost/bin/mattermost" version 2>&1)" ; then
|
||||
echo_failed
|
||||
fatal "Failed to determine the installed Mattermost version."
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
echononl "Verify Mattermost Version.."
|
||||
INSTALLED_MATTERMOST_VERSION="$(echo "$INSTALLED_MATTERMOST_VERSION_OUTPUT" | awk '/^Version:/ {print $2}')"
|
||||
if [[ "$INSTALLED_MATTERMOST_VERSION" = "$MM_NEW_VERSION" ]]; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Installed Mattermost version '${INSTALLED_MATTERMOST_VERSION}' does not match expected version '${MM_NEW_VERSION}'."
|
||||
fi
|
||||
|
||||
echononl "Verify Mattermost Edition.."
|
||||
if [[ "$MATTERMOST_EDITION" == "enterprise" ]]; then
|
||||
if echo "$INSTALLED_MATTERMOST_VERSION_OUTPUT" | grep -q "Build Enterprise Ready: true"; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Installed Mattermost binary is not Enterprise Ready."
|
||||
fi
|
||||
else
|
||||
if echo "$INSTALLED_MATTERMOST_VERSION_OUTPUT" | grep -q "Build Enterprise Ready: false"; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
fatal "Installed Mattermost binary is not Team Edition."
|
||||
fi
|
||||
fi
|
||||
|
||||
blank_line
|
||||
echo -e "\033[37m\033[1mSome post-installation stuff..\033[m"
|
||||
blank_line
|
||||
|
||||
echononl "Remove the temporary files.."
|
||||
rm -r ${MATTERMOST_TMP_DIR}/mattermost-upgrade/ > "$log_file" 2>&1
|
||||
rm -r "${MATTERMOST_TMP_DIR}/mattermost-upgrade/" > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
@@ -780,9 +974,21 @@ systemctl start mattermost.service > "$log_file" 2>&1
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo_failed
|
||||
error "$(cat "$log_file")"
|
||||
clean_up 1
|
||||
else
|
||||
echo_ok
|
||||
fi
|
||||
|
||||
echononl "Check Mattermost Service.."
|
||||
sleep 3
|
||||
if systemctl is-active --quiet mattermost.service ; then
|
||||
echo_ok
|
||||
else
|
||||
echo_failed
|
||||
systemctl status mattermost.service --no-pager >> "$log_file" 2>&1
|
||||
error "$(cat "$log_file")"
|
||||
clean_up 1
|
||||
fi
|
||||
|
||||
clean_up 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user