diff --git a/scripts/_common.sh b/scripts/_common.sh index 2cf1a6b..51e4547 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -6,13 +6,233 @@ pkg_dependencies="python3-dev python3-babel python3-venv uwsgi uwsgi-plugin-python3 git build-essential libxslt-dev zlib1g-dev libffi-dev libssl-dev" #================================================= -# PERSONAL HELPERS +# UWSGI HELPERS #================================================= -#================================================= -# EXPERIMENTAL HELPERS -#================================================= +# Check if system wide templates are available and correcly configured +# +# usage: ynh_check_global_uwsgi_config +ynh_check_global_uwsgi_config () { + uwsgi --version || ynh_die --message "You need to add uwsgi (and appropriate plugin) as a dependency" + + cat > /etc/systemd/system/uwsgi-app@.service < uwsgi-app@app` +ynh_add_uwsgi_service () { + ynh_check_global_uwsgi_config + + local others_var=${1:-} + local finaluwsgiini="/etc/uwsgi/apps-available/$app.ini" + + # www-data group is needed since it is this nginx who will start the service + usermod --append --groups www-data "$app" || ynh_die --message "It wasn't possible to add user $app to group www-data" + + ynh_backup_if_checksum_is_different "$finaluwsgiini" + cp ../conf/uwsgi.ini "$finaluwsgiini" + + # To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable. + # Substitute in a nginx config file only if the variable is not empty + if test -n "${final_path:-}"; then + ynh_replace_string --match_string "__FINALPATH__" --replace_string "$final_path" --target_file "$finaluwsgiini" + fi + if test -n "${path_url:-}"; then + ynh_replace_string --match_string "__PATH__" --replace_string "$path_url" --target_file "$finaluwsgiini" + fi + if test -n "${app:-}"; then + ynh_replace_string --match_string "__APP__" --replace_string "$app" --target_file "$finaluwsgiini" + fi + + # Replace all other variable given as arguments + for var_to_replace in $others_var + do + # ${var_to_replace^^} make the content of the variable on upper-cases + # ${!var_to_replace} get the content of the variable named $var_to_replace + ynh_replace_string --match_string "__${var_to_replace^^}__" --replace_string "${!var_to_replace}" --target_file "$finaluwsgiini" + done + + ynh_store_file_checksum --file "$finaluwsgiini" + + chown $app:root "$finaluwsgiini" + + # make sure the folder for logs exists and set authorizations + mkdir -p /var/log/uwsgi/$app + chown $app:root /var/log/uwsgi/$app + chmod -R u=rwX,g=rX,o= /var/log/uwsgi/$app + + # Setup specific Systemd rules if necessary + test -e ../conf/uwsgi-app@override.service && \ + mkdir /etc/systemd/system/uwsgi-app@$app.service.d && \ + cp ../conf/uwsgi-app@override.service /etc/systemd/system/uwsgi-app@$app.service.d/override.conf + + systemctl daemon-reload + systemctl enable "uwsgi-app@$app.service" --quiet + + # Add as a service + yunohost service add "uwsgi-app@$app" --log "/var/log/uwsgi/$app/$app.log" +} + +# Remove the dedicated uwsgi ini file +# +# usage: ynh_remove_uwsgi_service +ynh_remove_uwsgi_service () { + local finaluwsgiini="/etc/uwsgi/apps-available/$app.ini" + if [ -e "$finaluwsgiini" ]; then + yunohost service remove "uwsgi-app@$app" + systemctl disable "uwsgi-app@$app.service" --quiet + + ynh_secure_remove --file="$finaluwsgiini" + ynh_secure_remove --file="/var/log/uwsgi/$app" + ynh_secure_remove --file="/etc/systemd/system/uwsgi-app@$app.service.d" + fi + if [ -e /etc/init.d/uwsgi ] + then + # Redémarre le service uwsgi si il n'est pas désinstallé. + ynh_systemd_action --service_name=uwsgi --action=start + else + if yunohost service status | grep -q uwsgi + then + ynh_print_info --message="Remove uwsgi service" + yunohost service remove uwsgi + fi + fi +} + #================================================= -# FUTURE OFFICIAL HELPERS -#================================================= + +# Remove a file or a directory securely +# +# usage: ynh_regex_secure_remove --file=path_to_remove [--regex=regex to append to $file] [--non_recursive] [--dry_run] +# | arg: -f, --file - File or directory to remove +# | arg: -r, --regex - Regex to append to $file to filter the files to remove +# | arg: -n, --non_recursive - Perform a non recursive rm and a non recursive search with the regex +# | arg: -d, --dry_run - Do not remove, only list the files to remove +# +# Requires YunoHost version 2.6.4 or higher. +ynh_regex_secure_remove () { + # Declare an array to define the options of this helper. + local legacy_args=frnd + declare -Ar args_array=( [f]=file= [r]=regex= [n]=non_recursive [d]=dry_run ) + local file + local regex + local dry_run + local non_recursive + # Manage arguments with getopts + ynh_handle_getopts_args "$@" + regex=${regex:-} + dry_run=${dry_run:-0} + non_recursive=${non_recursive:-0} + + local forbidden_path=" +/var/www \ +/home/yunohost.app" + + # Fail if no argument is provided to the helper. + if [ -z "$file" ] + then + ynh_print_warn --message="ynh_regex_secure_remove called with no argument --file, ignoring." + return 0 + fi + + if [ -n "$regex" ] + then + if [ -e "$file" ] + then + if [ $non_recursive -eq 1 ]; then + local recursive="-maxdepth 1" + else + local recursive="" + fi + # Use find to list the files in $file and grep to filter with the regex + files_to_remove="$(find -P "$file" $recursive -name ".." -prune -o -print | grep --extended-regexp "$regex")" + else + ynh_print_info --message="'$file' wasn't deleted because it doesn't exist." + return 0 + fi + else + files_to_remove="$file" + fi + + # Check each file before removing it + while read file_to_remove + do + if [ -n "$file_to_remove" ] + then + # Check all forbidden path before removing anything + # First match all paths or subpaths in $forbidden_path + if [[ "$forbidden_path" =~ "$file_to_remove" ]] || \ + # Match all first level paths from / (Like /var, /root, etc...) + [[ "$file_to_remove" =~ ^/[[:alnum:]]+$ ]] || \ + # Match if the path finishes by /. Because it seems there is an empty variable + [ "${file_to_remove:${#file_to_remove}-1}" = "/" ] + then + ynh_print_err --message="Not deleting '$file_to_remove' because this path is forbidden !!!" + + # If the file to remove exists + elif [ -e "$file_to_remove" ] + then + if [ $dry_run -eq 1 ] + then + ynh_print_warn --message="File to remove: $file_to_remove" + else + if [ $non_recursive -eq 1 ]; then + local recursive="" + else + local recursive="--recursive" + fi + + # Remove a file or a directory + rm --force $recursive "$file_to_remove" + fi + else + # Ignore non existent files with regex, as we likely remove the parent directory before its content is listed. + if [ -z "$regex" ] + then + ynh_print_info --message="'$file_to_remove' wasn't deleted because it doesn't exist." + fi + fi + fi + done <<< "$(echo "$files_to_remove")" +} diff --git a/scripts/install b/scripts/install index ad92cdb..1d5a2d9 100755 --- a/scripts/install +++ b/scripts/install @@ -149,14 +149,11 @@ ynh_script_progression --message="Adding a configuration file..." --weight=1 secret_key=$(ynh_string_random) ynh_add_config --template="../conf/settings.yml" --destination="$final_path/searx/settings.yml" -ynh_add_config --template="../conf/uwsgi.ini" --destination="/etc/uwsgi/apps-available/$app.ini" # FIXME: this should be handled by the core in the future # You may need to use chmod 600 instead of 400, # for example if the app is expected to be able to modify its own config chmod 400 "$final_path/searx/settings.yml" chown $app:$app "$final_path/searx/settings.yml" -chmod 400 "/etc/uwsgi/apps-available/$app.ini" -chown $app:$app "/etc/uwsgi/apps-available/$app.ini" ### For more complex cases where you want to replace stuff using regexes, ### you shoud rely on ynh_replace_string (which is basically a wrapper for sed) @@ -166,23 +163,11 @@ chown $app:$app "/etc/uwsgi/apps-available/$app.ini" ### ynh_store_file_checksum --file="$final_path/some_config_file" #================================================= -# SETUP SYSTEMD +# CONFIGURE UWSGI FOR SEARX #================================================= -ynh_script_progression --message="Configuring a systemd service..." --weight=1 +ynh_script_progression --message="Configuring uWSGI for Searx..." --weight=2 -### `ynh_systemd_config` is used to configure a systemd script for an app. -### It can be used for apps that use sysvinit (with adaptation) or systemd. -### Have a look at the app to be sure this app needs a systemd script. -### `ynh_systemd_config` will use the file conf/systemd.service -### If you're not using these lines: -### - You can remove those files in conf/. -### - Remove the section "BACKUP SYSTEMD" in the backup script -### - Remove also the section "STOP AND REMOVE SERVICE" in the remove script -### - As well as the section "RESTORE SYSTEMD" in the restore script -### - And the section "SETUP SYSTEMD" in the upgrade script - -# Create a dedicated systemd config -ynh_add_systemd_config --service "$app-uwsgi" --template uwsgi.service +ynh_add_uwsgi_service #================================================= # GENERIC FINALIZATION @@ -200,7 +185,7 @@ ynh_script_progression --message="Starting a systemd service..." --weight=1 ### - And the section "STOP SYSTEMD SERVICE" and "START SYSTEMD SERVICE" in the change_url script # Start a systemd service -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/uwsgi/$app/$app.log" +--service_name=uwsgi-app@$app.service --action=start --line_match="spawned uWSGI master process" --log_path="/var/log/uwsgi/$app/$app.log" #================================================= # SETUP SSOWAT