Skip to content

Instantly share code, notes, and snippets.

@mbrunnen
Last active May 26, 2018 17:23
Show Gist options
  • Select an option

  • Save mbrunnen/3a8250576798daf20e7728d6c2adeb36 to your computer and use it in GitHub Desktop.

Select an option

Save mbrunnen/3a8250576798daf20e7728d6c2adeb36 to your computer and use it in GitHub Desktop.
Install Openproject 5.0 on Uberspace
#!/usr/bin/env bash
#===============================================================================
# AUTHOR: Manoel Brunnen, manoel.brunnen@gmail.com
# CREATED: 22.07.2016
# LICENSE: MIT
# FILE: openproject-5.0.sh
# USAGE: ./openproject-5.0.sh
#
# DESCRIPTION: Installing openproject 5 on uberspace
#
# No warranty! For nothing. Use it at your own risk.
#===============================================================================
#### Based on: ####
################################################################################
################################################################################
# Author: Frank Zisko, 2015
# Version: 3.2.0.5
# Licence: MIT
# Website: https://frank.zisko.io/leitstelle/2015-03-25-openproject-uberspace/
#
# No warranty! For nothing. Use it at your own risk.
#
# See also: https://www.openproject.org/open-source/manual-installation/manual-installation-guide/
################################################################################
################################################################################
set -e
set -o nounset # Treat unset variables as an error
### Logging ### ################################################################
LOG_PATH=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)/`basename "${BASH_SOURCE[0]}"`
# Backup stdout and stderr at fd 3 and fd 4
exec 3>&1 4>&2
# Restore stdout and stderr
trap 'exec 2>&4 1>&3' 0 1 2 3
# Use tee to redirect fd 1 to logfile.out and to stdout
exec 1> >(tee ${LOG_PATH}.out.log >&3)
# Use tee to redirect fd 2 to logfile.err and to stderr
exec 2> >(tee ${LOG_PATH}.err.log >&4)
### Log ### ####################################################################
JOB_NAME="Install OpenProject"
echo " "
echo "### Start Job: ${JOB_NAME} at $(date "+%Y-%m-%dT%H:%M:%S"). ###"
echo " " 1>&2
echo "### Start Job: ${JOB_NAME} at $(date "+%Y-%m-%dT%H:%M:%S"). ###" 1>&2
time_begin=$(date +"%s")
################################################################################
### Variables ### ##############################################################
################################################################################
# You just have to adjust these three variables:
# Subdomain for this service.
SUBDOMAIN=openproject
# Domain.
# An Uberspace domain (<projectname>.<uberuser>.<uberserver>.uberspace.de) will be automatically added.
DOMAINNAME="${SUBDOMAIN}.example.com"
# Free usable port. Will be tested before the installation.
PORT=65432
# UTF encoding.
LANG=en_US.UTF-8
# Project name. Used for installation and "virtual" home dir.
PROJECTNAME=openproject
# Place where all (other) projects are installed.
WORKSPACE=${HOME}/workspace
# The real home dir.
REALHOME=${HOME}
# Virtual home dir. It'll be usen for a clean installation and uninstallation.
VIRTHOME=${WORKSPACE}/${PROJECTNAME}-home
# This home dir.
HOME=${VIRTHOME}
# Versions.
OPENPROJECT_V="5"
RUBY_V="2.3.0" # 2.0.0, 2.1.2, 2.2.2
RUBYVERSION="2.3.0" # 2.0, 2.1, 2.2
RUBYGEM_V="2.3.0" # 2.0.0, 2.1.0, 2.2.0
NODE_V="0.12.7"
# Paths:
# Home bin.
PATH=${HOME}/bin:${HOME}/.local/bin:${PATH}
# Ruby.
PATH=/package/host/localhost/ruby-${RUBY_V}/bin:${PATH}
PATH=${HOME}/.gem/ruby/${RUBYGEM_V}/bin:${PATH}
# Node.js.c
PATH=/package/host/localhost/nodejs-${NODE_V}/bin:${PATH}
################################################################################
### Uninstall ### ##############################################################
################################################################################
if [[ ("${1}" == "uninstall") || ("${1}" == "uninstallall") ]]; then
echo "Uninstallation ..."
HOME=${REALHOME}
#### Services ####
echo " services ..."
# OpenProject Web.
SVC="${PROJECTNAME}-web"
if [ -d "${HOME}/service/${SVC}" ]; then
cd ${HOME}/service/${SVC}
svc -dx . log
rm ${HOME}/service/${SVC}
fi
if [ -d "${HOME}/etc/run-${SVC}" ]; then
rm -rf ${HOME}/etc/run-${SVC}
fi
if [ -f "${HOME}/service/${SVC}" ]; then
rm ${HOME}/service/${SVC}
fi
# OpenProject Worker.
SVC="${PROJECTNAME}-worker"
if [ -d "${HOME}/service/${SVC}" ]; then
cd ${HOME}/service/${SVC}
svc -dx . log
rm ${HOME}/service/${SVC}
fi
if [ -d "${HOME}/etc/run-${SVC}" ]; then
rm -rf ${HOME}/etc/run-${SVC}
fi
if [ -f "${HOME}/service/${SVC}" ]; then
rm ${HOME}/service/${SVC}
fi
#### HTML links ####
echo " html links ..."
if [ -n "${SUBDOMAIN}" ]; then
cd /var/www/virtual/${USER}/
rm -rf ${SUBDOMAIN}.${USER}.$(hostname -a).uberspace.de
fi
# Prevent deleting ${USER}s www directory, if ${DOMAINNAME} is empty.
if [ -n "${DOMAINNAME}" ]; then
cd /var/www/virtual/${USER}/
rm -rf ${DOMAINNAME}
fi
#### Installation folder and all its content ####
echo " project dir and virtual home dir ..."
# Virtual home directory.
if [ -d "${WORKSPACE}/${PROJECTNAME}-home" ]; then
rm -rf ${WORKSPACE}/${PROJECTNAME}-home
fi
# Project directory.
if [ -d "${WORKSPACE}/${PROJECTNAME}" ]; then
rm -rf ${WORKSPACE}/${PROJECTNAME}
fi
# Git directory.
if [ "${1}" == "uninstallall" ]; then
if [ -d "${WORKSPACE}/${PROJECTNAME}-git" ]; then
rm -rf ${WORKSPACE}/${PROJECTNAME}-git
fi
fi
#### Databases ####
if [[ ("${1}" == "uninstallall") || ("${1}" == "uninstalldb") ]]; then
echo " database ..."
# Drop existing databases.
# Check if database is existing.
# Connect to database and instantly exiting database returns nothing.
# No exisitng database returns an error.
if [ -z "$(mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` --database="${USER}_${PROJECTNAME}" --execute=exit)" ]; then
echo " Drop existing database ${USER}_${PROJECTNAME}."
mysql -e "DROP DATABASE ${USER}_${PROJECTNAME};"
fi
if [ -z "$(mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` --database="${USER}_${PROJECTNAME}_dev" --execute=exit)" ]; then
echo " Drop existing database ${USER}_${PROJECTNAME}_dev."
mysql -e "DROP DATABASE ${USER}_${PROJECTNAME}_dev;"
fi
if [ -z "$(mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` --database="${USER}_${PROJECTNAME}_test" --execute=exit)" ]; then
echo " Drop existing database ${USER}_${PROJECTNAME}_test."
mysql -e "DROP DATABASE ${USER}_${PROJECTNAME}_test;"
fi
fi
#### End uninstallation ####
echo "Uninstallation finished."
exit 0
fi
################################################################################
### Check ### ##################################################################
################################################################################
echo "Checking existing installation ..."
#### Exist ####
# Check existing installation of openproject-web.
if [ -f ${HOME}/bin/${PROJECTNAME}-web ]; then
echo "~/bin/${PROJECTNAME}-web exists."
IS_INSTALLED=true
fi
# Check existing installation of openproject-worker.
if [ -f ${HOME}/bin/${PROJECTNAME}-worker ]; then
echo "~/bin/${PROJECTNAME}-worker exists."
IS_INSTALLED=true
fi
# Check termination condition.
if [ -n "${IS_INSTALLED}" ]; then
echo "OpenProject files found. Maybe it is already installed. Aborting."
exit 1
fi
echo "Checking server port, ruby and node ..."
#### Port ####
# Check if port is (already) unused.
if [ -z "$(netstat -tulpen | grep ${PORT})" ]; then
echo " Your choosen port (${PORT}) is available."
else
echo " Your choosen port (${PORT}) is not available. Choose another."
echo " Aborting the script."
exit 2
fi
#### Ruby ####
# Check if ruby is available.
if [ -z "$(command -v ruby)" ]; then
echo " 'ruby' command not found."
RUBY_FOUND=false
else
echo " 'ruby' command found."
RUBY_FOUND=true
fi
# Check if gem is available.
if [ -z "$(command -v gem)" ]; then
echo " 'gem' command not found."
GEM_FOUND=false
else
echo " 'gem' command found."
GEM_FOUND=true
fi
# Check termination condition.
if [[ ! ( (${RUBY_FOUND} == true) && (${GEM_FOUND} == true) ) ]]; then
echo " Ruby is not complete. Aborting."
exit 3
fi
#### Node ####
# Check if node is available.
if [ -z "$(command -v node)" ]; then
echo " 'node' command not found."
echo " You may add 'export PATH=/package/host/localhost/nodejs-${NODE_V}/bin:\$PATH' into your ~/.bashrc file."
NODE_FOUND=false
else
echo " 'node' command found."
NODE_FOUND=true
fi
# Check if npm is available.
if [ -z "$(command -v npm)" ]; then
echo " 'npm' command not found."
echo " You may add 'export PATH=/package/host/localhost/nodejs-${NODE_V}/bin:\$PATH' into your ~/.bashrc file."
NPM_FOUND=false
else
echo " 'npm' command found."
NPM_FOUND=true
fi
# Check termination condition.
if [[ ! ( (${NODE_FOUND} == true) && (${NPM_FOUND} == true) ) ]]; then
echo " Node is not complete. Aborting."
exit 4
fi
################################################################################
### Setup environment ### ######################################################
################################################################################
echo "Setup build environment ..."
mkdir -p ${WORKSPACE}
mkdir -p ${WORKSPACE}/${PROJECTNAME}-home
# When you load this from your shell, you're in the installing environment.
cat > ${HOME}/.bashrc <<__EOF__
LANG=en_US.UTF-8
SUBDOMAIN=${SUBDOMAIN}
DOMAINNAME=${DOMAINNAME}
PORT=${PORT}
PROJECTNAME=${PROJECTNAME}
WORKSPACE=${WORKSPACE}
# The real home dir.
REALHOME=${REALHOME}
# Virtual home dir.
VIRTHOME=${VIRTHOME}
# This home dir.
HOME=${HOME}
alias getmyhomeback='HOME=${REALHOME}'
PATH=\${HOME}/bin:\${HOME}/.local/bin:\${PATH}
PATH=/package/host/localhost/ruby-${RUBY_V}/bin:\${PATH}
PATH=\${HOME}/.gem/ruby/${RUBYGEM_V}/bin:\${PATH}
PATH=/package/host/localhost/nodejs-${NODE_V}/bin:\${PATH}
__EOF__
################################################################################
### Download ### ###############################################################
################################################################################
echo "Cloneing OpenProject directory from repo ..."
if [ -d ${WORKSPACE}/${PROJECTNAME}-git ]; then
cd ${WORKSPACE}/${PROJECTNAME}-git
git checkout stable/${OPENPROJECT_V}
git pull --depth 1
else
git clone https://github.com/opf/openproject.git --branch stable/${OPENPROJECT_V} --depth 1 ${WORKSPACE}/${PROJECTNAME}-git
fi
if [ -d ${WORKSPACE}/${PROJECTNAME} ]; then
rm -rf ${WORKSPACE}/${PROJECTNAME}
cp -r ${WORKSPACE}/${PROJECTNAME}-git ${WORKSPACE}/${PROJECTNAME}
rm -rf ${WORKSPACE}/${PROJECTNAME}/.git
else
cp -r ${WORKSPACE}/${PROJECTNAME}-git ${WORKSPACE}/${PROJECTNAME}
rm -rf ${WORKSPACE}/${PROJECTNAME}/.git
fi
################################################################################
### Configure ### ##############################################################
################################################################################
echo "Configure OpenProject, its database and its gems ..."
#### configuration.yml ####
cat > ${WORKSPACE}/${PROJECTNAME}/config/configuration.yml <<__EOF__
production:
email_delivery:
delivery_method: :sendmail
sendmail_settings:
location: /usr/sbin/sendmail
arguments: -i
rails_cache_store: :memcache
__EOF__
#### database.yml ####
cat > ${WORKSPACE}/${PROJECTNAME}/config/database.yml <<__EOF__
production:
adapter: mysql2
database: ${USER}_${PROJECTNAME}
host: localhost
username: ${USER}
password: `my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'`
encoding: utf8
development:
adapter: mysql2
database: ${USER}_${PROJECTNAME}_dev
host: localhost
username: ${USER}
password: `my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'`
encoding: utf8
__EOF__
#### Gemfile ####
cat > ${WORKSPACE}/${PROJECTNAME}/Gemfile.local <<__EOF__
gem 'rails_12factor'
__EOF__
################################################################################
### Gems ### ###################################################################
################################################################################
mkdir -p ${HOME}/etc
echo "RUBYVERSION=${RUBYVERSION}" > ${HOME}/etc/rubyversion
echo "gem: --user-install --no-rdoc --no-ri" > ${HOME}/.gemrc
cd ${WORKSPACE}/${PROJECTNAME}
echo "Installing bundler via gem ..."
gem install --user bundler
echo "Installing ruby dependencies (gems) via bundler ..."
bundle install --path $HOME/.gem --without postgres:sqlite:development:test:therubyracer:docker
# bundle install --without postgres:sqlite:development:test:therubyracer:docker
################################################################################
### Databases ### ##############################################################
################################################################################
echo "Set up the database ..."
cd ${WORKSPACE}/${PROJECTNAME}
if [ "${1}" == "installclean" ]; then
echo " delete old ones ..."
# Drop existing databases.
# Check if database is existing.
# Connect to database and instantly exiting database returns nothing.
# A non existing database returns an error.
if [ -z "$(mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` --database="${USER}_${PROJECTNAME}" --execute=exit)" ]; then
echo "Drop existing database ${USER}_${PROJECTNAME}."
mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` -e "DROP DATABASE ${USER}_${PROJECTNAME}"
fi
if [ -z "$(mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` --database="${USER}_${PROJECTNAME}_dev" --execute=exit)" ]; then
echo "Drop existing database ${USER}_${PROJECTNAME}_dev."
mysql -e "DROP DATABASE ${USER}_${PROJECTNAME}_dev;"
fi
if [ -z "$(mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` --database="${USER}_${PROJECTNAME}_test" --execute=exit)" ]; then
echo "Drop existing database ${USER}_${PROJECTNAME}_test."
mysql -e "DROP DATABASE ${USER}_${PROJECTNAME}_test;"
fi
echo " create new one ..."
# Create new database.
mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` -e "CREATE DATABASE ${USER}_${PROJECTNAME} CHARACTER SET utf8"
#mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` -e "CREATE DATABASE ${USER}_${PROJECTNAME}_dev CHARACTER SET utf8"
#mysql --user="${USER}" --password=`my_print_defaults --defaults-file=${REALHOME}/.my.cnf client | grep -- --password | awk -F = '{ print $2 }'` -e "CREATE DATABASE ${USER}_${PROJECTNAME}_test CHARACTER SET utf8"
fi
echo " create, migrate and seed the database ..."
SECRET_KEY_BASE=$(./bin/rake secret)
echo "export SECRET_KEY_BASE=$SECRET_KEY_BASE" >> $HOME/.bashrc
RAILS_ENV=production bundle exec rake db:create db:migrate db:seed
################################################################################
### Node Package Manager & Bower ### ###########################################
################################################################################
cd ${WORKSPACE}/${PROJECTNAME}
# Node Package Manager.
cat > ${HOME}/.npmrc <<__EOF__
prefix = $HOME
umask = 077
__EOF__
# "Bower - A package manager for the web"
cat > ${HOME}/.bowerrc <<__EOF__
{
"interactive": false
}
__EOF__
# cat > ${WORKSPACE}/${PROJECTNAME}/.bowerrc <<__EOF__
# {
# "directory": "vendor/assets/components"
# }
# __EOF__
# Help: https://docs.npmjs.com/cli/install
echo "Installing bower via npm ..."
npm install -g bower
echo "Installing node modules via npm ..."
npm install
# echo "Installing bower components via bower ..."
# bower install
################################################################################
### Precompile OpenProject ### #################################################
################################################################################
echo "Precompile assets ..."
RAILS_ENV=production bundle exec rake assets:precompile
################################################################################
### Startscripts ### ###########################################################
################################################################################
echo "Create OpenProject start scripts ..."
# OpenProject web starter.
mkdir -p ${HOME}/bin
cat > ${HOME}/bin/${PROJECTNAME}-web <<__EOF__
#!/usr/bin/env bash
HOME=${WORKSPACE}/${PROJECTNAME}-home
PATH=\${HOME}/bin:\${HOME}/.local/bin:\${PATH}
PATH=/package/host/localhost/ruby-${RUBY_V}/bin:\${PATH}
PATH=\${HOME}/.gem/ruby/${RUBYGEM_V}/bin:\${PATH}
PATH=/package/host/localhost/nodejs-${NODE_V}/bin:\${PATH}
export SECRET_KEY_BASE=$SECRET_KEY_BASE
# Start the application in the project folder.
cd ${WORKSPACE}/${PROJECTNAME}
exec bundle exec unicorn --port ${PORT} --env production
__EOF__
chmod +x ${HOME}/bin/${PROJECTNAME}-web
# OpenProject worker starter.
mkdir -p ${HOME}/bin
cat > ${HOME}/bin/${PROJECTNAME}-worker <<__EOF__
#!/usr/bin/env bash
HOME=${WORKSPACE}/${PROJECTNAME}-home
PATH=\${HOME}/bin:\${HOME}/.local/bin:\${PATH}
PATH=/package/host/localhost/ruby-${RUBY_V}/bin:\${PATH}
PATH=\${HOME}/.gem/ruby/${RUBYGEM_V}/bin:\${PATH}
PATH=/package/host/localhost/nodejs-${NODE_V}/bin:\${PATH}
# Use the production database.
export RAILS_ENV=production
# Start the application in the project folder.
cd ${WORKSPACE}/${PROJECTNAME}
exec bundle exec rake jobs:work
__EOF__
chmod +x ${HOME}/bin/${PROJECTNAME}-worker
################################################################################
### Start Services ### #########################################################
################################################################################
echo "Install OpenProject services ..."
# We change $HOME back to the real one.
# We need this for managing the project as service.
HOME=${REALHOME}
test -d ${HOME}/service || uberspace-setup-svscan
uberspace-setup-service ${PROJECTNAME}-web ${WORKSPACE}/${PROJECTNAME}-home/bin/${PROJECTNAME}-web
uberspace-setup-service ${PROJECTNAME}-worker ${WORKSPACE}/${PROJECTNAME}-home/bin/${PROJECTNAME}-worker
################################################################################
### Rewrite Proxy ### ##########################################################
################################################################################
echo "Install OpenProject apache rewrite proxy ..."
mkdir -p /var/www/virtual/${USER}/${SUBDOMAIN}.${USER}.$(hostname -a).uberspace.de
if [ -n "${DOMAINNAME}" ]; then
ln -s /var/www/virtual/${USER}/${SUBDOMAIN}.${USER}.$(hostname -a).uberspace.de /var/www/virtual/${USER}/${DOMAINNAME}
fi
cat > /var/www/virtual/${USER}/${SUBDOMAIN}.${USER}.$(hostname -a).uberspace.de/.htaccess <<__EOF__
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteCond %{ENV:HTTPS} !=on
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule (.*) http://localhost:${PORT}/\$1 [P]
__EOF__
################################################################################
### Info ### ###################################################################
################################################################################
echo " "
echo "You can do your first login:"
echo " https://${DOMAINNAME}"
echo " user: admin"
echo " password: admin"
echo " Change the password immediately!"
echo " "
echo "To seed your OpenProject instance with roles, workflows, ...,"
echo " got to: https://${DOMAINNAME}/settings?tab=display"
echo " and set your language. "
echo " After that, got to: https://${DOMAINNAME}/admin/projects"
echo " select your language and click at 'loading default configuration'."
echo " "
echo "Restart OpenProject services:"
echo " svc -du ~/service/${PROJECTNAME}-web"
echo " svc -du ~/service/${PROJECTNAME}-worker"
echo "Logs will be written in:"
echo " ~/service/${PROJECTNAME}-web/log/main/current"
echo " ~/service/${PROJECTNAME}-worker/log/main/current"
echo " "
echo "For uninstallation call:"
echo " $(cd `dirname "${BASH_SOURCE[0]}"` && pwd)/`basename "${BASH_SOURCE[0]}"` uninstall"
echo "For uninstallation including databases and git repo use:"
echo " $(cd `dirname "${BASH_SOURCE[0]}"` && pwd)/`basename "${BASH_SOURCE[0]}"` uninstallall"
### Log ### ####################################################################
echo " "
time_end=$(date +"%s")
time_diff=$((${time_end}-${time_begin}))
echo "### Finished Job: ${JOB_NAME} at $(date "+%Y-%m-%dT%H:%M:%S"). ###"
echo " $((${time_diff} / 60)) minutes and $((${time_diff} % 60)) seconds elapsed."
echo " "
################################################################################
################################################################################
@Tschoepler
Copy link

Hi and thanks for this script. I get the following error:
openproject.sh: line 101: 1: unbound variable
Could you give a hint on how to fix this?

Also: have you tested this script with version 6 of OpenProject?

Again, thanks for sharing!

@mbrunnen
Copy link
Author

Hey, sorry for that late answer. I will check that later. Seems that the missing commandline argument, e.g. install, is the problem. You can remove set -o nounset at the beginning to kill the sympton.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment