|
- #!/usr/bin/env bash
-
- ###############################################################################
- # #
- # Redmine stable automatic installation script #
- # #
- # Designed for stressed VUAs with little to no wish to copypaste a gadzillion #
- # UNIX commands. #
- # #
- # Copyright (c) 2020 - Bryan Pedini #
- # #
- ###############################################################################
-
- _parse_params() {
- VERBOSE=true
- MIGRATE=false
- NO_CONFIGURE_MARIADB=false
- NO_CREATE_USER=false
- REDMINE_VERSION="4.1.0"
- REDMINE_INSTALL_DIR="/opt/redmine"
- for par in "$@"; do
- case "$par" in
- "-h" | "--help" | "--usage")
- _print_usage
- ;;
- "-q" | "--quiet")
- VERBOSE=false
- shift
- ;;
- "--redmine-version")
- [[ "$2:0:1" = "-" ]] && _print_usage
- REDMINE_VERSION="$2"
- shift
- shift
- ;;
- "--install-dir")
- [[ "$2:0:1" = "-" ]] && _print_usage
- REDMINE_INSTALL_DIR="$2"
- shift
- shift
- ;;
- "--no-configure-mariadb")
- NO_CONFIGURE_MARIADB=true
- shift
- ;;
- "--no-create-user")
- NO_CREATE_USER=true
- shift
- ;;
- "--migrate")
- MIGRATE=true
- shift
- ;;
- "--migration-source-sql")
- [[ "$2:0:1" = "-" ]] && _print_usage
- MIGRATION_SQL="$2"
- shift
- shift
- ;;
- "--migration-source-dir")
- [[ "$2:0:1" = "-" ]] && _print_usage
- MIGRATION_DIR="$2"
- shift
- shift
- ;;
- esac
- done
- if [[ ( "$MIGRATE" = true ) && ( "$MIGRATION_SQL" = "" ) ]]; then
- _print_usage "flag --migration passed but either \
- --migration-source-sql or
- --migration-source-dir not provided." 1
- fi
- }
-
- _print_usage() {
- echo "Usage: $0 [OPTIONS]"
- echo
- echo "OPTIONS"
- echo " -h, --help, --usage Prints this help message and exits"
- echo " -q, --quiet Turns off verbose logging (default: True)"
- echo " --redmine-version Install a custom version of the Redmine
- project (default: latest)"
- echo " --install-dir Specifies a custom path for installation
- (default: /opt/redmine)"
- echo " --no-configure-mariadb Does not launch the default MariaDB server
- configuration scriptlet (default: False)"
- echo " --no-create-user Does not create a \`redmine\` user
- (default: False)"
- echo " --migrate Launches a different procedure for
- installation, which also import previous
- existing data (default: False)"
- echo " --migration-source-sql Specifies the path of the SQL database
- export (default: \$PWD/redmine.sql)"
- echo " --migration-source-dir Specifies the path of the previous redmine
- installation. It can either be a different
- path, or the same as the current installation
- (default: /opt/redmine)"
- echo
- echo "Encountered error:"
- if [ "$1" ]; then
- echo " $1"
- if [ "$2" ]; then
- exit $2
- fi
- fi
- exit 0
- }
-
- # Update current system
- _update_system() {
- [[ "$VERBOSE" = true ]] && echo "Updating current system"
- ERR=$( { apt update 1>/dev/null; } 2>&1 | grep -v "stable CLI interface" )
- [[ "$ERR" ]] && echo "Error during package cache update: $ERR"
- ERR=$( { apt -y upgrade 1>/dev/null; } 2>&1 | grep -v \
- "stable CLI interface" )
- [[ "$ERR" ]] && echo "Error during system package updates: $ERR"
- }
-
- # Install required packages to run Redmine and Ruby on Rails underneath
- _install_rails_environment() {
- [[ "$VERBOSE" = true ]] && echo "Installing required packages to run \
- Redmine and Ruby on Rails underneath"
- ERR=$( { apt -y install build-essential ruby-dev libxslt1-dev \
- libmariadb-dev libxml2-dev zlib1g-dev imagemagick \
- libmagickwand-dev curl apache2 libapache2-mod-passenger \
- mariadb-client mariadb-server 1>/dev/null; } 2>&1 | grep -v \
- "stable CLI interface" )
- [[ "$ERR" ]] && echo "Error during package installations: $ERR"
- }
-
- # Add an unprivileged user to run the Redmine app afterwards
- _add_redmine_user() {
- [[ "$VERBOSE" = true ]] && echo "Adding an unprivileged user to run the \
- Redmine app afterwards"
- useradd -r -m -d "$REDMINE_INSTALL_DIR" -s /usr/bin/bash redmine &>/dev/null && \
- usermod -aG redmine www-data &>/dev/null
- }
-
- # Ask the user for mysql `root` password and configure mysql in unattended mode
- _configure_mariadb_server() {
- read -sp 'Please type a `root` password for mysql database: ' \
- MYSQL_ROOT_PASSWORD && echo ""
-
- [[ "$VERBOSE" = true ]] && echo "Configuring mysql in unattended mode"
- ERR=$( { apt -y install expect >/dev/null; } 2>&1 | grep -v \
- "stable CLI interface" )
- [[ "$ERR" ]] && echo "Error during package installations: $ERR"
- SECURE_MYSQL=$(expect -c "
- set timeout 10
- spawn mysql_secure_installation
- expect \"Enter current password for root (enter for none):\"
- send \"\r\"
- expect \"Set root password?\"
- send \"y\r\"
- expect \"New password:\"
- send \"$MYSQL_ROOT_PASSWORD\r\"
- expect \"Re-enter new password:\"
- send \"$MYSQL_ROOT_PASSWORD\r\"
- expect \"Remove anonymous users?\"
- send \"y\r\"
- expect \"Disallow root login remotely?\"
- send \"y\r\"
- expect \"Remove test database and access to it?\"
- send \"y\r\"
- expect \"Reload privilege tables now?\"
- send \"y\r\"
- expect eof
- ")
- ERR=$( { echo "$SECURE_MYSQL" 1>/dev/null; } 2>&1 )
- [[ "$ERR" ]] && echo "Error during mysql_initialization: $ERR"
- ERR=$( { apt -y remove --purge expect >/dev/null; } 2>&1 | \
- grep -v "stable CLI interface" )
- [[ "$ERR" ]] && echo "Error during package removals: $ERR"
-
- unset SECURE_MYSQL
- }
-
- # Create Redmine database with associated login
- _configure_redmine_database() {
- [[ "$VERBOSE" = true ]] && echo "Creating Redmine database with \
- associated login"
- MYSQL_ROOT_USER="root"
- QUERY="command=password&format=plain&scheme=rrnnnrrnrnnnrrnrnnrr"
- REDMINE_ADMIN_PASSWORD=$(curl -s \
- "https://www.passwordrandom.com/query?$QUERY")
- SQL="CREATE DATABASE redmine;"
- mysql -u$MYSQL_ROOT_USER -p$MYSQL_ROOT_PASSWORD -e "$SQL"
- SQL="GRANT ALL PRIVILEGES ON redmine.* TO redmine_admin@localhost
- IDENTIFIED BY '$REDMINE_ADMIN_PASSWORD';"
- mysql -u$MYSQL_ROOT_USER -p$MYSQL_ROOT_PASSWORD -e "$SQL"
- SQL="FLUSH PRIVILEGES;"
- mysql -u$MYSQL_ROOT_USER -p$MYSQL_ROOT_PASSWORD -e "$SQL"
-
- unset SQL; unset MYSQL_ROOT_USER; unset MYSQL_ROOT_PASSWORD; unset QUERY
- }
-
- # Download Redmine on temporary directory, extract it on /opt and reconfigure
- # default config parameters with real values
- _download_redmine() {
- [[ "$VERBOSE" = true ]] && echo "Downloading Redmine on temporary \
- directory"
- ERR=$( { wget -q \
- http://www.redmine.org/releases/redmine-${REDMINE_VERSION}.tar.gz -P \
- /tmp/ && wget -q \
- http://www.redmine.org/releases/redmine-${REDMINE_VERSION}.tar.gz.md5 \
- -P /tmp/ && cd /tmp/ && md5sum -c \
- redmine-${REDMINE_VERSION}.tar.gz.md5 1>/dev/null; } 2>&1 )
- [[ "$ERR" ]] && echo "Error downloading or verifying signature of \
- Redmine: $ERR"
- rm /tmp/redmine-${REDMINE_VERSION}.tar.gz.md5
-
- [[ "$VERBOSE" = true ]] && echo "Extracting Redmine on \
- $REDMINE_INSTALL_DIR"
- mkdir "$REDMINE_INSTALL_DIR" && chown redmine:redmine \
- "$REDMINE_INSTALL_DIR"
- sudo -u redmine tar xzf /tmp/redmine-${REDMINE_VERSION}.tar.gz -C \
- "$REDMINE_INSTALL_DIR" --strip-components=1
-
- [[ "$VERBOSE" = true ]] && echo "Configuring Redmine"
- sudo -u redmine cp \
- "$REDMINE_INSTALL_DIR"/config/configuration.yml{.example,} && sudo \
- -u redmine cp "$REDMINE_INSTALL_DIR"/config/database.yml{.example,} \
- && sudo -u redmine cp \
- "$REDMINE_INSTALL_DIR"/public/dispatch.fcgi{.example,}
- sed -i "0,/root/s//redmine_admin/" \
- "$REDMINE_INSTALL_DIR"/config/database.yml
- sed -i "0,/\"\"/s//\"$REDMINE_ADMIN_PASSWORD\"/" \
- "$REDMINE_INSTALL_DIR"/config/database.yml
- unset REDMINE_ADMIN_PASSWORD
- unset REDMINE_VERSION
- }
-
- _configure_redmine_permissions() {
- # Create required Redmine folders and set correct permissions
- [[ "$VERBOSE" = true ]] && echo "Creating required Redmine folders and \
- set correct permissions"
- sudo -u redmine mkdir -p tmp/pdf
- sudo -u redmine mkdir -p public/plugin_assets
- }
-
- _configure_redmine_dependencies() {
- # Install required Ruby files
- [[ "$VERBOSE" = true ]] && echo "Installing required Ruby files"
- cd "$REDMINE_INSTALL_DIR"
- ERR=$( { gem install bundler 1>/dev/null; } 2>&1 )
- [[ "$ERR" ]] && echo "Error while installing bundler Gem: $ERR"
- sudo -u redmine bundle config set path "vendor/bundle"
- sudo -u redmine bundle config set without "development test"
- ERR=$( { sudo -u redmine bundle install 1>/dev/null; } 2>&1 )
- [[ "$ERR" ]] && echo "Error while installing Redmine bundled Gems: $ERR"
- sudo -u redmine bundle exec rake generate_secret_token 1>/dev/null
- sudo -u redmine RAILS_ENV=production bundle exec rake db:migrate \
- 1>/dev/null
-
- # Only if not migrating, load default redmine data
- [[ ! "$MIGRATE" ]] && sudo -u redmine RAILS_ENV=production \
- REDMINE_LANG=en bundle exec rake redmine:load_default_data 1>/dev/null
- }
-
- # Configure Apache2 to run Redmine
- _configure_apache2() {
- # Ask the user for Apache2 Redmine hostname
- read -p 'Please type the FQDN Redmine should run on: ' \
- REDMINE_HOSTNAME && echo ""
-
- [[ "$VERBOSE" = true ]] && echo "Configuring Apache2 to run Redmine"
- cat << "EOF" > /etc/apache2/sites-available/redmine.conf
- <VirtualHost *:80>
- ServerName $REDMINE_HOSTNAME
- RailsEnv production
- DocumentRoot "$REDMINE_INSTALL_DIR/public"
-
- <Directory "$REDMINE_INSTALL_DIR/public">
- Allow from all
- Require all granted
- </Directory>
-
- ErrorLog \${APACHE_LOG_DIR}/redmine_error.log
- CustomLog \${APACHE_LOG_DIR}/redmine_access.log combined
- </VirtualHost>
- EOF
- unset REDMINE_HOSTNAME; unset REDMINE_INSTALL_DIR
- }
-
- # Enable passenger module if not already done
- _enable_redmine() {
- [[ "$VERBOSE" = true ]] && echo "Enabling passenger module if not already \
- done"
- [[ ! "$( apache2ctl -M | grep -i passenger )" ]] && a2enmod passenger
-
- # Enable redmine website over Apache2
- [[ "$VERBOSE" = true ]] && echo "Enabling redmine website over Apache2"
- a2ensite redmine 1>/dev/null
- systemctl reload apache2
- }
-
- # Main program function, calls all other functions in the correct order
- _main() {
- _update_system
- _install_rails_environment
- [[ "$NO_CREATE_USER" = false ]] && _add_redmine_user
- [[ "$NO_CONFIGURE_MARIADB" = false ]] && _configure_mariadb_server
- _configure_redmine_database
- _download_redmine
- _configure_redmine_permissions
- _configure_redmine_dependencies
- _configure_apache2
- _enable_redmine
- }
-
- # Program execution
- _parse_params $@
- _main
|