diff --git a/README.md b/README.md index 3d69cb6..9be4c9e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Discourse for YunoHost -[![Integration level](https://dash.yunohost.org/integration/discourse.svg)](https://ci-apps.yunohost.org/jenkins/job/discourse%20%28Community%29/lastBuild/consoleFull) +[![Integration level](https://dash.yunohost.org/integration/discourse.svg)](https://dash.yunohost.org/appci/app/discourse) ![](https://ci-apps.yunohost.org/ci/badges/discourse.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/discourse.maintain.svg) [![Install Discourse with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=discourse) -> *This package allows you to install discourse quickly and simply on a YunoHost server. -If you don't have YunoHost, please see [here](https://yunohost.org/#/install) to know how to install and enjoy it.* +> *This package allows you to install Discourse quickly and simply on a YunoHost server. +If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* ## Disclaimer @@ -23,6 +23,7 @@ Moreover, you should have in mind Discourse [hardware requirements](https://gith Finally, if installing on a low-end ARM device (e.g. Raspberry Pi): - installation can last up to 3 hours, - first access right after installation could take a couple of minutes. + ## Overview [Discourse](http://www.discourse.org) is the 100% open source discussion platform built for the next decade of the Internet. Use it as a: @@ -36,16 +37,15 @@ To learn more about the philosophy and goals of the project, [visit **discourse. ## Screenshots -Boing Boing - - - - -Mobile +![](https://cloud.githubusercontent.com/assets/1385470/25397876/3fe6cdac-29c0-11e7-8a41-9d0c0279f5a3.png) +![](https://cloud.githubusercontent.com/assets/1385470/25397920/71b24e4c-29c0-11e7-8bcf-7a47b888412e.png) +![](https://cloud.githubusercontent.com/assets/1385470/25398049/f0995962-29c0-11e7-99d7-a3b9c4f0b357.png) +![](https://cloud.githubusercontent.com/assets/1385470/25398115/2d560d96-29c1-11e7-9a96-b0134a4fedff.png) +![](https://www.discourse.org/a/img/about/mobile-devices-2x.jpg) ## Configuration -Use the admin panel of your discourse to configure this app. +Use the admin panel of your Discourse to configure this app. ### Configuring "Reply-By-Email" @@ -89,7 +89,7 @@ Discourse can now receive mail from `foo@theirexternalmail.com` and give it to t * private mode: Forum only accessible by YunoHost users * public mode: Visible by anyone -#### Multi-users support +#### Multi-user support Supported, with LDAP and SSO. @@ -105,18 +105,16 @@ When disabling Local Login and other authentication services, clicking the `Logi ![LDAP Login Popup](https://raw.githubusercontent.com/jonmbake/screenshots/master/discourse-ldap-auth/ldap_popup.png) - - #### Supported architectures -* Tested on x86_64 -* Tested on ARM +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/discourse%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/discourse/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/discourse%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/discourse/) ## Limitations -### Known problems -* In the administration dashboard, The installed version is shown as `unknown` (due the fact that we don't use git for installation); you can safely ignore that as the YunoHost package will be maintained. -* On ARM devices, default generated avatars are missing the profile initials (they are only a plain discus) +None at the moment. + +## Additional information ### Known non-impacting log messages ``` fatal: Not a git repository (or any of the parent directories): .git @@ -136,14 +134,15 @@ systemctl restart discourse * Report a bug: https://github.com/YunoHost-Apps/discourse_ynh/issues * Discourse website: https://discourse.org/ + * Upstream app repository: https://github.com/discourse/discourse * YunoHost website: https://yunohost.org/ --- -Developers info ---------------- +Developer info +---------------- -Please do your pull request to the [testing branch](https://github.com/YunoHost-Apps/discourse_ynh/tree/testing). +Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/discourse_ynh/tree/testing). To try the testing branch, please proceed like that. ``` diff --git a/check_process b/check_process index 9d7b966..0707237 100644 --- a/check_process +++ b/check_process @@ -12,26 +12,20 @@ setup_private=1 setup_public=1 upgrade=1 + # 2.2.3~ynh1 upgrade=1 from_commit=de467cfa38791f43215ffea88d4b85460e5c0457 + # 2.3.10~ynh1 + upgrade=1 from_commit=086de718f49a506c66498d2f7610f5fd0ce07d50 backup_restore=1 -# Activate multi-instance test only if you have more than 2Gb RAM! + # Activate multi-instance test only if you have more than 2Gb RAM! multi_instance=1 - incorrect_path=1 + # This test is no longer necessary since the version 2.7 (PR: https://github.com/YunoHost/yunohost/pull/304), you can still do it if your app could be installed with this version. + # incorrect_path=1 port_already_use=0 change_url=1 ;;; Levels - Level 1=auto - Level 2=auto - Level 3=auto -# LDAP integration by using discourse-ldap-lauth plugin -# HTTP auth currently not available (in base software or via a plugin) - Level 4=1 + # If the level 5 (Package linter) is forced to 1. Please add justifications here. Level 5=auto - Level 6=auto - Level 7=auto - Level 8=0 - Level 9=0 - Level 10=0 ;;; Options Email= Notification=none @@ -39,3 +33,5 @@ Notification=none ; commit=de467cfa38791f43215ffea88d4b85460e5c0457 name=Upgrade to 2.2.3 (fixes #16) manifest_arg=domain=DOMAIN&path=PATH&admin=USER&is_public=1& + ; commit=086de718f49a506c66498d2f7610f5fd0ce07d50 + name=2.3.10~ynh1 diff --git a/conf/app.src b/conf/app.src index 66ea285..d73b146 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,3 +1,6 @@ SOURCE_URL=https://github.com/discourse/discourse/archive/v2.3.10.tar.gz SOURCE_SUM=1f7a9672b983d876ed2719b3d347575a76000cc189bfa3e045341728f92fd3f8 +SOURCE_SUM_PRG=sha256sum SOURCE_FORMAT=tar.gz +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME= diff --git a/conf/nginx.conf b/conf/nginx.conf index c8b637d..4dee572 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -29,7 +29,7 @@ location __PATH__ { alias __FINALPATH__/public/; - add_header ETag ""; + proxy_hide_header ETag; if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; @@ -44,8 +44,8 @@ location ~* (assets|plugins|uploads)/.*\.(eot|ttf|woff|woff2|ico)$ { expires 1y; - add_header Cache-Control public,immutable; - add_header Access-Control-Allow-Origin *; + more_set_headers "Cache-Control : public,immutable"; + more_set_headers "Access-Control-Allow-Origin : *"; } location = __PATH__/srv/status { @@ -64,7 +64,7 @@ # longer term we should increas probably to 1y location ~ ^/javascripts/ { expires 1d; - add_header Cache-Control public,immutable; + more_set_headers "Cache-Control : public,immutable"; } location ~ ^/assets/(?.+)$ { @@ -72,7 +72,7 @@ # asset pipeline enables this # brotli_static on; gzip_static on; - add_header Cache-Control public,immutable; + more_set_headers "Cache-Control : public,immutable"; # HOOK in asset location (used for extensibility) # TODO I don't think this break is needed, it just breaks out of rewrite break; @@ -80,13 +80,13 @@ location ~ ^/plugins/ { expires 1y; - add_header Cache-Control public,immutable; + more_set_headers "Cache-Control : public,immutable"; } # cache emojis location ~ /images/emoji/ { expires 1y; - add_header Cache-Control public,immutable; + more_set_headers "Cache-Control : public,immutable"; } location ~ ^/uploads/ { @@ -104,7 +104,7 @@ proxy_set_header X-Sendfile-Type X-Accel-Redirect; proxy_set_header X-Accel-Mapping __FINALPATH__/public/=/downloads/; expires 1y; - add_header Cache-Control public,immutable; + more_set_headers "Cache-Control : public,immutable"; ## optional upload anti-hotlinking rules #valid_referers none blocked mysite.com *.mysite.com; @@ -206,7 +206,7 @@ } location @__NAME__ { - add_header Referrer-Policy 'no-referrer-when-downgrade'; + more_set_headers "Referrer-Policy : no-referrer-when-downgrade"; proxy_set_header Host $http_host; proxy_set_header X-Request-Start "t=${msec}"; proxy_set_header X-Real-IP $remote_addr; diff --git a/issue_template.md b/issue_template.md new file mode 100644 index 0000000..8a7c77f --- /dev/null +++ b/issue_template.md @@ -0,0 +1,46 @@ +--- +name: Bug report +about: Create a report to help us debug, it would be nice to fill the template as much as you can to help us, help you and help us all. + +--- + +**How to post a meaningful bug report** +1. *Read this whole template first.* +2. *Determine if you are on the right place:* + - *If you were performing an action on the app from the webadmin or the CLI (install, update, backup, restore, change url...), you are on the right place!* + - *Otherwise, the issue may be due to Discourse itself. Refer to its documentation or repository for help.* + - *If you have a doubt, post here, we will figure it out together.* +3. *Delete the italic comments as you write over them below, and remove this guide.* +--- + +**Describe the bug** +*A clear and concise description of what the bug is.* + +**Versions** +- Hardware: *VPS bought online / Old laptop or computer / Raspberry Pi at home / Internet Cube with VPN / Other ARM board / ...* +- YunoHost version: x.x.x +- I have access to my server: *Through SSH | through the webadmin | direct access via keyboard / screen | ...* +- Are you in a special context or did you perform some particular tweaking on your YunoHost instance ?: *no / yes* + - If yes, please explain: +- Using, or trying to install package version/branch: +- If upgrading, current package version: *can be found in the admin, or with `yunohost app info $app_id`* + +**To Reproduce** +*Steps to reproduce the behavior.* +- *If you performed a command from the CLI, the command itself is enough. For example:* + ```sh + sudo yunohost app install discourse + ``` +- *If you used the webadmin, please perform the equivalent command from the CLI first.* +- *If the error occurs in your browser, explain what you did:* + 1. *Go to '...'* + 2. *Click on '....'* + 3. *Scroll down to '....'* + 4. *See error* + +**Expected behavior** +*A clear and concise description of what you expected to happen. You can remove this section if the command above is enough to understand your intent.* + +**Logs** +*After a failed command, YunoHost makes the log available to you, but also to others, thanks to `yunohost log display [log name] --share`. The actual command, with the correct log name, is displayed at the end of the failed attempt in the CLI. Execute it and copy here the share link it outputs.* +*If applicable and useful, add screenshots to help explain your problem.* diff --git a/manifest.json b/manifest.json index 22d646d..99b0585 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Discussion platform", "fr": "Plateforme de discussion" }, - "version": "2.3.10~ynh1", + "version": "2.3.10~ynh2", "url": "http://Discourse.org", "license": "GPL-2.0", "maintainer": { @@ -15,7 +15,7 @@ "url": "" }, "requirements": { - "yunohost": ">= 2.7.12" + "yunohost": ">= 3.5" }, "multi_instance": true, "services": [ @@ -27,7 +27,7 @@ "name": "domain", "type": "domain", "ask": { - "en": "Choose a domain for Discourse", + "en": "Choose a domain name for Discourse", "fr": "Choisissez un nom de domaine pour Discourse" }, "example": "domain.org" diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 0000000..55e358e --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,18 @@ +## Problem +- *Description of why you made this PR* + +## Solution +- *And how do you fix that problem* + +## PR Status +- [ ] Code finished. +- [ ] Tested with Package_check. +- [ ] Fix or enhancement tested. +- [ ] Upgrade from last version tested. +- [ ] Can be reviewed and tested. + +## Package_check results +--- +*If you have access to [App Continuous Integration for packagers](https://yunohost.org/#/packaging_apps_ci) you can provide a link to the package_check results like below, replacing '-NUM-' in this link by the PR number and USERNAME by your username on the ci-apps-dev. Or you provide a screenshot or a pastebin of the results* + +[![Build Status](https://ci-apps-dev.yunohost.org/jenkins/job/discourse_ynh%20PR-NUM-%20(USERNAME)/badge/icon)](https://ci-apps-dev.yunohost.org/jenkins/job/discourse_ynh%20PR-NUM-%20(USERNAME)/) diff --git a/scripts/_common.sh b/scripts/_common.sh index 35f4d9d..b1c3267 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -1,11 +1,17 @@ #!/bin/bash -# -# Common variables -# -pkg_dependencies="g++ libjemalloc1 libjemalloc-dev 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 brotli" +#================================================= +# COMMON VARIABLES +#================================================= + +pkg_dependencies="g++ libjemalloc1|libjemalloc2 libjemalloc-dev zlib1g-dev libreadline-dev libpq-dev libssl-dev libyaml-dev libcurl4-openssl-dev libapr1-dev libxslt1-dev libxml2-dev vim imagemagick postgresql postgresql-server-dev-all postgresql-contrib optipng jhead jpegoptim gifsicle brotli" + RUBY_VERSION="2.6.5" +#================================================= +# PERSONAL HELPERS +#================================================= + # 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 ...] @@ -52,11 +58,11 @@ is_memory_available() { # terminates installation if requirements not met check_memory_requirements() { if ! is_swap_present ; then - ynh_die "You must have a swap partition in order to install and use this application" + ynh_die --message="You must have a swap partition in order to install and use this application" elif ! is_swappiness_sufficient ; then - ynh_die "Your swappiness must be higher than 50; please see https://en.wikipedia.org/wiki/Swappiness" + ynh_die --message="Your swappiness must be higher than 50; please see https://en.wikipedia.org/wiki/Swappiness" elif ! is_memory_available 1000000 ; then - ynh_die "You must have a minimum of 1Gb available memory (RAM+swap) for the installation" + ynh_die --message="You must have a minimum of 1Gb available memory (RAM+swap) for the installation" fi } # Checks discourse upgrade memory requirements @@ -64,519 +70,9 @@ check_memory_requirements() { # terminates upgrade if requirements not met check_memory_requirements_upgrade() { if ! is_memory_available 400000 ; then - ynh_die "You must have a minimum of 400Mb available memory (RAM+swap) for the upgrade" + ynh_die --message="You must have a minimum of 400Mb available memory (RAM+swap) for the upgrade" fi } -#================================================= -# POSTGRES HELPERS -#================================================= - -# Create a master password and set up global settings -# Please always call this script in install and restore scripts -# -# usage: ynh_psql_test_if_first_run - -ynh_psql_test_if_first_run() { - if [ -f /etc/yunohost/psql ]; - then - echo "PostgreSQL is already installed, no need to create master password" - else - pgsql=$(ynh_string_random) - pg_hba="" - echo "$pgsql" >> /etc/yunohost/psql - - if [ -e /etc/postgresql/9.4/ ] - then - pg_hba=/etc/postgresql/9.4/main/pg_hba.conf - elif [ -e /etc/postgresql/9.6/ ] - then - pg_hba=/etc/postgresql/9.6/main/pg_hba.conf - else - ynh_die "postgresql shoud be 9.4 or 9.6" - fi - - systemctl start postgresql - sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$pgsql'" postgres - - # force all user to connect to local database using passwords - # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF - # Note: we can't use peer since YunoHost create users with nologin - # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user - sed -i '/local\s*all\s*all\s*peer/i \ - local all all password' "$pg_hba" - systemctl enable postgresql - systemctl reload postgresql - fi -} - -# Open a connection as a user -# -# example: ynh_psql_connect_as 'user' 'pass' <<< "UPDATE ...;" -# example: ynh_psql_connect_as 'user' 'pass' < /path/to/file.sql -# -# usage: ynh_psql_connect_as user pwd [db] -# | arg: user - the user name to connect as -# | arg: pwd - the user password -# | arg: db - the database to connect to -ynh_psql_connect_as() { - user="$1" - pwd="$2" - db="$3" - sudo --login --user=postgres PGUSER="$user" PGPASSWORD="$pwd" psql "$db" -} - -# # Execute a command as root user -# -# usage: ynh_psql_execute_as_root sql [db] -# | arg: sql - the SQL command to execute -# | arg: db - the database to connect to -ynh_psql_execute_as_root () { - sql="$1" - sudo --login --user=postgres psql <<< "$sql" -} - -# Execute a command from a file as root user -# -# usage: ynh_psql_execute_file_as_root file [db] -# | arg: file - the file containing SQL commands -# | arg: db - the database to connect to -ynh_psql_execute_file_as_root() { - file="$1" - db="$2" - sudo --login --user=postgres psql "$db" < "$file" -} - -# Create a database, an user and its password. Then store the password in the app's config -# -# After executing this helper, the password of the created database will be available in $db_pwd -# It will also be stored as "psqlpwd" into the app settings. -# -# usage: ynh_psql_setup_db user name [pwd] -# | arg: user - Owner of the database -# | arg: name - Name of the database -# | arg: pwd - Password of the database. If not given, a password will be generated -ynh_psql_setup_db () { - db_user="$1" - db_name="$2" - new_db_pwd=$(ynh_string_random) # Generate a random password - # If $3 is not given, use new_db_pwd instead for db_pwd. - db_pwd="${3:-$new_db_pwd}" - ynh_psql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database - ynh_app_setting_set "$app" psqlpwd "$db_pwd" # Store the password in the app's config -} - -# Create a database and grant privilegies to a user -# -# usage: ynh_psql_create_db db [user [pwd]] -# | arg: db - the database name to create -# | arg: user - the user to grant privilegies -# | arg: pwd - the user password -ynh_psql_create_db() { - db="$1" - user="$2" - pwd="$3" - ynh_psql_create_user "$user" "$pwd" - sudo --login --user=postgres createdb --owner="$user" "$db" -} - -# Drop a database -# -# usage: ynh_psql_drop_db db -# | arg: db - the database name to drop -# | arg: user - the user to drop -ynh_psql_remove_db() { - db="$1" - user="$2" - sudo --login --user=postgres dropdb "$db" - ynh_psql_drop_user "$user" -} - -# Dump a database -# -# example: ynh_psql_dump_db 'roundcube' > ./dump.sql -# -# usage: ynh_psql_dump_db db -# | arg: db - the database name to dump -# | ret: the psqldump output -ynh_psql_dump_db() { - db="$1" - sudo --login --user=postgres pg_dump "$db" -} - - -# Create a user -# -# usage: ynh_psql_create_user user pwd [host] -# | arg: user - the user name to create -ynh_psql_create_user() { - user="$1" - pwd="$2" - sudo --login --user=postgres psql -c"CREATE USER $user WITH PASSWORD '$pwd'" postgres -} - -# Drop a user -# -# usage: ynh_psql_drop_user user -# | arg: user - the user name to drop -ynh_psql_drop_user() { - user="$1" - sudo --login --user=postgres dropuser "$user" -} - -# ============= MODIFIED EXISTING YUNOHOST HELPERS ============= - -# Create a system user -# -# usage: ynh_system_user_create user_name [home_dir] [use_shell] -# | arg: user_name - Name of the system user that will be create -# | arg: home_dir - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home -# | arg: use_shell - Create a user using the default shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell -ynh_system_user_create () { - if ! ynh_system_user_exists "$1" # Check if the user exists on the system - then # If the user doesn't exist - if [ $# -ge 2 ]; then # If a home dir is mentioned - local user_home_dir="-d $2" - else - local user_home_dir="--no-create-home" - fi - if [ $# -ge 3 ]; then # If we want a shell for the user - local shell="" # Use default shell - else - local shell="--shell /usr/sbin/nologin" - fi - useradd $user_home_dir --system --user-group $1 $shell || ynh_die "Unable to create $1 system account" - fi -} - -# ============= FUTURE YUNOHOST HELPERS ============= - -# Create a dedicated fail2ban config (jail and filter conf files) -# -# usage: ynh_add_fail2ban_config log_file filter [max_retry [ports]] -# | arg: log_file - Log file to be checked by fail2ban -# | arg: failregex - Failregex to be looked for by fail2ban -# | arg: max_retry - Maximum number of retries allowed before banning IP address - default: 3 -# | arg: ports - Ports blocked for a banned IP address - default: http,https -ynh_add_fail2ban_config () { - # Process parameters - logpath=$1 - failregex=$2 - max_retry=${3:-3} - ports=${4:-http,https} - - test -n "$logpath" || ynh_die "ynh_add_fail2ban_config expects a logfile path as first argument and received nothing." - test -n "$failregex" || ynh_die "ynh_add_fail2ban_config expects a failure regex as second argument and received nothing." - - finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf" - finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf" - ynh_backup_if_checksum_is_different "$finalfail2banjailconf" 1 - ynh_backup_if_checksum_is_different "$finalfail2banfilterconf" 1 - - cat > $finalfail2banjailconf < $finalfail2banfilterconf <&2 - echo "WARNING${fail2ban_error#*WARNING}" >&2 - fi -} - -# Remove the dedicated fail2ban config (jail and filter conf files) -# -# usage: ynh_remove_fail2ban_config -ynh_remove_fail2ban_config () { - ynh_secure_remove "/etc/fail2ban/jail.d/$app.conf" - ynh_secure_remove "/etc/fail2ban/filter.d/$app.conf" - systemctl restart fail2ban -} - -# Delete a file checksum from the app settings -# -# $app should be defined when calling this helper -# -# usage: ynh_remove_file_checksum file -# | arg: file - The file for which the checksum will be deleted -ynh_delete_file_checksum () { - local checksum_setting_name=checksum_${1//[\/ ]/_} # Replace all '/' and ' ' by '_' - ynh_app_setting_delete $app $checksum_setting_name -} - -rbenv_install_dir="/opt/rbenv" -# 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 - - (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 - - # Download ruby-build (replace if already exists) - if [ -d $rbenv_install_dir/plugins/ruby-build ]; then - rm -Rf $rbenv_install_dir/plugins/ruby-build - fi - # Build an app.src for ruby-build - mkdir -p "../conf" - echo "SOURCE_URL=https://github.com/rbenv/ruby-build/archive/v20200115.tar.gz -SOURCE_SUM=e680eb8a606be358740fb0dfcf08309081fa27a54224e00fc7673ed2c842032d" > "../conf/ruby-build.src" - # Download and extract ruby-build - ynh_setup_source "$rbenv_install_dir/plugins/ruby-build" ruby-build - # 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 --with-jemalloc" 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 -} - -# ============= EXPERIMENTAL HELPERS ============= - -# Returns true if upstream version is up to date -# -# This helper should be used to avoid an upgrade of the upstream version -# when it's not needed (but yet allowing to upgrade other parts of the -# YunoHost application (e.g. nginx conf) -# -# usage: ynh_is_upstream_up_to_date (returns a boolean) -ynh_is_upstream_up_to_date () { - local version=$(ynh_read_manifest "/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" "version" || echo 1.0) - version="${version/~ynh*/}" - local last_version=$(ynh_read_manifest "../manifest.json" "version" || echo 1.0) - last_version="${last_version/~ynh*/}" - [ "$version" = "$last_version" ] -} - -# Read the value of a key in a ynh manifest file -# -# usage: ynh_read_manifest manifest key -# | arg: manifest - Path of the manifest to read -# | arg: key - Name of the key to find -ynh_read_manifest () { - manifest="$1" - key="$2" - python3 -c "import sys, json;print(json.load(open('$manifest', encoding='utf-8'))['$key'])" -} - -# Read the upstream version from the manifest -# The version number in the manifest is defined by ~ynh -# For example : 4.3-2~ynh3 -# This include the number before ~ynh -# In the last example it return 4.3-2 -# -# usage: ynh_app_upstream_version -ynh_app_upstream_version () { - manifest_path="../manifest.json" - if [ ! -e "$manifest_path" ]; then - manifest_path="../settings/manifest.json" # Into the restore script, the manifest is not at the same place - fi - version_key=$(ynh_read_manifest "$manifest_path" "version") - echo "${version_key/~ynh*/}" -} - -# Read package version from the manifest -# The version number in the manifest is defined by ~ynh -# For example : 4.3-2~ynh3 -# This include the number after ~ynh -# In the last example it return 3 -# -# usage: ynh_app_package_version -ynh_app_package_version () { - manifest_path="../manifest.json" - if [ ! -e "$manifest_path" ]; then - manifest_path="../settings/manifest.json" # Into the restore script, the manifest is not at the same place - fi - version_key=$(ynh_read_manifest "$manifest_path" "version") - echo "${version_key/*~ynh/}" -} - -# Start or restart a service and follow its booting -# -# usage: ynh_check_starting "Line to match" [Log file] [Timeout] [Service name] -# -# | arg: Line to match - The line to find in the log to attest the service have finished to boot. -# | arg: Log file - The log file to watch; specify "systemd" to read systemd journal for specified service -# /var/log/$app/$app.log will be used if no other log is defined. -# | arg: Timeout - The maximum time to wait before ending the watching. Defaut 300 seconds. -# | arg: Service name -ynh_check_starting () { - local line_to_match="$1" - local service_name="${4:-$app}" - local app_log="${2:-/var/log/$service_name/$service_name.log}" - local timeout=${3:-300} - - echo "Starting of $service_name" >&2 - systemctl stop $service_name - local templog="$(mktemp)" - # Following the starting of the app in its log - if [ "$app_log" == "systemd" ] ; then - # Read the systemd journal - journalctl -u $service_name -f --since=-45 > "$templog" & - else - # Read the specified log file - tail -F -n0 "$app_log" > "$templog" & - fi - # Get the PID of the last command - local pid_tail=$! - systemctl start $service_name - - local i=0 - for i in `seq 1 $timeout` - do - # Read the log until the sentence is found, which means the app finished starting. Or run until the timeout. - if grep --quiet "$line_to_match" "$templog" - then - echo "The service $service_name has correctly started." >&2 - break - fi - echo -n "." >&2 - sleep 1 - done - if [ $i -eq $timeout ] - then - echo "The service $service_name didn't fully start before the timeout." >&2 - fi - - echo "" - ynh_clean_check_starting -} -# Clean temporary process and file used by ynh_check_starting -# (usually used in ynh_clean_setup scripts) -# -# usage: ynh_clean_check_starting - -ynh_clean_check_starting () { - # Stop the execution of tail. - kill -s 15 $pid_tail 2>&1 - ynh_secure_remove "$templog" 2>&1 -} ynh_maintenance_mode_ON () { # Load value of $path_url and $domain from the config if their not set @@ -655,6 +151,173 @@ ynh_maintenance_mode_OFF () { systemctl reload nginx } +#================================================= +# EXPERIMENTAL HELPERS +#================================================= + +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= + +#================================================= +# RUBY HELPER +#================================================= + +rbenv_install_dir="/opt/rbenv" +# 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.2.tar.gz +SOURCE_SUM=80ad89ffe04c0b481503bd375f05c212bbc7d44ef5f5e649e0acdf25eba86736" > "../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/v20191004.tar.gz +SOURCE_SUM=6f053957acb0af6d621ebf2b9dacc9c265844b2dc6842a021eb10f0a70094fe8" > "../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: -v, --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 () { + # Declare an array to define the options of this helper. + declare -Ar args_array=( [v]=ruby_version= ) + # Use rbenv, https://github.com/rbenv/rbenv to manage the ruby versions + local ruby_version + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + + # 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 + elif dpkg --compare-versions "$(/opt/rbenv/bin/rbenv --version | cut -d" " -f2)" lt "1.1.2" + 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 +} + +# Returns true if upstream version is up to date +# +# This helper should be used to avoid an upgrade of the upstream version +# when it's not needed (but yet allowing to upgrade other parts of the +# YunoHost application (e.g. nginx conf) +# +# usage: ynh_is_upstream_up_to_date (returns a boolean) +ynh_is_upstream_up_to_date () { + local version=$(ynh_read_manifest "/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" "version" || echo 1.0) + version="${version/~ynh*/}" + local last_version=$(ynh_read_manifest "../manifest.json" "version" || echo 1.0) + last_version="${last_version/~ynh*/}" + [ "$version" = "$last_version" ] +} + #================================================= # REDIS HELPERS #================================================= @@ -682,7 +345,7 @@ ynh_redis_get_free_db() { db=-1 done - test "$db" -eq -1 && ynh_die "No available Redis databases..." + test "$db" -eq -1 && ynh_die --message="No available Redis databases..." echo "$db" } @@ -696,226 +359,3 @@ ynh_redis_remove_db() { local db=$1 redis-cli -n "$db" flushall } - -#================================================= -# FIXED HELPERS FROM UNSTABLE -#================================================= - -# Internal helper design to allow helpers to use getopts to manage their arguments -# -# [internal] -# -# example: function my_helper() -# { -# declare -Ar args_array=( [a]=arg1= [b]=arg2= [c]=arg3 ) -# local arg1 -# local arg2 -# local arg3 -# ynh_handle_getopts_args "$@" -# -# [...] -# } -# my_helper --arg1 "val1" -b val2 -c -# -# usage: ynh_handle_getopts_args "$@" -# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function -# -# This helper need an array, named "args_array" with all the arguments used by the helper -# that want to use ynh_handle_getopts_args -# Be carreful, this array has to be an associative array, as the following example: -# declare -Ar args_array=( [a]=arg1 [b]=arg2= [c]=arg3 ) -# Let's explain this array: -# a, b and c are short options, -a, -b and -c -# arg1, arg2 and arg3 are the long options associated to the previous short ones. --arg1, --arg2 and --arg3 -# For each option, a short and long version has to be defined. -# Let's see something more significant -# declare -Ar args_array=( [u]=user [f]=finalpath= [d]=database ) -# -# NB: Because we're using 'declare' without -g, the array will be declared as a local variable. -# -# Please keep in mind that the long option will be used as a variable to store the values for this option. -# For the previous example, that means that $finalpath will be fill with the value given as argument for this option. -# -# Also, in the previous example, finalpath has a '=' at the end. That means this option need a value. -# So, the helper has to be call with --finalpath /final/path, --finalpath=/final/path or -f /final/path, the variable $finalpath will get the value /final/path -# If there's many values for an option, -f /final /path, the value will be separated by a ';' $finalpath=/final;/path -# For an option without value, like --user in the example, the helper can be called only with --user or -u. $user will then get the value 1. -# -# To keep a retrocompatibility, a package can still call a helper, using getopts, with positional arguments. -# The "legacy mode" will manage the positional arguments and fill the variable in the same order than they are given in $args_array. -# e.g. for `my_helper "val1" val2`, arg1 will be filled with val1, and arg2 with val2. -ynh_handle_getopts_args () { - # Manage arguments only if there's some provided - set +x - if [ $# -ne 0 ] - then - # Store arguments in an array to keep each argument separated - local arguments=("$@") - - # For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u) - # And built parameters string for getopts - # ${!args_array[@]} is the list of all option_flags in the array (An option_flag is 'u' in [u]=user, user is a value) - local getopts_parameters="" - local option_flag="" - for option_flag in "${!args_array[@]}" - do - # Concatenate each option_flags of the array to build the string of arguments for getopts - # Will looks like 'abcd' for -a -b -c -d - # If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob) - # Check the last character of the value associate to the option_flag - if [ "${args_array[$option_flag]: -1}" = "=" ] - then - # For an option with additionnal values, add a ':' after the letter for getopts. - getopts_parameters="${getopts_parameters}${option_flag}:" - else - getopts_parameters="${getopts_parameters}${option_flag}" - fi - # Check each argument given to the function - local arg="" - # ${#arguments[@]} is the size of the array - for arg in `seq 0 $(( ${#arguments[@]} - 1 ))` - do - # And replace long option (value of the option_flag) by the short option, the option_flag itself - # (e.g. for [u]=user, --user will be -u) - # Replace long option with = - arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}/-${option_flag} }" - # And long option without = - arguments[arg]="${arguments[arg]//--${args_array[$option_flag]%=}/-${option_flag}}" - done - done - - # Read and parse all the arguments - # Use a function here, to use standart arguments $@ and be able to use shift. - parse_arg () { - # Read all arguments, until no arguments are left - while [ $# -ne 0 ] - do - # Initialize the index of getopts - OPTIND=1 - # Parse with getopts only if the argument begin by -, that means the argument is an option - # getopts will fill $parameter with the letter of the option it has read. - local parameter="" - getopts ":$getopts_parameters" parameter || true - - if [ "$parameter" = "?" ] - then - ynh_die --message="Invalid argument: -${OPTARG:-}" - elif [ "$parameter" = ":" ] - then - ynh_die --message="-$OPTARG parameter requires an argument." - else - local shift_value=1 - # Use the long option, corresponding to the short option read by getopts, as a variable - # (e.g. for [u]=user, 'user' will be used as a variable) - # Also, remove '=' at the end of the long option - # The variable name will be stored in 'option_var' - local option_var="${args_array[$parameter]%=}" - # If this option doesn't take values - # if there's a '=' at the end of the long option name, this option takes values - if [ "${args_array[$parameter]: -1}" != "=" ] - then - # 'eval ${option_var}' will use the content of 'option_var' - eval ${option_var}=1 - else - # Read all other arguments to find multiple value for this option. - # Load args in a array - local all_args=("$@") - - # If the first argument is longer than 2 characters, - # There's a value attached to the option, in the same array cell - if [ ${#all_args[0]} -gt 2 ]; then - # Remove the option and the space, so keep only the value itself. - all_args[0]="${all_args[0]#-${parameter} }" - # Reduce the value of shift, because the option has been removed manually - shift_value=$(( shift_value - 1 )) - fi - - # Declare the content of option_var as a variable. - eval ${option_var}="" - # Then read the array value per value - local i - for i in `seq 0 $(( ${#all_args[@]} - 1 ))` - do - # If this argument is an option, end here. - if [ "${all_args[$i]:0:1}" == "-" ] - then - # Ignore the first value of the array, which is the option itself - if [ "$i" -ne 0 ]; then - break - fi - else - # Else, add this value to this option - # Each value will be separated by ';' - if [ -n "${!option_var}" ] - then - # If there's already another value for this option, add a ; before adding the new value - eval ${option_var}+="\;" - fi - # Escape double quote to prevent any interpretation during the eval - all_args[$i]="${all_args[$i]//\"/\\\"}" - # Escape $ as well to prevent the string following it to be seen as a variable. - all_args[$i]="${all_args[$i]//$/\\\$}" - - # For the record. - # We're using eval here to get the content of the variable stored itself as simple text in $option_var... - # Other ways to get that content would be to use either ${!option_var} or declare -g ${option_var} - # But... ${!option_var} can't be used as left part of an assignation. - # declare -g ${option_var} will create a local variable (despite -g !) and will not be available for the helper itself. - # So... Stop fucking arguing each time that eval is evil... Go find an other working solution if you can find one! - - eval ${option_var}+=\"${all_args[$i]}\" - shift_value=$(( shift_value + 1 )) - fi - done - fi - fi - - # Shift the parameter and its argument(s) - shift $shift_value - done - } - - # LEGACY MODE - # Check if there's getopts arguments - if [ "${arguments[0]:0:1}" != "-" ] - then - # If not, enter in legacy mode and manage the arguments as positionnal ones.. - # Dot not echo, to prevent to go through a helper output. But print only in the log. - set -x; echo "! Helper used in legacy mode !" > /dev/null; set +x - local i - for i in `seq 0 $(( ${#arguments[@]} -1 ))` - do - # Try to use legacy_args as a list of option_flag of the array args_array - # Otherwise, fallback to getopts_parameters to get the option_flag. But an associative arrays isn't always sorted in the correct order... - # Remove all ':' in getopts_parameters - getopts_parameters=${legacy_args:-${getopts_parameters//:}} - # Get the option_flag from getopts_parameters, by using the option_flag according to the position of the argument. - option_flag=${getopts_parameters:$i:1} - if [ -z "$option_flag" ]; then - ynh_print_warn --message="Too many arguments ! \"${arguments[$i]}\" will be ignored." - continue - fi - # Use the long option, corresponding to the option_flag, as a variable - # (e.g. for [u]=user, 'user' will be used as a variable) - # Also, remove '=' at the end of the long option - # The variable name will be stored in 'option_var' - local option_var="${args_array[$option_flag]%=}" - - # Escape double quote to prevent any interpretation during the eval - arguments[$i]="${arguments[$i]//\"/\\\"}" - # Escape $ as well to prevent the string following it to be seen as a variable. - arguments[$i]="${arguments[$i]//$/\\\$}" - - # Store each value given as argument in the corresponding variable - # The values will be stored in the same order than $args_array - eval ${option_var}+=\"${arguments[$i]}\" - done - unset legacy_args - else - # END LEGACY MODE - # Call parse_arg and pass the modified list of args as an array of arguments. - parse_arg "${arguments[@]}" - fi - fi - set -x -} diff --git a/scripts/backup b/scripts/backup index d0fe227..18653c8 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,63 +1,78 @@ #!/bin/bash - +#================================================= +# GENERIC START #================================================= # IMPORT GENERIC HELPERS #================================================= -if [ ! -e _common.sh ]; then - # Fetch helpers file if not in current directory - cp ../settings/scripts/_common.sh ./_common.sh - chmod a+rx _common.sh -fi -source _common.sh +#Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers #================================================= # MANAGE SCRIPT FAILURE #================================================= +ynh_clean_setup () { + # Clean remainings not handled by remove script + ynh_clean_check_starting +} # Exit if an error occurs during the execution of the script ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= +ynh_print_info --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -final_path=$(ynh_app_setting_get "$app" final_path) -db_name=$(ynh_app_setting_get $app db_name) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +unicorn_workers=$(ynh_app_setting_get --app=$app --key=unicorn_workers) #================================================= -# STANDARD BACKUP STEPS +# DECLARE DATA AND CONF FILES TO BACKUP #================================================= -# BACKUP APP MAIN DIR -#================================================= - -ynh_backup "$final_path" +ynh_print_info --message="Declaring files to be backed up..." #================================================= -# BACKUP NGINX CONFIGURATION +# BACKUP THE APP MAIN DIR #================================================= -ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" +ynh_backup --src_path="$final_path" +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP #================================================= # BACKUP LOGROTATE #================================================= -ynh_backup "/etc/logrotate.d/$app" +ynh_backup --src_path="/etc/logrotate.d/$app" #================================================= # BACKUP SYSTEMD #================================================= -ynh_backup "/etc/systemd/system/$app.service" +ynh_backup --src_path="/etc/systemd/system/$app.service" #================================================= # BACKUP THE POSTGRESQL DATABASE #================================================= +ynh_print_info --message="Backing up the PostgreSQL database..." -ynh_psql_dump_db "$db_name" > ${YNH_CWD}/db.sql +ynh_psql_dump_db --database="$db_name" > db.sql + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/change_url b/scripts/change_url index 50255cf..b163620 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -24,19 +24,33 @@ app=$YNH_APP_INSTANCE_NAME #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." -db_name=$(ynh_app_setting_get "$app" db_name) -db_pwd=$(ynh_app_setting_get $app db_pwd) -final_path=$(ynh_app_setting_get "$app" final_path) +# Needed for helper "ynh_add_nginx_config" +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +# Add settings here as needed by your application +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) +unicorn_workers=$(ynh_app_setting_get --app=$app --key=unicorn_workers) #================================================= -# CHECK PATHS SYNTAX +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= +ynh_script_progression --message="Backing up the app before changing its url (may take a while)..." -test -n "$old_path" || old_path="/" -test -n "$new_path" || new_path="/" -new_path=$(ynh_normalize_url_path $new_path) -old_path=$(ynh_normalize_url_path $old_path) +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. + ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" + + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors #================================================= # CHECK WHICH PARTS SHOULD BE CHANGED @@ -57,82 +71,94 @@ fi #================================================= # STANDARD MODIFICATIONS #================================================= -# MODIFY URL IN NGINX CONF FILE +# STOP SYSTEMD SERVICE #================================================= +ynh_script_progression --message="Stopping a systemd service..." + +ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" + +#================================================= +# MODIFY URL IN NGINX CONF +#================================================= +ynh_script_progression --message="Updating nginx web server configuration..." nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf # Change the path in the nginx config file if [ $change_path -eq 1 ] then + # Make a backup of the original nginx config file if modified + ynh_backup_if_checksum_is_different --file="$nginx_conf_path" + # Set global variables for nginx helper domain="$old_domain" path_url="$new_path" + # Create a dedicated nginx config ynh_add_nginx_config # Reference: https://meta.discourse.org/t/subfolder-support-with-docker/30507?u=falco&source_topic_id=54191 if [ "$path_url" != "/" ] ; then - ynh_replace_string '$proxy_add_x_forwarded_for' '$http_your_original_ip_header' "/etc/nginx/conf.d/$domain.d/$app.conf" + ynh_replace_string --match_string='$proxy_add_x_forwarded_for' --replace_string='$http_your_original_ip_header' --target_file="/etc/nginx/conf.d/$domain.d/$app.conf" fi - ynh_store_file_checksum "/etc/nginx/conf.d/$domain.d/$app.conf" + ynh_store_file_checksum --file="/etc/nginx/conf.d/$domain.d/$app.conf" fi # Change the domain for nginx if [ $change_domain -eq 1 ] then # Delete file checksum for the old conf file location - ynh_delete_file_checksum "$nginx_conf_path" + ynh_delete_file_checksum --file="$nginx_conf_path" mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf # Store file checksum for the new config file location - ynh_store_file_checksum "/etc/nginx/conf.d/$new_domain.d/$app.conf" + ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" fi #================================================= # SPECIFIC MODIFICATIONS #================================================= -# Stop Discourse service -systemctl stop $app - discourse_config_file="$final_path/config/discourse.conf" # Configure hostname -ynh_replace_string "hostname = .*" "hostname = \"$new_domain\"" "$discourse_config_file" -ynh_replace_string "relative_url_root = .*" "relative_url_root = ${path_url%/}" "$discourse_config_file" -ynh_replace_string "smtp_domain = .*" "smtp_domain = $new_domain" "$discourse_config_file" +ynh_replace_string --match_string="hostname = .*" --replace_string="hostname = \"$new_domain\"" --target_file="$discourse_config_file" +ynh_replace_string --match_string="relative_url_root = .*" --replace_string="relative_url_root = ${new_path%/}" --target_file="$discourse_config_file" +ynh_replace_string --match_string="smtp_domain = .*" --replace_string="smtp_domain = $new_domain" --target_file="$discourse_config_file" # Calculate and store the config file checksum -ynh_store_file_checksum "$discourse_config_file" +ynh_store_file_checksum --file="$discourse_config_file" # Change URL setting -echo "UPDATE site_settings SET value = replace(value, '${old_path%/}/images/', '${new_path%/}/images/'); -UPDATE site_settings SET value = '${new_path}') WHERE name='long_polling_base_url';" - -ynh_psql_connect_as $db_name $db_pwd $db_name <<< "UPDATE site_settings SET value = replace(value, '${old_path%/}/images/', '${new_path%/}/images/'); +ynh_psql_connect_as --user=$db_user --password=$db_pwd --database=$db_name <<< "UPDATE site_settings SET value = replace(value, '${old_path%/}/images/', '${new_path%/}/images/'); UPDATE site_settings SET value = '${new_path}' WHERE name='long_polling_base_url';" -# Get the number of Unicorn workers used -unicorn_workers=$(cat /etc/systemd/system/$app.service |grep UNICORN_WORKERS | sed "s/.*UNICORN_WORKERS=//") -if [ -z "$unicorn_workers" ] ; then - # By default, 3 workers are used - unicorn_workers=3 -fi -# Wait for discourse to be fully started -ynh_check_starting "INFO -- : worker=$((unicorn_workers-1)) ready" "$final_path/log/unicorn.stderr.log" "240" "$app" - -# # Remap URLs in forum posts +# Remap URLs in forum posts exec_login_as $app RAILS_ENV=production bundle exec script/discourse remap ${old_path%/}/uploads ${new_path%/}/uploads <<< "YES # " rake_exec="exec_login_as $app RAILS_ENV=production bin/rake" # Regenerate assets -$rake_exec assets:precompile +ynh_exec_warn_less $rake_exec assets:precompile # Regenerate all forum posts -$rake_exec posts:rebake +ynh_exec_warn_less $rake_exec posts:rebake #================================================= -# GENERIC FINALIZATION +# GENERIC FINALISATION +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="$final_path/log/unicorn.stderr.log" --line_match="INFO -- : worker=$((unicorn_workers-1)) ready" + #================================================= # RELOAD NGINX #================================================= +ynh_script_progression --message="Reloading nginx web server..." -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Change of URL completed for $app" diff --git a/scripts/install b/scripts/install index b6c9d84..cabdc87 100644 --- a/scripts/install +++ b/scripts/install @@ -1,14 +1,13 @@ #!/bin/bash -shopt -s extglob # sets extended pattern matching options in the bash shell #================================================= -# GENERIC STARTING +# GENERIC START #================================================= # IMPORT GENERIC HELPERS #================================================= -source /usr/share/yunohost/helpers source _common.sh +source /usr/share/yunohost/helpers #================================================= # MANAGE SCRIPT FAILURE @@ -18,34 +17,30 @@ ynh_clean_setup () { # Clean remainings not handled by remove script ynh_clean_check_starting } -ynh_abort_if_errors # Stop script if an error is detected +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors #================================================= # RETRIEVE ARGUMENTS FROM THE MANIFEST #================================================= -# Retrieve app id -app=$YNH_APP_INSTANCE_NAME - -# Retrieve arguments domain=$YNH_APP_ARG_DOMAIN path_url=$YNH_APP_ARG_PATH admin=$YNH_APP_ARG_ADMIN is_public=$YNH_APP_ARG_IS_PUBLIC +app=$YNH_APP_INSTANCE_NAME + #================================================= # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= - -path_url=$(ynh_normalize_url_path $path_url) # Check and normalize path +ynh_script_progression --message="Validating installation parameters..." final_path=/var/www/$app -test ! -e "$final_path" || ynh_die "This path already contains a folder" +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" -# Check web path availability -ynh_webpath_available $domain $path_url # Register (book) web path -ynh_webpath_register $app $domain $path_url +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url # Check memory requirements check_memory_requirements @@ -53,43 +48,43 @@ check_memory_requirements #================================================= # STORE SETTINGS FROM MANIFEST #================================================= +ynh_script_progression --message="Storing installation settings..." -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 +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url +ynh_app_setting_set --app=$app --key=admin --value=$admin +ynh_app_setting_set --app=$app --key=is_public --value=$is_public #================================================= # STANDARD MODIFICATIONS #================================================= # INSTALL DEPENDENCIES #================================================= +ynh_script_progression --message="Installing dependencies..." -ynh_install_app_dependencies "$pkg_dependencies" +ynh_install_app_dependencies $pkg_dependencies #================================================= -# CREATE DEDICATED USER +# CREATE A POSTGRESQL DATABASE #================================================= +ynh_script_progression --message="Creating a PostgreSQL database..." -# Create a system user allowing login -ynh_system_user_create $app $final_path 1 - -#================================================= -# CREATE A POSTGRES DATABASE -#================================================= - -db_name=$(ynh_sanitize_dbid $app) +db_name=$(ynh_sanitize_dbid --db_name=$app) +db_user=$db_name db_pwd=$(ynh_string_random) -ynh_app_setting_set $app db_name $db_name -ynh_app_setting_set $app db_pwd $db_pwd +ynh_app_setting_set --app=$app --key=db_name --value=$db_name +ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd ynh_psql_test_if_first_run -ynh_psql_create_db $db_name $db_name $db_pwd +ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd # Set extensions -ynh_psql_execute_as_root "\connect $db_name -CREATE EXTENSION IF NOT EXISTS hstore; CREATE EXTENSION IF NOT EXISTS pg_trgm;" +ynh_psql_execute_as_root --sql="CREATE EXTENSION IF NOT EXISTS hstore;" --database=$db_name +ynh_psql_execute_as_root --sql="CREATE EXTENSION IF NOT EXISTS pg_trgm;" --database=$db_name #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= +ynh_script_progression --message="Setting up source files..." + # Specific actions on ARM architecture if [ -n "$(uname -m | grep arm)" ] ; then # Unapply commit cf9b4a789b855b5199e98a13424e409854a8e848 that breaks ARM @@ -99,79 +94,91 @@ if [ -n "$(uname -m | grep arm)" ] ; then cp ../sources/patches_arm/* ../sources/patches fi +ynh_app_setting_set --app=$app --key=final_path --value=$final_path # Download, check integrity, uncompress and patch the source from app.src -# Use the patch from https://meta.discourse.org/t/uglifier-error-during-assets-precompile/96970/4 to fix the Uglifier error -ynh_setup_source "$final_path" +ynh_setup_source --dest_dir="$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_setup_source --dest_dir="$final_path/plugins/discourse-ldap-auth" --source_id=ldap-auth #================================================= # INSTALL RUBY #================================================= +ynh_script_progression --message="Installing Ruby..." -ynh_install_ruby $RUBY_VERSION +ynh_install_ruby --ruby_version=$RUBY_VERSION #================================================= # NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Configuring nginx web server..." # Create a dedicated nginx config ynh_add_nginx_config # Reference: https://meta.discourse.org/t/subfolder-support-with-docker/30507?u=falco&source_topic_id=54191 if [ "$path_url" != "/" ] ; then - ynh_replace_string '$proxy_add_x_forwarded_for' '$http_your_original_ip_header' "/etc/nginx/conf.d/$domain.d/$app.conf" + ynh_replace_string --match_string='$proxy_add_x_forwarded_for' --replace_string='$http_your_original_ip_header' --target_file="/etc/nginx/conf.d/$domain.d/$app.conf" fi -ynh_store_file_checksum "/etc/nginx/conf.d/$domain.d/$app.conf" +ynh_store_file_checksum --file="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." + +# Create a system user +ynh_system_user_create --username=$app --home_dir=$final_path --use_shell #================================================= # SPECIFIC SETUP -#================================================= - #================================================= # CONFIGURE DISCOURSE #================================================= +ynh_script_progression --message="Configuring Discourse..." # Configure database discourse_config_file="$final_path/config/discourse.conf" cp $final_path/config/discourse_defaults.conf $discourse_config_file -ynh_replace_string "db_name = discourse" "db_name = $db_name" "$discourse_config_file" -ynh_replace_string "db_username = discourse" "db_username = $db_name" "$discourse_config_file" -ynh_replace_string "db_password =" "db_password = $db_pwd" "$discourse_config_file" +ynh_replace_string --match_string="db_name = discourse" --replace_string="db_name = $db_name" --target_file="$discourse_config_file" +ynh_replace_string --match_string="db_username = discourse" --replace_string="db_username = $db_name" --target_file="$discourse_config_file" +ynh_replace_string --match_string="db_password =" --replace_string="db_password = $db_pwd" --target_file="$discourse_config_file" # Configure hostname -ynh_replace_string "hostname = \"www.example.com\"" "hostname = \"$domain\"" "$discourse_config_file" -ynh_replace_string "relative_url_root =" "relative_url_root = ${path_url%/}" "$discourse_config_file" +ynh_replace_string --match_string="hostname = \"www.example.com\"" --replace_string="hostname = \"$domain\"" --target_file="$discourse_config_file" +ynh_replace_string --match_string="relative_url_root =" --replace_string="relative_url_root = ${path_url%/}" --target_file="$discourse_config_file" + # Serve static assets (i.e. images, js, etc.) -ynh_replace_string "serve_static_assets = false" "serve_static_assets = true" "$discourse_config_file" +ynh_replace_string --match_string="serve_static_assets = false" --replace_string="serve_static_assets = true" --target_file="$discourse_config_file" + # Don't show miniprofiler -ynh_replace_string "load_mini_profiler = true" "load_mini_profiler = false" "$discourse_config_file" +ynh_replace_string --match_string="load_mini_profiler = true" --replace_string="load_mini_profiler = false" --target_file="$discourse_config_file" # Configure e-mail server admin_mail=$(ynh_user_get_info "$admin" mail) -ynh_replace_string "developer_emails =" "developer_emails = $admin_mail" "$discourse_config_file" -ynh_replace_string "smtp_address =" "smtp_address = localhost" "$discourse_config_file" -ynh_replace_string "smtp_domain =" "smtp_domain = $domain" "$discourse_config_file" -ynh_replace_string "smtp_enable_start_tls = true" "smtp_enable_start_tls = false" "$discourse_config_file" +ynh_replace_string --match_string="developer_emails =" --replace_string="developer_emails = $admin_mail" --target_file="$discourse_config_file" +ynh_replace_string --match_string="smtp_address =" --replace_string="smtp_address = localhost" --target_file="$discourse_config_file" +ynh_replace_string --match_string="smtp_domain =" --replace_string="smtp_domain = $domain" --target_file="$discourse_config_file" +ynh_replace_string --match_string="smtp_enable_start_tls = true" --replace_string="smtp_enable_start_tls = false" --target_file="$discourse_config_file" # Configure redis redis_db=$(ynh_redis_get_free_db) -ynh_app_setting_set "$app" redis_db "$redis_db" -ynh_replace_string "redis_db = 0" "redis_db = $redis_db" "$discourse_config_file" +ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db" +ynh_replace_string --match_string="redis_db = 0" --replace_string="redis_db = $redis_db" --target_file="$discourse_config_file" # Don't notify on new versions (handled by the YunoHost package) -ynh_replace_string "new_version_emails = true" "new_version_emails = false" "$discourse_config_file" +ynh_replace_string --match_string="new_version_emails = true" --replace_string="new_version_emails = false" --target_file="$discourse_config_file" # Calculate and store the config file checksum -ynh_store_file_checksum "$discourse_config_file" +ynh_store_file_checksum --file="$discourse_config_file" # Configure LDAP plugin ldap_config_file="$final_path/plugins/discourse-ldap-auth/config/settings.yml" -ynh_replace_string "adfs.example.com" "localhost" "$ldap_config_file" -ynh_replace_string "dc=example,dc=com" "ou=users,dc=yunohost,dc=org" "$ldap_config_file" -ynh_replace_string "sAMAccountName" "uid" "$ldap_config_file" -ynh_store_file_checksum "$ldap_config_file" +ynh_replace_string --match_string="adfs.example.com" --replace_string="localhost" --target_file="$ldap_config_file" +ynh_replace_string --match_string="dc=example,dc=com" --replace_string="ou=users,dc=yunohost,dc=org" --target_file="$ldap_config_file" +ynh_replace_string --match_string="sAMAccountName" --replace_string="uid" --target_file="$ldap_config_file" +ynh_store_file_checksum --file="$ldap_config_file" # Disable svgo worker echo "svgo: false" > $final_path/.image_optim.yml @@ -179,34 +186,38 @@ echo "svgo: false" > $final_path/.image_optim.yml #================================================= # SETUP UNICORN, A RUBY SERVER #================================================= +ynh_script_progression --message="Setting up Unicorn..." + unicorn_config_file="$final_path/config/unicorn.conf.rb" # Use socket connection -ynh_replace_string 'listen (ENV\["UNICORN_PORT"\] || 3000).to_i' '# listen (ENV["UNICORN_PORT"] || 3000).to_i' "$unicorn_config_file" -ynh_replace_string '# listen "#{discourse_path}/tmp/sockets/unicorn.sock"' 'listen "#{discourse_path}/tmp/sockets/unicorn.sock"' "$unicorn_config_file" +ynh_replace_string --match_string='listen (ENV\["UNICORN_PORT"\] || 3000).to_i' --replace_string='# listen (ENV["UNICORN_PORT"] || 3000).to_i' "--target_file=$unicorn_config_file" +ynh_replace_string --match_string='# listen "#{discourse_path}/tmp/sockets/unicorn.sock"' --replace_string='listen "#{discourse_path}/tmp/sockets/unicorn.sock"' --target_file="$unicorn_config_file" # Calculate and store the config file checksum -ynh_store_file_checksum "$unicorn_config_file" +ynh_store_file_checksum --file="$unicorn_config_file" # Set a secret value cp ../conf/secrets.yml "$final_path/config/secrets.yml" -ynh_replace_string "__SECRET__" "$(ynh_string_random)" "$final_path/config/secrets.yml" +ynh_replace_string --match_string="__SECRET__" --replace_string="$(ynh_string_random)" --target_file="$final_path/config/secrets.yml" # Calculate and store the config file checksum -ynh_store_file_checksum "$final_path/config/secrets.yml" +ynh_store_file_checksum --file="$final_path/config/secrets.yml" # Set permissions to app files chown -R $app: $final_path +pushd "$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" +popd -(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") # Specific actions on ARM architecture if [ -n "$(uname -m | grep arm)" ] ; then # Define the platform specifically to retrieve binaries # for libv8 because it currently doesn't compile on ARM devices exec_login_as $app bundle config specific_platform arm-linux fi + # Install dependencies exec_login_as $app bundle config set path 'vendor/bundle' exec_login_as $app bundle config set with 'development' @@ -223,16 +234,19 @@ fi #================================================= # PREPARE THE DATABASE #================================================= +ynh_script_progression --message="Preparing the database..." rake_exec="exec_login_as $app RAILS_ENV=production bin/rake" -$rake_exec db:migrate -$rake_exec assets:precompile +ynh_exec_warn_less $rake_exec db:migrate +ynh_exec_warn_less $rake_exec assets:precompile #================================================= # POPULATE THE DATABASE #================================================= +ynh_script_progression --message="Populating the database..." + #Set default data (especially to have correct image URLs for subfolder install) -ynh_psql_connect_as $db_name $db_pwd $db_name <<< "INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUES ('title', 1, 'YunoHost Forum', 'NOW()', 'NOW()'); +ynh_psql_connect_as --user=$db_user --password=$db_pwd --database=$db_name <<< "INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUES ('title', 1, 'YunoHost Forum', 'NOW()', 'NOW()'); INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUES ('site_description', 1, 'YunoHost Forum', 'NOW()', 'NOW()'); INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUES ('contact_email', 14, '$admin_mail', 'NOW()', 'NOW()'); INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUES ('contact_url', 1, '$domain$path_url', 'NOW()', 'NOW()'); @@ -247,17 +261,9 @@ INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUE " #================================================= -# FIX INITIAL POSTS LINKS FOR SUBFOLDER INSTALL -#================================================= - -if [ "$path_url" != "/" ] ; then - exec_login_as $app RAILS_ENV=production bundle exec script/discourse remap /images/welcome/ $path_url/images/welcome/ <<< "YES - " -fi - -#================================================= -# CREATE ADMIN USER +# CREATE DISCOURSE ADMIN USER #================================================= +ynh_script_progression --message="Creating Discourse admin user..." # Create a random password admin_pwd=$(ynh_string_random) @@ -270,6 +276,7 @@ y #================================================= # CONFIGURE PLUGINS #================================================= +ynh_script_progression --message="Configuring plugins..." # Patch ldap-auth plugin dependency (omniauth-ldap) to fix it when using domain subfolder # (Can only do that now because we are patching dependencies which have just been downloaded) @@ -280,8 +287,9 @@ patch -p1 < $YNH_CWD/../conf/ldap-auth-fix-subfolder.patch) #================================================= # SETUP SYSTEMD #================================================= +ynh_script_progression --message="Configuring a systemd service..." -ynh_replace_string "__RBENVROOT__" "$RBENV_ROOT" "../conf/systemd.service" +ynh_replace_string --match_string="__RBENVROOT__" --replace_string="$RBENV_ROOT" --target_file="../conf/systemd.service" # We assume for the moment that ARM devices are only dual core, so # we restrict the number of workers to 2 (the default is 3) @@ -292,9 +300,10 @@ else additional_env="" unicorn_workers=3 fi +ynh_app_setting_set --app=$app --key=unicorn_workers --value=$unicorn_workers -ynh_replace_string "__ADDITIONAL_ENV__" "$additional_env" "../conf/systemd.service" -ynh_replace_string "__LIBJEMALLOC__" "$(ldconfig -p | grep libjemalloc | awk 'END {print $NF}')" "../conf/systemd.service" +ynh_replace_string --match_string="__ADDITIONAL_ENV__" --replace_string="$additional_env" --target_file="../conf/systemd.service" +ynh_replace_string --match_string="__LIBJEMALLOC__" --replace_string="$(ldconfig -p | grep libjemalloc | awk 'END {print $NF}')" --target_file="../conf/systemd.service" ynh_add_systemd_config #================================================= @@ -302,6 +311,7 @@ ynh_add_systemd_config #================================================= # SECURE FILES AND DIRECTORIES #================================================= +ynh_script_progression --message="Securing files and directories..." # Add a pids and socket directory for the systemd script. mkdir -p "$final_path/tmp/pids" @@ -317,43 +327,56 @@ cd public/forum && ln -s ../uploads && ln -s ../backups # Set permissions to app files chown -R $app: $final_path + # Restrict rights to log directory (needed by logrotate) chmod g-w $final_path/log #================================================= # SETUP LOGROTATE #================================================= +ynh_script_progression --message="Configuring log rotation..." # Use logrotate to manage application logfile(s) -ynh_use_logrotate "$final_path/log/unicorn.stderr.log" -ynh_use_logrotate "$final_path/log/unicorn.stdout.log" -ynh_use_logrotate "$final_path/log/production.log" +ynh_use_logrotate --logfile="$final_path/log/unicorn.stderr.log" +ynh_use_logrotate --logfile="$final_path/log/unicorn.stdout.log" +ynh_use_logrotate --logfile="$final_path/log/production.log" #================================================= -# ADVERTISE SERVICE IN ADMIN PANEL +# INTEGRATE SERVICE IN YUNOHOST #================================================= +ynh_script_progression --message="Integrating service in YunoHost..." yunohost service add $app --log "$final_path/log/unicorn.stderr.log" "$final_path/log/unicorn.stdout.log" "$final_path/log/production.log" +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="$final_path/log/unicorn.stderr.log" --line_match="INFO -- : worker=$((unicorn_workers-1)) ready" + #================================================= # SETUP SSOWAT #================================================= +ynh_script_progression --message="Configuring SSOwat..." -# If app is public, add url to SSOWat conf as skipped_uris -if [ $is_public -eq 1 ]; then - # unprotected_uris allows SSO credentials to be passed anyway. - ynh_app_setting_set "$app" skipped_uris "/" +# Make app public if necessary +if [ $is_public -eq 1 ] +then + # unprotected_uris allows SSO credentials to be passed anyway. + ynh_app_setting_set --app=$app --key=skipped_uris --value="/" fi #================================================= # RELOAD NGINX #================================================= +ynh_script_progression --message="Reloading nginx web server..." -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload #================================================= -# START UNICORN +# END OF SCRIPT #================================================= -# Wait for discourse to be fully started -ynh_check_starting "INFO -- : worker=$((unicorn_workers-1)) ready" "$final_path/log/unicorn.stderr.log" "240" "$app" +ynh_script_progression --message="Installation of $app completed" diff --git a/scripts/remove b/scripts/remove index 732c003..73a031d 100644 --- a/scripts/remove +++ b/scripts/remove @@ -6,73 +6,85 @@ # IMPORT GENERIC HELPERS #================================================= -source /usr/share/yunohost/helpers source _common.sh +source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -db_name=$(ynh_app_setting_get $app db_name) -final_path=$(ynh_app_setting_get $app final_path) -redis_db=$(ynh_app_setting_get $app redis_db) +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +redis_db=$(ynh_app_setting_get --app=$app --key=redis_db) #================================================= # STANDARD REMOVE #================================================= -# STOP AND REMOVE SERVICE +# REMOVE SERVICE INTEGRATION IN YUNOHOST #================================================= -ynh_remove_systemd_config - -#================================================= -# REMOVE SERVICE FROM ADMIN PANEL -#================================================= - -if yunohost service status | grep -q $app +# Remove the service from the list of services known by Yunohost (added from `yunohost service add`) +if ynh_exec_warn_less yunohost service status $app >/dev/null then - echo "Remove $app services" + ynh_script_progression --message="Removing $app service..." yunohost service remove $app fi +#================================================= +# STOP AND REMOVE SERVICE +#================================================= +ynh_script_progression --message="Stopping and removing the systemd service..." + +# Remove the dedicated systemd config +ynh_remove_systemd_config + +#================================================= +# REMOVE THE POSTGRESQL DATABASE +#================================================= +ynh_script_progression --message="Removing the PostgreSQL database..." + +# Remove a database if it exists, along with the associated user +ynh_psql_remove_db --db_user="$db_user" --db_name="$db_name" + +#================================================= +# REMOVE RUBY +#================================================= +ynh_script_progression --message="Removing Ruby..." + +ynh_remove_ruby + +#================================================= +# REMOVE THE REDIS DATABASE +#================================================= +ynh_script_progression --message="Removing the redis database..." + +ynh_redis_remove_db "$redis_db" + #================================================= # REMOVE DEPENDENCIES #================================================= +ynh_script_progression --message="Removing dependencies..." # Remove metapackage and its dependencies ynh_remove_app_dependencies -#================================================= -# REMOVE RUBY -#================================================= - -ynh_remove_ruby - -#================================================= -# REMOVE THE POSTGRES DATABASE -#================================================= - -ynh_psql_remove_db $db_name $db_name - -#================================================= -# REMOVE THE REDIS DATABASE -#================================================= - -ynh_redis_remove_db "$redis_db" - #================================================= # REMOVE APP MAIN DIR #================================================= +ynh_script_progression --message="Removing app main directory..." # Remove the app directory securely -ynh_secure_remove "$final_path" +ynh_secure_remove --file="$final_path" #================================================= # REMOVE NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Removing nginx web server configuration..." # Remove the dedicated nginx config ynh_remove_nginx_config @@ -80,6 +92,7 @@ ynh_remove_nginx_config #================================================= # REMOVE LOGROTATE CONFIGURATION #================================================= +ynh_script_progression --message="Removing logrotate configuration..." # Remove the app-specific logrotate config ynh_remove_logrotate @@ -89,6 +102,13 @@ ynh_remove_logrotate #================================================= # REMOVE DEDICATED USER #================================================= +ynh_script_progression --message="Removing the dedicated system user..." # Delete a system user -ynh_system_user_delete $app +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" diff --git a/scripts/restore b/scripts/restore index 0f6428c..8317aed 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,73 +1,105 @@ #!/bin/bash +#================================================= +# GENERIC START #================================================= # IMPORT GENERIC HELPERS #================================================= -if [ ! -e _common.sh ]; then - # Fetch helpers file if not in current directory - cp ../settings/scripts/_common.sh ./_common.sh - chmod a+rx _common.sh -fi +#Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -source _common.sh #================================================= # MANAGE SCRIPT FAILURE #================================================= +ynh_clean_setup () { + # Clean remainings not handled by remove script + ynh_clean_check_starting +} # Exit if an error occurs during the execution of the script ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -path_url=$(ynh_app_setting_get $app path) -is_public=$(ynh_app_setting_get $app is_public) -final_path=$(ynh_app_setting_get $app final_path) -db_name=$(ynh_app_setting_get $app db_name) -db_pwd=$(ynh_app_setting_get $app db_pwd) +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= +ynh_script_progression --message="Validating restoration parameters..." -ynh_webpath_available $domain $path_url \ - || ynh_die "Path not available: ${domain}${path_url}" +ynh_webpath_available --domain=$domain --path_url=$path_url \ + || ynh_die --message="Path not available: ${domain}${path_url}" test ! -d $final_path \ - || ynh_die "There is already a directory: $final_path " + || ynh_die --message="There is already a directory: $final_path " - # Check memory requirements - check_memory_requirements +# Check memory requirements +check_memory_requirements #================================================= # STANDARD RESTORATION STEPS #================================================= -# RESTORE ALL FILES +# RESTORE THE NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Restoring the nginx configuration..." -# Restore all config and data -ynh_restore +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." + +ynh_restore_file --origin_path="$final_path" + +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." + +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir=$final_path --use_shell + +#================================================= +# RESTORE USER RIGHTS +#================================================= +ynh_script_progression --message="Restoring user rights..." + +# Restore permissions on app files +chown -R $app: $final_path + +#================================================= +# SPECIFIC RESTORATION #================================================= # REINSTALL DEPENDENCIES #================================================= +ynh_script_progression --message="Reinstalling dependencies..." -ynh_install_app_dependencies "$pkg_dependencies" +# Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies #================================================= # INSTALL RUBY #================================================= +ynh_script_progression --message="Install Ruby..." -ynh_install_ruby $RUBY_VERSION +ynh_install_ruby --ruby_version=$RUBY_VERSION #================================================= # REINSTALL BUNDLE GEM #================================================= +ynh_script_progression --message="Reinstall Bundle Gem..." (cd "$final_path" gem install bundler) @@ -75,54 +107,64 @@ gem install bundler) #================================================= # RESTORE THE POSTGRESQL DATABASE #================================================= +ynh_script_progression --message="Restoring the PostgreSQL database..." +db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) ynh_psql_test_if_first_run -ynh_psql_setup_db "$db_name" "$db_name" "$db_pwd" +ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd # Set extensions -ynh_psql_execute_as_root "\connect $db_name -CREATE EXTENSION IF NOT EXISTS hstore; CREATE EXTENSION IF NOT EXISTS pg_trgm;" +ynh_psql_execute_as_root --sql="CREATE EXTENSION IF NOT EXISTS hstore;" --database=$db_name +ynh_psql_execute_as_root --sql="CREATE EXTENSION IF NOT EXISTS pg_trgm;" --database=$db_name # Restore dump -ynh_psql_execute_file_as_root ./db.sql "$db_name" +ynh_psql_execute_file_as_root --file="./db.sql" --database="$db_name" #================================================= # RESTORE SYSTEMD #================================================= +ynh_script_progression --message="Restoring the systemd configuration..." +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" systemctl daemon-reload systemctl enable $app.service #================================================= -# RECREATE OF THE DEDICATED USER -#================================================= - -# Create a system user allowing login (if not existing) -ynh_system_user_create $app $final_path 1 - -#================================================= -# RESTORE USER RIGHTS -#================================================= - -chown -R $app: $final_path - -#================================================= -# ADVERTISE SERVICE IN ADMIN PANEL +# INTEGRATE SERVICE IN YUNOHOST #================================================= +ynh_script_progression --message="Integrating service in YunoHost..." yunohost service add $app --log "$final_path/log/unicorn.stderr.log" "$final_path/log/unicorn.stdout.log" "$final_path/log/production.log" #================================================= -# GENERIC FINALIZATION -#================================================= -# RELOAD NGINX AND DISCOURSE +# START SYSTEMD SERVICE #================================================= +ynh_script_progression --message="Starting a systemd service..." if [ -n "$(uname -m | grep arm)" ] ; then unicorn_workers=2 else unicorn_workers=3 fi -# Wait for discourse to be fully started -ynh_check_starting "INFO -- : worker=$((unicorn_workers-1)) ready" "$final_path/log/unicorn.stderr.log" "240" "$app" +ynh_app_setting_set --app=$app --key=unicorn_workers --value=$unicorn_workers +ynh_systemd_action --service_name=$app --action="start" --log_path="$final_path/log/unicorn.stderr.log" --line_match="INFO -- : worker=$((unicorn_workers-1)) ready" +#================================================= +# RESTORE THE LOGROTATE CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring logrotate configuration..." -systemctl reload nginx +ynh_restore_file --origin_path="/etc/logrotate.d/$app" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading nginx web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" diff --git a/scripts/upgrade b/scripts/upgrade index 36832c7..2c3f006 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -6,94 +6,102 @@ # IMPORT GENERIC HELPERS #================================================= -if [ ! -e _common.sh ]; then - # Fetch helpers file if not in current directory - cp ../settings/scripts/_common.sh ./_common.sh - chmod a+rx _common.sh -fi -source /usr/share/yunohost/helpers source _common.sh - -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors +source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -path_url=$(ynh_app_setting_get $app path) -final_path=$(ynh_app_setting_get $app final_path) -is_public=$(ynh_app_setting_get $app is_public) -admin=$(ynh_app_setting_get $app admin) -db_name=$(ynh_app_setting_get $app db_name) -db_pwd=$(ynh_app_setting_get $app db_pwd) -redis_db=$(ynh_app_setting_get $app redis_db) +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +admin=$(ynh_app_setting_get --app=$app --key=admin) +is_public=$(ynh_app_setting_get --app=$app --key=is_public) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) +redis_db=$(ynh_app_setting_get --app=$app --key=redis_db) +unicorn_workers=$(ynh_app_setting_get --app=$app --key=unicorn_workers) # Check memory requirements check_memory_requirements_upgrade #================================================= -# BACKUP BEFORE UPGRADE +# CHECK VERSION #================================================= +ynh_script_progression --message="Checking version..." -# Stop services -systemctl stop $app +upgrade_type=$(ynh_check_app_version_changed) + +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." + +# If unicorn_workers doesn't exist, create it +if [ -z "$unicorn_workers" ] +then + # We assume for the moment that ARM devices are only dual core, so + # we restrict the number of workers to 2 (the default is 3) + if [ -n "$(uname -m | grep arm)" ] + then + unicorn_workers=2 + else + unicorn_workers=3 + fi + ynh_app_setting_set --app=$app --key=unicorn_workers --value=$unicorn_workers +fi + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." # Backup the current version of the app -if [[ $(ynh_app_setting_get $app disable_backup_before_upgrade) != '1' ]] -then - ynh_backup_before_upgrade - ynh_clean_setup () { - ynh_restore_upgradebackup - } -fi +ynh_backup_before_upgrade +ynh_clean_setup () { + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors #================================================= # ENABLE MAINTENANCE MODE #================================================= +ynh_script_progression --message="Enabling maintenance mode..." ynh_maintenance_mode_ON #================================================= -# INSTALL DEPENDENCIES +# STANDARD UPGRADE STEPS #================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." -ynh_install_app_dependencies "$pkg_dependencies" +ynh_systemd_action --service_name=$app --action="stop" --log_path="$final_path/log/unicorn.stderr.log" #================================================= -# NGINX CONFIGURATION +# DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= -# Create a dedicated nginx config -ynh_add_nginx_config +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Upgrading source files..." -# Reference: https://meta.discourse.org/t/subfolder-support-with-docker/30507?u=falco&source_topic_id=54191 -if [ "$path_url" != "/" ] ; then - ynh_replace_string '$proxy_add_x_forwarded_for' '$http_your_original_ip_header' "/etc/nginx/conf.d/$domain.d/$app.conf" -fi -ynh_store_file_checksum "/etc/nginx/conf.d/$domain.d/$app.conf" - -if ! ynh_is_upstream_up_to_date ; then - - #================================================= - # DOWNLOAD, CHECK AND UNPACK SOURCE - #================================================= # Specific actions on ARM architecture if [ -n "$(uname -m | grep arm)" ] ; then - # Unapply commit cf9b4a789b855b5199e98a13424e409854a8e848 that breaks ARM - # compatibility by pointing to a recent libv8 version - # This is due to this libv8 issue (https://github.com/cowboyd/libv8/issues/261) - # that prevents it from being compiled on ARM hence no binary gem is available yet - cp ../sources/patches_arm/* ../sources/patches + # Unapply commit cf9b4a789b855b5199e98a13424e409854a8e848 that breaks ARM + # compatibility by pointing to a recent libv8 version + # This is due to this libv8 issue (https://github.com/cowboyd/libv8/issues/261) + # that prevents it from being compiled on ARM hence no binary gem is available yet + cp ../sources/patches_arm/* ../sources/patches fi - ynh_app_setting_set $app final_path $final_path + # Backup files to keep tmpdir=$(mktemp -d) cp -Rp $final_path/plugins $final_path/config/discourse.conf $tmpdir @@ -107,9 +115,9 @@ if ! ynh_is_upstream_up_to_date ; then cp -Rp $final_path/log $tmpdir fi # Remove destination directory - ynh_secure_remove $final_path + ynh_secure_remove --file=$final_path # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source "$final_path" + ynh_setup_source --dest_dir="$final_path" # Restore previous files if [ -d $tmpdir/uploads ] ; then cp -Rp $tmpdir/uploads $final_path/public @@ -122,114 +130,162 @@ if ! ynh_is_upstream_up_to_date ; then fi ( cd $tmpdir/plugins/ - for discourse_plugin_dir in */ - do + for discourse_plugin_dir in */ + do # Only copy plugins not included in Discourse archive - if [ ! -d "$final_path/plugins/$discourse_plugin_dir" ] - then - cp -a "$discourse_plugin_dir" "$final_path/plugins/$discourse_plugin_dir" - fi - done - ) + if [ ! -d "$final_path/plugins/$discourse_plugin_dir" ] + then + cp -a "$discourse_plugin_dir" "$final_path/plugins/$discourse_plugin_dir" + fi + done + ) cp -Rp $tmpdir/log $final_path cp -p $tmpdir/discourse.conf $final_path/config # Install LDAP plugin - ynh_secure_remove "$final_path/plugins/discourse-ldap-auth" + ynh_secure_remove --file="$final_path/plugins/discourse-ldap-auth" mkdir -p "$final_path/plugins/discourse-ldap-auth" - ynh_setup_source "$final_path/plugins/discourse-ldap-auth" ldap-auth + ynh_setup_source --dest_dir="$final_path/plugins/discourse-ldap-auth" --source_id=ldap-auth +fi - #================================================= - # INSTALL RUBY - #================================================= +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading nginx web server configuration..." - ynh_install_ruby $RUBY_VERSION +# Create a dedicated nginx config +ynh_add_nginx_config - #================================================= - # SPECIFIC SETUP - #================================================= +# Reference: https://meta.discourse.org/t/subfolder-support-with-docker/30507?u=falco&source_topic_id=54191 +if [ "$path_url" != "/" ] ; then + ynh_replace_string --match_string='$proxy_add_x_forwarded_for' --replace_string='$http_your_original_ip_header' --target_file="/etc/nginx/conf.d/$domain.d/$app.conf" +fi +ynh_store_file_checksum --file="/etc/nginx/conf.d/$domain.d/$app.conf" - #================================================= - # CONFIGURE DISCOURSE - #================================================= +#================================================= +# UPGRADE DEPENDENCIES +#================================================= +ynh_script_progression --message="Upgrading dependencies..." - # Make a backup of the original config file if modified - ynh_backup_if_checksum_is_different "$final_path/config/discourse.conf" - # Configure database +ynh_install_app_dependencies "$pkg_dependencies" + +#================================================= +# INSTALL RUBY +#================================================= +ynh_script_progression --message="Installing Ruby..." + +ynh_install_ruby --ruby_version=$RUBY_VERSION + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir=$final_path --use_shell + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# CONFIGURE DISCOURSE +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Configuring Discourse..." + + # Configure Discourse discourse_config_file="$final_path/config/discourse.conf" + # Make a backup of the original config file if modified + ynh_backup_if_checksum_is_different --file="$discourse_config_file" + cp $final_path/config/discourse_defaults.conf $discourse_config_file - ynh_replace_string "db_name = discourse" "db_name = $db_name" "$discourse_config_file" - ynh_replace_string "db_username = discourse" "db_username = $db_name" "$discourse_config_file" - ynh_replace_string "db_password =" "db_password = $db_pwd" "$discourse_config_file" + ynh_replace_string --match_string="db_name = discourse" --replace_string="db_name = $db_name" --target_file="$discourse_config_file" + ynh_replace_string --match_string="db_username = discourse" --replace_string="db_username = $db_name" --target_file="$discourse_config_file" + ynh_replace_string --match_string="db_password =" --replace_string="db_password = $db_pwd" --target_file="$discourse_config_file" # Configure hostname - ynh_replace_string "hostname = \"www.example.com\"" "hostname = \"$domain\"" "$discourse_config_file" - ynh_replace_string "relative_url_root =" "relative_url_root = ${path_url%/}" "$discourse_config_file" + ynh_replace_string --match_string="hostname = \"www.example.com\"" --replace_string="hostname = \"$domain\"" --target_file="$discourse_config_file" + ynh_replace_string --match_string="relative_url_root =" --replace_string="relative_url_root = ${path_url%/}" --target_file="$discourse_config_file" # Serve static assets (i.e. images, js, etc.) - ynh_replace_string "serve_static_assets = false" "serve_static_assets = true" "$discourse_config_file" + ynh_replace_string --match_string="serve_static_assets = false" --replace_string="serve_static_assets = true" --target_file="$discourse_config_file" # Don't show miniprofiler - ynh_replace_string "load_mini_profiler = true" "load_mini_profiler = false" "$discourse_config_file" - - + ynh_replace_string --match_string="load_mini_profiler = true" --replace_string="load_mini_profiler = false" --target_file="$discourse_config_file" # Configure e-mail server admin_mail=$(ynh_user_get_info "$admin" mail) - ynh_replace_string "developer_emails =" "developer_emails = $admin_mail" "$discourse_config_file" - ynh_replace_string "smtp_address =" "smtp_address = localhost" "$discourse_config_file" - ynh_replace_string "smtp_domain =" "smtp_domain = $domain" "$discourse_config_file" - ynh_replace_string "smtp_enable_start_tls = true" "smtp_enable_start_tls = false" "$discourse_config_file" - + ynh_replace_string --match_string="developer_emails =" --replace_string="developer_emails = $admin_mail" --target_file="$discourse_config_file" + ynh_replace_string --match_string="smtp_address =" --replace_string="smtp_address = localhost" --target_file="$discourse_config_file" + ynh_replace_string --match_string="smtp_domain =" --replace_string="smtp_domain = $domain" --target_file="$discourse_config_file" + ynh_replace_string --match_string="smtp_enable_start_tls = true" --replace_string="smtp_enable_start_tls = false" --target_file="$discourse_config_file" # Configure redis - ynh_replace_string "redis_db = 0" "redis_db = $redis_db" "$discourse_config_file" - + ynh_replace_string --match_string="redis_db = 0" --replace_string="redis_db = $redis_db" --target_file="$discourse_config_file" # Don't notify on new versions (handled by the YunoHost package) - ynh_replace_string "new_version_emails = true" "new_version_emails = false" "$discourse_config_file" + ynh_replace_string --match_string="new_version_emails = true" --replace_string="new_version_emails = false" --target_file="$discourse_config_file" # Calculate and store the config file checksum - ynh_store_file_checksum "$discourse_config_file" - - # Make a backup of the original config file if modified - ynh_backup_if_checksum_is_different "$final_path/plugins/discourse-ldap-auth/config/settings.yml" + ynh_store_file_checksum --file="$discourse_config_file" # Configure LDAP plugin ldap_config_file="$final_path/plugins/discourse-ldap-auth/config/settings.yml" - ynh_replace_string "adfs.example.com" "localhost" "$ldap_config_file" - ynh_replace_string "dc=example,dc=com" "ou=users,dc=yunohost,dc=org" "$ldap_config_file" - ynh_replace_string "sAMAccountName" "uid" "$ldap_config_file" - ynh_store_file_checksum "$ldap_config_file" + # Make a backup of the original config file if modified + ynh_backup_if_checksum_is_different "$ldap_config_file" + + ynh_replace_string --match_string="adfs.example.com" --replace_string="localhost" --target_file="$ldap_config_file" + ynh_replace_string --match_string="dc=example,dc=com" --replace_string="ou=users,dc=yunohost,dc=org" --target_file="$ldap_config_file" + ynh_replace_string --match_string="sAMAccountName" --replace_string="uid" --target_file="$ldap_config_file" + + # Calculate and store the config file checksum + ynh_store_file_checksum --file="$ldap_config_file" # Disable svgo worker echo "svgo: false" > $final_path/.image_optim.yml +fi + +#================================================= +# SETUP UNICORN, A RUBY SERVER +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Setting up Unicorn..." - #================================================= - # SETUP UNICORN, A RUBY SERVER - #================================================= unicorn_config_file="$final_path/config/unicorn.conf.rb" + # Make a backup of the original config file if modified + ynh_backup_if_checksum_is_different "$unicorn_config_file" + # Use socket connection - ynh_replace_string 'listen (ENV\["UNICORN_PORT"\] || 3000).to_i' '# listen (ENV["UNICORN_PORT"] || 3000).to_i' "$unicorn_config_file" - ynh_replace_string '# listen "#{discourse_path}/tmp/sockets/unicorn.sock"' 'listen "#{discourse_path}/tmp/sockets/unicorn.sock"' "$unicorn_config_file" + ynh_replace_string --match_string='listen (ENV\["UNICORN_PORT"\] || 3000).to_i' --replace_string='# listen (ENV["UNICORN_PORT"] || 3000).to_i' --target_file="$unicorn_config_file" + ynh_replace_string --match_string='# listen "#{discourse_path}/tmp/sockets/unicorn.sock"' --replace_string='listen "#{discourse_path}/tmp/sockets/unicorn.sock"' --target_file="$unicorn_config_file" + # Calculate and store the config file checksum - ynh_store_file_checksum "$unicorn_config_file" + ynh_store_file_checksum --file="$unicorn_config_file" + + secret_config_file="$final_path/config/secrets.yml" + # Make a backup of the original config file if modified + ynh_backup_if_checksum_is_different "$secret_config_file" # Set a secret value cp ../conf/secrets.yml "$final_path/config/secrets.yml" - ynh_replace_string "__SECRET__" "$(ynh_string_random)" "$final_path/config/secrets.yml" + ynh_replace_string --match_string="__SECRET__" --replace_string="$(ynh_string_random)" --target_file="$secret_config_file" + # Calculate and store the config file checksum - ynh_store_file_checksum "$final_path/config/secrets.yml" + ynh_store_file_checksum --file="$secret_config_file" # Set permissions to app files chown -R $app: $final_path - - (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") + ( + 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" + ) # Specific actions on ARM architecture if [ -n "$(uname -m | grep arm)" ] ; then - # Define the platform specifically to retrieve binaries - # for libv8 because it currently doesn't compile on ARM devices - exec_login_as $app bundle config specific_platform arm-linux + # Define the platform specifically to retrieve binaries + # for libv8 because it currently doesn't compile on ARM devices + exec_login_as $app bundle config specific_platform arm-linux fi # Install dependencies exec_login_as $app bundle config set path 'vendor/bundle' @@ -239,82 +295,125 @@ if ! ynh_is_upstream_up_to_date ; then # On ARM architecture, replace bundled libpsl by system native libpsl # because the provided binary isn't compatible if [ -n "$(uname -m | grep arm)" ] ; then - (cd $final_path/vendor/bundle/ruby/*/gems/mini_suffix-*/vendor - rm libpsl.so - ln -s $(ldconfig -p | grep libpsl | awk 'END {print $NF}') libpsl.so) + ( + cd $final_path/vendor/bundle/ruby/*/gems/mini_suffix-*/vendor + rm libpsl.so + ln -s $(ldconfig -p | grep libpsl | awk 'END {print $NF}') libpsl.so + ) fi +fi - #================================================= - # PREPARE THE DATABASE - #================================================= +#================================================= +# PREPARE THE DATABASE +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Preparing the database..." rake_exec="exec_login_as $app RAILS_ENV=production bin/rake" - $rake_exec db:migrate - $rake_exec assets:precompile + ynh_exec_warn_less $rake_exec db:migrate + ynh_exec_warn_less $rake_exec assets:precompile +fi - #================================================= - # CONFIGURE PLUGINS - #================================================= +#================================================= +# CONFIGURE PLUGINS +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Configuring plugins..." # Patch ldap-auth plugin dependency (omniauth-ldap) to fix it when using domain subfolder # (Can only do that now because we are patching dependencies which have just been downloaded) # Patch applied: https://github.com/omniauth/omniauth-ldap/pull/16 - (cd $final_path/plugins/discourse-ldap-auth/gems/${RUBY_VERSION}/gems/omniauth-ldap*/ - patch -p1 < $YNH_CWD/../conf/ldap-auth-fix-subfolder.patch) - - #================================================= - # GENERIC FINALIZATION - #================================================= - # SECURE FILES AND DIRECTORIES - #================================================= - - # Add a pids and socket directory for the systemd script. - mkdir -p "$final_path/tmp/pids" - mkdir "$final_path/tmp/sockets" - - # Create specific folders and links for subfolder compatibilityn - # (see: https://meta.discourse.org/t/subfolder-support-with-docker/30507) ( + cd $final_path/plugins/discourse-ldap-auth/gems/${RUBY_VERSION}/gems/omniauth-ldap*/ + patch -p1 < $YNH_CWD/../conf/ldap-auth-fix-subfolder.patch + ) +fi + +#================================================= +# SETUP SYSTEMD +#================================================= +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Configuring a systemd service..." + + ynh_replace_string --match_string="__RBENVROOT__" --replace_string="$RBENV_ROOT" --target_file="../conf/systemd.service" + + additional_env="UNICORN_WORKERS=$unicorn_workers" + ynh_replace_string --match_string="__ADDITIONAL_ENV__" --replace_string="$additional_env" --target_file="../conf/systemd.service" + ynh_replace_string --match_string="__LIBJEMALLOC__" --replace_string="$(ldconfig -p | grep libjemalloc | awk 'END {print $NF}')" --target_file="../conf/systemd.service" + ynh_add_systemd_config +fi + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= +ynh_script_progression --message="Securing files and directories..." + +# Add a pids and socket directory for the systemd script. +mkdir -p "$final_path/tmp/pids" +mkdir -p "$final_path/tmp/sockets" + +# Create specific folders and links for subfolder compatibilityn +# (see: https://meta.discourse.org/t/subfolder-support-with-docker/30507) +( cd $final_path mkdir -p "public/forum" - cd public/forum && ln -s ../uploads && ln -s ../backups - ) + cd public/forum + if [ ! -L ./uploads ]; then + ln -s ../uploads + fi + if [ ! -L ./backups ]; then + ln -s ../backups + fi +) + +# Set permissions to app files +chown -R $app: $final_path +# Restrict rights to log directory (needed by logrotate) +chmod g-w $final_path/log - # Set permissions to app files - chown -R $app: $final_path - # Restrict rights to log directory (needed by logrotate) - chmod g-w $final_path/log -fi #================================================= # SETUP SSOWAT #================================================= +ynh_script_progression --message="Upgrading SSOwat configuration..." # If app is public, add url to SSOWat conf as skipped_uris -if [ $is_public -eq 1 ]; then - # unprotected_uris allows SSO credentials to be passed anyway. - ynh_app_setting_set "$app" skipped_uris "/" +if [ $is_public -eq 1 ] +then + # unprotected_uris allows SSO credentials to be passed anyway. + ynh_app_setting_set "$app" skipped_uris "/" fi #================================================= -# RELOAD NGINX +# START SYSTEMD SERVICE #================================================= +ynh_script_progression --message="Starting a systemd service..." -systemctl reload nginx - -#================================================= -# START UNICORN -#================================================= - -if [ -n "$(uname -m | grep arm)" ] ; then - unicorn_workers=2 -else - unicorn_workers=3 -fi # Wait for discourse to be fully started -ynh_check_starting "INFO -- : worker=$((unicorn_workers-1)) ready" "$final_path/log/unicorn.stderr.log" "240" "$app" +ynh_systemd_action --service_name=$app --action="start" --log_path="$final_path/log/unicorn.stderr.log" --line_match="INFO -- : worker=$((unicorn_workers-1)) ready" #================================================= # DISABLE MAINTENANCE MODE #================================================= +ynh_script_progression --message="Disabling maintenance mode..." ynh_maintenance_mode_OFF + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading nginx web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Upgrade of $app completed"