diff --git a/README.md b/README.md index 2254fa9..b54d1ba 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Instant messaging server matrix network. Yunohost chatroom with matrix : [https://riot.im/app/#/room/#yunohost:matrix.org](https://riot.im/app/#/room/#yunohost:matrix.org) -**Shipped version:** 0.34.0.1 +**Shipped version:** 0.99.2 Configuration ------------- @@ -36,7 +36,9 @@ If you want a web client you can also install riot with this package: https://gi ### Access by federation -To be accessible by the federation you need to put the following line in the dns configuration: +If your server name is identical to the domain on which synapse is installed, and the default port 8448 is used, your server is normally already accessible by the federation. + +If not, you may need to put the following line in the dns configuration: ``` _matrix._tcp. IN SRV 10 0 @@ -47,8 +49,12 @@ _matrix._tcp.example.com. 3600 IN SRV 10 0 SYNAPSE_PORT example.com. ``` You need to replace SYNAPSE_PORT by the real port. This port can be obtained by the command: `yunohost app setting SYNAPSE_INSTANCE_NAME synapse_tls_port` +For more details, see : https://github.com/matrix-org/synapse#setting-up-federation + If it is not automatically done, you need to open this in your ISP box. +You also need a valid TLS certificate for the domain used by synapse. To do that you can refer to the documentation here : https://yunohost.org/#/certificate_en + ### Turnserver For Voip and video conferencing a turnserver is also installed (and configured). The turnserver listens on two UDP and TCP ports. You can get them with these commands: diff --git a/actions.json b/actions.json new file mode 100644 index 0000000..a7a05e7 --- /dev/null +++ b/actions.json @@ -0,0 +1,47 @@ +[{ + "id": "update_turnserver_ip", + "name": "Update turnserver ip", + "command": "/opt/yunohost/matrix-$YNH_APP_INSTANCE_NAME/Coturn_config_rotate.sh", + "user": "root", + "accepted_return_codes": [0], + "description": { + "en": "Update the ip in the turnserver config" + } +},{ + "id": "open_turnserver_firewall_ports", + "name": "Open ports for turnserver", + "command": "yunohost firewall allow Both 49153:49193", + "user": "root", + "accepted_return_codes": [0], + "description": { + "en": "Open the ports range 49153:49193 with TCP and UDP to be able to use correctly the turnserver." + } +},{ + "id": "close_turnserver_firewall_ports", + "name": "Close ports for turnserver", + "command": "yunohost firewall disallow Both 49153:49193", + "user": "root", + "accepted_return_codes": [0], + "description": { + "en": "Close the ports range 49153:49193 with TCP and UDP. (Undo \"Open ports for turnserver\" action)" + } +},{ + "id": "set_admin_user", + "name": "Set a user as admin", + "command": "[[ \"$(su --command=\"psql matrix_synapse\" postgres <<< \"UPDATE users SET admin = 1 WHERE name = '@$YNH_ACTION_USERNAME:$(yunohost app setting $YNH_APP_INSTANCE_NAME special_domain)'\")\" == 'UPDATE 1' ]]", + "user": "root", + "accepted_return_codes": [0], + "description": { + "en": "Set a synapse user as admin in the synapse server. It probably usefull only to manage the community function." + }, + "arguments": [ + { + "name": "username", + "type": "string", + "ask": { + "en": "username of the user to set as admin" + }, + "example": "bob" + } + ] +}] diff --git a/check_process b/check_process index 8963b91..455b786 100644 --- a/check_process +++ b/check_process @@ -12,6 +12,7 @@ setup_public=1 upgrade=1 upgrade=1 from_commit=db374d2bff981d2660ebdac52ee77c684383c00d + upgrade=1 from_commit=ca5bc8dba9f7594bf985c69543f0c10a093fc097 backup_restore=1 multi_instance=1 incorrect_path=0 @@ -32,3 +33,5 @@ ;;; Upgrade options ; commit=db374d2bff981d2660ebdac52ee77c684383c00d name=Fix postgresql helper from old_version_for_CI_2 branch + ; commit=ca5bc8dba9f7594bf985c69543f0c10a093fc097 + name=Migrate from self signed certificate to cert managed by Yunohost diff --git a/conf/armv7_jessie.src b/conf/armv7_jessie.src index 62bc395..8638170 100644 --- a/conf/armv7_jessie.src +++ b/conf/armv7_jessie.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/YunoHost-Apps/synapse_python_build/releases/download/v0.34.0.1/matrix-synapse_0.34.0.1-jessie-bin1_armv7l.tar.gz -SOURCE_SUM=211fc5b8d1534f56b40d462ce745a5011a262663c64cd9ce46427d1702069f3b +SOURCE_URL=https://github.com/YunoHost-Apps/synapse_python_build/releases/download/v0.99.2/matrix-synapse_0.99.2-jessie-bin1_armv7l.tar.gz +SOURCE_SUM=dd8252d1a6484e21378262e93410155eadf54e31a56426cf2ff587ac773365ef # (Optional) Program to check the integrity (sha256sum, md5sum...) # default: sha256 SOURCE_SUM_PRG=sha256sum diff --git a/conf/armv7_stretch.src b/conf/armv7_stretch.src index 133b504..12b4e32 100644 --- a/conf/armv7_stretch.src +++ b/conf/armv7_stretch.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://github.com/YunoHost-Apps/synapse_python_build/releases/download/v0.34.0.1/matrix-synapse_0.34.0.1-stretch-bin1_armv7l.tar.gz -SOURCE_SUM=88c44e8f6a224bb58db6fb043dad686a711c614a949464ad628bec88863750a1 +SOURCE_URL=https://github.com/YunoHost-Apps/synapse_python_build/releases/download/v0.99.2/matrix-synapse_0.99.2-stretch-bin1_armv7l.tar.gz +SOURCE_SUM=28226b32d1e82e281835e4c47fd745b0901c67cf3a87db9ff7982fa0e1591cf4 # (Optional) Program to check the integrity (sha256sum, md5sum...) # default: sha256 SOURCE_SUM_PRG=sha256sum diff --git a/conf/f2b_filter.conf b/conf/f2b_filter.conf new file mode 100644 index 0000000..c3205ab --- /dev/null +++ b/conf/f2b_filter.conf @@ -0,0 +1,14 @@ +[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: \{('type': 'm.id.user'(, )?|'user'\: '(.+?)'(, )?){2}\}, medium\: None, address: None, user\: '\7'%(__synapse_start_line)s WARNING \- \- (Attempted to login as @\7\:.+ but they do not exist|Failed password login for user @\7\:.+)$ +ignoreregex = + +[Init] + +maxlines = 20 diff --git a/conf/f2b_jail.conf b/conf/f2b_jail.conf new file mode 100644 index 0000000..3680686 --- /dev/null +++ b/conf/f2b_jail.conf @@ -0,0 +1,6 @@ +[__APP__] +enabled = true +port = http,https +filter = __APP__ +logpath = /var/log/matrix-__APP__/homeserver.log +maxretry = 3 diff --git a/conf/homeserver.yaml b/conf/homeserver.yaml index 3d1c66a..c866bf7 100644 --- a/conf/homeserver.yaml +++ b/conf/homeserver.yaml @@ -4,13 +4,13 @@ # autogenerates on launch with your own SSL certificate + key pair # if you like. Any required intermediary certificates can be # appended after the primary certificate in hierarchical order. -tls_certificate_path: "/etc/matrix-__APP__/__DOMAIN__.tls.crt" +tls_certificate_path: "/etc/yunohost/certs/__DOMAIN__/crt.pem" # PEM encoded private key for TLS -tls_private_key_path: "/etc/matrix-__APP__/__DOMAIN__.tls.key" +tls_private_key_path: "/etc/yunohost/certs/__DOMAIN__/key.pem" # PEM dh parameters for ephemeral keys -tls_dh_params_path: "/etc/matrix-__APP__/__DOMAIN__.tls.dh" +tls_dh_params_path: "/etc/ssl/private/dh2048.pem" # Don't bind to the https port no_tls: False diff --git a/conf/python_source.src b/conf/python_source.src deleted file mode 100644 index 46373b9..0000000 --- a/conf/python_source.src +++ /dev/null @@ -1,5 +0,0 @@ -SOURCE_URL=https://github.com/matrix-org/synapse/archive/v0.34.0.1.tar.gz -SOURCE_SUM=69cc92ac9b3fd5097c2fa4da9c99e481bb18c9e861d5917b2acd70a0dbade0ef -SOURCE_FORMAT=tar.gz -SOURCE_FILENAME=synapse_source.tar.gz -SOURCE_EXTRACT=false diff --git a/config_panel.json b/config_panel.json new file mode 100644 index 0000000..0b02983 --- /dev/null +++ b/config_panel.json @@ -0,0 +1,39 @@ +{ + "name": "Synapse configuration panel", + "version": "0.1", + "panel": [{ + "name": "Synapse config", + "id": "synapse_config", + "sections": [{ + "name": "Synapse server configuration", + "id": "server_config", + "options": [{ + "name": "Server statistics", + "id": "server_statistics", + "type": "bool", + "help": "True to send anonymous statistics about synapse to improve the performances", + "default": false + },{ + "name": "Server public", + "id": "is_public", + "type": "bool", + "help": "Is it a public server", + "default": false + }] + }] + },{ + "name": "Package config", + "id": "package_config", + "sections": [{ + "name": "Synapse server configuration", + "id": "package_config", + "options": [{ + "name": "Backup before upgrade", + "id": "backup_before_upgrade", + "type": "bool", + "help": "True to do a backup before every upgrade", + "default": true + }] + }] + }] +} diff --git a/manifest.json b/manifest.json index 2726f24..9ba3cb1 100644 --- a/manifest.json +++ b/manifest.json @@ -9,7 +9,7 @@ "en": "Instant messaging server who use matrix", "fr": "Un serveur de messagerie instantané basé sur matrix" }, - "version": "0.34.0.1~ynh1", + "version": "0.99.2~ynh1", "url": "http://matrix.org", "license": "Apache-2.0", "maintainer": { diff --git a/scripts/backup b/scripts/backup index d817ae5..15161d4 100644 --- a/scripts/backup +++ b/scripts/backup @@ -78,4 +78,11 @@ ynh_psql_dump_db "$synapse_db_name" > ${YNH_CWD}/dump.sql # BACKUP SYNAPSE LOG #================================================= -ynh_backup "/var/log/matrix-$app" \ No newline at end of file +ynh_backup "/var/log/matrix-$app" + +#================================================= +# BACKUP FAIL2BAN CONFIG +#================================================= + +ynh_backup "/etc/fail2ban/jail.d/$app.conf" +ynh_backup "/etc/fail2ban/filter.d/$app.conf" diff --git a/scripts/config b/scripts/config new file mode 100644 index 0000000..ea60910 --- /dev/null +++ b/scripts/config @@ -0,0 +1,130 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source /usr/share/yunohost/helpers + +# Stop script if errors +ynh_abort_if_errors + +# Import common fonctions +source ./psql.sh +source ./experimental_helper.sh +source ./_common.sh + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# SHOW_CONFIG FUNCTION FOR 'SHOW' COMMAND +#================================================= + +show_config() { + # here you are supposed to read some config file/database/other then print the values + # echo "YNH_CONFIG_${PANEL_ID}_${SECTION_ID}_${OPTION_ID}=value" + echo "YNH_CONFIG_SYNAPSE_CONFIG_SERVER_CONFIG_SERVER_STATISTICS=$(ynh_app_setting_get $app report_stats)" + + backup_before_upgrade=$(ynh_app_setting_get $app disable_backup_before_upgrade) + if [[ ${backup_before_upgrade:-0} -eq 1 ]] + then + echo "YNH_CONFIG_PACKAGE_CONFIG_PACKAGE_CONFIG_BACKUP_BEFORE_UPGRADE=False" + else + echo "YNH_CONFIG_PACKAGE_CONFIG_PACKAGE_CONFIG_BACKUP_BEFORE_UPGRADE=True" + fi + is_public=$(ynh_app_setting_get $app is_public) + if [[ ${is_public} -eq 1 ]] + then + echo "YNH_CONFIG_SYNAPSE_CONFIG_SERVER_CONFIG_IS_PUBLIC=False" + else + echo "YNH_CONFIG_SYNAPSE_CONFIG_SERVER_CONFIG_IS_PUBLIC=True" + fi +} + +#================================================= +# MODIFY THE CONFIGURATION +#================================================= + +apply_config() { + ynh_app_setting_set $app report_stats $YNH_CONFIG_SYNAPSE_CONFIG_SERVER_CONFIG_SERVER_STATISTICS + + if ${YNH_CONFIG_PACKAGE_CONFIG_PACKAGE_CONFIG_BACKUP_BEFORE_UPGRADE,,} + then + ynh_app_setting_set $app disable_backup_before_upgrade 0 + else + ynh_app_setting_set $app disable_backup_before_upgrade 1 + fi + + if ${YNH_CONFIG_SYNAPSE_CONFIG_SERVER_CONFIG_IS_PUBLIC,,} + then + ynh_app_setting_set $app is_public 1 + else + ynh_app_setting_set $app is_public 0 + fi + + domain=$(ynh_app_setting_get $app special_domain) + synapse_db_pwd=$(ynh_app_setting_get $app synapse_db_pwd) + is_public=$(ynh_app_setting_get $app is_public) + port=$(ynh_app_setting_get $app synapse_port) + synapse_tls_port=$(ynh_app_setting_get $app synapse_tls_port) + turnserver_tls_port=$(ynh_app_setting_get $app turnserver_tls_port) + turnserver_pwd=$(ynh_app_setting_get $app turnserver_pwd) + registration_shared_secret=$(ynh_app_setting_get $app registration_shared_secret) + form_secret=$(ynh_app_setting_get $app form_secret) + report_stats=$(ynh_app_setting_get $app report_stats) + synapse_user="matrix-$app" + synapse_db_name="matrix_$app" + synapse_db_user="matrix_$app" + + # Configure Synapse + + # WARNING : theses command are used in INSTALL, UPGRADE, CONFIG (3 times) + # For any update do it in all files + + homeserver_config_path="/etc/matrix-$app/homeserver.yaml" + + ynh_backup_if_checksum_is_different "$homeserver_config_path" + + cp ../conf/homeserver.yaml "$homeserver_config_path" + cp ../conf/log.yaml /etc/matrix-$app/log.yaml + + ynh_replace_string __APP__ $app "$homeserver_config_path" + ynh_replace_string __DOMAIN__ $domain "$homeserver_config_path" + ynh_replace_string __SYNAPSE_DB_USER__ $synapse_db_user "$homeserver_config_path" + ynh_replace_string __SYNAPSE_DB_PWD__ $synapse_db_pwd "$homeserver_config_path" + ynh_replace_string __PORT__ $port "$homeserver_config_path" + ynh_replace_string __TLS_PORT__ $synapse_tls_port "$homeserver_config_path" + ynh_replace_string __TURNSERVER_TLS_PORT__ $turnserver_tls_port "$homeserver_config_path" + ynh_replace_string __TURNPWD__ $turnserver_pwd "$homeserver_config_path" + ynh_replace_string __REGISTRATION_SECRET__ "$registration_shared_secret" "$homeserver_config_path" + ynh_replace_string __FORM_SECRET__ "$form_secret" "$homeserver_config_path" + ynh_replace_string __REPORT_STATS__ "$report_stats" "$homeserver_config_path" + + if [ "$is_public" = "0" ] + then + ynh_replace_string __ALLOWED_ACCESS__ False "$homeserver_config_path" + else + ynh_replace_string __ALLOWED_ACCESS__ True "$homeserver_config_path" + fi + + ynh_store_file_checksum "$homeserver_config_path" + setfacl -R -m user:turnserver:rX /etc/matrix-$app + + systemctl restart matrix-$app +} + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SELECT THE ACTION FOLLOWING THE GIVEN ARGUMENT +#================================================= +case $1 in + show) show_config;; + apply) apply_config;; +esac diff --git a/scripts/experimental_helper.sh b/scripts/experimental_helper.sh index 660007b..aafe0fc 100644 --- a/scripts/experimental_helper.sh +++ b/scripts/experimental_helper.sh @@ -145,3 +145,358 @@ $(yunohost tools diagnosis | grep -B 100 "services:" | sed '/services:/d')" # Send the email to the recipients echo "$mail_message" | $mail_bin -a "Content-Type: text/plain; charset=UTF-8" -s "$mail_subject" "$recipients" } + +# Internal helper design to allow helpers to use getopts to manage their arguments +# +# [internal] +# +# example: function my_helper() +# { +# declare -Ar args_array=( [a]=arg1= [b]=arg2= [c]=arg3 ) +# local arg1 +# local arg2 +# local arg3 +# ynh_handle_getopts_args "$@" +# +# [...] +# } +# my_helper --arg1 "val1" -b val2 -c +# +# usage: ynh_handle_getopts_args "$@" +# | arg: $@ - Simply "$@" to tranfert all the positionnal arguments to the function +# +# This helper need an array, named "args_array" with all the arguments used by the helper +# that want to use ynh_handle_getopts_args +# Be carreful, this array has to be an associative array, as the following example: +# declare -Ar args_array=( [a]=arg1 [b]=arg2= [c]=arg3 ) +# Let's explain this array: +# a, b and c are short options, -a, -b and -c +# arg1, arg2 and arg3 are the long options associated to the previous short ones. --arg1, --arg2 and --arg3 +# For each option, a short and long version has to be defined. +# Let's see something more significant +# declare -Ar args_array=( [u]=user [f]=finalpath= [d]=database ) +# +# NB: Because we're using 'declare' without -g, the array will be declared as a local variable. +# +# Please keep in mind that the long option will be used as a variable to store the values for this option. +# For the previous example, that means that $finalpath will be fill with the value given as argument for this option. +# +# Also, in the previous example, finalpath has a '=' at the end. That means this option need a value. +# So, the helper has to be call with --finalpath /final/path, --finalpath=/final/path or -f /final/path, the variable $finalpath will get the value /final/path +# If there's many values for an option, -f /final /path, the value will be separated by a ';' $finalpath=/final;/path +# For an option without value, like --user in the example, the helper can be called only with --user or -u. $user will then get the value 1. +# +# To keep a retrocompatibility, a package can still call a helper, using getopts, with positional arguments. +# The "legacy mode" will manage the positional arguments and fill the variable in the same order than they are given in $args_array. +# e.g. for `my_helper "val1" val2`, arg1 will be filled with val1, and arg2 with val2. +ynh_handle_getopts_args () { + # Manage arguments only if there's some provided + set +x + if [ $# -ne 0 ] + then + # Store arguments in an array to keep each argument separated + local arguments=("$@") + + # For each option in the array, reduce to short options for getopts (e.g. for [u]=user, --user will be -u) + # And built parameters string for getopts + # ${!args_array[@]} is the list of all option_flags in the array (An option_flag is 'u' in [u]=user, user is a value) + local getopts_parameters="" + local option_flag="" + for option_flag in "${!args_array[@]}" + do + # Concatenate each option_flags of the array to build the string of arguments for getopts + # Will looks like 'abcd' for -a -b -c -d + # If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob) + # Check the last character of the value associate to the option_flag + if [ "${args_array[$option_flag]: -1}" = "=" ] + then + # For an option with additionnal values, add a ':' after the letter for getopts. + getopts_parameters="${getopts_parameters}${option_flag}:" + else + getopts_parameters="${getopts_parameters}${option_flag}" + fi + # Check each argument given to the function + local arg="" + # ${#arguments[@]} is the size of the array + for arg in `seq 0 $(( ${#arguments[@]} - 1 ))` + do + # And replace long option (value of the option_flag) by the short option, the option_flag itself + # (e.g. for [u]=user, --user will be -u) + # Replace long option with = + arguments[arg]="${arguments[arg]//--${args_array[$option_flag]}/-${option_flag} }" + # And long option without = + arguments[arg]="${arguments[arg]//--${args_array[$option_flag]%=}/-${option_flag}}" + done + done + + # Read and parse all the arguments + # Use a function here, to use standart arguments $@ and be able to use shift. + parse_arg () { + # Read all arguments, until no arguments are left + while [ $# -ne 0 ] + do + # Initialize the index of getopts + OPTIND=1 + # Parse with getopts only if the argument begin by -, that means the argument is an option + # getopts will fill $parameter with the letter of the option it has read. + local parameter="" + getopts ":$getopts_parameters" parameter || true + + if [ "$parameter" = "?" ] + then + ynh_die --message="Invalid argument: -${OPTARG:-}" + elif [ "$parameter" = ":" ] + then + ynh_die --message="-$OPTARG parameter requires an argument." + else + local shift_value=1 + # Use the long option, corresponding to the short option read by getopts, as a variable + # (e.g. for [u]=user, 'user' will be used as a variable) + # Also, remove '=' at the end of the long option + # The variable name will be stored in 'option_var' + local option_var="${args_array[$parameter]%=}" + # If this option doesn't take values + # if there's a '=' at the end of the long option name, this option takes values + if [ "${args_array[$parameter]: -1}" != "=" ] + then + # 'eval ${option_var}' will use the content of 'option_var' + eval ${option_var}=1 + else + # Read all other arguments to find multiple value for this option. + # Load args in a array + local all_args=("$@") + + # If the first argument is longer than 2 characters, + # There's a value attached to the option, in the same array cell + if [ ${#all_args[0]} -gt 2 ]; then + # Remove the option and the space, so keep only the value itself. + all_args[0]="${all_args[0]#-${parameter} }" + # Reduce the value of shift, because the option has been removed manually + shift_value=$(( shift_value - 1 )) + fi + + # Declare the content of option_var as a variable. + eval ${option_var}="" + # Then read the array value per value + local i + for i in `seq 0 $(( ${#all_args[@]} - 1 ))` + do + # If this argument is an option, end here. + if [ "${all_args[$i]:0:1}" == "-" ] + then + # Ignore the first value of the array, which is the option itself + if [ "$i" -ne 0 ]; then + break + fi + else + # Else, add this value to this option + # Each value will be separated by ';' + if [ -n "${!option_var}" ] + then + # If there's already another value for this option, add a ; before adding the new value + eval ${option_var}+="\;" + fi + # Escape double quote to prevent any interpretation during the eval + all_args[$i]="${all_args[$i]//\"/\\\"}" + + eval ${option_var}+=\"${all_args[$i]}\" + shift_value=$(( shift_value + 1 )) + fi + done + fi + fi + + # Shift the parameter and its argument(s) + shift $shift_value + done + } + + # LEGACY MODE + # Check if there's getopts arguments + if [ "${arguments[0]:0:1}" != "-" ] + then + # If not, enter in legacy mode and manage the arguments as positionnal ones.. + # Dot not echo, to prevent to go through a helper output. But print only in the log. + set -x; echo "! Helper used in legacy mode !" > /dev/null; set +x + local i + for i in `seq 0 $(( ${#arguments[@]} -1 ))` + do + # Try to use legacy_args as a list of option_flag of the array args_array + # Otherwise, fallback to getopts_parameters to get the option_flag. But an associative arrays isn't always sorted in the correct order... + # Remove all ':' in getopts_parameters + getopts_parameters=${legacy_args:-${getopts_parameters//:}} + # Get the option_flag from getopts_parameters, by using the option_flag according to the position of the argument. + option_flag=${getopts_parameters:$i:1} + if [ -z "$option_flag" ]; then + ynh_print_warn --message="Too many arguments ! \"${arguments[$i]}\" will be ignored." + continue + fi + # Use the long option, corresponding to the option_flag, as a variable + # (e.g. for [u]=user, 'user' will be used as a variable) + # Also, remove '=' at the end of the long option + # The variable name will be stored in 'option_var' + local option_var="${args_array[$option_flag]%=}" + + # Escape double quote to prevent any interpretation during the eval + arguments[$i]="${arguments[$i]//\"/\\\"}" + + # Store each value given as argument in the corresponding variable + # The values will be stored in the same order than $args_array + eval ${option_var}+=\"${arguments[$i]}\" + done + unset legacy_args + else + # END LEGACY MODE + # Call parse_arg and pass the modified list of args as an array of arguments. + parse_arg "${arguments[@]}" + fi + fi + set -x +} + +# 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 < /dev/null + chown root:ssl-cert /etc/ssl/private/dh2048.pem + chmod 640 /etc/ssl/private/dh2048.pem +fi + #================================================= # INSTALL DEPENDENCIES #================================================= @@ -148,34 +163,29 @@ else pip3 install --upgrade pip pip3 install --upgrade setuptools wheel pip3 install --upgrade cffi ndg-httpsclient psycopg2 lxml - - ynh_setup_source "/tmp" "python_source" - pip3 install --upgrade "/tmp/synapse_source.tar.gz" + pip3 install --upgrade matrix-synapse==$upstream_version matrix-synapse-ldap3 # This function was defined when we called "source $final_path/bin/activate". With this function we undo what "$final_path/bin/activate" does deactivate fi #================================================= -# CREATE SYNAPSE KEYS +# CREATE SYNAPSE CONFIG #================================================= # Go in virtualenvironnement PS1=${PS1:-} source $final_path/bin/activate -# Get the dh.pem if exist -test -e /etc/matrix-$app/dh.pem && mv /etc/matrix-$app/dh.pem $domain.tls.dh - -# Generate config and keys +# Generate config python -m synapse.app.homeserver --keys-directory /etc/matrix-$app/ --generate-config --generate-keys --server-name $domain --report-stats=no -c homeserver.yml # This function was defined when we called "source $final_path/bin/activate". With this function we undo what "$final_path/bin/activate" does deactivate # Get random values from config -registration_shared_secret=$(egrep "registration_shared_secret" homeserver.yml | cut -d'"' -f2) -form_secret=$(egrep "form_secret" homeserver.yml | cut -d'"' -f2) +registration_shared_secret=$(egrep "^registration_shared_secret" homeserver.yml | cut -d'"' -f2) +form_secret=$(egrep "^form_secret" homeserver.yml | cut -d'"' -f2) # store in yunohost settings ynh_app_setting_set $app registration_shared_secret "$registration_shared_secret" @@ -208,7 +218,7 @@ ynh_app_setting_set $app turnserver_pwd $turnserver_pwd # Configure Synapse -# WARNING : theses command are used in INSTALL, UPGRADE (2 times) +# WARNING : theses command are used in INSTALL, UPGRADE, CONFIG (3 times) # For any update do it in all files homeserver_config_path="/etc/matrix-$app/homeserver.yaml" @@ -223,8 +233,8 @@ ynh_replace_string __SYNAPSE_DB_PWD__ $synapse_db_pwd "$homeserver_config_path" ynh_replace_string __PORT__ $port "$homeserver_config_path" ynh_replace_string __TLS_PORT__ $synapse_tls_port "$homeserver_config_path" ynh_replace_string __TURNSERVER_TLS_PORT__ $turnserver_tls_port "$homeserver_config_path" -ynh_replace_string __TURNPWD__ $turnserver_pwd "$homeserver_config_path" -ynh_replace_string __REGISTRATION_SECRET__ "$registration_shared_secret" "$homeserver_config_path" +ynh_replace_special_string __TURNPWD__ $turnserver_pwd "$homeserver_config_path" +ynh_replace_special_string __REGISTRATION_SECRET__ "$registration_shared_secret" "$homeserver_config_path" ynh_replace_string __FORM_SECRET__ "$form_secret" "$homeserver_config_path" ynh_replace_string __REPORT_STATS__ "$report_stats" "$homeserver_config_path" @@ -319,7 +329,7 @@ chown $synapse_user:root -R /var/lib/matrix-$app chown $synapse_user:root -R /var/log/matrix-$app chown $synapse_user:root -R /etc/matrix-$app chmod u=rwX,g=rX,o= -R /etc/matrix-$app -chmod 600 /etc/matrix-$app/{$domain.signing.key,$domain.tls.crt,$domain.tls.dh,$domain.tls.key} +chmod 600 /etc/matrix-$app/$domain.signing.key setfacl -R -m user:turnserver:rX /etc/matrix-$app setfacl -R -m user:turnserver:rwX /var/log/matrix-$app @@ -335,7 +345,16 @@ yunohost service add coturn-$app #================================================= systemctl restart coturn-$app.service -ynh_check_starting "Synapse now listening on port $synapse_tls_port" "/var/log/matrix-$app/homeserver.log" 300 "matrix-$app" +ynh_check_starting "Synapse now listening on TCP port $synapse_tls_port" "/var/log/matrix-$app/homeserver.log" 300 "matrix-$app" + +#================================================= +# SETUP FAIL2BAN +#================================================= + +# WARNING : theses command are used in INSTALL, UPGRADE +# For any update do it in all files + +ynh_add_fail2ban_config -t #================================================= # SEND A README FOR THE ADMIN @@ -344,14 +363,20 @@ ynh_check_starting "Synapse now listening on port $synapse_tls_port" "/var/log/m # WARNING : theses command are used in INSTALL, RESTORE # For any update do it in all files -message="To federate this app you need to add this line in your DNS configuration: +message="If your server name is identical to the domain on which synapse is installed, and the default port 8448 is used, your server is normally already accessible by the federation. + +If not, you may need to put the following line in the dns configuration: _matrix._tcp.$domain. 3600 IN SRV 10 0 $synapse_tls_port $domain. +For more details, see : https://github.com/matrix-org/synapse#setting-up-federation + You also need to open the TCP port $synapse_tls_port on your ISP box if it's not automatically done. Your synapse server also implements a turnserver (for VoIP), to have this fully functional please read the 'Turnserver' section in the README available here: https://github.com/YunoHost-Apps/synapse_ynh . -If you're facing an issue or want to improve this app, please open a new issue in this project: https://github.com/YunoHost-Apps/synapse_ynh" +If you're facing an issue or want to improve this app, please open a new issue in this project: https://github.com/YunoHost-Apps/synapse_ynh + +You also need a valid TLS certificate for the domain used by synapse. To do that you can refer to the documentation here : https://yunohost.org/#/certificate_en" ynh_send_readme_to_admin "$message" diff --git a/scripts/remove b/scripts/remove index e3cbf9a..01dcc21 100755 --- a/scripts/remove +++ b/scripts/remove @@ -101,6 +101,12 @@ ynh_psql_remove_db $synapse_db_name $synapse_db_user ynh_system_user_delete $synapse_user +#================================================= +# REMOVE FAIL2BAN CONFIG +#================================================= + +ynh_remove_fail2ban_config $synapse_user + #================================================= # REMOVE LOGROTATE CONFIGURATION #================================================= diff --git a/scripts/restore b/scripts/restore index 09b0280..8b940dc 100644 --- a/scripts/restore +++ b/scripts/restore @@ -53,6 +53,21 @@ ynh_webpath_available $domain $path_url || ynh_die "$domain/$path_url is not ava # Restore all config and data ynh_restore +#================================================= +# CREATE A DH FILE +#================================================= + +# WARNING : theses command are used in INSTALL, UPGRADE, RESTORE +# For any update do it in all files + +# Make dh cert for synapse if it doesn't exist +if [[ ! -e /etc/ssl/private/dh2048.pem ]] +then + openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048 -dsaparam 2> /dev/null + chown root:ssl-cert /etc/ssl/private/dh2048.pem + chmod 640 /etc/ssl/private/dh2048.pem +fi + #================================================= # REINSTALL DEPENDENCIES #================================================= @@ -177,7 +192,7 @@ chown $synapse_user:root -R /var/lib/matrix-$app chown $synapse_user:root -R /var/log/matrix-$app chown $synapse_user:root -R /etc/matrix-$app chmod u=rwX,g=rX,o= -R /etc/matrix-$app -chmod 600 /etc/matrix-$app/{$domain.signing.key,$domain.tls.crt,$domain.tls.dh,$domain.tls.key} +chmod 600 /etc/matrix-$app/$domain.signing.key setfacl -R -m user:turnserver:rX /etc/matrix-$app setfacl -R -m user:turnserver:rwX /var/log/matrix-$app @@ -194,7 +209,13 @@ yunohost service add coturn-$app systemctl reload nginx.service systemctl restart coturn-$app.service -ynh_check_starting "Synapse now listening on port $synapse_tls_port" "/var/log/matrix-$app/homeserver.log" 300 "matrix-$app" +ynh_check_starting "Synapse now listening on TCP port $synapse_tls_port" "/var/log/matrix-$app/homeserver.log" 300 "matrix-$app" + +#================================================= +# SETUP FAIL2BAN +#================================================= + +systemctl try-reload-or-restart fail2ban #================================================= # SEND A README FOR THE ADMIN diff --git a/scripts/upgrade b/scripts/upgrade index 1c4912b..fd9e4f4 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -109,17 +109,14 @@ else source $final_path/bin/activate pip3 install --upgrade setuptools wheel pip3 install --upgrade cffi ndg-httpsclient psycopg2 lxml - - # Download and check the checksum for the synapse source - ynh_setup_source "/tmp" "python_source" - pip3 install --upgrade "/tmp/synapse_source.tar.gz" + pip3 install --upgrade matrix-synapse==$upstream_version matrix-synapse-ldap3 # This function was defined when we called "source $final_path/bin/activate". With this function we undo what "$final_path/bin/activate" does deactivate fi #================================================= -# MIGRATION 1 : USE SYNAPSE OWN KEYS +# MIGRATION 1 : GENERATE SYNAPSE SECRET #================================================= if [[ -z "$registration_shared_secret" ]] @@ -128,10 +125,6 @@ then PS1=${PS1:-} source $final_path/bin/activate - # Get the dh.pem if exist - test -e /etc/matrix-$app/dh.pem && mv /etc/matrix-$app/dh.pem /etc/matrix-$app/$domain.tls.dh - test -e /etc/matrix-$app/homeserver.signing.key && mv /etc/matrix-$app/homeserver.signing.key /etc/matrix-$app/$domain.signing.key - # Generate config and keys python -m synapse.app.homeserver --keys-directory /etc/matrix-$app/ --generate-config --generate-keys --server-name $domain --report-stats=no -c homeserver.yml @@ -139,8 +132,8 @@ then deactivate # Get random values from config - registration_shared_secret=$(egrep "registration_shared_secret" homeserver.yml | cut -d'"' -f2) - form_secret=$(egrep "form_secret" homeserver.yml | cut -d'"' -f1) + registration_shared_secret=$(egrep "^registration_shared_secret" homeserver.yml | cut -d'"' -f2) + form_secret=$(egrep "^form_secret" homeserver.yml | cut -d'"' -f1) # store in yunohost settings ynh_app_setting_set $app registration_shared_secret "$registration_shared_secret" @@ -151,11 +144,14 @@ fi # UPDATE SYNAPSE CONFIG #================================================= -# WARNING : theses command are used in INSTALL, UPGRADE +# WARNING : theses command are used in INSTALL, UPGRADE, CONFIG # For any update do it in all files homeserver_config_path="/etc/matrix-$app/homeserver.yaml" +ynh_backup_if_checksum_is_different "$homeserver_config_path" +ynh_backup_if_checksum_is_different /etc/matrix-$app/log.yaml + cp ../conf/homeserver.yaml "$homeserver_config_path" cp ../conf/log.yaml /etc/matrix-$app/log.yaml @@ -166,8 +162,8 @@ ynh_replace_string __SYNAPSE_DB_PWD__ $synapse_db_pwd "$homeserver_config_path" ynh_replace_string __PORT__ $port "$homeserver_config_path" ynh_replace_string __TLS_PORT__ $synapse_tls_port "$homeserver_config_path" ynh_replace_string __TURNSERVER_TLS_PORT__ $turnserver_tls_port "$homeserver_config_path" -ynh_replace_string __TURNPWD__ $turnserver_pwd "$homeserver_config_path" -ynh_replace_string __REGISTRATION_SECRET__ "$registration_shared_secret" "$homeserver_config_path" +ynh_replace_special_string __TURNPWD__ $turnserver_pwd "$homeserver_config_path" +ynh_replace_special_string __REGISTRATION_SECRET__ "$registration_shared_secret" "$homeserver_config_path" ynh_replace_string __FORM_SECRET__ "$form_secret" "$homeserver_config_path" ynh_replace_string __REPORT_STATS__ "$report_stats" "$homeserver_config_path" @@ -228,6 +224,21 @@ then adduser turnserver ssl-cert fi +#================================================= +# MIGRATION 4 : CREATE A DH FILE +#================================================= + +# WARNING : theses command are used in INSTALL, UPGRADE, RESTORE +# For any update do it in all files + +# Make dh cert for synapse if it doesn't exist +if [[ ! -e /etc/ssl/private/dh2048.pem ]] +then + openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048 -dsaparam 2> /dev/null + chown root:ssl-cert /etc/ssl/private/dh2048.pem + chmod 640 /etc/ssl/private/dh2048.pem +fi + #================================================= # STANDARD UPGRADE STEPS #================================================= @@ -296,6 +307,15 @@ ynh_add_systemd_config matrix-$app matrix-synapse.service cp ../conf/default_coturn /etc/default/coturn-$app ynh_add_systemd_config coturn-$app coturn-synapse.service +#================================================= +# SETUP FAIL2BAN +#================================================= + +# WARNING : theses command are used in INSTALL, UPGRADE +# For any update do it in all files + +ynh_add_fail2ban_config -t + #================================================= # GENERIC FINALIZATION #================================================= @@ -310,7 +330,7 @@ chown $synapse_user:root -R /var/lib/matrix-$app chown $synapse_user:root -R /var/log/matrix-$app chown $synapse_user:root -R /etc/matrix-$app chmod u=rwX,g=rX,o= -R /etc/matrix-$app -chmod 600 /etc/matrix-$app/{$domain.signing.key,$domain.tls.crt,$domain.tls.dh,$domain.tls.key} +chmod 600 /etc/matrix-$app/$domain.signing.key setfacl -R -m user:turnserver:rX /etc/matrix-$app setfacl -R -m user:turnserver:rwX /var/log/matrix-$app @@ -325,4 +345,4 @@ ynh_app_setting_set $app synapse_version $upstream_version #================================================= systemctl restart coturn-$app.service -ynh_check_starting "Synapse now listening on port $synapse_tls_port" "/var/log/matrix-$app/homeserver.log" 300 "matrix-$app" +ynh_check_starting "Synapse now listening on TCP port $synapse_tls_port" "/var/log/matrix-$app/homeserver.log" 300 "matrix-$app"