diff --git a/conf/discourse-puma.service b/conf/discourse-puma.service index da71b50..b129f7b 100644 --- a/conf/discourse-puma.service +++ b/conf/discourse-puma.service @@ -12,8 +12,8 @@ User=__APP__ Group=__APP__ WorkingDirectory=__FINALPATH__ Environment=RAILS_ENV=production -ExecStart=__FINALPATH__/bin/bundle exec puma --config config/puma.rb -e production -ExecStop=__FINALPATH__/bin/bundle exec pumactl stop +ExecStart=__RBENVROOT__/shims/bundle exec puma --config config/puma.rb -e production +ExecStop=__RBENVROOT__/shims/bundle exec pumactl stop RemainAfterExit=true Restart=always RestartSec=10 diff --git a/conf/discourse-sidekiq.service b/conf/discourse-sidekiq.service index db6bc23..a226b1b 100644 --- a/conf/discourse-sidekiq.service +++ b/conf/discourse-sidekiq.service @@ -7,7 +7,7 @@ User=__APP__ Group=__APP__ WorkingDirectory=__FINALPATH__ Environment=RAILS_ENV=production -ExecStart=__FINALPATH__/bin/bundle exec sidekiq -C config/sidekiq.yml +ExecStart=__RBENVROOT__/shims/bundle exec sidekiq -C config/sidekiq.yml Restart=always RestartSec=10 diff --git a/scripts/_common.sh b/scripts/_common.sh index bd9ea6b..4cb925c 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -3,8 +3,17 @@ # Common variables # -pkg_dependencies="ruby-zip libssl-dev libyaml-dev libcurl4-openssl-dev ruby gem libapr1-dev libxslt1-dev checkinstall libxml2-dev ruby-dev vim libmagickwand-dev imagemagick postgresql postgresql-server-dev-all" +pkg_dependencies="zlib1g-dev libreadline-dev libpq-dev libssl-dev libyaml-dev libcurl4-openssl-dev libapr1-dev libxslt1-dev checkinstall libxml2-dev vim imagemagick postgresql postgresql-server-dev-all postgresql-contrib optipng jhead jpegoptim gifsicle" +RUBY_VERSION="2.4.4" +# Execute a command as another user with login +# (hence in user home dir, with prior loading of .profile, etc.) +# usage: exec_login_as USER COMMAND [ARG ...] +exec_login_as() { + local user=$1 + shift 1 + exec_as $user --login "$@" +} # Execute a command as another user # usage: exec_as USER COMMAND [ARG ...] exec_as() { @@ -371,3 +380,139 @@ ynh_check_starting_systemd () { echo "" ynh_clean_check_starting_systemd } + + +rbenv_install_dir="/opt/rbenv" +ruby_version_path="/opt/rbenv/versions" +# RBENV_ROOT is the directory of rbenv, it needs to be loaded as a environment variable. +export RBENV_ROOT="$rbenv_install_dir" + +# Install ruby version management +# +# [internal] +# +# usage: ynh_install_rbenv +ynh_install_rbenv () { + echo "Installation of rbenv - ruby version management" >&2 + # Build an app.src for rbenv + mkdir -p "../conf" + echo "SOURCE_URL=https://github.com/rbenv/rbenv/archive/v1.1.1.tar.gz +SOURCE_SUM=41f1a60714c55eceb21d692a469aee1ec4f46bba351d0dfcb0c660ff9cf1a1c9" > "../conf/rbenv.src" + # Download and extract rbenv + ynh_setup_source "$rbenv_install_dir" rbenv + + # Build an app.src for ruby-build + mkdir -p "../conf" + echo "SOURCE_URL=https://github.com/rbenv/ruby-build/archive/v20180329.tar.gz +SOURCE_SUM=4c8610c178ef2fa6bb29d4bcfca52608914632a51a56a5e70aeec8bf0894167b" > "../conf/ruby-build.src" + # Download and extract ruby-build + ynh_setup_source "$rbenv_install_dir/plugins/ruby-build" ruby-build + + (cd $rbenv_install_dir + ./src/configure && make -C src) + +# Create shims directory if needed +if [ ! -d $rbenv_install_dir/shims ] ; then + mkdir $rbenv_install_dir/shims +fi +} + +# Install a specific version of ruby +# +# ynh_install_ruby will install the version of ruby provided as argument by using rbenv. +# +# rbenv (ruby version management) stores the target ruby version in a .ruby_version file created in the target folder (using rbenv local ) +# It then uses that information for every ruby user that uses rbenv provided ruby command +# +# This helper creates a /etc/profile.d/rbenv.sh that configures PATH environment for rbenv +# for every LOGIN user, hence your user must have a defined shell (as opposed to /usr/sbin/nologin) +# +# Don't forget to execute ruby-dependent command in a login environment +# (e.g. sudo --login option) +# When not possible (e.g. in systemd service definition), please use direct path +# to rbenv shims (e.g. $RBENV_ROOT/shims/bundle) +# +# usage: ynh_install_ruby ruby_version user +# | arg: ruby_version - Version of ruby to install. +# If possible, prefer to use major version number (e.g. 8 instead of 8.10.0). +# The crontab will handle the update of minor versions when needed. +ynh_install_ruby () { + # Use rbenv, https://github.com/rbenv/rbenv to manage the ruby versions + local ruby_version="$1" + + # Create $rbenv_install_dir + mkdir -p "$rbenv_install_dir/plugins/ruby-build" + + # Load rbenv path in PATH + CLEAR_PATH="$rbenv_install_dir/bin:$PATH" + + # Remove /usr/local/bin in PATH in case of ruby prior installation + PATH=$(echo $CLEAR_PATH | sed 's@/usr/local/bin:@@') + + # Move an existing ruby binary, to avoid to block rbenv + test -x /usr/bin/ruby && mv /usr/bin/ruby /usr/bin/ruby_rbenv + + # If rbenv is not previously setup, install it + if ! type rbenv > /dev/null 2>&1 + then + ynh_install_rbenv + fi + + # Restore /usr/local/bin in PATH (if needed) + PATH=$CLEAR_PATH + + # And replace the old ruby binary + test -x /usr/bin/ruby_rbenv && mv /usr/bin/ruby_rbenv /usr/bin/ruby + + # Install the requested version of ruby + CONFIGURE_OPTS="--disable-install-doc" MAKE_OPTS="-j2" rbenv install --skip-existing $ruby_version + + # Store the ID of this app and the version of ruby requested for it + echo "$YNH_APP_ID:$ruby_version" | tee --append "$rbenv_install_dir/ynh_app_version" + + # Store ruby_version into the config of this app + ynh_app_setting_set $app ruby_version $ruby_version + + # Set environment for ruby users + echo "#rbenv +export RBENV_ROOT=$rbenv_install_dir +export PATH=\"$rbenv_install_dir/bin:$PATH\" +eval \"\$(rbenv init -)\" +#rbenv" > /etc/profile.d/rbenv.sh + + # Load the right environment for the Installation + eval "$(rbenv init -)" + + (cd $final_path + rbenv local $ruby_version) +} + +# Remove the version of ruby used by the app. +# +# This helper will check if another app uses the same version of ruby, +# if not, this version of ruby will be removed. +# If no other app uses ruby, rbenv will be also removed. +# +# usage: ynh_remove_ruby +ynh_remove_ruby () { + ruby_version=$(ynh_app_setting_get $app ruby_version) + + # Remove the line for this app + sed --in-place "/$YNH_APP_ID:$ruby_version/d" "$rbenv_install_dir/ynh_app_version" + + # If no other app uses this version of ruby, remove it. + if ! grep --quiet "$ruby_version" "$rbenv_install_dir/ynh_app_version" + then + $rbenv_install_dir/bin/rbenv uninstall --force $ruby_version + fi + + # Remove rbenv environment configuration + rm /etc/profile.d/rbenv.sh + + # If no other app uses rbenv, remove rbenv and dedicated group + if [ ! -s "$rbenv_install_dir/ynh_app_version" ] + then + ynh_secure_remove "$rbenv_install_dir" + fi +} + diff --git a/scripts/install b/scripts/install index eb75374..4e1d7f5 100644 --- a/scripts/install +++ b/scripts/install @@ -55,6 +55,7 @@ ynh_app_setting_set $app domain "$domain" ynh_app_setting_set $app path_url "$path_url" ynh_app_setting_set $app admin "$admin" ynh_app_setting_set $app is_public "$is_public" +ynh_app_setting_set $app final_path $final_path #================================================= # STANDARD MODIFICATIONS @@ -64,6 +65,13 @@ ynh_app_setting_set $app is_public "$is_public" ynh_install_app_dependencies "$pkg_dependencies" +#================================================= +# CREATE DEDICATED USER +#================================================= + +# Create a system user allowing login +ynh_system_user_create $app $final_path 1 + #================================================= # CREATE A POSTGRES DATABASE #================================================= @@ -82,13 +90,18 @@ CREATE EXTENSION IF NOT EXISTS hstore; CREATE EXTENSION IF NOT EXISTS pg_trgm;" # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= -ynh_app_setting_set $app final_path $final_path # Download, check integrity, uncompress and patch the source from app.src ynh_setup_source "$final_path" # Install LDAP plugin mkdir -p "$final_path/plugins/discourse-ldap-auth" ynh_setup_source "$final_path/plugins/discourse-ldap-auth" ldap-auth +#================================================= +# INSTALL RUBY +#================================================= + +ynh_install_ruby $RUBY_VERSION + #================================================= # NGINX CONFIGURATION #================================================= @@ -101,13 +114,6 @@ fi # Create a dedicated nginx config ynh_add_nginx_config -#================================================= -# CREATE DEDICATED USER -#================================================= - -# Create a system user -ynh_system_user_create $app "$final_path" - #================================================= # SPECIFIC SETUP #================================================= @@ -173,14 +179,13 @@ ynh_store_file_checksum "$final_path/config/secrets.yml" chown -R $app: $final_path -# Install puma with gem (cd "$final_path" # Install bundler, a gems installer gem install bundler # Install without documentation -exec_as $app echo "gem: --no-ri --no-rdoc" >> "$final_path/.gemrc" +exec_as $app echo "gem: --no-ri --no-rdoc" >> "$final_path/.gemrc") # Install dependencies -exec_as $app bundle install --path vendor/bundle --with development) +exec_login_as $app MAKEFLAGS=-j2 bundle install --jobs 2 --path vendor/bundle --with development #================================================= # SETUP SIDEKIQ @@ -191,10 +196,9 @@ cp ../conf/sidekiq.yml "$final_path/config/sidekiq.yml" # PREPARE THE DATABASE #================================================= -rake_exec="exec_as $app bin/rake RAILS_ENV=production" -(cd "$final_path" +rake_exec="exec_login_as $app RAILS_ENV=production bin/rake" $rake_exec db:migrate -$rake_exec assets:precompile) +$rake_exec assets:precompile #================================================= # POPULATE THE DATABASE @@ -218,8 +222,8 @@ INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUE #================================================= if [ "$path_url" != "/" ] ; then - (cd /$final_path ; RAILS_ENV=production sudo -H -E -u $app bundle exec script/discourse remap /images/welcome/ $path_url/images/welcome/ <<< "YES - ") + exec_login_as $app RAILS_ENV=production bundle exec script/discourse remap /images/welcome/ $path_url/images/welcome/ <<< "YES + " fi #================================================= @@ -228,12 +232,11 @@ fi # Create a random password admin_pwd=$(ynh_string_random) -(cd "$final_path" $rake_exec admin:create <<< "$admin_mail $admin_pwd $admin_pwd y -") +" #================================================= # CONFIGURE PLUGINS @@ -249,6 +252,9 @@ patch -p1 < $YNH_CWD/../conf/ldap-auth-fix-subfolder.patch) # SETUP SYSTEMD #================================================= +ynh_replace_string "__RBENVROOT__" "$RBENV_ROOT" "../conf/discourse-puma.service" +ynh_replace_string "__RBENVROOT__" "$RBENV_ROOT" "../conf/discourse-sidekiq.service" + ynh_add_systemd_config $app-puma discourse-puma.service ynh_add_systemd_config $app-sidekiq discourse-sidekiq.service diff --git a/scripts/remove b/scripts/remove index 5e0530c..8e933f4 100644 --- a/scripts/remove +++ b/scripts/remove @@ -28,16 +28,6 @@ final_path=$(ynh_app_setting_get $app final_path) ynh_remove_systemd_config discourse-puma ynh_remove_systemd_config discourse-sidekiq -# STOP AND REMOVE SERVICE -#================================================= - -# Remove the dedicated systemd config -# ynh_remove_systemd_config - -# service $app stop -# rm "/etc/init.d/$app" -# update-rc.d -f $app remove - #================================================= # REMOVE SERVICE FROM ADMIN PANEL #================================================= @@ -56,6 +46,12 @@ fi # Remove metapackage and its dependencies ynh_remove_app_dependencies +#================================================= +# REMOVE RUBY +#================================================= + +ynh_remove_ruby + #================================================= # REMOVE THE POSTGRES DATABASE #================================================= diff --git a/scripts/restore b/scripts/restore index d3032e4..7bea313 100644 --- a/scripts/restore +++ b/scripts/restore @@ -56,6 +56,12 @@ ynh_restore ynh_install_app_dependencies "$pkg_dependencies" +#================================================= +# INSTALL RUBY +#================================================= + +ynh_install_ruby $RUBY_VERSION + #================================================= # REINSTALL BUNDLE GEM #================================================= @@ -94,7 +100,8 @@ ynh_use_logrotate # RECREATE OF THE DEDICATED USER #================================================= -ynh_system_user_create $app # Recreate the dedicated user, if not existing +# Create a system user allowing login (if not existing) +ynh_system_user_create $app $final_path 1 #================================================= # RESTORE USER RIGHTS diff --git a/scripts/upgrade b/scripts/upgrade index 8a3313d..9855e4a 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -58,15 +58,10 @@ fi ynh_install_app_dependencies "$pkg_dependencies" #================================================= -# DOWNLOAD, CHECK AND UNPACK SOURCE +# INSTALL RUBY #================================================= -ynh_app_setting_set $app final_path $final_path -# Download, check integrity, uncompress and patch the source from app.src -ynh_setup_source "$final_path" -# Install LDAP plugin -mkdir -p "$final_path/plugins/discourse-ldap-auth" -ynh_setup_source "$final_path/plugins/discourse-ldap-auth" ldap-auth +ynh_install_ruby $RUBY_VERSION #================================================= # NGINX CONFIGURATION @@ -80,6 +75,17 @@ fi # Create a dedicated nginx config ynh_add_nginx_config +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +ynh_app_setting_set $app final_path $final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source "$final_path" +# Install LDAP plugin +mkdir -p "$final_path/plugins/discourse-ldap-auth" +ynh_setup_source "$final_path/plugins/discourse-ldap-auth" ldap-auth + #================================================= # SPECIFIC SETUP #================================================= @@ -129,9 +135,14 @@ ynh_store_file_checksum "$ldap_config_file" # SETUP PUMA, A RUBY SERVER #================================================= puma_config_file="$final_path/config/puma.rb" +# Set log files location ynh_replace_string "#{APP_ROOT}/log/puma" "/var/log/$app/puma" "$puma_config_file" +# Set application absolute path ynh_replace_string "/home/discourse/discourse" "/var/www/$app" "$puma_config_file" +# Don't daemonize so we get logs in journalctl ynh_replace_string "daemonize true" "daemonize false" "$puma_config_file" +# Don't preload threads to avoid warnings +ynh_replace_string "preload_app" "#preload_app" "$puma_config_file" # Calculate and store the config file checksum ynh_store_file_checksum "$puma_config_file" @@ -152,7 +163,7 @@ gem install bundler # Install without documentation exec_as $app echo "gem: --no-ri --no-rdoc" >> "$final_path/.gemrc" # Install dependencies -exec_as $app bundle install --path vendor/bundle --with development) +exec_login_as $app bundle install --path vendor/bundle --with development) #================================================= # SETUP SIDEKIQ @@ -163,20 +174,9 @@ cp ../conf/sidekiq.yml "$final_path/config/sidekiq.yml" # PREPARE THE DATABASE #================================================= -(cd "$final_path" -rake_exec="exec_as $app bin/rake RAILS_ENV=production" +rake_exec="exec_login_as $app RAILS_ENV=production bin/rake" $rake_exec db:migrate -$rake_exec assets:precompile) - -#================================================= -# CONFIGURE PLUGINS -#================================================= - -# Patch ldap-auth plugin to fix it when using domain subfolder -# (Can only do that now because we are patching dependencies which have just been downloaded) -#(cd $final_path/plugins/discourse-ldap-auth -#patch -p1 < $YNH_CWD/../conf/ldap-auth-fix-subfolder.patch) -# No need to patch dependencies if they haven't changed +$rake_exec assets:precompile #================================================= # GENERIC FINALIZATION