diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml
index ea8339e24..d12557b90 100644
--- a/data/actionsmap/yunohost.yml
+++ b/data/actionsmap/yunohost.yml
@@ -1840,6 +1840,32 @@ tools:
full: --force
action: store_true
+ ### tools_regen_conf()
+ regen-conf:
+ action_help: Regenerate the configuration file(s)
+ api: PUT /tools/regenconf
+ arguments:
+ names:
+ help: Categories to regenerate configuration of (all by default)
+ nargs: "*"
+ metavar: NAME
+ -d:
+ full: --with-diff
+ help: Show differences in case of configuration changes
+ action: store_true
+ -f:
+ full: --force
+ help: Override all manual modifications in configuration files
+ action: store_true
+ -n:
+ full: --dry-run
+ help: Show what would have been regenerated
+ action: store_true
+ -p:
+ full: --list-pending
+ help: List pending configuration files and exit
+ action: store_true
+
subcategories:
migrations:
@@ -2000,6 +2026,10 @@ log:
full: --limit
help: Maximum number of logs
type: int
+ -d:
+ full: --with-details
+ help: Show additional infos (e.g. operation success) but may significantly increase command time. Consider using --limit in combination with this.
+ action: store_true
### log_display()
display:
diff --git a/data/actionsmap/yunohost_completion.py b/data/actionsmap/yunohost_completion.py
new file mode 100644
index 000000000..a4c17c4d6
--- /dev/null
+++ b/data/actionsmap/yunohost_completion.py
@@ -0,0 +1,86 @@
+"""
+Simple automated generation of a bash_completion file
+for yunohost command from the actionsmap.
+
+Generates a bash completion file assuming the structure
+`yunohost domain action`
+adds `--help` at the end if one presses [tab] again.
+
+author: Christophe Vuillot
+"""
+import os
+import yaml
+
+THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml'
+BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost'
+
+with open(ACTIONSMAP_FILE, 'r') as stream:
+
+ # Getting the dictionary containning what actions are possible per domain
+ OPTION_TREE = yaml.load(stream)
+ DOMAINS = [str for str in OPTION_TREE.keys() if not str.startswith('_')]
+ DOMAINS_STR = '"{}"'.format(' '.join(DOMAINS))
+ ACTIONS_DICT = {}
+ for domain in DOMAINS:
+ ACTIONS = [str for str in OPTION_TREE[domain]['actions'].keys()
+ if not str.startswith('_')]
+ ACTIONS_STR = '"{}"'.format(' '.join(ACTIONS))
+ ACTIONS_DICT[domain] = ACTIONS_STR
+
+ with open(BASH_COMPLETION_FILE, 'w') as generated_file:
+
+ # header of the file
+ generated_file.write('#\n')
+ generated_file.write('# completion for yunohost\n')
+ generated_file.write('# automatically generated from the actionsmap\n')
+ generated_file.write('#\n\n')
+
+ # Start of the completion function
+ generated_file.write('_yunohost()\n')
+ generated_file.write('{\n')
+
+ # Defining local variable for previously and currently typed words
+ generated_file.write('\tlocal cur prev opts narg\n')
+ generated_file.write('\tCOMPREPLY=()\n\n')
+ generated_file.write('\t# the number of words already typed\n')
+ generated_file.write('\tnarg=${#COMP_WORDS[@]}\n\n')
+ generated_file.write('\t# the current word being typed\n')
+ generated_file.write('\tcur="${COMP_WORDS[COMP_CWORD]}"\n\n')
+ generated_file.write('\t# the last typed word\n')
+ generated_file.write('\tprev="${COMP_WORDS[COMP_CWORD-1]}"\n\n')
+
+ # If one is currently typing a domain then match with the domain list
+ generated_file.write('\t# If one is currently typing a domain,\n')
+ generated_file.write('\t# match with domains\n')
+ generated_file.write('\tif [[ $narg == 2 ]]; then\n')
+ generated_file.write('\t\topts={}\n'.format(DOMAINS_STR))
+ generated_file.write('\tfi\n\n')
+
+ # If one is currently typing an action then match with the action list
+ # of the previously typed domain
+ generated_file.write('\t# If one already typed a domain,\n')
+ generated_file.write('\t# match the actions of that domain\n')
+ generated_file.write('\tif [[ $narg == 3 ]]; then\n')
+ for domain in DOMAINS:
+ generated_file.write('\t\tif [[ $prev == "{}" ]]; then\n'.format(domain))
+ generated_file.write('\t\t\topts={}\n'.format(ACTIONS_DICT[domain]))
+ generated_file.write('\t\tfi\n')
+ generated_file.write('\tfi\n\n')
+
+ # If both domain and action have been typed or the domain
+ # was not recognized propose --help (only once)
+ generated_file.write('\t# If no options were found propose --help\n')
+ generated_file.write('\tif [ -z "$opts" ]; then\n')
+ generated_file.write('\t\tif [[ $prev != "--help" ]]; then\n')
+ generated_file.write('\t\t\topts=( --help )\n')
+ generated_file.write('\t\tfi\n')
+ generated_file.write('\tfi\n')
+
+ # generate the completion list from the possible options
+ generated_file.write('\tCOMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )\n')
+ generated_file.write('\treturn 0\n')
+ generated_file.write('}\n\n')
+
+ # Add the function to bash completion
+ generated_file.write('complete -F _yunohost yunohost')
diff --git a/data/bash-completion.d/yunohost b/data/bash-completion.d/yunohost
index 106f8fbdf..2572a391d 100644
--- a/data/bash-completion.d/yunohost
+++ b/data/bash-completion.d/yunohost
@@ -1,12 +1,3 @@
-#
-# Bash completion for yunohost
-#
-
-_python_argcomplete() {
- local IFS=''
- COMPREPLY=( $(IFS="$IFS" COMP_LINE="$COMP_LINE" COMP_POINT="$COMP_POINT" _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" _ARGCOMPLETE=1 "$1" 8>&1 9>&2 1>/dev/null 2>/dev/null) )
- if [[ $? != 0 ]]; then
- unset COMPREPLY
- fi
-}
-complete -o nospace -o default -F _python_argcomplete "yunohost"
+# This file is automatically generated
+# during Debian's package build by the script
+# data/actionsmap/yunohost_completion.py
diff --git a/data/helpers.d/package b/data/helpers.d/apt
similarity index 91%
rename from data/helpers.d/package
rename to data/helpers.d/apt
index 000b0ee74..9d5ad3ac2 100644
--- a/data/helpers.d/package
+++ b/data/helpers.d/apt
@@ -5,6 +5,8 @@
# [internal]
#
# usage: ynh_wait_dpkg_free
+#
+# Requires YunoHost version 3.3.1 or higher.
ynh_wait_dpkg_free() {
local try
# With seq 1 17, timeout will be almost 30 minutes
@@ -44,6 +46,8 @@ ynh_wait_dpkg_free() {
#
# usage: ynh_package_is_installed --package=name
# | arg: -p, --package - the package name to check
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_package_is_installed() {
# Declare an array to define the options of this helper.
local legacy_args=p
@@ -64,6 +68,8 @@ ynh_package_is_installed() {
# usage: ynh_package_version --package=name
# | arg: -p, --package - the package name to get version
# | ret: the version or an empty string
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_package_version() {
# Declare an array to define the options of this helper.
local legacy_args=p
@@ -84,6 +90,8 @@ ynh_package_version() {
# [internal]
#
# usage: ynh_apt update
+#
+# Requires YunoHost version 2.4.0.3 or higher.
ynh_apt() {
ynh_wait_dpkg_free
DEBIAN_FRONTEND=noninteractive apt-get -y $@
@@ -92,6 +100,8 @@ ynh_apt() {
# Update package index files
#
# usage: ynh_package_update
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_package_update() {
ynh_apt update
}
@@ -100,6 +110,8 @@ ynh_package_update() {
#
# usage: ynh_package_install name [name [...]]
# | arg: name - the package name to install
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_package_install() {
ynh_apt --no-remove -o Dpkg::Options::=--force-confdef \
-o Dpkg::Options::=--force-confold install $@
@@ -109,6 +121,8 @@ ynh_package_install() {
#
# usage: ynh_package_remove name [name [...]]
# | arg: name - the package name to remove
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_package_remove() {
ynh_apt remove $@
}
@@ -117,6 +131,8 @@ ynh_package_remove() {
#
# usage: ynh_package_autoremove name [name [...]]
# | arg: name - the package name to remove
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_package_autoremove() {
ynh_apt autoremove $@
}
@@ -125,6 +141,8 @@ ynh_package_autoremove() {
#
# usage: ynh_package_autopurge name [name [...]]
# | arg: name - the package name to autoremove and purge
+#
+# Requires YunoHost version 2.7.2 or higher.
ynh_package_autopurge() {
ynh_apt autoremove --purge $@
}
@@ -139,6 +157,8 @@ ynh_package_autopurge() {
#
# usage: ynh_package_install_from_equivs controlfile
# | arg: controlfile - path of the equivs control file
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_package_install_from_equivs () {
local controlfile=$1
@@ -146,7 +166,7 @@ ynh_package_install_from_equivs () {
local pkgname=$(grep '^Package: ' $controlfile | cut -d' ' -f 2) # Retrieve the name of the debian package
local pkgversion=$(grep '^Version: ' $controlfile | cut -d' ' -f 2) # And its version number
[[ -z "$pkgname" || -z "$pkgversion" ]] \
- && echo "Invalid control file" && exit 1 # Check if this 2 variables aren't empty.
+ && ynh_die --message="Invalid control file" # Check if this 2 variables aren't empty.
# Update packages cache
ynh_package_update
@@ -181,6 +201,8 @@ ynh_package_install_from_equivs () {
# You can give a choice between some package with this syntax : "dep1|dep2"
# Example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5"
# This mean in the dependence tree : dep1 & dep2 & (dep3 | dep4 | dep5)
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_install_app_dependencies () {
local dependencies=$@
local dependencies=${dependencies// /, }
@@ -217,6 +239,8 @@ EOF
# Dependencies will removed only if no other package need them.
#
# usage: ynh_remove_app_dependencies
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_remove_app_dependencies () {
local dep_app=${app//_/-} # Replace all '_' by '-'
ynh_package_autopurge ${dep_app}-ynh-deps # Remove the fake package and its dependencies if they not still used.
diff --git a/data/helpers.d/backend b/data/helpers.d/backend
deleted file mode 100644
index 1532601a8..000000000
--- a/data/helpers.d/backend
+++ /dev/null
@@ -1,437 +0,0 @@
-#!/bin/bash
-
-# Use logrotate to manage the logfile
-#
-# usage: ynh_use_logrotate [--logfile=/log/file] [--nonappend] [--specific_user=user/group]
-# | arg: -l, --logfile= - absolute path of logfile
-# | arg: -n, --nonappend - (Option) Replace the config file instead of appending this new config.
-# | arg: -u, --specific_user : run logrotate as the specified user and group. If not specified logrotate is runned as root.
-#
-# If no argument provided, a standard directory will be use. /var/log/${app}
-# You can provide a path with the directory only or with the logfile.
-# /parentdir/logdir
-# /parentdir/logdir/logfile.log
-#
-# It's possible to use this helper several times, each config will be added to the same logrotate config file.
-# Unless you use the option --non-append
-ynh_use_logrotate () {
- # Declare an array to define the options of this helper.
- local legacy_args=lnuya
- declare -Ar args_array=( [l]=logfile= [n]=nonappend [u]=specific_user= [y]=non [a]=append )
- # [y]=non [a]=append are only for legacy purpose, to not fail on the old option '--non-append'
- local logfile
- local nonappend
- local specific_user
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
- local logfile="${logfile:-}"
- local nonappend="${nonappend:-0}"
- local specific_user="${specific_user:-}"
-
- # LEGACY CODE - PRE GETOPTS
- if [ $# -gt 0 ] && [ "$1" == "--non-append" ]; then
- nonappend=1
- # Destroy this argument for the next command.
- shift
- elif [ $# -gt 1 ] && [ "$2" == "--non-append" ]; then
- nonappend=1
- fi
-
- if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]; then
- if [ "$(echo ${1##*.})" == "log" ]; then # Keep only the extension to check if it's a logfile
- local logfile=$1 # In this case, focus logrotate on the logfile
- else
- local logfile=$1/*.log # Else, uses the directory and all logfile into it.
- fi
- fi
- # LEGACY CODE
-
- local customtee="tee -a"
- if [ "$nonappend" -eq 1 ]; then
- customtee="tee"
- fi
- if [ -n "$logfile" ]
- then
- if [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile
- local logfile="$1/*.log" # Else, uses the directory and all logfile into it.
- fi
- else
- logfile="/var/log/${app}/*.log" # Without argument, use a defaut directory in /var/log
- fi
- local su_directive=""
- if [[ -n $specific_user ]]; then
- su_directive=" # Run logorotate as specific user - group
- su ${specific_user%/*} ${specific_user#*/}"
- fi
-
- cat > ./${app}-logrotate << EOF # Build a config file for logrotate
-$logfile {
- # Rotate if the logfile exceeds 100Mo
- size 100M
- # Keep 12 old log maximum
- rotate 12
- # Compress the logs with gzip
- compress
- # Compress the log at the next cycle. So keep always 2 non compressed logs
- delaycompress
- # Copy and truncate the log to allow to continue write on it. Instead of move the log.
- copytruncate
- # Do not do an error if the log is missing
- missingok
- # Not rotate if the log is empty
- notifempty
- # Keep old logs in the same dir
- noolddir
- $su_directive
-}
-EOF
- sudo mkdir -p $(dirname "$logfile") # Create the log directory, if not exist
- cat ${app}-logrotate | sudo $customtee /etc/logrotate.d/$app > /dev/null # Append this config to the existing config file, or replace the whole config file (depending on $customtee)
-}
-
-# Remove the app's logrotate config.
-#
-# usage: ynh_remove_logrotate
-ynh_remove_logrotate () {
- if [ -e "/etc/logrotate.d/$app" ]; then
- sudo rm "/etc/logrotate.d/$app"
- fi
-}
-
-# Create a dedicated systemd config
-#
-# usage: ynh_add_systemd_config [--service=service] [--template=template]
-# | arg: -s, --service - Service name (optionnal, $app by default)
-# | arg: -t, --template - Name of template file (optionnal, this is 'systemd' by default, meaning ./conf/systemd.service will be used as template)
-#
-# This will use the template ../conf/.service
-# to generate a systemd config, by replacing the following keywords
-# with global variables that should be defined before calling
-# this helper :
-#
-# __APP__ by $app
-# __FINALPATH__ by $final_path
-#
-ynh_add_systemd_config () {
- # Declare an array to define the options of this helper.
- local legacy_args=st
- declare -Ar args_array=( [s]=service= [t]=template= )
- local service
- local template
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
- local service="${service:-$app}"
- local template="${template:-systemd.service}"
-
- finalsystemdconf="/etc/systemd/system/$service.service"
- ynh_backup_if_checksum_is_different --file="$finalsystemdconf"
- sudo cp ../conf/$template "$finalsystemdconf"
-
- # 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="$finalsystemdconf"
- fi
- if test -n "${app:-}"; then
- ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$finalsystemdconf"
- fi
- ynh_store_file_checksum --file="$finalsystemdconf"
-
- sudo chown root: "$finalsystemdconf"
- sudo systemctl enable $service
- sudo systemctl daemon-reload
-}
-
-# Remove the dedicated systemd config
-#
-# usage: ynh_remove_systemd_config [--service=service]
-# | arg: -s, --service - Service name (optionnal, $app by default)
-#
-ynh_remove_systemd_config () {
- # Declare an array to define the options of this helper.
- local legacy_args=s
- declare -Ar args_array=( [s]=service= )
- local service
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
- local service="${service:-$app}"
-
- local finalsystemdconf="/etc/systemd/system/$service.service"
- if [ -e "$finalsystemdconf" ]; then
- sudo systemctl stop $service
- sudo systemctl disable $service
- ynh_secure_remove --file="$finalsystemdconf"
- sudo systemctl daemon-reload
- fi
-}
-
-# Create a dedicated nginx config
-#
-# usage: ynh_add_nginx_config "list of others variables to replace"
-#
-# | arg: list of others variables to replace separeted by a space
-# | for example : 'path_2 port_2 ...'
-#
-# This will use a template in ../conf/nginx.conf
-# __PATH__ by $path_url
-# __DOMAIN__ by $domain
-# __PORT__ by $port
-# __NAME__ by $app
-# __FINALPATH__ by $final_path
-#
-# And dynamic variables (from the last example) :
-# __PATH_2__ by $path_2
-# __PORT_2__ by $port_2
-#
-ynh_add_nginx_config () {
- finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
- local others_var=${1:-}
- ynh_backup_if_checksum_is_different --file="$finalnginxconf"
- sudo cp ../conf/nginx.conf "$finalnginxconf"
-
- # 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 "${path_url:-}"; then
- # path_url_slash_less is path_url, or a blank value if path_url is only '/'
- local path_url_slash_less=${path_url%/}
- ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$finalnginxconf"
- ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$finalnginxconf"
- fi
- if test -n "${domain:-}"; then
- ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$finalnginxconf"
- fi
- if test -n "${port:-}"; then
- ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$finalnginxconf"
- fi
- if test -n "${app:-}"; then
- ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$finalnginxconf"
- fi
- if test -n "${final_path:-}"; then
- ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalnginxconf"
- 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="$finalnginxconf"
- done
-
- if [ "${path_url:-}" != "/" ]
- then
- ynh_replace_string --match_string="^#sub_path_only" --replace_string="" --target_file="$finalnginxconf"
- else
- ynh_replace_string --match_string="^#root_path_only" --replace_string="" --target_file="$finalnginxconf"
- fi
-
- ynh_store_file_checksum --file="$finalnginxconf"
-
- sudo systemctl reload nginx
-}
-
-# Remove the dedicated nginx config
-#
-# usage: ynh_remove_nginx_config
-ynh_remove_nginx_config () {
- ynh_secure_remove --file="/etc/nginx/conf.d/$domain.d/$app.conf"
- sudo systemctl reload nginx
-}
-
-# Create a dedicated php-fpm config
-#
-# usage: ynh_add_fpm_config
-ynh_add_fpm_config () {
- # Configure PHP-FPM 7.0 by default
- local fpm_config_dir="/etc/php/7.0/fpm"
- local fpm_service="php7.0-fpm"
- # Configure PHP-FPM 5 on Debian Jessie
- if [ "$(ynh_get_debian_release)" == "jessie" ]; then
- fpm_config_dir="/etc/php5/fpm"
- fpm_service="php5-fpm"
- fi
- ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
- ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
- finalphpconf="$fpm_config_dir/pool.d/$app.conf"
- ynh_backup_if_checksum_is_different --file="$finalphpconf"
- sudo cp ../conf/php-fpm.conf "$finalphpconf"
- ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$finalphpconf"
- ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalphpconf"
- ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$finalphpconf"
- sudo chown root: "$finalphpconf"
- ynh_store_file_checksum --file="$finalphpconf"
-
- if [ -e "../conf/php-fpm.ini" ]
- then
- echo "Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead." >&2
- finalphpini="$fpm_config_dir/conf.d/20-$app.ini"
- ynh_backup_if_checksum_is_different "$finalphpini"
- sudo cp ../conf/php-fpm.ini "$finalphpini"
- sudo chown root: "$finalphpini"
- ynh_store_file_checksum "$finalphpini"
- fi
- sudo systemctl reload $fpm_service
-}
-
-# Remove the dedicated php-fpm config
-#
-# usage: ynh_remove_fpm_config
-ynh_remove_fpm_config () {
- local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
- local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
- # Assume php version 7 if not set
- if [ -z "$fpm_config_dir" ]; then
- fpm_config_dir="/etc/php/7.0/fpm"
- fpm_service="php7.0-fpm"
- fi
- ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
- ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini" 2>&1
- sudo systemctl reload $fpm_service
-}
-
-# Create a dedicated fail2ban config (jail and filter conf files)
-#
-# usage 1: ynh_add_fail2ban_config --logpath=log_file --failregex=filter [--max_retry=max_retry] [--ports=ports]
-# | arg: -l, --logpath= - Log file to be checked by fail2ban
-# | arg: -r, --failregex= - Failregex to be looked for by fail2ban
-# | arg: -m, --max_retry= - Maximum number of retries allowed before banning IP address - default: 3
-# | arg: -p, --ports= - Ports blocked for a banned IP address - default: http,https
-#
-# -----------------------------------------------------------------------------
-#
-# usage 2: ynh_add_fail2ban_config --use_template [--others_var="list of others variables to replace"]
-# | arg: -t, --use_template - Use this helper in template mode
-# | arg: -v, --others_var= - List of others variables to replace separeted by a space
-# | for example : 'var_1 var_2 ...'
-#
-# This will use a template in ../conf/f2b_jail.conf and ../conf/f2b_filter.conf
-# __APP__ by $app
-#
-# You can dynamically replace others variables by example :
-# __VAR_1__ by $var_1
-# __VAR_2__ by $var_2
-#
-# Generally your template will look like that by example (for synapse):
-#
-# f2b_jail.conf:
-# [__APP__]
-# enabled = true
-# port = http,https
-# filter = __APP__
-# logpath = /var/log/__APP__/logfile.log
-# maxretry = 3
-#
-# f2b_filter.conf:
-# [INCLUDES]
-# before = common.conf
-# [Definition]
-#
-# # Part of regex definition (just used to make more easy to make the global regex)
-# __synapse_start_line = .? \- synapse\..+ \-
-#
-# # Regex definition.
-# failregex = ^%(__synapse_start_line)s INFO \- POST\-(\d+)\- \- \d+ \- Received request\: POST /_matrix/client/r0/login\??%(__synapse_start_line)s INFO \- POST\-\1\- Got login request with identifier: \{u'type': u'm.id.user', u'user'\: u'(.+?)'\}, medium\: None, address: None, user\: u'\5'%(__synapse_start_line)s WARNING \- \- (Attempted to login as @\5\:.+ but they do not exist|Failed password login for user @\5\:.+)$
-#
-# ignoreregex =
-#
-# -----------------------------------------------------------------------------
-#
-# Note about the "failregex" option:
-# regex to match the password failure messages in the logfile. The
-# host must be matched by a group named "host". The tag "" can
-# be used for standard IP/hostname matching and is only an alias for
-# (?:::f{4,6}:)?(?P[\w\-.^_]+)
-#
-# You can find some more explainations about how to make a regex here :
-# https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Filters
-#
-# Note that the logfile need to exist before to call this helper !!
-#
-# To validate your regex you can test with this command:
-# fail2ban-regex /var/log/YOUR_LOG_FILE_PATH /etc/fail2ban/filter.d/YOUR_APP.conf
-#
-ynh_add_fail2ban_config () {
- # Declare an array to define the options of this helper.
- local legacy_args=lrmptv
- declare -Ar args_array=( [l]=logpath= [r]=failregex= [m]=max_retry= [p]=ports= [t]=use_template [v]=others_var=)
- local logpath
- local failregex
- local max_retry
- local ports
- local others_var
- local use_template
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
- use_template="${use_template:-0}"
- max_retry=${max_retry:-3}
- ports=${ports:-http,https}
-
- finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf"
- finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf"
- ynh_backup_if_checksum_is_different "$finalfail2banjailconf"
- ynh_backup_if_checksum_is_different "$finalfail2banfilterconf"
-
- if [ $use_template -eq 1 ]
- then
- # Usage 2, templates
- cp ../conf/f2b_jail.conf $finalfail2banjailconf
- cp ../conf/f2b_filter.conf $finalfail2banfilterconf
-
- if [ -n "${app:-}" ]
- then
- ynh_replace_string "__APP__" "$app" "$finalfail2banjailconf"
- ynh_replace_string "__APP__" "$app" "$finalfail2banfilterconf"
- 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="$finalfail2banjailconf"
- ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banfilterconf"
- done
-
- else
- # Usage 1, no template. Build a config file from scratch.
- 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."
-
- tee $finalfail2banjailconf < This line will be added into CSV file
@@ -35,7 +30,7 @@ CAN_BIND=${CAN_BIND:-1}
#
# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "conf/"
# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/$app.conf"
-#
+#
# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "conf"
# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf"
#
@@ -46,6 +41,7 @@ CAN_BIND=${CAN_BIND:-1}
# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "/conf/"
# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/$app.conf"
#
+# Requires YunoHost version 2.4.0 or higher.
ynh_backup() {
# TODO find a way to avoid injection by file strange naming !
@@ -67,25 +63,23 @@ ynh_backup() {
# If backing up core only (used by ynh_backup_before_upgrade),
# don't backup big data items
if [ "$is_big" == "1" ] && [ "$BACKUP_CORE_ONLY" == "1" ] ; then
- echo "$src_path will not be saved, because backup_core_only is set." >&2
+ ynh_print_info --message="$src_path will not be saved, because backup_core_only is set."
return 0
fi
-
+
# ==============================================================================
# Format correctly source and destination paths
# ==============================================================================
# Be sure the source path is not empty
[[ -e "${src_path}" ]] || {
- echo "Source path '${src_path}' does not exist" >&2
+ ynh_print_warn --message="Source path '${src_path}' does not exist"
if [ "$not_mandatory" == "0" ]
then
- echo "Source path '${SRC_PATH}' does not exist" >&2
-
# This is a temporary fix for fail2ban config files missing after the migration to stretch.
if echo "${src_path}" | grep --quiet "/etc/fail2ban"
then
touch "${src_path}"
- echo "The missing file will be replaced by a dummy one for the backup !!!" >&2
+ ynh_print_info --message="The missing file will be replaced by a dummy one for the backup !!!"
else
return 1
fi
@@ -129,7 +123,7 @@ ynh_backup() {
# Check if dest_path already exists in tmp archive
[[ ! -e "${dest_path}" ]] || {
- echo "Destination path '${dest_path}' already exist" >&2
+ ynh_print_err --message="Destination path '${dest_path}' already exist"
return 1
}
@@ -158,6 +152,7 @@ ynh_backup() {
#
# usage: ynh_restore
#
+# Requires YunoHost version 2.6.4 or higher.
ynh_restore () {
# Deduce the relative path of $YNH_CWD
local REL_DIR="${YNH_CWD#$YNH_BACKUP_DIR/}"
@@ -193,32 +188,30 @@ with open(sys.argv[1], 'r') as backup_file:
return $?
}
-# Restore a file or a directory
+# Restore a file or a directory
#
# Use the registered path in backup_list by ynh_backup to restore the file at
-# the good place.
+# the right place.
#
# usage: ynh_restore_file --origin_path=origin_path [--dest_path=dest_path] [--not_mandatory]
-# | arg: -o, --origin_path - Path where was located the file or the directory before
-# to be backuped or relative path to $YNH_CWD where it is located in the backup archive
-# | arg: -d, --dest_path - Path where restore the file or the dir, if unspecified,
-# the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in
-# the archive, the destination will be searched into backup.csv
+# | arg: -o, --origin_path - Path where was located the file or the directory before to be backuped or relative path to $YNH_CWD where it is located in the backup archive
+# | arg: -d, --dest_path - Path where restore the file or the dir, if unspecified, the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in the archive, the destination will be searched into backup.csv
# | arg: -m, --not_mandatory - Indicate that if the file is missing, the restore process can ignore it.
#
-# If DEST_PATH already exists and is lighter than 500 Mo, a backup will be made in
+# examples:
+# ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf"
+# # You can also use relative paths:
+# ynh_restore_file "conf/nginx.conf"
+#
+# If DEST_PATH already exists and is lighter than 500 Mo, a backup will be made in
# /home/yunohost.conf/backup/. Otherwise, the existing file is removed.
#
-# examples:
-# ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf"
-# # if apps/wordpress/etc/nginx/conf.d/$domain.d/$app.conf exists, restore it into
-# # /etc/nginx/conf.d/$domain.d/$app.conf
-# # if no, search a correspondance in the csv (eg: conf/nginx.conf) and restore it into
-# # /etc/nginx/conf.d/$domain.d/$app.conf
-#
-# # DON'T GIVE THE ARCHIVE PATH:
-# ynh_restore_file "conf/nginx.conf"
+# if apps/wordpress/etc/nginx/conf.d/$domain.d/$app.conf exists, restore it into
+# /etc/nginx/conf.d/$domain.d/$app.conf
+# if no, search for a match in the csv (eg: conf/nginx.conf) and restore it into
+# /etc/nginx/conf.d/$domain.d/$app.conf
#
+# Requires YunoHost version 2.6.4 or higher.
ynh_restore_file () {
# Declare an array to define the options of this helper.
local legacy_args=odm
@@ -253,7 +246,7 @@ ynh_restore_file () {
then
local backup_file="/home/yunohost.conf/backup/${dest_path}.backup.$(date '+%Y%m%d.%H%M%S')"
mkdir -p "$(dirname "$backup_file")"
- mv "${dest_path}" "$backup_file" # Move the current file or directory
+ mv "${dest_path}" "$backup_file" # Move the current file or directory
else
ynh_secure_remove --file=${dest_path}
fi
@@ -283,91 +276,74 @@ ynh_bind_or_cp() {
local AS_ROOT=${3:-0}
local NO_ROOT=0
[[ "${AS_ROOT}" = "1" ]] || NO_ROOT=1
- echo "This helper is deprecated, you should use ynh_backup instead" >&2
+ ynh_print_warn --message="This helper is deprecated, you should use ynh_backup instead"
ynh_backup "$1" "$2" 1
}
-# Create a directory under /tmp
-#
-# [internal]
-#
-# Deprecated helper
-#
-# usage: ynh_mkdir_tmp
-# | ret: the created directory path
-ynh_mkdir_tmp() {
- echo "The helper ynh_mkdir_tmp is deprecated." >&2
- echo "You should use 'mktemp -d' instead and manage permissions \
-properly with chmod/chown." >&2
- local TMP_DIR=$(mktemp -d)
-
- # Give rights to other users could be a security risk.
- # But for retrocompatibility we need it. (This helpers is deprecated)
- chmod 755 $TMP_DIR
- echo $TMP_DIR
-}
-
# Calculate and store a file checksum into the app settings
#
# $app should be defined when calling this helper
#
# usage: ynh_store_file_checksum --file=file
# | arg: -f, --file - The file on which the checksum will performed, then stored.
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_store_file_checksum () {
- # Declare an array to define the options of this helper.
- local legacy_args=f
- declare -Ar args_array=( [f]=file= )
- local file
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
+ # Declare an array to define the options of this helper.
+ local legacy_args=f
+ declare -Ar args_array=( [f]=file= )
+ local file
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
- local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
- ynh_app_setting_set --app=$app --key=$checksum_setting_name --value=$(sudo md5sum "$file" | cut -d' ' -f1)
+ local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
+ ynh_app_setting_set --app=$app --key=$checksum_setting_name --value=$(sudo md5sum "$file" | cut -d' ' -f1)
- # If backup_file_checksum isn't empty, ynh_backup_if_checksum_is_different has made a backup
- if [ -n "${backup_file_checksum-}" ]
- then
- # Print the diff between the previous file and the new one.
- # diff return 1 if the files are different, so the || true
- diff --report-identical-files --unified --color=always $backup_file_checksum $file >&2 || true
- fi
- # Unset the variable, so it wouldn't trig a ynh_store_file_checksum without a ynh_backup_if_checksum_is_different before it.
- unset backup_file_checksum
+ # If backup_file_checksum isn't empty, ynh_backup_if_checksum_is_different has made a backup
+ if [ -n "${backup_file_checksum-}" ]
+ then
+ # Print the diff between the previous file and the new one.
+ # diff return 1 if the files are different, so the || true
+ diff --report-identical-files --unified --color=always $backup_file_checksum $file >&2 || true
+ fi
+ # Unset the variable, so it wouldn't trig a ynh_store_file_checksum without a ynh_backup_if_checksum_is_different before it.
+ unset backup_file_checksum
}
# Verify the checksum and backup the file if it's different
-# This helper is primarily meant to allow to easily backup personalised/manually
+# This helper is primarily meant to allow to easily backup personalised/manually
# modified config files.
#
# $app should be defined when calling this helper
#
# usage: ynh_backup_if_checksum_is_different --file=file
# | arg: -f, --file - The file on which the checksum test will be perfomed.
+# | ret: the name of a backup file, or nothing
#
-# | ret: Return the name a the backup file, or nothing
+# Requires YunoHost version 2.6.4 or higher.
ynh_backup_if_checksum_is_different () {
- # Declare an array to define the options of this helper.
- local legacy_args=f
- declare -Ar args_array=( [f]=file= )
- local file
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
+ # Declare an array to define the options of this helper.
+ local legacy_args=f
+ declare -Ar args_array=( [f]=file= )
+ local file
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
- local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
- local checksum_value=$(ynh_app_setting_get --app=$app --key=$checksum_setting_name)
- # backup_file_checksum isn't declare as local, so it can be reuse by ynh_store_file_checksum
- backup_file_checksum=""
- if [ -n "$checksum_value" ]
- then # Proceed only if a value was stored into the app settings
- if ! echo "$checksum_value $file" | sudo md5sum -c --status
- then # If the checksum is now different
- backup_file_checksum="/home/yunohost.conf/backup/$file.backup.$(date '+%Y%m%d.%H%M%S')"
- sudo mkdir -p "$(dirname "$backup_file_checksum")"
- sudo cp -a "$file" "$backup_file_checksum" # Backup the current file
- ynh_print_warn "File $file has been manually modified since the installation or last upgrade. So it has been duplicated in $backup_file_checksum"
- echo "$backup_file_checksum" # Return the name of the backup file
- fi
- fi
+ local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
+ local checksum_value=$(ynh_app_setting_get --app=$app --key=$checksum_setting_name)
+ # backup_file_checksum isn't declare as local, so it can be reuse by ynh_store_file_checksum
+ backup_file_checksum=""
+ if [ -n "$checksum_value" ]
+ then # Proceed only if a value was stored into the app settings
+ if ! echo "$checksum_value $file" | sudo md5sum -c --status
+ then # If the checksum is now different
+ backup_file_checksum="/home/yunohost.conf/backup/$file.backup.$(date '+%Y%m%d.%H%M%S')"
+ sudo mkdir -p "$(dirname "$backup_file_checksum")"
+ sudo cp -a "$file" "$backup_file_checksum" # Backup the current file
+ ynh_print_warn "File $file has been manually modified since the installation or last upgrade. So it has been duplicated in $backup_file_checksum"
+ echo "$backup_file_checksum" # Return the name of the backup file
+ fi
+ fi
}
# Delete a file checksum from the app settings
@@ -376,53 +352,97 @@ ynh_backup_if_checksum_is_different () {
#
# usage: ynh_remove_file_checksum file
# | arg: -f, --file= - The file for which the checksum will be deleted
-ynh_delete_file_checksum () {
- # Declare an array to define the options of this helper.
- local legacy_args=f
- declare -Ar args_array=( [f]=file= )
- local file
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
-
- local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
- ynh_app_setting_delete --app=$app --key=$checksum_setting_name
-}
-
-# Remove a file or a directory securely
#
-# usage: ynh_secure_remove --file=path_to_remove
-# | arg: -f, --file - File or directory to remove
-ynh_secure_remove () {
- # Declare an array to define the options of this helper.
- local legacy_args=f
- declare -Ar args_array=( [f]=file= )
- local file
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
+# Requires YunoHost version 3.3.1 or higher.
+ynh_delete_file_checksum () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=f
+ declare -Ar args_array=( [f]=file= )
+ local file
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
- local forbidden_path=" \
- /var/www \
- /home/yunohost.app"
-
- if [ $# -ge 2 ]
- then
- echo "/!\ Packager ! You provided more than one argument to ynh_secure_remove but it will be ignored... Use this helper with one argument at time." >&2
- fi
-
- if [[ "$forbidden_path" =~ "$file" \
- # Match all paths or subpaths in $forbidden_path
- || "$file" =~ ^/[[:alnum:]]+$ \
- # Match all first level paths from / (Like /var, /root, etc...)
- || "${file:${#file}-1}" = "/" ]]
- # Match if the path finishes by /. Because it seems there is an empty variable
- then
- echo "Avoid deleting $file." >&2
- else
- if [ -e "$file" ]
- then
- sudo rm -R "$file"
- else
- echo "$file wasn't deleted because it doesn't exist." >&2
- fi
- fi
+ local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
+ ynh_app_setting_delete --app=$app --key=$checksum_setting_name
+}
+
+# Make a backup in case of failed upgrade
+#
+# usage:
+# ynh_backup_before_upgrade
+# ynh_clean_setup () {
+# ynh_restore_upgradebackup
+# }
+# ynh_abort_if_errors
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_backup_before_upgrade () {
+ if [ ! -e "/etc/yunohost/apps/$app/scripts/backup" ]
+ then
+ ynh_print_warn --message="This app doesn't have any backup script."
+ return
+ fi
+ backup_number=1
+ local old_backup_number=2
+ local app_bck=${app//_/-} # Replace all '_' by '-'
+ NO_BACKUP_UPGRADE=${NO_BACKUP_UPGRADE:-0}
+
+ if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
+ then
+ # Check if a backup already exists with the prefix 1
+ if sudo yunohost backup list | grep -q $app_bck-pre-upgrade1
+ then
+ # Prefix becomes 2 to preserve the previous backup
+ backup_number=2
+ old_backup_number=1
+ fi
+
+ # Create backup
+ sudo BACKUP_CORE_ONLY=1 yunohost backup create --apps $app --name $app_bck-pre-upgrade$backup_number --debug
+ if [ "$?" -eq 0 ]
+ then
+ # If the backup succeeded, remove the previous backup
+ if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$old_backup_number
+ then
+ # Remove the previous backup only if it exists
+ sudo yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null
+ fi
+ else
+ ynh_die --message="Backup failed, the upgrade process was aborted."
+ fi
+ else
+ ynh_print_warn --message="\$NO_BACKUP_UPGRADE is set, backup will be avoided. Be careful, this upgrade is going to be operated without a security backup"
+ fi
+}
+
+# Restore a previous backup if the upgrade process failed
+#
+# usage:
+# ynh_backup_before_upgrade
+# ynh_clean_setup () {
+# ynh_restore_upgradebackup
+# }
+# ynh_abort_if_errors
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_restore_upgradebackup () {
+ ynh_print_err --message="Upgrade failed."
+ local app_bck=${app//_/-} # Replace all '_' by '-'
+
+ NO_BACKUP_UPGRADE=${NO_BACKUP_UPGRADE:-0}
+
+ if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
+ then
+ # Check if an existing backup can be found before removing and restoring the application.
+ if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$backup_number
+ then
+ # Remove the application then restore it
+ sudo yunohost app remove $app
+ # Restore the backup
+ sudo yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug
+ ynh_die --message="The app was restored to the way it was before the failed upgrade."
+ fi
+ else
+ ynh_print_warn --message="\$NO_BACKUP_UPGRADE is set, that means there's no backup to restore. You have to fix this upgrade by yourself !"
+ fi
}
diff --git a/data/helpers.d/debug b/data/helpers.d/debug
deleted file mode 100644
index a8b7c8d69..000000000
--- a/data/helpers.d/debug
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/bash
-
-# Debugger for app packagers
-#
-# usage: ynh_debug [--message=message] [--trace=1/0]
-# | arg: -m, --message= - The text to print
-# | arg: -t, --trace= - Turn on or off the trace of the script. Usefull to trace nonly a small part of a script.
-ynh_debug () {
- # Disable set xtrace for the helper itself, to not pollute the debug log
- set +x
- # Declare an array to define the options of this helper.
- local legacy_args=mt
- declare -Ar args_array=( [m]=message= [t]=trace= )
- local message
- local trace
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
- # Redisable xtrace, ynh_handle_getopts_args set it back
- set +x
- message=${message:-}
- trace=${trace:-}
-
- if [ -n "$message" ]
- then
- ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2
- fi
-
- if [ "$trace" == "1" ]
- then
- ynh_debug --message="Enable debugging"
- set +x
- # Get the current file descriptor of xtrace
- old_bash_xtracefd=$BASH_XTRACEFD
- # Add the current file name and the line number of any command currently running while tracing.
- PS4='$(basename ${BASH_SOURCE[0]})-L${LINENO}: '
- # Force xtrace to stderr
- BASH_XTRACEFD=2
- fi
- if [ "$trace" == "0" ]
- then
- ynh_debug --message="Disable debugging"
- set +x
- # Put xtrace back to its original fild descriptor
- BASH_XTRACEFD=$old_bash_xtracefd
- fi
- # Renable set xtrace
- set -x
-}
-
-# Execute a command and print the result as debug
-#
-# usage: ynh_debug_exec command to execute
-# usage: ynh_debug_exec "command to execute | following command"
-# In case of use of pipes, you have to use double quotes. Otherwise, this helper will be executed with the first command, then be sent to the next pipe.
-#
-# | arg: command - command to execute
-ynh_debug_exec () {
- ynh_debug --message="$(eval $@)"
-}
diff --git a/data/helpers.d/fail2ban b/data/helpers.d/fail2ban
new file mode 100644
index 000000000..85f568520
--- /dev/null
+++ b/data/helpers.d/fail2ban
@@ -0,0 +1,151 @@
+#!/bin/bash
+
+# Create a dedicated fail2ban config (jail and filter conf files)
+#
+# usage 1: ynh_add_fail2ban_config --logpath=log_file --failregex=filter [--max_retry=max_retry] [--ports=ports]
+# | arg: -l, --logpath= - Log file to be checked by fail2ban
+# | arg: -r, --failregex= - Failregex to be looked for by fail2ban
+# | arg: -m, --max_retry= - Maximum number of retries allowed before banning IP address - default: 3
+# | arg: -p, --ports= - Ports blocked for a banned IP address - default: http,https
+#
+# -----------------------------------------------------------------------------
+#
+# usage 2: ynh_add_fail2ban_config --use_template [--others_var="list of others variables to replace"]
+# | arg: -t, --use_template - Use this helper in template mode
+# | arg: -v, --others_var= - List of others variables to replace separeted by a space
+# | for example : 'var_1 var_2 ...'
+#
+# This will use a template in ../conf/f2b_jail.conf and ../conf/f2b_filter.conf
+# __APP__ by $app
+#
+# You can dynamically replace others variables by example :
+# __VAR_1__ by $var_1
+# __VAR_2__ by $var_2
+#
+# Generally your template will look like that by example (for synapse):
+#
+# f2b_jail.conf:
+# [__APP__]
+# enabled = true
+# port = http,https
+# filter = __APP__
+# logpath = /var/log/__APP__/logfile.log
+# maxretry = 3
+#
+# f2b_filter.conf:
+# [INCLUDES]
+# before = common.conf
+# [Definition]
+#
+# # Part of regex definition (just used to make more easy to make the global regex)
+# __synapse_start_line = .? \- synapse\..+ \-
+#
+# # Regex definition.
+# failregex = ^%(__synapse_start_line)s INFO \- POST\-(\d+)\- \- \d+ \- Received request\: POST /_matrix/client/r0/login\??%(__synapse_start_line)s INFO \- POST\-\1\- Got login request with identifier: \{u'type': u'm.id.user', u'user'\: u'(.+?)'\}, medium\: None, address: None, user\: u'\5'%(__synapse_start_line)s WARNING \- \- (Attempted to login as @\5\:.+ but they do not exist|Failed password login for user @\5\:.+)$
+#
+# ignoreregex =
+#
+# -----------------------------------------------------------------------------
+#
+# Note about the "failregex" option:
+# regex to match the password failure messages in the logfile. The
+# host must be matched by a group named "host". The tag "" can
+# be used for standard IP/hostname matching and is only an alias for
+# (?:::f{4,6}:)?(?P[\w\-.^_]+)
+#
+# You can find some more explainations about how to make a regex here :
+# https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Filters
+#
+# Note that the logfile need to exist before to call this helper !!
+#
+# To validate your regex you can test with this command:
+# fail2ban-regex /var/log/YOUR_LOG_FILE_PATH /etc/fail2ban/filter.d/YOUR_APP.conf
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_add_fail2ban_config () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=lrmptv
+ declare -Ar args_array=( [l]=logpath= [r]=failregex= [m]=max_retry= [p]=ports= [t]=use_template [v]=others_var=)
+ local logpath
+ local failregex
+ local max_retry
+ local ports
+ local others_var
+ local use_template
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ use_template="${use_template:-0}"
+ max_retry=${max_retry:-3}
+ ports=${ports:-http,https}
+
+ finalfail2banjailconf="/etc/fail2ban/jail.d/$app.conf"
+ finalfail2banfilterconf="/etc/fail2ban/filter.d/$app.conf"
+ ynh_backup_if_checksum_is_different "$finalfail2banjailconf"
+ ynh_backup_if_checksum_is_different "$finalfail2banfilterconf"
+
+ if [ $use_template -eq 1 ]
+ then
+ # Usage 2, templates
+ cp ../conf/f2b_jail.conf $finalfail2banjailconf
+ cp ../conf/f2b_filter.conf $finalfail2banfilterconf
+
+ if [ -n "${app:-}" ]
+ then
+ ynh_replace_string "__APP__" "$app" "$finalfail2banjailconf"
+ ynh_replace_string "__APP__" "$app" "$finalfail2banfilterconf"
+ 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="$finalfail2banjailconf"
+ ynh_replace_string --match_string="__${var_to_replace^^}__" --replace_string="${!var_to_replace}" --target_file="$finalfail2banfilterconf"
+ done
+
+ else
+ # Usage 1, no template. Build a config file from scratch.
+ 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."
+
+ tee $finalfail2banjailconf <&1
}
@@ -128,6 +145,8 @@ ynh_exec_warn_less () {
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
+#
+# Requires YunoHost version 3.2.0 or higher.
ynh_exec_quiet () {
eval $@ > /dev/null
}
@@ -140,6 +159,8 @@ ynh_exec_quiet () {
# If the command to execute uses double quotes, they have to be escaped or they will be interpreted and removed.
#
# | arg: command - command to execute
+#
+# Requires YunoHost version 3.2.0 or higher.
ynh_exec_fully_quiet () {
eval $@ > /dev/null 2>&1
}
@@ -148,6 +169,8 @@ ynh_exec_fully_quiet () {
#
# usage: ynh_print_OFF
# WARNING: You should be careful with this helper, and never forget to use ynh_print_ON as soon as possible to restore the logging.
+#
+# Requires YunoHost version 3.2.0 or higher.
ynh_print_OFF () {
set +x
}
@@ -155,6 +178,8 @@ ynh_print_OFF () {
# Restore the logging after ynh_print_OFF
#
# usage: ynh_print_ON
+#
+# Requires YunoHost version 3.2.0 or higher.
ynh_print_ON () {
set -x
# Print an echo only for the log, to be able to know that ynh_print_ON has been called.
@@ -167,13 +192,17 @@ ynh_print_ON () {
# | arg: -m, --message= - The text to print
# | arg: -w, --weight= - The weight for this progression. This value is 1 by default. Use a bigger value for a longer part of the script.
# | arg: -t, --time= - Print the execution time since the last call to this helper. Especially usefull to define weights.
+# The execution time is given for the duration since the previous call. So the weight should be applied to this previous call.
# | arg: -l, --last= - Use for the last call of the helper, to fill te progression bar.
+#
+# Requires YunoHost version 3.?.? or higher.
increment_progression=0
previous_weight=0
# Define base_time when the file is sourced
base_time=$(date +%s)
ynh_script_progression () {
# Declare an array to define the options of this helper.
+ local legacy_args=mwtl
declare -Ar args_array=( [m]=message= [w]=weight= [t]=time [l]=last )
local message
local weight
@@ -195,9 +224,9 @@ ynh_script_progression () {
local weight_calls=$(grep --perl-regexp --count "^[^#]*ynh_script_progression.*(--weight|-w )" $0)
# Get the weight of each occurrences of 'ynh_script_progression' in the script using --weight
- local weight_valuesA="$(grep --perl-regexp "^[^#]*ynh_script_progression.*--weight" $0 | sed 's/.*--weight[= ]\([[:digit:]].*\)/\1/g')"
- # Get the weight of each occurrences of 'ynh_script_progression' in the script using -w
- local weight_valuesB="$(grep --perl-regexp "^[^#]*ynh_script_progression.*-w " $0 | sed 's/.*-w[= ]\([[:digit:]].*\)/\1/g')"
+ local weight_valuesA="$(grep --perl-regexp "^[^#]*ynh_script_progression.*--weight" $0 | sed 's/.*--weight[= ]\([[:digit:]]*\).*/\1/g')"
+ # Get the weight of each occurrences of 'ynh_script_progression' in the script using -w
+ local weight_valuesB="$(grep --perl-regexp "^[^#]*ynh_script_progression.*-w " $0 | sed 's/.*-w[= ]\([[:digit:]]*\).*/\1/g')"
# Each value will be on a different line.
# Remove each 'end of line' and replace it by a '+' to sum the values.
local weight_values=$(( $(echo "$weight_valuesA" | tr '\n' '+') + $(echo "$weight_valuesB" | tr '\n' '+') 0 ))
@@ -214,8 +243,9 @@ ynh_script_progression () {
# Set the scale of the progression bar
local scale=20
- # progress_string(1,2) should have the size of the scale.
- local progress_string1="####################"
+ # progress_string(0,1,2) should have the size of the scale.
+ local progress_string2="####################"
+ local progress_string1="++++++++++++++++++++"
local progress_string0="...................."
# Reduce $increment_progression to the size of the scale
@@ -227,8 +257,17 @@ ynh_script_progression () {
local effective_progression=$scale
fi
- # Build $progression_bar from progress_string(1,2) according to $effective_progression
- local progression_bar="${progress_string1:0:$effective_progression}${progress_string0:0:$(( $scale - $effective_progression ))}"
+ # Build $progression_bar from progress_string(0,1,2) according to $effective_progression and the weight of the current task
+ # expected_progression is the progression expected after the current task
+ local expected_progression="$(( ( $increment_progression + $weight ) * $scale / $max_progression - $effective_progression ))"
+ if [ $last -eq 1 ]
+ then
+ expected_progression=0
+ fi
+ # left_progression is the progression not yet done
+ local left_progression="$(( $scale - $effective_progression - $expected_progression ))"
+ # Build the progression bar with $effective_progression, work done, $expected_progression, current work and $left_progression, work to be done.
+ local progression_bar="${progress_string2:0:$effective_progression}${progress_string1:0:$expected_progression}${progress_string0:0:$left_progression}"
local print_exec_time=""
if [ $time -eq 1 ]
@@ -238,3 +277,69 @@ ynh_script_progression () {
ynh_print_info "[$progression_bar] > ${message}${print_exec_time}"
}
+
+# Debugger for app packagers
+#
+# usage: ynh_debug [--message=message] [--trace=1/0]
+# | arg: -m, --message= - The text to print
+# | arg: -t, --trace= - Turn on or off the trace of the script. Usefull to trace nonly a small part of a script.
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_debug () {
+ # Disable set xtrace for the helper itself, to not pollute the debug log
+ set +x
+ # Declare an array to define the options of this helper.
+ local legacy_args=mt
+ declare -Ar args_array=( [m]=message= [t]=trace= )
+ local message
+ local trace
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ # Redisable xtrace, ynh_handle_getopts_args set it back
+ set +x
+ message=${message:-}
+ trace=${trace:-}
+
+ if [ -n "$message" ]
+ then
+ ynh_print_log "\e[34m\e[1m[DEBUG]\e[0m ${message}" >&2
+ fi
+
+ if [ "$trace" == "1" ]
+ then
+ ynh_debug --message="Enable debugging"
+ set +x
+ # Get the current file descriptor of xtrace
+ old_bash_xtracefd=$BASH_XTRACEFD
+ # Add the current file name and the line number of any command currently running while tracing.
+ PS4='$(basename ${BASH_SOURCE[0]})-L${LINENO}: '
+ # Force xtrace to stderr
+ BASH_XTRACEFD=2
+ # Force stdout to stderr
+ exec 1>&2
+ fi
+ if [ "$trace" == "0" ]
+ then
+ ynh_debug --message="Disable debugging"
+ set +x
+ # Put xtrace back to its original fild descriptor
+ BASH_XTRACEFD=$old_bash_xtracefd
+ # Restore stdout
+ exec 1>&1
+ fi
+ # Renable set xtrace
+ set -x
+}
+
+# Execute a command and print the result as debug
+#
+# usage: ynh_debug_exec command to execute
+# usage: ynh_debug_exec "command to execute | following command"
+# In case of use of pipes, you have to use double quotes. Otherwise, this helper will be executed with the first command, then be sent to the next pipe.
+#
+# | arg: command - command to execute
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_debug_exec () {
+ ynh_debug --message="$(eval $@)"
+}
diff --git a/data/helpers.d/logrotate b/data/helpers.d/logrotate
new file mode 100644
index 000000000..47ce46cf6
--- /dev/null
+++ b/data/helpers.d/logrotate
@@ -0,0 +1,103 @@
+#!/bin/bash
+
+# Use logrotate to manage the logfile
+#
+# usage: ynh_use_logrotate [--logfile=/log/file] [--nonappend] [--specific_user=user/group]
+# | arg: -l, --logfile - absolute path of logfile
+# | arg: -n, --nonappend - (optional) Replace the config file instead of appending this new config.
+# | arg: -u, --specific_user : run logrotate as the specified user and group. If not specified logrotate is runned as root.
+#
+# If no --logfile is provided, /var/log/${app} will be used as default.
+# logfile can be just a directory, or a full path to a logfile :
+# /parentdir/logdir
+# /parentdir/logdir/logfile.log
+#
+# It's possible to use this helper multiple times, each config will be added to
+# the same logrotate config file. Unless you use the option --non-append
+#
+# Requires YunoHost version 2.6.4 or higher.
+ynh_use_logrotate () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=lnuya
+ declare -Ar args_array=( [l]=logfile= [n]=nonappend [u]=specific_user= [y]=non [a]=append )
+ # [y]=non [a]=append are only for legacy purpose, to not fail on the old option '--non-append'
+ local logfile
+ local nonappend
+ local specific_user
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ local logfile="${logfile:-}"
+ local nonappend="${nonappend:-0}"
+ local specific_user="${specific_user:-}"
+
+ # LEGACY CODE - PRE GETOPTS
+ if [ $# -gt 0 ] && [ "$1" == "--non-append" ]; then
+ nonappend=1
+ # Destroy this argument for the next command.
+ shift
+ elif [ $# -gt 1 ] && [ "$2" == "--non-append" ]; then
+ nonappend=1
+ fi
+
+ if [ $# -gt 0 ] && [ "$(echo ${1:0:1})" != "-" ]; then
+ if [ "$(echo ${1##*.})" == "log" ]; then # Keep only the extension to check if it's a logfile
+ local logfile=$1 # In this case, focus logrotate on the logfile
+ else
+ local logfile=$1/*.log # Else, uses the directory and all logfile into it.
+ fi
+ fi
+ # LEGACY CODE
+
+ local customtee="tee -a"
+ if [ "$nonappend" -eq 1 ]; then
+ customtee="tee"
+ fi
+ if [ -n "$logfile" ]
+ then
+ if [ "$(echo ${logfile##*.})" != "log" ]; then # Keep only the extension to check if it's a logfile
+ local logfile="$logfile/*.log" # Else, uses the directory and all logfile into it.
+ fi
+ else
+ logfile="/var/log/${app}/*.log" # Without argument, use a defaut directory in /var/log
+ fi
+ local su_directive=""
+ if [[ -n $specific_user ]]; then
+ su_directive=" # Run logorotate as specific user - group
+ su ${specific_user%/*} ${specific_user#*/}"
+ fi
+
+ cat > ./${app}-logrotate << EOF # Build a config file for logrotate
+$logfile {
+ # Rotate if the logfile exceeds 100Mo
+ size 100M
+ # Keep 12 old log maximum
+ rotate 12
+ # Compress the logs with gzip
+ compress
+ # Compress the log at the next cycle. So keep always 2 non compressed logs
+ delaycompress
+ # Copy and truncate the log to allow to continue write on it. Instead of move the log.
+ copytruncate
+ # Do not do an error if the log is missing
+ missingok
+ # Not rotate if the log is empty
+ notifempty
+ # Keep old logs in the same dir
+ noolddir
+ $su_directive
+}
+EOF
+ sudo mkdir -p $(dirname "$logfile") # Create the log directory, if not exist
+ cat ${app}-logrotate | sudo $customtee /etc/logrotate.d/$app > /dev/null # Append this config to the existing config file, or replace the whole config file (depending on $customtee)
+}
+
+# Remove the app's logrotate config.
+#
+# usage: ynh_remove_logrotate
+#
+# Requires YunoHost version 2.6.4 or higher.
+ynh_remove_logrotate () {
+ if [ -e "/etc/logrotate.d/$app" ]; then
+ sudo rm "/etc/logrotate.d/$app"
+ fi
+}
diff --git a/data/helpers.d/mysql b/data/helpers.d/mysql
index fa1a61dab..39f93891c 100644
--- a/data/helpers.d/mysql
+++ b/data/helpers.d/mysql
@@ -11,6 +11,8 @@ MYSQL_ROOT_PWD_FILE=/etc/yunohost/mysql
# | arg: -u, --user - the user name to connect as
# | arg: -p, --password - the user password
# | arg: -d, --database - the database to connect to
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_connect_as() {
# Declare an array to define the options of this helper.
local legacy_args=upd
@@ -30,6 +32,8 @@ ynh_mysql_connect_as() {
# usage: ynh_mysql_execute_as_root --sql=sql [--database=database]
# | arg: -s, --sql - the SQL command to execute
# | arg: -d, --database - the database to connect to
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_execute_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=sd
@@ -49,6 +53,8 @@ ynh_mysql_execute_as_root() {
# usage: ynh_mysql_execute_file_as_root --file=file [--database=database]
# | arg: -f, --file - the file containing SQL commands
# | arg: -d, --database - the database to connect to
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_execute_file_as_root() {
# Declare an array to define the options of this helper.
local legacy_args=fd
@@ -71,6 +77,8 @@ ynh_mysql_execute_file_as_root() {
# | arg: db - the database name to create
# | arg: user - the user to grant privilegies
# | arg: pwd - the password to identify user by
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_create_db() {
local db=$1
@@ -95,6 +103,8 @@ ynh_mysql_create_db() {
#
# usage: ynh_mysql_drop_db db
# | arg: db - the database name to drop
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_drop_db() {
ynh_mysql_execute_as_root --sql="DROP DATABASE ${1};"
}
@@ -106,6 +116,8 @@ ynh_mysql_drop_db() {
# usage: ynh_mysql_dump_db --database=database
# | arg: -d, --database - the database name to dump
# | ret: the mysqldump output
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_dump_db() {
# Declare an array to define the options of this helper.
local legacy_args=d
@@ -124,6 +136,8 @@ ynh_mysql_dump_db() {
# usage: ynh_mysql_create_user user pwd [host]
# | arg: user - the user name to create
# | arg: pwd - the password to identify user by
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_create_user() {
ynh_mysql_execute_as_root \
--sql="CREATE USER '${1}'@'localhost' IDENTIFIED BY '${2}';"
@@ -133,6 +147,8 @@ ynh_mysql_create_user() {
#
# usage: ynh_mysql_user_exists --user=user
# | arg: -u, --user - the user for which to check existence
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_user_exists()
{
# Declare an array to define the options of this helper.
@@ -156,6 +172,8 @@ ynh_mysql_user_exists()
#
# usage: ynh_mysql_drop_user user
# | arg: user - the user name to drop
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_mysql_drop_user() {
ynh_mysql_execute_as_root --sql="DROP USER '${1}'@'localhost';"
}
@@ -168,7 +186,9 @@ ynh_mysql_drop_user() {
# usage: ynh_mysql_setup_db --db_user=user --db_name=name [--db_pwd=pwd]
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
-# | arg: -p, --db_pwd - Password of the database. If not given, a password will be generated
+# | arg: -p, --db_pwd - Password of the database. If not provided, a password will be generated
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_mysql_setup_db () {
# Declare an array to define the options of this helper.
local legacy_args=unp
@@ -180,7 +200,7 @@ ynh_mysql_setup_db () {
ynh_handle_getopts_args "$@"
local new_db_pwd=$(ynh_string_random) # Generate a random password
- # If $db_pwd is not given, use new_db_pwd instead for db_pwd
+ # If $db_pwd is not provided, use new_db_pwd instead for db_pwd
db_pwd="${db_pwd:-$new_db_pwd}"
ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database
@@ -192,6 +212,8 @@ ynh_mysql_setup_db () {
# usage: ynh_mysql_remove_db --db_user=user --db_name=name
# | arg: -u, --db_user - Owner of the database
# | arg: -n, --db_name - Name of the database
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_mysql_remove_db () {
# Declare an array to define the options of this helper.
local legacy_args=un
@@ -203,10 +225,10 @@ ynh_mysql_remove_db () {
local mysql_root_password=$(sudo cat $MYSQL_ROOT_PWD_FILE)
if mysqlshow -u root -p$mysql_root_password | grep -q "^| $db_name"; then # Check if the database exists
- echo "Removing database $db_name" >&2
+ ynh_print_info --message="Removing database $db_name"
ynh_mysql_drop_db $db_name # Remove the database
else
- echo "Database $db_name not found" >&2
+ ynh_print_warn --message="Database $db_name not found"
fi
# Remove mysql user if it exists
@@ -215,22 +237,3 @@ ynh_mysql_remove_db () {
fi
}
-# Sanitize a string intended to be the name of a database
-# (More specifically : replace - and . by _)
-#
-# example: dbname=$(ynh_sanitize_dbid $app)
-#
-# usage: ynh_sanitize_dbid --db_name=name
-# | arg: -n, --db_name - name to correct/sanitize
-# | ret: the corrected name
-ynh_sanitize_dbid () {
- # Declare an array to define the options of this helper.
- local legacy_args=n
- declare -Ar args_array=( [n]=db_name= )
- local db_name
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
-
- # We should avoid having - and . in the name of databases. They are replaced by _
- echo ${db_name//[-.]/_}
-}
diff --git a/data/helpers.d/network b/data/helpers.d/network
index a765d6346..0f75cb165 100644
--- a/data/helpers.d/network
+++ b/data/helpers.d/network
@@ -1,41 +1,13 @@
#!/bin/bash
-# Normalize the url path syntax
-# Handle the slash at the beginning of path and its absence at ending
-# Return a normalized url path
-#
-# example: url_path=$(ynh_normalize_url_path $url_path)
-# ynh_normalize_url_path example -> /example
-# ynh_normalize_url_path /example -> /example
-# ynh_normalize_url_path /example/ -> /example
-# ynh_normalize_url_path / -> /
-#
-# usage: ynh_normalize_url_path --path_url=path_to_normalize
-# | arg: -p, --path_url - URL path to normalize before using it
-ynh_normalize_url_path () {
- # Declare an array to define the options of this helper.
- local legacy_args=p
- declare -Ar args_array=( [p]=path_url= )
- local path_url
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
-
- test -n "$path_url" || ynh_die --message="ynh_normalize_url_path expect a URL path as first argument and received nothing."
- if [ "${path_url:0:1}" != "/" ]; then # If the first character is not a /
- path_url="/$path_url" # Add / at begin of path variable
- fi
- if [ "${path_url:${#path_url}-1}" == "/" ] && [ ${#path_url} -gt 1 ]; then # If the last character is a / and that not the only character.
- path_url="${path_url:0:${#path_url}-1}" # Delete the last character
- fi
- echo $path_url
-}
-
# Find a free port and return it
#
# example: port=$(ynh_find_port --port=8080)
#
# usage: ynh_find_port --port=begin_port
# | arg: -p, --port - port to start to search
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_find_port () {
# Declare an array to define the options of this helper.
local legacy_args=p
@@ -52,42 +24,77 @@ ynh_find_port () {
echo $port
}
-# Check availability of a web path
+# Validate an IP address
#
-# example: ynh_webpath_available --domain=some.domain.tld --path_url=/coffee
+# usage: ynh_validate_ip --family=family --ip_address=ip_address
+# | ret: 0 for valid ip addresses, 1 otherwise
#
-# usage: ynh_webpath_available --domain=domain --path_url=path
-# | arg: -d, --domain - the domain/host of the url
-# | arg: -p, --path_url - the web path to check the availability of
-ynh_webpath_available () {
- # Declare an array to define the options of this helper.
- local legacy_args=dp
- declare -Ar args_array=( [d]=domain= [p]=path_url= )
- local domain
- local path_url
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
+# example: ynh_validate_ip 4 111.222.333.444
+#
+# Requires YunoHost version 2.2.4 or higher.
+ynh_validate_ip()
+{
+ # http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python#319298
- sudo yunohost domain url-available $domain $path_url
+ # Declare an array to define the options of this helper.
+ local legacy_args=fi
+ declare -Ar args_array=( [f]=family= [i]=ip_address= )
+ local family
+ local ip_address
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ [ "$family" == "4" ] || [ "$family" == "6" ] || return 1
+
+ python /dev/stdin << EOF
+import socket
+import sys
+family = { "4" : socket.AF_INET, "6" : socket.AF_INET6 }
+try:
+ socket.inet_pton(family["$family"], "$ip_address")
+except socket.error:
+ sys.exit(1)
+sys.exit(0)
+EOF
}
-# Register/book a web path for an app
+# Validate an IPv4 address
#
-# example: ynh_webpath_register --app=wordpress --domain=some.domain.tld --path_url=/coffee
+# example: ynh_validate_ip4 111.222.333.444
#
-# usage: ynh_webpath_register --app=app --domain=domain --path_url=path
-# | arg: -a, --app - the app for which the domain should be registered
-# | arg: -d, --domain - the domain/host of the web path
-# | arg: -p, --path_url - the web path to be registered
-ynh_webpath_register () {
- # Declare an array to define the options of this helper.
- local legacy_args=adp
- declare -Ar args_array=( [a]=app= [d]=domain= [p]=path_url= )
- local app
- local domain
- local path_url
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
+# usage: ynh_validate_ip4 --ip_address=ip_address
+# | ret: 0 for valid ipv4 addresses, 1 otherwise
+#
+# Requires YunoHost version 2.2.4 or higher.
+ynh_validate_ip4()
+{
+ # Declare an array to define the options of this helper.
+ local legacy_args=i
+ declare -Ar args_array=( [i]=ip_address= )
+ local ip_address
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
- sudo yunohost app register-url $app $domain $path_url
+ ynh_validate_ip 4 $ip_address
+}
+
+
+# Validate an IPv6 address
+#
+# example: ynh_validate_ip6 2000:dead:beef::1
+#
+# usage: ynh_validate_ip6 --ip_address=ip_address
+# | ret: 0 for valid ipv6 addresses, 1 otherwise
+#
+# Requires YunoHost version 2.2.4 or higher.
+ynh_validate_ip6()
+{
+ # Declare an array to define the options of this helper.
+ local legacy_args=i
+ declare -Ar args_array=( [i]=ip_address= )
+ local ip_address
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ ynh_validate_ip 6 $ip_address
}
diff --git a/data/helpers.d/nginx b/data/helpers.d/nginx
new file mode 100644
index 000000000..ce6b61d3c
--- /dev/null
+++ b/data/helpers.d/nginx
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# Create a dedicated nginx config
+#
+# usage: ynh_add_nginx_config "list of others variables to replace"
+#
+# | arg: list - (Optional) list of others variables to replace separated by spaces. For example : 'path_2 port_2 ...'
+#
+# This will use a template in ../conf/nginx.conf
+# __PATH__ by $path_url
+# __DOMAIN__ by $domain
+# __PORT__ by $port
+# __NAME__ by $app
+# __FINALPATH__ by $final_path
+#
+# And dynamic variables (from the last example) :
+# __PATH_2__ by $path_2
+# __PORT_2__ by $port_2
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_add_nginx_config () {
+ finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf"
+ local others_var=${1:-}
+ ynh_backup_if_checksum_is_different --file="$finalnginxconf"
+ sudo cp ../conf/nginx.conf "$finalnginxconf"
+
+ # 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 "${path_url:-}"; then
+ # path_url_slash_less is path_url, or a blank value if path_url is only '/'
+ local path_url_slash_less=${path_url%/}
+ ynh_replace_string --match_string="__PATH__/" --replace_string="$path_url_slash_less/" --target_file="$finalnginxconf"
+ ynh_replace_string --match_string="__PATH__" --replace_string="$path_url" --target_file="$finalnginxconf"
+ fi
+ if test -n "${domain:-}"; then
+ ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$finalnginxconf"
+ fi
+ if test -n "${port:-}"; then
+ ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$finalnginxconf"
+ fi
+ if test -n "${app:-}"; then
+ ynh_replace_string --match_string="__NAME__" --replace_string="$app" --target_file="$finalnginxconf"
+ fi
+ if test -n "${final_path:-}"; then
+ ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalnginxconf"
+ 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="$finalnginxconf"
+ done
+
+ if [ "${path_url:-}" != "/" ]
+ then
+ ynh_replace_string --match_string="^#sub_path_only" --replace_string="" --target_file="$finalnginxconf"
+ else
+ ynh_replace_string --match_string="^#root_path_only" --replace_string="" --target_file="$finalnginxconf"
+ fi
+
+ ynh_store_file_checksum --file="$finalnginxconf"
+
+ ynh_systemd_action --service_name=nginx --action=reload
+}
+
+# Remove the dedicated nginx config
+#
+# usage: ynh_remove_nginx_config
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_remove_nginx_config () {
+ ynh_secure_remove --file="/etc/nginx/conf.d/$domain.d/$app.conf"
+ ynh_systemd_action --service_name=nginx --action=reload
+}
diff --git a/data/helpers.d/nodejs b/data/helpers.d/nodejs
index 098ed4410..9295c4348 100644
--- a/data/helpers.d/nodejs
+++ b/data/helpers.d/nodejs
@@ -10,8 +10,10 @@ export N_PREFIX="$n_install_dir"
# [internal]
#
# usage: ynh_install_n
+#
+# Requires YunoHost version 2.7.12 or higher.
ynh_install_n () {
- echo "Installation of N - Node.js version management" >&2
+ ynh_print_info --message="Installation of N - Node.js version management"
# Build an app.src for n
mkdir -p "../conf"
echo "SOURCE_URL=https://github.com/tj/n/archive/v2.1.7.tar.gz
@@ -36,6 +38,8 @@ SOURCE_SUM=2ba3c9d4dd3c7e38885b37e02337906a1ee91febe6d5c9159d89a9050f2eea8f" > "
# That's means it has to be added to any systemd script.
#
# usage: ynh_use_nodejs
+#
+# Requires YunoHost version 2.7.12 or higher.
ynh_use_nodejs () {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
@@ -59,6 +63,8 @@ ynh_use_nodejs () {
# | arg: -n, --nodejs_version - Version of node 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.
+#
+# Requires YunoHost version 2.7.12 or higher.
ynh_install_nodejs () {
# Use n, https://github.com/tj/n to manage the nodejs versions
@@ -117,7 +123,7 @@ ynh_install_nodejs () {
fi
# Store the ID of this app and the version of node requested for it
- echo "$YNH_APP_ID:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version"
+ echo "$YNH_APP_INSTANCE_NAME:$nodejs_version" | tee --append "$n_install_dir/ynh_app_version"
# Store nodejs_version into the config of this app
ynh_app_setting_set --app=$app --key=nodejs_version --value=$nodejs_version
@@ -135,11 +141,13 @@ ynh_install_nodejs () {
# If no other app uses node, n will be also removed.
#
# usage: ynh_remove_nodejs
+#
+# Requires YunoHost version 2.7.12 or higher.
ynh_remove_nodejs () {
nodejs_version=$(ynh_app_setting_get --app=$app --key=nodejs_version)
# Remove the line for this app
- sed --in-place "/$YNH_APP_ID:$nodejs_version/d" "$n_install_dir/ynh_app_version"
+ sed --in-place "/$YNH_APP_INSTANCE_NAME:$nodejs_version/d" "$n_install_dir/ynh_app_version"
# If no other app uses this version of nodejs, remove it.
if ! grep --quiet "$nodejs_version" "$n_install_dir/ynh_app_version"
@@ -164,6 +172,8 @@ ynh_remove_nodejs () {
# This cron will check and update all minor node versions used by your apps.
#
# usage: ynh_cron_upgrade_node
+#
+# Requires YunoHost version 2.7.12 or higher.
ynh_cron_upgrade_node () {
# Build the update script
cat > "$n_install_dir/node_update.sh" << EOF
diff --git a/data/helpers.d/php b/data/helpers.d/php
new file mode 100644
index 000000000..c9e3ba9ed
--- /dev/null
+++ b/data/helpers.d/php
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+# Create a dedicated php-fpm config
+#
+# usage: ynh_add_fpm_config [--phpversion=7.X]
+# | arg: -v, --phpversion - Version of php to use.
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_add_fpm_config () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=v
+ declare -Ar args_array=( [v]=phpversion= )
+ local phpversion
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ # Configure PHP-FPM 7.0 by default
+ phpversion="${phpversion:-7.0}"
+
+ local fpm_config_dir="/etc/php/$phpversion/fpm"
+ local fpm_service="php${phpversion}-fpm"
+ # Configure PHP-FPM 5 on Debian Jessie
+ if [ "$(ynh_get_debian_release)" == "jessie" ]; then
+ fpm_config_dir="/etc/php5/fpm"
+ fpm_service="php5-fpm"
+ fi
+ ynh_app_setting_set --app=$app --key=fpm_config_dir --value="$fpm_config_dir"
+ ynh_app_setting_set --app=$app --key=fpm_service --value="$fpm_service"
+ finalphpconf="$fpm_config_dir/pool.d/$app.conf"
+ ynh_backup_if_checksum_is_different --file="$finalphpconf"
+ sudo cp ../conf/php-fpm.conf "$finalphpconf"
+ ynh_replace_string --match_string="__NAMETOCHANGE__" --replace_string="$app" --target_file="$finalphpconf"
+ ynh_replace_string --match_string="__FINALPATH__" --replace_string="$final_path" --target_file="$finalphpconf"
+ ynh_replace_string --match_string="__USER__" --replace_string="$app" --target_file="$finalphpconf"
+ ynh_replace_string --match_string="__PHPVERSION__" --replace_string="$phpversion" --target_file="$finalphpconf"
+ sudo chown root: "$finalphpconf"
+ ynh_store_file_checksum --file="$finalphpconf"
+
+ if [ -e "../conf/php-fpm.ini" ]
+ then
+ echo "Packagers ! Please do not use a separate php ini file, merge your directives in the pool file instead." >&2
+ finalphpini="$fpm_config_dir/conf.d/20-$app.ini"
+ ynh_backup_if_checksum_is_different "$finalphpini"
+ sudo cp ../conf/php-fpm.ini "$finalphpini"
+ sudo chown root: "$finalphpini"
+ ynh_store_file_checksum "$finalphpini"
+ fi
+ ynh_systemd_action --service_name=$fpm_service --action=reload
+}
+
+# Remove the dedicated php-fpm config
+#
+# usage: ynh_remove_fpm_config
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_remove_fpm_config () {
+ local fpm_config_dir=$(ynh_app_setting_get --app=$app --key=fpm_config_dir)
+ local fpm_service=$(ynh_app_setting_get --app=$app --key=fpm_service)
+ # Assume php version 7 if not set
+ if [ -z "$fpm_config_dir" ]; then
+ fpm_config_dir="/etc/php/7.0/fpm"
+ fpm_service="php7.0-fpm"
+ fi
+ ynh_secure_remove --file="$fpm_config_dir/pool.d/$app.conf"
+ ynh_secure_remove --file="$fpm_config_dir/conf.d/20-$app.ini" 2>&1
+ ynh_systemd_action --service_name=$fpm_service --action=reload
+}
diff --git a/data/helpers.d/postgresql b/data/helpers.d/postgresql
new file mode 100644
index 000000000..8e3297458
--- /dev/null
+++ b/data/helpers.d/postgresql
@@ -0,0 +1,299 @@
+#!/bin/bash
+
+PSQL_ROOT_PWD_FILE=/etc/yunohost/psql
+
+# 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=user --password=password [--database=database]
+# | arg: -u, --user - the user name to connect as
+# | arg: -p, --password - the user password
+# | arg: -d, --database - the database to connect to
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_connect_as() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=upd
+ declare -Ar args_array=([u]=user= [p]=password= [d]=database=)
+ local user
+ local password
+ local database
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ database="${database:-}"
+
+ sudo --login --user=postgres PGUSER="$user" PGPASSWORD="$password" psql "$database"
+}
+
+# Execute a command as root user
+#
+# usage: ynh_psql_execute_as_root --sql=sql [--database=database]
+# | arg: -s, --sql - the SQL command to execute
+# | arg: -d, --database - the database to connect to
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_execute_as_root() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=sd
+ declare -Ar args_array=([s]=sql= [d]=database=)
+ local sql
+ local database
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ database="${database:-}"
+
+ ynh_psql_connect_as --user="postgres" --password="$(sudo cat $PSQL_ROOT_PWD_FILE)" \
+ --database="$database" <<<"$sql"
+}
+
+# Execute a command from a file as root user
+#
+# usage: ynh_psql_execute_file_as_root --file=file [--database=database]
+# | arg: -f, --file - the file containing SQL commands
+# | arg: -d, --database - the database to connect to
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_execute_file_as_root() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=fd
+ declare -Ar args_array=([f]=file= [d]=database=)
+ local file
+ local database
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ database="${database:-}"
+
+ ynh_psql_connect_as --user="postgres" --password="$(sudo cat $PSQL_ROOT_PWD_FILE)" \
+ --database="$database" <"$file"
+}
+
+# Create a database and grant optionnaly privilegies to a user
+#
+# [internal]
+#
+# usage: ynh_psql_create_db db [user]
+# | arg: db - the database name to create
+# | arg: user - the user to grant privilegies
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_create_db() {
+ local db=$1
+ local user=${2:-}
+
+ local sql="CREATE DATABASE ${db};"
+
+ # grant all privilegies to user
+ if [ -n "$user" ]; then
+ sql+="GRANT ALL PRIVILEGES ON DATABASE ${db} TO ${user} WITH GRANT OPTION;"
+ fi
+
+ ynh_psql_execute_as_root --sql="$sql"
+}
+
+# Drop a database
+#
+# [internal]
+#
+# If you intend to drop the database *and* the associated user,
+# consider using ynh_psql_remove_db instead.
+#
+# usage: ynh_psql_drop_db db
+# | arg: db - the database name to drop
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_drop_db() {
+ local db=$1
+ # First, force disconnection of all clients connected to the database
+ # https://stackoverflow.com/questions/5408156/how-to-drop-a-postgresql-database-if-there-are-active-connections-to-it
+ # https://dba.stackexchange.com/questions/16426/how-to-drop-all-connections-to-a-specific-database-without-stopping-the-server
+ ynh_psql_execute_as_root --sql="SELECT pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$db';" --database="$db"
+ sudo --login --user=postgres dropdb $db
+}
+
+# Dump a database
+#
+# example: ynh_psql_dump_db 'roundcube' > ./dump.sql
+#
+# usage: ynh_psql_dump_db --database=database
+# | arg: -d, --database - the database name to dump
+# | ret: the psqldump output
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_dump_db() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=d
+ declare -Ar args_array=([d]=database=)
+ local database
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ sudo --login --user=postgres pg_dump "$database"
+}
+
+# Create a user
+#
+# [internal]
+#
+# usage: ynh_psql_create_user user pwd
+# | arg: user - the user name to create
+# | arg: pwd - the password to identify user by
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_create_user() {
+ local user=$1
+ local pwd=$2
+ ynh_psql_execute_as_root --sql="CREATE USER $user WITH ENCRYPTED PASSWORD '$pwd'"
+}
+
+# Check if a psql user exists
+#
+# usage: ynh_psql_user_exists --user=user
+# | arg: -u, --user - the user for which to check existence
+ynh_psql_user_exists() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=u
+ declare -Ar args_array=([u]=user=)
+ local user
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(sudo cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT rolname FROM pg_roles WHERE rolname='$user';" | grep --quiet "$user" ; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+# Check if a psql database exists
+#
+# usage: ynh_psql_database_exists --database=database
+# | arg: -d, --database - the database for which to check existence
+ynh_psql_database_exists() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=d
+ declare -Ar args_array=([d]=database=)
+ local database
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ if ! sudo --login --user=postgres PGUSER="postgres" PGPASSWORD="$(sudo cat $PSQL_ROOT_PWD_FILE)" psql -tAc "SELECT datname FROM pg_database WHERE datname='$database';" | grep --quiet "$database"; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+# Drop a user
+#
+# [internal]
+#
+# usage: ynh_psql_drop_user user
+# | arg: user - the user name to drop
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_psql_drop_user() {
+ ynh_psql_execute_as_root --sql="DROP USER ${1};"
+}
+
+# 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 --db_user=user --db_name=name [--db_pwd=pwd]
+# | arg: -u, --db_user - Owner of the database
+# | arg: -n, --db_name - Name of the database
+# | arg: -p, --db_pwd - Password of the database. If not given, a password will be generated
+ynh_psql_setup_db() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=unp
+ declare -Ar args_array=([u]=db_user= [n]=db_name= [p]=db_pwd=)
+ local db_user
+ local db_name
+ db_pwd=""
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ local new_db_pwd=$(ynh_string_random) # Generate a random password
+ # If $db_pwd is not given, use new_db_pwd instead for db_pwd
+ db_pwd="${db_pwd:-$new_db_pwd}"
+
+ if ! ynh_psql_user_exists --user=$db_user; then
+ ynh_psql_create_user "$db_user" "$db_pwd"
+ fi
+
+ ynh_psql_create_db "$db_name" "$db_user" # Create the database
+ ynh_app_setting_set --app=$app --key=psqlpwd --value=$db_pwd # Store the password in the app's config
+}
+
+# Remove a database if it exists, and the associated user
+#
+# usage: ynh_psql_remove_db --db_user=user --db_name=name
+# | arg: -u, --db_user - Owner of the database
+# | arg: -n, --db_name - Name of the database
+ynh_psql_remove_db() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=un
+ declare -Ar args_array=([u]=db_user= [n]=db_name=)
+ local db_user
+ local db_name
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ local psql_root_password=$(sudo cat $PSQL_ROOT_PWD_FILE)
+ if ynh_psql_database_exists --database=$db_name; then # Check if the database exists
+ ynh_print_info --message="Removing database $db_name"
+ ynh_psql_drop_db $db_name # Remove the database
+ else
+ ynh_print_warn --message="Database $db_name not found"
+ fi
+
+ # Remove psql user if it exists
+ if ynh_psql_user_exists --user=$db_user; then
+ ynh_print_info --message="Removing user $db_user"
+ ynh_psql_drop_user $db_user
+ else
+ ynh_print_warn --message="User $db_user not found"
+ fi
+}
+
+# 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 "$PSQL_ROOT_PWD_FILE" ]; then
+ echo "PostgreSQL is already installed, no need to create master password"
+ else
+ local pgsql="$(ynh_string_random)"
+ echo "$pgsql" >/etc/yunohost/psql
+
+ if [ -e /etc/postgresql/9.4/ ]; then
+ local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf
+ local logfile=/var/log/postgresql/postgresql-9.4-main.log
+ elif [ -e /etc/postgresql/9.6/ ]; then
+ local pg_hba=/etc/postgresql/9.6/main/pg_hba.conf
+ local logfile=/var/log/postgresql/postgresql-9.6-main.log
+ else
+ ynh_die "postgresql shoud be 9.4 or 9.6"
+ fi
+
+ ynh_systemd_action --service_name=postgresql --action=start
+
+ 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
+ ynh_replace_string --match_string="local\(\s*\)all\(\s*\)all\(\s*\)peer" --replace_string="local\1all\2all\3password" --target_file="$pg_hba"
+
+ # Advertise service in admin panel
+ yunohost service add postgresql --log "$logfile"
+
+ systemctl enable postgresql
+ ynh_systemd_action --service_name=postgresql --action=reload
+ fi
+}
diff --git a/data/helpers.d/psql b/data/helpers.d/psql
deleted file mode 100644
index 2ef13482a..000000000
--- a/data/helpers.d/psql
+++ /dev/null
@@ -1,148 +0,0 @@
-# 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
- local pgsql="$(ynh_string_random)"
- echo "$pgsql" > /etc/yunohost/psql
-
- if [ -e /etc/postgresql/9.4/ ]
- then
- local pg_hba=/etc/postgresql/9.4/main/pg_hba.conf
- elif [ -e /etc/postgresql/9.6/ ]
- then
- local 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() {
- local user="$1"
- local pwd="$2"
- local 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
-ynh_psql_execute_as_root () {
- local 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() {
- local file="$1"
- local 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 () {
- local db_user="$1"
- local db_name="$2"
- local new_db_pwd=$(ynh_string_random) # Generate a random password
- # If $3 is not given, use new_db_pwd instead for db_pwd.
- local 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() {
- local db="$1"
- local user="$2"
- local 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() {
- local db="$1"
- local 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() {
- local 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() {
- local user="$1"
- local 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() {
- local user="$1"
- sudo --login --user=postgres dropuser "$user"
-}
diff --git a/data/helpers.d/setting b/data/helpers.d/setting
index c9334c60a..9ac7efb23 100644
--- a/data/helpers.d/setting
+++ b/data/helpers.d/setting
@@ -5,6 +5,8 @@
# usage: ynh_app_setting_get --app=app --key=key
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting to get
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_get() {
# Declare an array to define the options of this helper.
local legacy_args=ak
@@ -14,7 +16,7 @@ ynh_app_setting_get() {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- sudo yunohost app setting "$app" "$key" --output-as plain --quiet
+ ynh_app_setting "get" "$app" "$key"
}
# Set an application setting
@@ -23,6 +25,8 @@ ynh_app_setting_get() {
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting name to set
# | arg: -v, --value - the setting value to set
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_set() {
# Declare an array to define the options of this helper.
local legacy_args=akv
@@ -33,7 +37,7 @@ ynh_app_setting_set() {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- sudo yunohost app setting "$app" "$key" --value="$value" --quiet
+ ynh_app_setting "set" "$app" "$key" "$value"
}
# Delete an application setting
@@ -41,6 +45,8 @@ ynh_app_setting_set() {
# usage: ynh_app_setting_delete --app=app --key=key
# | arg: -a, --app - the application id
# | arg: -k, --key - the setting to delete
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_delete() {
# Declare an array to define the options of this helper.
local legacy_args=ak
@@ -50,7 +56,84 @@ ynh_app_setting_delete() {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- sudo yunohost app setting -d "$app" "$key" --quiet
+ ynh_app_setting "delete" "$app" "$key"
+}
+
+# Small "hard-coded" interface to avoid calling "yunohost app" directly each
+# time dealing with a setting is needed (which may be so slow on ARM boards)
+#
+# [internal]
+#
+ynh_app_setting()
+{
+ ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python - < /example
+# ynh_normalize_url_path /example # -> /example
+# ynh_normalize_url_path /example/ # -> /example
+# ynh_normalize_url_path / # -> /
+#
+# usage: ynh_normalize_url_path --path_url=path_to_normalize
+# | arg: -p, --path_url - URL path to normalize before using it
+#
+# Requires YunoHost version 2.6.4 or higher.
+ynh_normalize_url_path () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=p
+ declare -Ar args_array=( [p]=path_url= )
+ local path_url
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ test -n "$path_url" || ynh_die --message="ynh_normalize_url_path expect a URL path as first argument and received nothing."
+ if [ "${path_url:0:1}" != "/" ]; then # If the first character is not a /
+ path_url="/$path_url" # Add / at begin of path variable
+ fi
+ if [ "${path_url:${#path_url}-1}" == "/" ] && [ ${#path_url} -gt 1 ]; then # If the last character is a / and that not the only character.
+ path_url="${path_url:0:${#path_url}-1}" # Delete the last character
+ fi
+ echo $path_url
+}
diff --git a/data/helpers.d/system b/data/helpers.d/system
deleted file mode 100644
index 9a4219e11..000000000
--- a/data/helpers.d/system
+++ /dev/null
@@ -1,161 +0,0 @@
-#!/bin/bash
-
-# Manage a fail of the script
-#
-# [internal]
-#
-# usage:
-# ynh_exit_properly is used only by the helper ynh_abort_if_errors.
-# You should not use it directly.
-# Instead, add to your script:
-# ynh_clean_setup () {
-# instructions...
-# }
-#
-# This function provide a way to clean some residual of installation that not managed by remove script.
-#
-# It prints a warning to inform that the script was failed, and execute the ynh_clean_setup function if used in the app script
-#
-ynh_exit_properly () {
- local exit_code=$?
- if [ "$exit_code" -eq 0 ]; then
- exit 0 # Exit without error if the script ended correctly
- fi
-
- trap '' EXIT # Ignore new exit signals
- set +eu # Do not exit anymore if a command fail or if a variable is empty
-
- echo -e "!!\n $app's script has encountered an error. Its execution was cancelled.\n!!" >&2
-
- if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
- ynh_clean_setup # Call the function to do specific cleaning for the app.
- fi
-
- ynh_die # Exit with error status
-}
-
-# Exits if an error occurs during the execution of the script.
-#
-# usage: ynh_abort_if_errors
-#
-# This configure the rest of the script execution such that, if an error occurs
-# or if an empty variable is used, the execution of the script stops
-# immediately and a call to `ynh_clean_setup` is triggered if it has been
-# defined by your script.
-#
-ynh_abort_if_errors () {
- set -eu # Exit if a command fail, and if a variable is used unset.
- trap ynh_exit_properly EXIT # Capturing exit signals on shell script
-}
-
-# Fetch the Debian release codename
-#
-# usage: ynh_get_debian_release
-# | ret: The Debian release codename (i.e. jessie, stretch, ...)
-ynh_get_debian_release () {
- echo $(lsb_release --codename --short)
-}
-
-# Read the value of a key in a ynh manifest file
-#
-# usage: ynh_read_manifest manifest key
-# | arg: -m, --manifest= - Path of the manifest to read
-# | arg: -k, --key= - Name of the key to find
-ynh_read_manifest () {
- # Declare an array to define the options of this helper.
- declare -Ar args_array=( [m]=manifest= [k]=manifest_key= )
- local manifest
- local manifest_key
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
-
- if [ ! -e "$manifest" ]; then
- # If the manifest isn't found, try the common place for backup and restore script.
- manifest="../settings/manifest.json"
- fi
-
- jq ".$manifest_key" "$manifest" --raw-output
-}
-
-# 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 [-m manifest]
-# | arg: -m, --manifest= - Path of the manifest to read
-ynh_app_upstream_version () {
- declare -Ar args_array=( [m]=manifest= )
- local manifest
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
-
- manifest="${manifest:-../manifest.json}"
- version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="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 [-m manifest]
-# | arg: -m, --manifest= - Path of the manifest to read
-ynh_app_package_version () {
- declare -Ar args_array=( [m]=manifest= )
- local manifest
- # Manage arguments with getopts
- ynh_handle_getopts_args "$@"
-
- manifest="${manifest:-../manifest.json}"
- version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
- echo "${version_key/*~ynh/}"
-}
-
-# Checks the app version to upgrade with the existing app version and returns:
-# - UPGRADE_APP if the upstream app version has changed
-# - UPGRADE_PACKAGE if only the YunoHost package has changed
-#
-## It stops the current script without error if the package is up-to-date
-#
-# This helper should be used to avoid an upgrade of an app, or the upstream part
-# of it, when it's not needed
-#
-# To force an upgrade, even if the package is up to date,
-# you have to set the variable YNH_FORCE_UPGRADE before.
-# example: sudo YNH_FORCE_UPGRADE=1 yunohost app upgrade MyApp
-#
-# usage: ynh_check_app_version_changed
-ynh_check_app_version_changed () {
- local force_upgrade=${YNH_FORCE_UPGRADE:-0}
- local package_check=${PACKAGE_CHECK_EXEC:-0}
-
- # By default, upstream app version has changed
- local return_value="UPGRADE_APP"
-
- local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)
- local current_upstream_version="$(ynh_app_upstream_version --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json")"
- local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version" || echo 1.0)
- local update_upstream_version="$(ynh_app_upstream_version)"
-
- if [ "$current_version" == "$update_version" ] ; then
- # Complete versions are the same
- if [ "$force_upgrade" != "0" ]
- then
- echo "Upgrade forced by YNH_FORCE_UPGRADE." >&2
- unset YNH_FORCE_UPGRADE
- elif [ "$package_check" != "0" ]
- then
- echo "Upgrade forced for package check." >&2
- else
- ynh_die "Up-to-date, nothing to do" 0
- fi
- elif [ "$current_upstream_version" == "$update_upstream_version" ] ; then
- # Upstream versions are the same, only YunoHost package versions differ
- return_value="UPGRADE_PACKAGE"
- fi
- echo $return_value
-}
diff --git a/data/helpers.d/systemd b/data/helpers.d/systemd
new file mode 100644
index 000000000..c4100bf8a
--- /dev/null
+++ b/data/helpers.d/systemd
@@ -0,0 +1,179 @@
+#!/bin/bash
+
+# Create a dedicated systemd config
+#
+# usage: ynh_add_systemd_config [--service=service] [--template=template]
+# | arg: -s, --service - Service name (optionnal, $app by default)
+# | arg: -t, --template - Name of template file (optionnal, this is 'systemd' by default, meaning ./conf/systemd.service will be used as template)
+#
+# This will use the template ../conf/.service
+# to generate a systemd config, by replacing the following keywords
+# with global variables that should be defined before calling
+# this helper :
+#
+# __APP__ by $app
+# __FINALPATH__ by $final_path
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_add_systemd_config () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=st
+ declare -Ar args_array=( [s]=service= [t]=template= )
+ local service
+ local template
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ local service="${service:-$app}"
+ local template="${template:-systemd.service}"
+
+ finalsystemdconf="/etc/systemd/system/$service.service"
+ ynh_backup_if_checksum_is_different --file="$finalsystemdconf"
+ sudo cp ../conf/$template "$finalsystemdconf"
+
+ # 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="$finalsystemdconf"
+ fi
+ if test -n "${app:-}"; then
+ ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$finalsystemdconf"
+ fi
+ ynh_store_file_checksum --file="$finalsystemdconf"
+
+ sudo chown root: "$finalsystemdconf"
+ sudo systemctl enable $service
+ sudo systemctl daemon-reload
+}
+
+# Remove the dedicated systemd config
+#
+# usage: ynh_remove_systemd_config [--service=service]
+# | arg: -s, --service - Service name (optionnal, $app by default)
+#
+# Requires YunoHost version 2.7.2 or higher.
+ynh_remove_systemd_config () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=s
+ declare -Ar args_array=( [s]=service= )
+ local service
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+ local service="${service:-$app}"
+
+ local finalsystemdconf="/etc/systemd/system/$service.service"
+ if [ -e "$finalsystemdconf" ]; then
+ ynh_systemd_action --service_name=$service --action=stop
+ systemctl disable $service
+ ynh_secure_remove --file="$finalsystemdconf"
+ systemctl daemon-reload
+ fi
+}
+
+# Start (or other actions) a service, print a log in case of failure and optionnaly wait until the service is completely started
+#
+# usage: ynh_systemd_action [-n service_name] [-a action] [ [-l "line to match"] [-p log_path] [-t timeout] [-e length] ]
+# | arg: -n, --service_name= - Name of the service to start. Default : $app
+# | arg: -a, --action= - Action to perform with systemctl. Default: start
+# | arg: -l, --line_match= - Line to match - The line to find in the log to attest the service have finished to boot.
+# If not defined it don't wait until the service is completely started.
+# WARNING: When using --line_match, you should always add `ynh_clean_check_starting` into your
+# `ynh_clean_setup` at the beginning of the script. Otherwise, tail will not stop in case of failure
+# of the script. The script will then hang forever.
+# | arg: -p, --log_path= - Log file - Path to the log file. Default : /var/log/$app/$app.log
+# | arg: -t, --timeout= - Timeout - The maximum time to wait before ending the watching. Default : 300 seconds.
+# | arg: -e, --length= - Length of the error log : Default : 20
+ynh_systemd_action() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=nalpte
+ declare -Ar args_array=( [n]=service_name= [a]=action= [l]=line_match= [p]=log_path= [t]=timeout= [e]=length= )
+ local service_name
+ local action
+ local line_match
+ local length
+ local log_path
+ local timeout
+
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ local service_name="${service_name:-$app}"
+ local action=${action:-start}
+ local log_path="${log_path:-/var/log/$service_name/$service_name.log}"
+ local length=${length:-20}
+ local timeout=${timeout:-300}
+
+ # Start to read the log
+ if [[ -n "${line_match:-}" ]]
+ then
+ local templog="$(mktemp)"
+ # Following the starting of the app in its log
+ if [ "$log_path" == "systemd" ] ; then
+ # Read the systemd journal
+ journalctl --unit=$service_name --follow --since=-0 --quiet > "$templog" &
+ # Get the PID of the journalctl command
+ local pid_tail=$!
+ else
+ # Read the specified log file
+ tail -F -n0 "$log_path" > "$templog" 2>&1 &
+ # Get the PID of the tail command
+ local pid_tail=$!
+ fi
+ fi
+
+ ynh_print_info --message="${action^} the service $service_name"
+
+ # Use reload-or-restart instead of reload. So it wouldn't fail if the service isn't running.
+ if [ "$action" == "reload" ]; then
+ action="reload-or-restart"
+ fi
+
+ systemctl $action $service_name \
+ || ( journalctl --no-pager --lines=$length -u $service_name >&2 \
+ ; test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2 \
+ ; false )
+
+ # Start the timeout and try to find line_match
+ if [[ -n "${line_match:-}" ]]
+ then
+ local i=0
+ for i in $(seq 1 $timeout)
+ do
+ # Read the log until the sentence is found, that means the app finished to start. Or run until the timeout
+ if grep --quiet "$line_match" "$templog"
+ then
+ ynh_print_info --message="The service $service_name has correctly started."
+ break
+ fi
+ if [ $i -eq 3 ]; then
+ echo -n "Please wait, the service $service_name is ${action}ing" >&2
+ fi
+ if [ $i -ge 3 ]; then
+ echo -n "." >&2
+ fi
+ sleep 1
+ done
+ if [ $i -ge 3 ]; then
+ echo "" >&2
+ fi
+ if [ $i -eq $timeout ]
+ then
+ ynh_print_warn --message="The service $service_name didn't fully started before the timeout."
+ ynh_print_warn --message="Please find here an extract of the end of the log of the service $service_name:"
+ journalctl --no-pager --lines=$length -u $service_name >&2
+ test -e "$log_path" && echo "--" >&2 && tail --lines=$length "$log_path" >&2
+ fi
+ ynh_clean_check_starting
+ fi
+}
+
+# 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
+}
+
+
diff --git a/data/helpers.d/user b/data/helpers.d/user
index d716bf03b..0c4591dcd 100644
--- a/data/helpers.d/user
+++ b/data/helpers.d/user
@@ -6,6 +6,8 @@
#
# usage: ynh_user_exists --username=username
# | arg: -u, --username - the username to check
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
@@ -25,6 +27,8 @@ ynh_user_exists() {
# | arg: -u, --username - the username to retrieve info from
# | arg: -k, --key - the key to retrieve
# | ret: string - the key's value
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_user_get_info() {
# Declare an array to define the options of this helper.
local legacy_args=uk
@@ -43,6 +47,8 @@ ynh_user_get_info() {
#
# usage: ynh_user_list
# | ret: string - one username per line
+#
+# Requires YunoHost version 2.4.0 or higher.
ynh_user_list() {
sudo yunohost user list --output-as plain --quiet \
| awk '/^##username$/{getline; print}'
@@ -52,6 +58,8 @@ ynh_user_list() {
#
# usage: ynh_system_user_exists --username=username
# | arg: -u, --username - the username to check
+#
+# Requires YunoHost version 2.2.4 or higher.
ynh_system_user_exists() {
# Declare an array to define the options of this helper.
local legacy_args=u
@@ -63,19 +71,35 @@ ynh_system_user_exists() {
getent passwd "$username" &>/dev/null
}
+# Check if a group exists on the system
+#
+# usage: ynh_system_group_exists --group=group
+# | arg: -g, --group - the group to check
+ynh_system_group_exists() {
+ # Declare an array to define the options of this helper.
+ local legacy_args=g
+ declare -Ar args_array=( [g]=group= )
+ local group
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ getent group "$group" &>/dev/null
+}
+
# Create a system user
#
# examples:
-# - ynh_system_user_create --username=nextcloud -> creates a nextcloud user with
-# no home directory and /usr/sbin/nologin login shell (hence no login capability)
-# - ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell --> creates a
-# discourse user using /var/www/discourse as home directory and the default login shell
+# # Create a nextcloud user with no home directory and /usr/sbin/nologin login shell (hence no login capability)
+# ynh_system_user_create --username=nextcloud
+# # Create a discourse user using /var/www/discourse as home directory and the default login shell
+# ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell
#
# usage: ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell]
# | arg: -u, --username - Name of the system user that will be create
# | arg: -h, --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: -s, --use_shell - Create a user using the default login shell if present.
-# If this argument is omitted, the user will be created with /usr/sbin/nologin shell
+# | arg: -s, --use_shell - Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_create () {
# Declare an array to define the options of this helper.
local legacy_args=uhs
@@ -108,6 +132,8 @@ ynh_system_user_create () {
#
# usage: ynh_system_user_delete --username=user_name
# | arg: -u, --username - Name of the system user that will be create
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_system_user_delete () {
# Declare an array to define the options of this helper.
local legacy_args=u
@@ -116,11 +142,19 @@ ynh_system_user_delete () {
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
- if ynh_system_user_exists "$username" # Check if the user exists on the system
+ # Check if the user exists on the system
+ if ynh_system_user_exists "$username"
then
- echo "Remove the user $username" >&2
- sudo userdel $username
+ ynh_print_info --message="Remove the user $username"
+ deluser $username
else
- echo "The user $username was not found" >&2
+ ynh_print_warn --message="The user $username was not found"
+ fi
+
+ # Check if the group exists on the system
+ if ynh_system_group_exists "$username"
+ then
+ ynh_print_info --message="Remove the group $username"
+ delgroup $username
fi
}
diff --git a/data/helpers.d/utils b/data/helpers.d/utils
index 5ba2946a2..1dd83c0e2 100644
--- a/data/helpers.d/utils
+++ b/data/helpers.d/utils
@@ -1,109 +1,53 @@
#!/bin/bash
-# Extract a key from a plain command output
+# Manage a fail of the script
#
-# example: yunohost user info tata --output-as plain | ynh_get_plain_key mail
-#
-# usage: ynh_get_plain_key key [subkey [subsubkey ...]]
-# | ret: string - the key's value
-ynh_get_plain_key() {
- local prefix="#"
- local founded=0
- local key=$1
- shift
- while read line; do
- if [[ "$founded" == "1" ]] ; then
- [[ "$line" =~ ^${prefix}[^#] ]] && return
- echo $line
- elif [[ "$line" =~ ^${prefix}${key}$ ]]; then
- if [[ -n "${1:-}" ]]; then
- prefix+="#"
- key=$1
- shift
- else
- founded=1
- fi
- fi
- done
-}
-
-# Restore a previous backup if the upgrade process failed
+# [internal]
#
# usage:
-# ynh_backup_before_upgrade
+# ynh_exit_properly is used only by the helper ynh_abort_if_errors.
+# You should not use it directly.
+# Instead, add to your script:
# ynh_clean_setup () {
-# ynh_restore_upgradebackup
+# instructions...
# }
-# ynh_abort_if_errors
#
-ynh_restore_upgradebackup () {
- echo "Upgrade failed." >&2
- local app_bck=${app//_/-} # Replace all '_' by '-'
-
- NO_BACKUP_UPGRADE=${NO_BACKUP_UPGRADE:-0}
-
- if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
- then
- # Check if an existing backup can be found before removing and restoring the application.
- if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$backup_number
- then
- # Remove the application then restore it
- sudo yunohost app remove $app
- # Restore the backup
- sudo yunohost backup restore $app_bck-pre-upgrade$backup_number --apps $app --force --debug
- ynh_die --message="The app was restored to the way it was before the failed upgrade."
- fi
- else
- echo "\$NO_BACKUP_UPGRADE is set, that means there's no backup to restore. You have to fix this upgrade by yourself !" >&2
- fi
-}
-
-# Make a backup in case of failed upgrade
+# This function provide a way to clean some residual of installation that not managed by remove script.
#
-# usage:
-# ynh_backup_before_upgrade
-# ynh_clean_setup () {
-# ynh_restore_upgradebackup
-# }
-# ynh_abort_if_errors
+# It prints a warning to inform that the script was failed, and execute the ynh_clean_setup function if used in the app script
#
-ynh_backup_before_upgrade () {
- if [ ! -e "/etc/yunohost/apps/$app/scripts/backup" ]
- then
- echo "This app doesn't have any backup script." >&2
- return
+# Requires YunoHost version 2.6.4 or higher.
+ynh_exit_properly () {
+ local exit_code=$?
+ if [ "$exit_code" -eq 0 ]; then
+ exit 0 # Exit without error if the script ended correctly
fi
- backup_number=1
- local old_backup_number=2
- local app_bck=${app//_/-} # Replace all '_' by '-'
- NO_BACKUP_UPGRADE=${NO_BACKUP_UPGRADE:-0}
- if [ "$NO_BACKUP_UPGRADE" -eq 0 ]
- then
- # Check if a backup already exists with the prefix 1
- if sudo yunohost backup list | grep -q $app_bck-pre-upgrade1
- then
- # Prefix becomes 2 to preserve the previous backup
- backup_number=2
- old_backup_number=1
- fi
+ trap '' EXIT # Ignore new exit signals
+ set +eu # Do not exit anymore if a command fail or if a variable is empty
- # Create backup
- sudo BACKUP_CORE_ONLY=1 yunohost backup create --apps $app --name $app_bck-pre-upgrade$backup_number --debug
- if [ "$?" -eq 0 ]
- then
- # If the backup succeeded, remove the previous backup
- if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$old_backup_number
- then
- # Remove the previous backup only if it exists
- sudo yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null
- fi
- else
- ynh_die --message="Backup failed, the upgrade process was aborted."
- fi
- else
- echo "\$NO_BACKUP_UPGRADE is set, backup will be avoided. Be careful, this upgrade is going to be operated without a security backup"
- fi
+ ynh_print_err --message="!!\n $app's script has encountered an error. Its execution was cancelled.\n!!"
+
+ if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script.
+ ynh_clean_setup # Call the function to do specific cleaning for the app.
+ fi
+
+ ynh_die # Exit with error status
+}
+
+# Exits if an error occurs during the execution of the script.
+#
+# usage: ynh_abort_if_errors
+#
+# This configure the rest of the script execution such that, if an error occurs
+# or if an empty variable is used, the execution of the script stops
+# immediately and a call to `ynh_clean_setup` is triggered if it has been
+# defined by your script.
+#
+# Requires YunoHost version 2.6.4 or higher.
+ynh_abort_if_errors () {
+ set -eu # Exit if a command fail, and if a variable is used unset.
+ trap ynh_exit_properly EXIT # Capturing exit signals on shell script
}
# Download, check integrity, uncompress and patch the source from app.src
@@ -125,7 +69,7 @@ ynh_backup_before_upgrade () {
# SOURCE_IN_SUBDIR=false
# # (Optionnal) Name of the local archive (offline setup support)
# # default: ${src_id}.${src_format}
-# SOURCE_FILENAME=example.tar.gz
+# SOURCE_FILENAME=example.tar.gz
# # (Optional) If it set as false don't extract the source.
# # (Useful to get a debian package or a python wheel.)
# # default: true
@@ -150,6 +94,8 @@ ynh_backup_before_upgrade () {
# usage: ynh_setup_source --dest_dir=dest_dir [--source_id=source_id]
# | arg: -d, --dest_dir - Directory where to setup sources
# | arg: -s, --source_id - Name of the app, if the package contains more than one app
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_setup_source () {
# Declare an array to define the options of this helper.
local legacy_args=ds
@@ -160,15 +106,22 @@ ynh_setup_source () {
ynh_handle_getopts_args "$@"
source_id="${source_id:-app}" # If the argument is not given, source_id equals "app"
+ local src_file_path="$YNH_CWD/../conf/${source_id}.src"
+ # In case of restore script the src file is in an other path.
+ # So try to use the restore path if the general path point to no file.
+ if [ ! -e "$src_file_path" ]; then
+ src_file_path="$YNH_CWD/../settings/conf/${source_id}.src"
+ fi
+
# Load value from configuration file (see above for a small doc about this file
# format)
- local src_url=$(grep 'SOURCE_URL=' "$YNH_CWD/../conf/${source_id}.src" | cut -d= -f2-)
- local src_sum=$(grep 'SOURCE_SUM=' "$YNH_CWD/../conf/${source_id}.src" | cut -d= -f2-)
- local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$YNH_CWD/../conf/${source_id}.src" | cut -d= -f2-)
- local src_format=$(grep 'SOURCE_FORMAT=' "$YNH_CWD/../conf/${source_id}.src" | cut -d= -f2-)
- local src_extract=$(grep 'SOURCE_EXTRACT=' "$YNH_CWD/../conf/${source_id}.src" | cut -d= -f2-)
- local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$YNH_CWD/../conf/${source_id}.src" | cut -d= -f2-)
- local src_filename=$(grep 'SOURCE_FILENAME=' "$YNH_CWD/../conf/${source_id}.src" | cut -d= -f2-)
+ local src_url=$(grep 'SOURCE_URL=' "$src_file_path" | cut -d= -f2-)
+ local src_sum=$(grep 'SOURCE_SUM=' "$src_file_path" | cut -d= -f2-)
+ local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$src_file_path" | cut -d= -f2-)
+ local src_format=$(grep 'SOURCE_FORMAT=' "$src_file_path" | cut -d= -f2-)
+ local src_extract=$(grep 'SOURCE_EXTRACT=' "$src_file_path" | cut -d= -f2-)
+ local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$src_file_path" | cut -d= -f2-)
+ local src_filename=$(grep 'SOURCE_FILENAME=' "$src_file_path" | cut -d= -f2-)
# Default value
src_sumprg=${src_sumprg:-sha256sum}
@@ -199,7 +152,7 @@ ynh_setup_source () {
then
mv $src_filename $dest_dir
elif [ "$src_format" = "zip" ]
- then
+ then
# Zip format
# Using of a temp directory, because unzip doesn't manage --strip-components
if $src_in_subdir ; then
@@ -249,45 +202,47 @@ ynh_setup_source () {
# $domain and $path_url should be defined externally (and correspond to the domain.tld and the /path (of the app?))
#
# example: ynh_local_curl "/install.php?installButton" "foo=$var1" "bar=$var2"
-#
+#
# usage: ynh_local_curl "page_uri" "key1=value1" "key2=value2" ...
# | arg: page_uri - Path (relative to $path_url) of the page where POST data will be sent
# | arg: key1=value1 - (Optionnal) POST key and corresponding value
# | arg: key2=value2 - (Optionnal) Another POST key and corresponding value
# | arg: ... - (Optionnal) More POST keys and values
+#
+# Requires YunoHost version 2.6.4 or higher.
ynh_local_curl () {
- # Define url of page to curl
- local local_page=$(ynh_normalize_url_path $1)
- local full_path=$path_url$local_page
-
- if [ "${path_url}" == "/" ]; then
- full_path=$local_page
- fi
-
- local full_page_url=https://localhost$full_path
+ # Define url of page to curl
+ local local_page=$(ynh_normalize_url_path $1)
+ local full_path=$path_url$local_page
- # Concatenate all other arguments with '&' to prepare POST data
- local POST_data=""
- local arg=""
- for arg in "${@:2}"
- do
- POST_data="${POST_data}${arg}&"
- done
- if [ -n "$POST_data" ]
- then
- # Add --data arg and remove the last character, which is an unecessary '&'
- POST_data="--data ${POST_data::-1}"
- fi
-
- # Wait untils nginx has fully reloaded (avoid curl fail with http2)
- sleep 2
+ if [ "${path_url}" == "/" ]; then
+ full_path=$local_page
+ fi
- # Curl the URL
- curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url"
+ local full_page_url=https://localhost$full_path
+
+ # Concatenate all other arguments with '&' to prepare POST data
+ local POST_data=""
+ local arg=""
+ for arg in "${@:2}"
+ do
+ POST_data="${POST_data}${arg}&"
+ done
+ if [ -n "$POST_data" ]
+ then
+ # Add --data arg and remove the last character, which is an unecessary '&'
+ POST_data="--data ${POST_data::-1}"
+ fi
+
+ # Wait untils nginx has fully reloaded (avoid curl fail with http2)
+ sleep 2
+
+ # Curl the URL
+ curl --silent --show-error -kL -H "Host: $domain" --resolve $domain:443:127.0.0.1 $POST_data "$full_page_url"
}
# Render templates with Jinja2
-#
+#
# Attention : Variables should be exported before calling this helper to be
# accessible inside templates.
#
@@ -303,3 +258,220 @@ ynh_render_template() {
jinja2.Template(sys.stdin.read()
).render(os.environ));' < $template_path > $output_path
}
+
+# Fetch the Debian release codename
+#
+# usage: ynh_get_debian_release
+# | ret: The Debian release codename (i.e. jessie, stretch, ...)
+#
+# Requires YunoHost version 2.7.12 or higher.
+ynh_get_debian_release () {
+ echo $(lsb_release --codename --short)
+}
+
+# Create a directory under /tmp
+#
+# [internal]
+#
+# Deprecated helper
+#
+# usage: ynh_mkdir_tmp
+# | ret: the created directory path
+ynh_mkdir_tmp() {
+ ynh_print_warn --message="The helper ynh_mkdir_tmp is deprecated."
+ ynh_print_warn --message="You should use 'mktemp -d' instead and manage permissions \
+properly with chmod/chown."
+ local TMP_DIR=$(mktemp -d)
+
+ # Give rights to other users could be a security risk.
+ # But for retrocompatibility we need it. (This helpers is deprecated)
+ chmod 755 $TMP_DIR
+ echo $TMP_DIR
+}
+
+# Remove a file or a directory securely
+#
+# usage: ynh_secure_remove --file=path_to_remove
+# | arg: -f, --file - File or directory to remove
+#
+# Requires YunoHost version 2.6.4 or higher.
+ynh_secure_remove () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=f
+ declare -Ar args_array=( [f]=file= )
+ local file
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ local forbidden_path=" \
+ /var/www \
+ /home/yunohost.app"
+
+ if [ $# -ge 2 ]
+ then
+ ynh_print_warn --message="/!\ Packager ! You provided more than one argument to ynh_secure_remove but it will be ignored... Use this helper with one argument at time."
+ fi
+
+ if [[ "$forbidden_path" =~ "$file" \
+ # Match all paths or subpaths in $forbidden_path
+ || "$file" =~ ^/[[:alnum:]]+$ \
+ # Match all first level paths from / (Like /var, /root, etc...)
+ || "${file:${#file}-1}" = "/" ]]
+ # Match if the path finishes by /. Because it seems there is an empty variable
+ then
+ ynh_print_warn --message="Avoid deleting $file."
+ else
+ if [ -e "$file" ]
+ then
+ sudo rm -R "$file"
+ else
+ ynh_print_info --message="$file wasn't deleted because it doesn't exist."
+ fi
+ fi
+}
+
+# Extract a key from a plain command output
+#
+# example: yunohost user info tata --output-as plain | ynh_get_plain_key mail
+#
+# usage: ynh_get_plain_key key [subkey [subsubkey ...]]
+# | ret: string - the key's value
+#
+# Requires YunoHost version 2.2.4 or higher.
+ynh_get_plain_key() {
+ local prefix="#"
+ local founded=0
+ local key=$1
+ shift
+ while read line; do
+ if [[ "$founded" == "1" ]] ; then
+ [[ "$line" =~ ^${prefix}[^#] ]] && return
+ echo $line
+ elif [[ "$line" =~ ^${prefix}${key}$ ]]; then
+ if [[ -n "${1:-}" ]]; then
+ prefix+="#"
+ key=$1
+ shift
+ else
+ founded=1
+ fi
+ fi
+ done
+}
+
+# Read the value of a key in a ynh manifest file
+#
+# usage: ynh_read_manifest manifest key
+# | arg: -m, --manifest= - Path of the manifest to read
+# | arg: -k, --key= - Name of the key to find
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_read_manifest () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=mk
+ declare -Ar args_array=( [m]=manifest= [k]=manifest_key= )
+ local manifest
+ local manifest_key
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ if [ ! -e "$manifest" ]; then
+ # If the manifest isn't found, try the common place for backup and restore script.
+ manifest="../settings/manifest.json"
+ fi
+
+ jq ".$manifest_key" "$manifest" --raw-output
+}
+
+# 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 [-m manifest]
+# | arg: -m, --manifest= - Path of the manifest to read
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_app_upstream_version () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=m
+ declare -Ar args_array=( [m]=manifest= )
+ local manifest
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ manifest="${manifest:-../manifest.json}"
+ version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="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 [-m manifest]
+# | arg: -m, --manifest= - Path of the manifest to read
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_app_package_version () {
+ # Declare an array to define the options of this helper.
+ local legacy_args=m
+ declare -Ar args_array=( [m]=manifest= )
+ local manifest
+ # Manage arguments with getopts
+ ynh_handle_getopts_args "$@"
+
+ manifest="${manifest:-../manifest.json}"
+ version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
+ echo "${version_key/*~ynh/}"
+}
+
+# Checks the app version to upgrade with the existing app version and returns:
+# - UPGRADE_APP if the upstream app version has changed
+# - UPGRADE_PACKAGE if only the YunoHost package has changed
+#
+# It stops the current script without error if the package is up-to-date
+#
+# This helper should be used to avoid an upgrade of an app, or the upstream part
+# of it, when it's not needed
+#
+# To force an upgrade, even if the package is up to date,
+# you have to set the variable YNH_FORCE_UPGRADE before.
+# example: sudo YNH_FORCE_UPGRADE=1 yunohost app upgrade MyApp
+#
+# usage: ynh_check_app_version_changed
+#
+# Requires YunoHost version 3.?.? or higher.
+ynh_check_app_version_changed () {
+ local force_upgrade=${YNH_FORCE_UPGRADE:-0}
+ local package_check=${PACKAGE_CHECK_EXEC:-0}
+
+ # By default, upstream app version has changed
+ local return_value="UPGRADE_APP"
+
+ local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)
+ local current_upstream_version="$(ynh_app_upstream_version --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json")"
+ local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version" || echo 1.0)
+ local update_upstream_version="$(ynh_app_upstream_version)"
+
+ if [ "$current_version" == "$update_version" ] ; then
+ # Complete versions are the same
+ if [ "$force_upgrade" != "0" ]
+ then
+ ynh_print_info --message="Upgrade forced by YNH_FORCE_UPGRADE."
+ unset YNH_FORCE_UPGRADE
+ elif [ "$package_check" != "0" ]
+ then
+ ynh_print_info --message="Upgrade forced for package check."
+ else
+ ynh_die "Up-to-date, nothing to do" 0
+ fi
+ elif [ "$current_upstream_version" == "$update_upstream_version" ] ; then
+ # Upstream versions are the same, only YunoHost package versions differ
+ return_value="UPGRADE_PACKAGE"
+ fi
+ echo $return_value
+}
diff --git a/data/hooks/backup/32-conf_cron b/data/hooks/backup/32-conf_cron
index 063ec1a3f..acbd009ab 100755
--- a/data/hooks/backup/32-conf_cron
+++ b/data/hooks/backup/32-conf_cron
@@ -10,6 +10,6 @@ source /usr/share/yunohost/helpers
backup_dir="${1}/conf/cron"
# Backup the configuration
-for f in $(ls -1B /etc/cron.d/yunohost*); do
+for f in $(ls -1B /etc/cron.d/yunohost* 2> /dev/null); do
ynh_backup "$f" "${backup_dir}/${f##*/}"
done
diff --git a/data/hooks/conf_regen/03-ssh b/data/hooks/conf_regen/03-ssh
index 5bb9cf916..54b7c55b7 100755
--- a/data/hooks/conf_regen/03-ssh
+++ b/data/hooks/conf_regen/03-ssh
@@ -12,7 +12,7 @@ do_pre_regen() {
[[ ! -f /etc/yunohost/from_script ]] || return 0
cd /usr/share/yunohost/templates/ssh
-
+
# do not listen to IPv6 if unavailable
[[ -f /proc/net/if_inet6 ]] && ipv6_enabled=true || ipv6_enabled=false
@@ -23,6 +23,9 @@ do_pre_regen() {
ssh_keys="$ssh_keys $(ls /etc/ssh/ssh_host_dsa_key 2>/dev/null || true)"
fi
+ # Support different strategy for security configurations
+ export compatibility="$(yunohost settings get 'security.ssh.compatibility')"
+
export ssh_keys
export ipv6_enabled
ynh_render_template "sshd_config" "${pending_dir}/etc/ssh/sshd_config"
diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx
index 7ca63c003..59654a771 100755
--- a/data/hooks/conf_regen/15-nginx
+++ b/data/hooks/conf_regen/15-nginx
@@ -10,7 +10,25 @@ do_init_regen() {
exit 1
fi
- do_pre_regen ""
+ cd /usr/share/yunohost/templates/nginx
+
+ nginx_dir="/etc/nginx"
+ nginx_conf_dir="${nginx_dir}/conf.d"
+ mkdir -p "$nginx_conf_dir"
+
+ # install plain conf files
+ cp plain/* "$nginx_conf_dir"
+
+ # probably run with init: just disable default site, restart NGINX and exit
+ rm -f "${nginx_dir}/sites-enabled/default"
+
+ export compatibility="intermediate"
+ ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
+
+ # Restart nginx if conf looks good, otherwise display error and exit unhappy
+ nginx -t 2>/dev/null && service nginx restart || (nginx -t && exit 1)
+
+ exit 0
}
do_pre_regen() {
@@ -22,20 +40,16 @@ do_pre_regen() {
nginx_conf_dir="${nginx_dir}/conf.d"
mkdir -p "$nginx_conf_dir"
- # install plain conf files
+ # install / update plain conf files
cp plain/* "$nginx_conf_dir"
- # probably run with init: just disable default site, restart NGINX and exit
- if [[ -z "$pending_dir" ]]; then
- rm -f "${nginx_dir}/sites-enabled/default"
- service nginx restart
- exit 0
- fi
-
# retrieve variables
main_domain=$(cat /etc/yunohost/current_host)
domain_list=$(sudo yunohost domain list --output-as plain --quiet)
+ # Support different strategy for security configurations
+ export compatibility="$(yunohost settings get 'security.nginx.compatibility')"
+
# add domain conf files
for domain in $domain_list; do
domain_conf_dir="${nginx_conf_dir}/${domain}.d"
@@ -58,6 +72,8 @@ do_pre_regen() {
done
+ ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
+
# remove old domain conf files
conf_files=$(ls -1 /etc/nginx/conf.d \
| awk '/^[^\.]+\.[^\.]+.*\.conf$/ { print $1 }')
diff --git a/data/templates/nginx/plain/global.conf b/data/templates/nginx/plain/global.conf
index ca8721afb..b3a5f356a 100644
--- a/data/templates/nginx/plain/global.conf
+++ b/data/templates/nginx/plain/global.conf
@@ -1,2 +1 @@
server_tokens off;
-gzip_types text/css text/javascript application/javascript;
diff --git a/data/templates/nginx/plain/yunohost_panel.conf.inc b/data/templates/nginx/plain/yunohost_panel.conf.inc
index 34afe136d..1c5a2d656 100644
--- a/data/templates/nginx/plain/yunohost_panel.conf.inc
+++ b/data/templates/nginx/plain/yunohost_panel.conf.inc
@@ -1,8 +1,8 @@
-# Insert YunoHost panel
-sub_filter '';
+# Insert YunoHost button + portal overlay
+sub_filter '';
sub_filter_once on;
# Apply to other mime types than text/html
sub_filter_types application/xhtml+xml;
# Prevent YunoHost panel files from being blocked by specific app rules
-location ~ ynhpanel\.(js|json|css) {
+location ~ (ynh_portal.js|ynh_overlay.css|ynh_userinfo.json) {
}
diff --git a/data/templates/nginx/server.tpl.conf b/data/templates/nginx/server.tpl.conf
index 43d38ca98..4a5e91557 100644
--- a/data/templates/nginx/server.tpl.conf
+++ b/data/templates/nginx/server.tpl.conf
@@ -1,3 +1,8 @@
+map $http_upgrade $connection_upgrade {
+ default upgrade;
+ '' close;
+}
+
server {
listen 80;
listen [::]:80;
@@ -29,6 +34,14 @@ server {
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
+ {% if compatibility == "modern" %}
+ # Ciphers with modern compatibility
+ # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern
+ # The following configuration use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...)
+ ssl_protocols TLSv1.2;
+ ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
+ ssl_prefer_server_ciphers on;
+ {% else %}
# As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_prefer_server_ciphers on;
@@ -38,15 +51,10 @@ server {
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
- # Ciphers with modern compatibility
- # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern
- # Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...)
- #ssl_protocols TLSv1.2;
- #ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
-
# Uncomment the following directive after DH generation
# > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048
#ssl_dhparam /etc/ssl/private/dh2048.pem;
+ {% endif %}
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
@@ -71,6 +79,10 @@ server {
resolver_timeout 5s;
{% endif %}
+ # Disable gzip to protect against BREACH
+ # Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!)
+ gzip off;
+
access_by_lua_file /usr/share/ssowat/access.lua;
include /etc/nginx/conf.d/{{ domain }}.d/*.conf;
diff --git a/data/templates/nginx/plain/yunohost_admin.conf b/data/templates/nginx/yunohost_admin.conf
similarity index 84%
rename from data/templates/nginx/plain/yunohost_admin.conf
rename to data/templates/nginx/yunohost_admin.conf
index 2493e4033..e0d9f6bb1 100644
--- a/data/templates/nginx/plain/yunohost_admin.conf
+++ b/data/templates/nginx/yunohost_admin.conf
@@ -20,6 +20,14 @@ server {
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
+ {% if compatibility == "modern" %}
+ # Ciphers with modern compatibility
+ # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern
+ # Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...)
+ ssl_protocols TLSv1.2;
+ ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
+ ssl_prefer_server_ciphers on;
+ {% else %}
# As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_prefer_server_ciphers on;
@@ -29,20 +37,15 @@ server {
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
- # Ciphers with modern compatibility
- # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern
- # Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...)
- #ssl_protocols TLSv1.2;
- #ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
-
# Uncomment the following directive after DH generation
# > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048
#ssl_dhparam /etc/ssl/private/dh2048.pem;
-
+ {% endif %}
+
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
- # https://observatory.mozilla.org/
- more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
+ # https://observatory.mozilla.org/
+ more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
more_set_headers "Referrer-Policy : 'same-origin'";
more_set_headers "Content-Security-Policy : upgrade-insecure-requests; object-src 'none'; script-src https: 'unsafe-eval'";
more_set_headers "X-Content-Type-Options : nosniff";
@@ -51,6 +54,10 @@ server {
more_set_headers "X-Permitted-Cross-Domain-Policies : none";
more_set_headers "X-Frame-Options : SAMEORIGIN";
+ # Disable gzip to protect against BREACH
+ # Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!)
+ gzip off;
+
location / {
return 302 https://$http_host/yunohost/admin;
}
diff --git a/data/templates/postfix/plain/master.cf b/data/templates/postfix/plain/master.cf
index 2d8712604..377a90971 100644
--- a/data/templates/postfix/plain/master.cf
+++ b/data/templates/postfix/plain/master.cf
@@ -122,6 +122,6 @@ mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}
-# Dovecot LDA
-dovecot unix - n n - - pipe
- flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} -m ${extension}
+# Dovecot LDA
+dovecot unix - n n - - pipe
+ flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} -m ${extension} -a ${recipient}
diff --git a/data/templates/slapd/slapd.default b/data/templates/slapd/slapd.default
index 372b8f4ab..0041b30c5 100644
--- a/data/templates/slapd/slapd.default
+++ b/data/templates/slapd/slapd.default
@@ -21,7 +21,7 @@ SLAPD_PIDFILE=
# sockets.
# Example usage:
# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
-SLAPD_SERVICES="ldap:/// ldapi:///"
+SLAPD_SERVICES="ldap://127.0.0.1:389/ ldap://[::1]:389/ ldapi:///"
# If SLAPD_NO_START is set, the init script will not start or restart
# slapd (but stop will still work). Uncomment this if you are
diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config
index ed870e5dc..8dc0e8dfc 100644
--- a/data/templates/ssh/sshd_config
+++ b/data/templates/ssh/sshd_config
@@ -15,10 +15,17 @@ HostKey {{ key }}{% endfor %}
# https://infosec.mozilla.org/guidelines/openssh
# ##############################################
-# Keys, ciphers and MACS
-KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
-Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
-MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
+{% if compatibility == "intermediate" %}
+ KexAlgorithms diffie-hellman-group-exchange-sha256
+ Ciphers aes256-ctr,aes192-ctr,aes128-ctr
+ MACs hmac-sha2-512,hmac-sha2-256
+{% else %}
+ # By default use "modern" Mozilla configuration
+ # Keys, ciphers and MACS
+ KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
+ Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
+ MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
+{% endif %}
# Use kernel sandbox mechanisms where possible in unprivileged processes
UsePrivilegeSeparation sandbox
diff --git a/data/templates/yunohost/services.yml b/data/templates/yunohost/services.yml
index 62509e1e9..0d79b182f 100644
--- a/data/templates/yunohost/services.yml
+++ b/data/templates/yunohost/services.yml
@@ -20,8 +20,6 @@ mysql:
glances: {}
ssh:
log: /var/log/auth.log
-ssl:
- status: null
metronome:
log: [/var/log/metronome/metronome.log,/var/log/metronome/metronome.err]
slapd:
@@ -34,10 +32,9 @@ yunohost-firewall:
need_lock: true
nslcd:
log: /var/log/syslog
-nsswitch:
- status: null
-yunohost:
- status: null
+nsswitch: null
+ssl: null
+yunohost: null
bind9: null
tahoe-lafs: null
memcached: null
diff --git a/debian/changelog b/debian/changelog
index 7be4212fe..a22959899 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,119 @@
+yunohost (3.5.2.2) stable; urgency=low
+
+ - Hotfix for ynh_psql_remove_db (from ljf)
+
+ -- Alexandre Aubin Thu, 18 Apr 2019 17:32:00 +0000
+
+yunohost (3.5.2.1) stable; urgency=low
+
+ - [fix] Fresh install was broken because of yunohost_admin.conf initialization
+
+ -- Alexandre Aubin Thu, 11 Apr 2019 14:38:00 +0000
+
+yunohost (3.5.2) stable; urgency=low
+
+ - Release as stable !
+ - [doc] Update script to automatically generate helper doc
+ - [i18n] Update translations for Catalan, Arabic, Italian
+
+ Thanks to all contributors: Aleks, xaloc, BoF, silkevicious ! <3
+
+ -- Alexandre Aubin Wed, 10 Apr 2019 01:53:00 +0000
+
+yunohost (3.5.1.1) testing; urgency=low
+
+ - [fix] enabled/disabled status for sysv services
+ - [fix] Nodejs helpers : use YNH_APP_INSTANCE_NAME instead of YNH_APP_ID (#700)
+ - [fix] nginx diagnosis when there's an error throwing a huge useless traceback. Use Popen instead to display the real error
+ - [fix] service_status returns different type of data if you ask for one or multiple services
+
+ -- Alexandre Aubin Wed, 03 Apr 2019 17:28:00 +0000
+
+yunohost (3.5.1) testing; urgency=low
+
+ - [fix] Fix the dbus interface to get info for services (#698)
+ - [mod] Use ask key for display_text instead and support i18n (#697)
+ - [fix] Rework tools update (#695)
+ - [enh] Nginx conf tweaks for theme (#689)
+ - [fix] Fix argument escaping in getopts (#685, #683)
+ - [enh] Support php versions in ynh_add_fpm_config (#674)
+ - [enh] Check that required services are up before running app install and upgrade (#670)
+ - [doc] Add min version for all helpers (#664)
+ - [enh] Add a setting to control compatibility/security tradeoff for nginx and ssh configurations (#640)
+ - [enh] Hooks to allow apps to extend the recommended DNS configuration (#517)
+ - Misc technical fixes / improvements (0bd781b, fad3edf, 1268872, 847ceca, 26e77b7, b6cff68)
+ - [i18n] Update translation for French, Catalan, Esperanto, Occitan
+
+ Thanks to all contributors: Aleks, Bram, Gabriel Corona, Jibec, Josue, Maniack C, Mélanie C., Quentí, Romuald du Song, ljf, ppr, Xaloc ! <3
+
+ -- Alexandre Aubin Wed, 03 Apr 2019 02:13:00 +0000
+
+yunohost (3.5.0.2) testing; urgency=low
+
+ - [fix] Make sure that `ynh_system_user_delete` also deletes the group (#680)
+ - [enh] `ynh_systemd_action` : reload-or-restart instead of just reload (#681)
+
+ Last minute fixes by Maniack ;)
+
+ -- Alexandre Aubin Thu, 14 Mar 2019 03:45:00 +0000
+
+yunohost (3.5.0.1) testing; urgency=low
+
+ - [fix] #675 introduced a bug in nginx conf ...
+
+ -- Alexandre Aubin Wed, 13 Mar 2019 19:23:00 +0000
+
+yunohost (3.5.0) testing; urgency=low
+
+ Core
+ ----
+
+ - [fix] Disable gzip entirely to avoid BREACH attacks (#675)
+ - [fix] Backup tests were broken (#673)
+ - [fix] Backup fails because output directory not empty (#672)
+ - [fix] Reject app password if they contains { or } (#671)
+ - [enh] Allow `display_text` 'fake' argument in manifest.json (#669)
+ - [fix] Optimize dyndns requests (#662)
+ - [enh] Don't add Strict-Transport-Security header in nginx conf if using a selfsigned cert (#661)
+ - [enh] Add apt-transport-https to dependencies (#658)
+ - [enh] Cache results from meltdown vulnerability checker (#656)
+ - [enh] Ensure the tar file is closed during the backup (#655)
+ - [enh] Be able to define hook to trigger when changing a setting (#654)
+ - [enh] Assert dpkg is not broken before app install (#652)
+ - [fix] Loading only one helper file leads to errors because missing getopts (#651)
+ - [enh] Improve / add some messages to improve UX (#650)
+ - [enh] Reload fail2ban instead of restart (#649)
+ - [enh] Add IPv6 resolvers from diyisp.org to resolv.dnsmasq.conf (#639)
+ - [fix] Remove old SMTP port (465) from fail2ban jail.conf (#637)
+ - [enh] Improve protection against indexation from the robots. (#622)
+ - [enh] Allow hooks to return data (#526)
+ - [fix] Do not make version number available from web API to unauthenticated users (#291)
+ - [i18n] Improve Russian and Chinese (Mandarin) translations
+
+ App helpers
+ -----------
+
+ - [enh] Optimize app setting helpers (#663, #676)
+ - [enh] Handle `ynh_install_nodejs` for arm64 / aarch64 (#660)
+ - [enh] Update postgresql helpers (#657)
+ - [enh] Print diff of files when backup by `ynh_backup_if_checksum_is_different` (#648)
+ - [enh] Add app debugger helper (#647)
+ - [fix] Escape double quote before eval in getopts (#646)
+ - [fix] `ynh_local_curl` not using the right url in some cases (#644)
+ - [fix] Get rid of annoying 'unable to initialize frontend' messages (#643)
+ - [enh] Check if dpkg is not broken when calling `ynh_wait_dpkg_free` (#638)
+ - [enh] Warn the packager that `ynh_secure_remove` should be used with only one arg… (#635, #642)
+ - [enh] Add `ynh_script_progression` helper (#634)
+ - [enh] Add `ynh_systemd_action` helper (#633)
+ - [enh] Allow to dig deeper into an archive with `ynh_setup_source` (#630)
+ - [enh] Use getops (#561)
+ - [enh] Add `ynh_check_app_version_changed` helper (#521)
+ - [enh] Add fail2ban helpers (#364)
+
+ Contributors: Alexandre Aubin, Jimmy Monin, Josué Tille, Kayou, Laurent Peuch, Lukas Fülling, Maniack Crudelis, Taekiro, frju365, ljf, opi, yalh76, Алексей
+
+ -- Alexandre Aubin Wed, 13 Mar 2019 16:10:00 +0000
+
yunohost (3.4.2.4) stable; urgency=low
- [fix] Meltdown vulnerability checker something outputing trash instead of pure json
diff --git a/debian/control b/debian/control
index 685c194ba..bb697d074 100644
--- a/debian/control
+++ b/debian/control
@@ -8,6 +8,7 @@ X-Python-Version: >= 2.7
Homepage: https://yunohost.org/
Package: yunohost
+Essential: yes
Architecture: all
Depends: ${python:Depends}, ${misc:Depends}
, moulinette (>= 2.7.1), ssowat (>= 2.7.1)
diff --git a/debian/postinst b/debian/postinst
index df7112b9d..83220ae0b 100644
--- a/debian/postinst
+++ b/debian/postinst
@@ -12,7 +12,7 @@ do_configure() {
bash /usr/share/yunohost/hooks/conf_regen/15-nginx init
else
echo "Regenerating configuration, this might take a while..."
- yunohost service regen-conf --output-as none
+ yunohost tools regen-conf --output-as none
echo "Launching migrations.."
yunohost tools migrations migrate --auto
diff --git a/debian/rules b/debian/rules
index ce03d0e31..d012c73f3 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,6 +7,10 @@
%:
dh ${@} --with=python2,systemd
+override_dh_auto_build:
+ # Generate bash completion file
+ python data/actionsmap/yunohost_completion.py
+
override_dh_installinit:
dh_installinit -pyunohost --name=yunohost-api --restart-after-upgrade
dh_installinit -pyunohost --name=yunohost-firewall --noscripts
diff --git a/doc/generate_helper_doc.py b/doc/generate_helper_doc.py
index 7d8c489b7..5b51dda02 100644
--- a/doc/generate_helper_doc.py
+++ b/doc/generate_helper_doc.py
@@ -4,7 +4,12 @@ import os
import glob
import datetime
-def render(data):
+def render(helpers):
+
+ data = { "helpers": helpers,
+ "date": datetime.datetime.now().strftime("%m/%d/%Y"),
+ "version": open("../debian/changelog").readlines()[0].split()[1].strip("()")
+ }
from jinja2 import Template
from ansi2html import Ansi2HTMLConverter
@@ -43,7 +48,7 @@ class Parser():
"code": [] }
for i, line in enumerate(self.file):
-
+
if line.startswith("#!/bin/bash"):
continue
@@ -103,7 +108,6 @@ class Parser():
b["usage"] = ""
b["args"] = []
b["ret"] = ""
- b["example"] = ""
subblocks = '\n'.join(b["comments"]).split("\n\n")
@@ -114,17 +118,29 @@ class Parser():
b["brief"] = subblock
continue
- elif subblock.startswith("example"):
+ elif subblock.startswith("example:"):
b["example"] = " ".join(subblock.split()[1:])
continue
+ elif subblock.startswith("examples:"):
+ b["examples"] = subblock.split("\n")[1:]
+ continue
+
elif subblock.startswith("usage"):
for line in subblock.split("\n"):
if line.startswith("| arg"):
- argname = line.split()[2]
- argdescr = " ".join(line.split()[4:])
- b["args"].append((argname, argdescr))
+ linesplit = line.split()
+ argname = linesplit[2]
+ # Detect that there's a long argument version (-f, --foo - Some description)
+ if argname.endswith(",") and linesplit[3].startswith("--"):
+ argname = argname.strip(",")
+ arglongname = linesplit[3]
+ argdescr = " ".join(linesplit[5:])
+ b["args"].append((argname, arglongname, argdescr))
+ else:
+ argdescr = " ".join(linesplit[4:])
+ b["args"].append((argname, argdescr))
elif line.startswith("| ret"):
b["ret"] = " ".join(line.split()[2:])
else:
@@ -136,9 +152,17 @@ class Parser():
elif subblock.startswith("| arg"):
for line in subblock.split("\n"):
if line.startswith("| arg"):
- argname = line.split()[2]
- argdescr = line.split()[4:]
- b["args"].append((argname, argdescr))
+ linesplit = line.split()
+ argname = linesplit[2]
+ # Detect that there's a long argument version (-f, --foo - Some description)
+ if argname.endswith(",") and linesplit[3].startswith("--"):
+ argname = argname.strip(",")
+ arglongname = linesplit[3]
+ argdescr = " ".join(linesplit[5:])
+ b["args"].append((argname, arglongname, argdescr))
+ else:
+ argdescr = " ".join(linesplit[4:])
+ b["args"].append((argname, argdescr))
continue
else:
diff --git a/doc/helper_doc_template.html b/doc/helper_doc_template.html
index 1fa1f68ad..92611c737 100644
--- a/doc/helper_doc_template.html
+++ b/doc/helper_doc_template.html
@@ -2,7 +2,7 @@
App helpers
-{% for category, helpers in data %}
+{% for category, helpers in data.helpers %}
{{ category }}
@@ -27,8 +27,12 @@
Arguments:
- {% for name, descr in h.args %}
-
{{ name }} : {{ descr }}
+ {% for infos in h.args %}
+ {% if infos|length == 2 %}
+
{{ infos[0] }} : {{ infos[1] }}
+ {% else %}
+
{{ infos[0] }}, {{ infos[1] }} : {{ infos[2] }}
+ {% endif %}
{% endfor %}
@@ -38,11 +42,25 @@
Returns: {{ h.ret }}
{% endif %}
- {% if h.example %}
+ {% if "example" in h.keys() %}
Example: {{ h.example }}
{% endif %}
+ {% if "examples" in h.keys() %}
+
+ Examples:
+ {% for example in h.examples %}
+ {% if not example.strip().startswith("# ") %}
+ {{ example }}
+ {% else %}
+ {{ example.strip("# ") }}
+ {% endif %}
+
+ {% endfor %}
+