|
|
@@ -0,0 +1,718 @@
|
|
|
+#!/bin/bash
|
|
|
+
|
|
|
+: ${ROOT_MAILTO:="root@localhost"}
|
|
|
+: ${ASTERISK_VER:=""}
|
|
|
+: ${FREEPBX_VER:=""}
|
|
|
+: ${APP_DATA:=""}
|
|
|
+
|
|
|
+declare -A appDataDirs=(
|
|
|
+ [CRONDIR]=/var/spool/cron
|
|
|
+ [ASTHOME]=/home/asterisk
|
|
|
+ [ASTETCDIR]=/etc/asterisk
|
|
|
+ [ASTVARLIBDIR]=/var/lib/asterisk
|
|
|
+ [ASTSPOOLDIR]=/var/spool/asterisk
|
|
|
+ [ASTRUNDIR]=/var/run/asterisk
|
|
|
+ [HTTPDHOME]=/var/www
|
|
|
+ [HTTPDLOGDIR]=/var/log/apache2
|
|
|
+ [CERTBOTETCDIR]=/etc/letsencrypt
|
|
|
+ [ASTLOGDIR]=/var/log/asterisk
|
|
|
+ [F2BLOGDIR]=/var/log/fail2ban
|
|
|
+ [F2BLIBDIR]=/var/lib/fail2ban
|
|
|
+ [SSLCRTDIR]=/etc/pki/pbx
|
|
|
+ [ROOTHOME]=/root
|
|
|
+)
|
|
|
+
|
|
|
+declare -A appFilesConf=(
|
|
|
+ [FPBXCFGFILE]=/etc/freepbx.conf
|
|
|
+ [AMPCFGFILE]=/etc/amportal.conf
|
|
|
+)
|
|
|
+
|
|
|
+declare -A appCacheDirs=(
|
|
|
+ [ASTRUNDIR]=/var/run/asterisk
|
|
|
+ [PHPOPCACHEDIR]=/var/lib/php/opcache
|
|
|
+ [PHPSESSDIR]=/var/lib/php/session
|
|
|
+ [PHPWSDLDIR]=/var/lib/php/wsdlcache
|
|
|
+)
|
|
|
+
|
|
|
+declare -A fpbxDirs=(
|
|
|
+ [AMPWEBROOT]=/var/www/html
|
|
|
+ [ASTETCDIR]=/etc/asterisk
|
|
|
+ [ASTVARLIBDIR]=/var/lib/asterisk
|
|
|
+ [ASTAGIDIR]=/var/lib/asterisk/agi-bin
|
|
|
+ [ASTSPOOLDIR]=/var/spool/asterisk
|
|
|
+ [ASTRUNDIR]=/var/run/asterisk
|
|
|
+ [ASTLOGDIR]=/var/log/asterisk
|
|
|
+ [AMPBIN]=/var/lib/asterisk/bin
|
|
|
+ [AMPSBIN]=/var/lib/asterisk/sbin
|
|
|
+ [AMPCGIBIN]=/var/www/cgi-bin
|
|
|
+ [AMPPLAYBACK]=/var/lib/asterisk/playback
|
|
|
+ [CERTKEYLOC]=/etc/asterisk/keys
|
|
|
+)
|
|
|
+
|
|
|
+declare -A fpbxDirsExtra=(
|
|
|
+ [ASTMODDIR]=/usr/lib/asterisk/modules
|
|
|
+)
|
|
|
+
|
|
|
+declare -A fpbxFilesLog=(
|
|
|
+ [FPBXDBUGFILE]=/var/log/asterisk/freepbx-debug.log
|
|
|
+ [FPBXLOGFILE]=/var/log/asterisk/freepbx.log
|
|
|
+ [FPBXSECLOGFILE]=/var/log/asterisk/freepbx_security.log
|
|
|
+)
|
|
|
+
|
|
|
+declare -A fpbxSipSettings=(
|
|
|
+ [rtpstart]=${APP_PORT_RTP_START}
|
|
|
+ [rtpend]=${APP_PORT_RTP_END}
|
|
|
+ [udpport-0.0.0.0]=${APP_PORT_PJSIP}
|
|
|
+ [tcpport-0.0.0.0]=${APP_PORT_PJSIP}
|
|
|
+ [bindport]=${APP_PORT_SIP}
|
|
|
+)
|
|
|
+
|
|
|
+[ ! -z ${APP_FQDN} ] && HOSTNAME="${APP_FQDN}"
|
|
|
+: ${SERVERNAME:=$HOSTNAME}
|
|
|
+: ${MYSQL_SERVER:="db"}
|
|
|
+: ${MYSQL_ROOT_PASSWORD:=""}
|
|
|
+: ${MYSQL_DATABASE:="asterisk"}
|
|
|
+: ${MYSQL_USER:="asterisk"}
|
|
|
+: ${MYSQL_PASSWORD:=""}
|
|
|
+: ${APP_PORT_MYSQL:="3306"}
|
|
|
+: ${HTTPD_HTTPS_ENABLED:="true"}
|
|
|
+: ${HTTPD_REDIRECT_HTTP_TO_HTTPS:="false"}
|
|
|
+: ${HTTPD_ALLOW_FROM:=""}
|
|
|
+: ${CRON_ENABLED:="true"}
|
|
|
+: ${HTTPD_ENABLED:="true"}
|
|
|
+: ${ASTERISK_ENABLED:="false"}
|
|
|
+: ${ICZRPBX_ENABLED:="true"}
|
|
|
+: ${FAIL2BAN_ENABLED:="true"}
|
|
|
+: ${POSTFIX_ENABLED:="true"}
|
|
|
+: ${SMTP_RELAYHOST:=""}
|
|
|
+: ${SMTP_RELAYHOST_USERNAME:=""}
|
|
|
+: ${SMTP_RELAYHOST_PASSWORD:=""}
|
|
|
+: ${SMTP_ALLOWED_SENDER_DOMAINS:=""}
|
|
|
+: ${SMTP_MESSAGE_SIZE_LIMIT:="0"}
|
|
|
+: ${SMTP_MAIL_FROM:=""}
|
|
|
+: ${RELAYHOST:="$SMTP_RELAYHOST"}
|
|
|
+: ${RELAYHOST_USERNAME:="$SMTP_RELAYHOST_USERNAME"}
|
|
|
+: ${RELAYHOST_PASSWORD:="$SMTP_RELAYHOST_PASSWORD"}
|
|
|
+: ${ALLOWED_SENDER_DOMAINS:="$SMTP_ALLOWED_SENDER_DOMAINS"}
|
|
|
+: ${MESSAGE_SIZE_LIMIT:="$SMTP_MESSAGE_SIZE_LIMIT"}
|
|
|
+: ${SUPERVISOR_DIR:="/etc/supervisor/conf.d"}
|
|
|
+: ${HTTPD_CONF_DIR:="/etc/apache2"}
|
|
|
+: ${PHP_CONF:="/etc/php/7.4/apache2/php.ini"}
|
|
|
+
|
|
|
+dirEmpty() {
|
|
|
+ [ -z "$(ls -A "$1/")" ]
|
|
|
+}
|
|
|
+
|
|
|
+symlinkDir() {
|
|
|
+ local dirOriginal="$1"
|
|
|
+ local dirCustom="$2"
|
|
|
+ echo "---> directory data override detected: original:[$dirOriginal] custom:[$dirCustom]"
|
|
|
+ if [ -e "$dirOriginal" ] && dirEmpty "$dirCustom"; then
|
|
|
+ echo "---> empty dir '$dirCustom' detected copying '$dirOriginal' contents to '$dirCustom'..."
|
|
|
+ rsync -a -q "$dirOriginal/" "$dirCustom/"
|
|
|
+ fi
|
|
|
+ if [ ! -e "$dirOriginal" ]; then
|
|
|
+ echo "---> WARNING: original data directory doesn't exist... creating empty directory: '$dirOriginal'"
|
|
|
+ mkdir -p "$dirOriginal"
|
|
|
+ fi
|
|
|
+ if [ -e "$dirOriginal" ]; then
|
|
|
+ echo -e "---> renaming '${dirOriginal}' to '${dirOriginal}.dist'"
|
|
|
+ mv "$dirOriginal" "$dirOriginal".dist
|
|
|
+ fi
|
|
|
+ echo "---> symlinking '$dirCustom' to '$dirOriginal'"
|
|
|
+ ln -s "$dirCustom" "$dirOriginal"
|
|
|
+}
|
|
|
+
|
|
|
+symlinkFile() {
|
|
|
+ local fileOriginal="$1"
|
|
|
+ local fileCustom="$2"
|
|
|
+ echo "--> file data override detected: original:[$fileOriginal] custom:[$fileCustom]"
|
|
|
+ if [ -e "$fileOriginal" ]; then
|
|
|
+ if [ ! -e "$fileCustom" ]; then
|
|
|
+ echo "---> INFO: detected not existing file '$fileCustom'. copying '$fileOriginal' to '$fileCustom'..."
|
|
|
+ rsync -a -q "$fileOriginal" "$fileCustom"
|
|
|
+ fi
|
|
|
+ echo -e "---> renaming '${fileOriginal}' to '${fileOriginal}.dist'... "
|
|
|
+ mv "$fileOriginal" "$fileOriginal".dist
|
|
|
+ else
|
|
|
+ echo "---> WARNING: original data file doesn't exist... creating symlink from a not existing source: '$fileOriginal'"
|
|
|
+ fi
|
|
|
+ echo "---> symlinking '$fileCustom' to '$fileOriginal'"
|
|
|
+ [ ! -e "$(dirname "$fileCustom")" ] && mkdir -p "$(dirname "$fileCustom")"
|
|
|
+ ln -s "$fileCustom" "$fileOriginal"
|
|
|
+}
|
|
|
+
|
|
|
+chkService() {
|
|
|
+ local SERVICE_VAR="$1"
|
|
|
+ eval local SERVICE_ENABLED="\$$(echo $SERVICE_VAR)"
|
|
|
+ eval local SERVICE_DAEMON="\$$(echo $SERVICE_VAR | sed 's/_.*//')_DAEMON"
|
|
|
+ local SERVICE="$(echo $SERVICE_VAR | sed 's/_.*//' | sed -e 's/\(.*\)/\L\1/')"
|
|
|
+ [ -z "$SERVICE_DAEMON" ] && local SERVICE_DAEMON="$SERVICE"
|
|
|
+ if [ "$SERVICE_ENABLED" = "true" ]; then
|
|
|
+ autostart=true
|
|
|
+ echo "=> Enabling $SERVICE_DAEMON service... because $SERVICE_VAR=$SERVICE_ENABLED"
|
|
|
+ echo "--> configuring $SERVICE_DAEMON service..."
|
|
|
+ cfgService_$SERVICE
|
|
|
+ else
|
|
|
+ autostart=false
|
|
|
+ echo "=> Disabling $SERVICE_DAEMON service... because $SERVICE_VAR=$SERVICE_ENABLED"
|
|
|
+ fi
|
|
|
+ sed "s/autostart=.*/autostart=$autostart/" -i ${SUPERVISOR_DIR}/$SERVICE_DAEMON.conf
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_postfix() {
|
|
|
+postconf -e inet_protocols=ipv4
|
|
|
+
|
|
|
+if [ ! -z "$HOSTNAME" ]; then
|
|
|
+ postconf -e myhostname="$HOSTNAME"
|
|
|
+else
|
|
|
+ postconf -# myhostname
|
|
|
+fi
|
|
|
+
|
|
|
+postconf -# relayhost
|
|
|
+postconf -# smtp_sasl_auth_enable
|
|
|
+postconf -# smtp_sasl_password_maps
|
|
|
+postconf -# smtp_sasl_security_options
|
|
|
+if [ ! -z "$MYNETWORKS" ]; then
|
|
|
+ postconf -e mynetworks=$MYNETWORKS
|
|
|
+else
|
|
|
+ postconf -e "mynetworks=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
|
|
|
+fi
|
|
|
+[ ! -f /etc/aliases ] && echo "postmaster: root" > /etc/aliases
|
|
|
+[ ${ROOT_MAILTO} ] && echo "root: ${ROOT_MAILTO}" >> /etc/aliases && newaliases
|
|
|
+postconf -e "maillog_file = /dev/stdout"
|
|
|
+postconf -e "inet_protocols = ipv4"
|
|
|
+postconf -e "mailbox_size_limit = 0"
|
|
|
+postconf -e "message_size_limit = ${MESSAGE_SIZE_LIMIT}"
|
|
|
+if [ ! -z "$SMTP_MAIL_FROM" ]; then
|
|
|
+ echo "/.+/ $SMTP_MAIL_FROM" > /etc/postfix/sender_canonical_maps
|
|
|
+ echo "/From:.*/ REPLACE From: $SMTP_MAIL_FROM" > /etc/postfix/header_checks
|
|
|
+ postconf -e "sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps"
|
|
|
+ postconf -e "smtp_header_checks = regexp:/etc/postfix/header_checks"
|
|
|
+fi
|
|
|
+postconf -M telegram-mailgate/unix="telegram-mailgate unix - n n - - pipe flags= user=list argv=/usr/local/bin/telegram-mailgate.py --key ${TG_BOT_APIKEY} --chatid ${TG_BOT_CHATID} --queue-id \${queue_id} \${recipient}"
|
|
|
+postconf -e "content_filter = telegram-mailgate"
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_cron() {
|
|
|
+ ls -la /var/spool/cron/crontabs
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_letsencrypt() {
|
|
|
+ if [ -e "/etc/letsencrypt/live/${APP_FQDN}/privkey.pem" ] ; then
|
|
|
+ echo "--> Let's Encrypt certificate already exist... trying to renew"
|
|
|
+ certbot renew --standalone
|
|
|
+ else
|
|
|
+ echo "--> generating HTTPS Let's Encrypt certificate"
|
|
|
+ certbot certonly --standalone --expand -n --agree-tos --email ${ROOT_MAILTO} -d ${APP_FQDN}
|
|
|
+ fi
|
|
|
+ echo '#!/bin/bash
|
|
|
+/usr/bin/certbot renew --noninteractive --no-random-sleep-on-renew --deploy-hook "/usr/bin/supervisorctl restart httpd"
|
|
|
+exit $?' > /etc/cron.daily/certbot && chmod 755 /etc/cron.daily/certbot
|
|
|
+}
|
|
|
+
|
|
|
+iniParser() {
|
|
|
+ ini="$@"
|
|
|
+ while read setting ; do
|
|
|
+ section="$(echo $setting | awk -F" " '{print $1}')"
|
|
|
+ k=$(echo $setting | sed -e "s/^${section} //" | awk -F"=" '{print $1}' | tr '[:upper:]' '[:lower:]')
|
|
|
+ v=$(echo $setting | sed -e "s/'//g" | awk -F"=" '{print $2}')
|
|
|
+ sed -e "/^\[${section}\]$/I,/^\(\|;\|#\)\[/ s/^\(;\|#\)${k}/${k}/" -e "/^\[${section}\]$/I,/^\[/ s|^${k}.*=.*|${k}=${v}|I" -i "${ini}"
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_fail2ban() {
|
|
|
+ echo "--> reconfiguring Fail2ban settings..."
|
|
|
+ echo "DEFAULT LOGTARGET=/var/log/fail2ban/fail2ban.log" | iniParser /etc/fail2ban/fail2ban.conf
|
|
|
+ sed "s/%(mta)s-whois\[/%(mta)s\[/g" -i /etc/fail2ban/jail.conf
|
|
|
+ touch /var/log/fail2ban/fail2ban.log
|
|
|
+ set | grep ^"FAIL2BAN_" | sed -e 's/^FAIL2BAN_//' | sed -e 's/_/ /' | iniParser "/etc/fail2ban/jail.d/99-local.conf"
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_httpd() {
|
|
|
+ if [ "${HTTPD_HTTPS_ENABLED}" = "true" ]; then
|
|
|
+ echo "--> enabling Apache ssl module"
|
|
|
+ a2enmod ssl
|
|
|
+ else
|
|
|
+ echo "--> disabling Apache ssl module"
|
|
|
+ a2dismod ssl
|
|
|
+ fi
|
|
|
+ a2enmod rewrite
|
|
|
+ rm -f /var/www/html/index.html
|
|
|
+ echo "--> setting Apache ServerName to ${SERVERNAME}"
|
|
|
+ sed "s/#ServerName .*/ServerName ${SERVERNAME}/" -i "${HTTPD_CONF_DIR}/sites-enabled/000-default.conf"
|
|
|
+ echo "ServerName ${SERVERNAME}" >> "${HTTPD_CONF_DIR}/apache2.conf"
|
|
|
+ echo "--> setting Apache user and group"
|
|
|
+ sed -i "s/^User.*/User ${APP_USR}/" /etc/apache2/apache2.conf
|
|
|
+ sed -i "s/^Group.*/Group ${APP_GRP}/" /etc/apache2/apache2.conf
|
|
|
+ sed -i "s/AllowOverride None/AllowOverride All/" /etc/apache2/apache2.conf
|
|
|
+
|
|
|
+print_AllowFrom() {
|
|
|
+ if [ ! -z "${HTTPD_ALLOW_FROM}" ]; then
|
|
|
+ for IP in $(echo ${HTTPD_ALLOW_FROM} | sed -e "s/'//g") ; do
|
|
|
+ echo " Require ip ${IP}"
|
|
|
+ done
|
|
|
+ else
|
|
|
+ echo " Require all granted"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+echo "# default HTTP virtualhost
|
|
|
+<VirtualHost *:${APP_PORT_HTTP}>
|
|
|
+ DocumentRoot /var/www/html
|
|
|
+$(if [ "${HTTPD_REDIRECT_HTTP_TO_HTTPS}" = "true" ]; then
|
|
|
+echo " <IfModule mod_rewrite.c>
|
|
|
+ RewriteEngine on
|
|
|
+ RewriteCond %{REQUEST_URI} !\.well-known/acme-challenge
|
|
|
+ RewriteCond %{HTTPS} off
|
|
|
+ #RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
|
|
|
+ RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
|
|
+ </IfModule>"
|
|
|
+fi)
|
|
|
+ <Directory /var/www/html>
|
|
|
+ Options Includes FollowSymLinks MultiViews
|
|
|
+ AllowOverride All
|
|
|
+$(print_AllowFrom)
|
|
|
+ </Directory>
|
|
|
+</VirtualHost>
|
|
|
+
|
|
|
+$(if [ ! -z "${APP_FQDN}" ]; then
|
|
|
+echo "# HTTP virtualhost
|
|
|
+<VirtualHost *:${APP_PORT_HTTP}>
|
|
|
+ ServerName ${APP_FQDN}
|
|
|
+$(if [ "${HTTPD_REDIRECT_HTTP_TO_HTTPS}" = "true" ]; then
|
|
|
+echo "# enable http to https automatic rewrite
|
|
|
+<IfModule mod_rewrite.c>
|
|
|
+ RewriteEngine on
|
|
|
+ RewriteCond %{REQUEST_URI} !\.well-known/acme-challenge
|
|
|
+ RewriteCond %{HTTPS} off
|
|
|
+ #RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
|
|
|
+ RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
|
|
+</IfModule>"
|
|
|
+fi)
|
|
|
+ <Directory /var/www/html>
|
|
|
+ Options Includes FollowSymLinks MultiViews
|
|
|
+ DirectoryIndex index.php
|
|
|
+ AllowOverride All
|
|
|
+$(print_AllowFrom)
|
|
|
+ </Directory>
|
|
|
+</VirtualHost>"
|
|
|
+fi)
|
|
|
+
|
|
|
+$(if [ "${HTTPD_HTTPS_ENABLED}" = "true" ]; then
|
|
|
+echo "SSLPassPhraseDialog builtin
|
|
|
+SSLSessionCache shmcb:/run/apache2/sslcache(512000)
|
|
|
+SSLSessionCacheTimeout 300
|
|
|
+SSLCryptoDevice builtin"
|
|
|
+fi)
|
|
|
+
|
|
|
+$(if [[ "${HTTPD_HTTPS_ENABLED}" = "true" && "${LETSENCRYPT_ENABLED}" != "true" ]]; then
|
|
|
+echo "# enable default ssl virtualhost with self signed certificate
|
|
|
+<VirtualHost _default_:${APP_PORT_HTTPS}>
|
|
|
+ ErrorLog ${appDataDirs[HTTPDLOGDIR]}/ssl_error.log
|
|
|
+ TransferLog ${appDataDirs[HTTPDLOGDIR]}/ssl_access.log
|
|
|
+ LogLevel warn
|
|
|
+ SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
|
|
|
+ SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
|
|
+ SSLHonorCipherOrder off
|
|
|
+ SSLSessionTickets off
|
|
|
+ SSLCertificateFile ${appDataDirs[SSLCRTDIR]}/iczrpbx.crt
|
|
|
+ SSLCertificateKeyFile ${appDataDirs[SSLCRTDIR]}/iczrpbx.key
|
|
|
+ #SSLCertificateChainFile ${appDataDirs[SSLCRTDIR]}/chain.crt
|
|
|
+
|
|
|
+ <Directory /var/www/html>
|
|
|
+ Options Includes FollowSymLinks MultiViews
|
|
|
+ AllowOverride All
|
|
|
+$(print_AllowFrom)
|
|
|
+ </Directory>
|
|
|
+</VirtualHost>"
|
|
|
+fi)
|
|
|
+
|
|
|
+$(if [[ ! -z "${APP_FQDN}" && "${LETSENCRYPT_ENABLED}" = "true" && -e "/etc/letsencrypt/live/${APP_FQDN}/cert.pem" ]]; then
|
|
|
+echo "# HTTPS virtualhost
|
|
|
+<VirtualHost *:${APP_PORT_HTTPS}>
|
|
|
+ ServerName ${APP_FQDN}
|
|
|
+
|
|
|
+ SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
|
|
|
+ SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
|
|
+ SSLHonorCipherOrder off
|
|
|
+ SSLSessionTickets off
|
|
|
+ SSLCertificateChainFile /etc/letsencrypt/live/${APP_FQDN}/chain.pem
|
|
|
+ SSLCertificateFile /etc/letsencrypt/live/${APP_FQDN}/cert.pem
|
|
|
+ SSLCertificateKeyFile /etc/letsencrypt/live/${APP_FQDN}/privkey.pem
|
|
|
+
|
|
|
+ <Directory /var/www/html>
|
|
|
+ Options Includes FollowSymLinks MultiViews
|
|
|
+ AllowOverride All
|
|
|
+$(print_AllowFrom)
|
|
|
+ </Directory>
|
|
|
+</VirtualHost>"
|
|
|
+fi)
|
|
|
+
|
|
|
+" > "${HTTPD_CONF_DIR}/conf-enabled/virtual.conf"
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_asterisk() {
|
|
|
+ echo "=> Starting Asterisk"
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_iczrpbx() {
|
|
|
+ freepbx_reload() {
|
|
|
+ echo "---> reloading FreePBX..."
|
|
|
+ su - ${APP_USR} -s /bin/bash -c "fwconsole reload"
|
|
|
+ }
|
|
|
+ echo "---> verifing FreePBX configurations"
|
|
|
+ if [ ! -z "${APP_DATA}" ]; then
|
|
|
+ echo "---> using '${APP_DATA}' as basedir for FreePBX install"
|
|
|
+ for k in ${!fpbxDirs[@]}; do
|
|
|
+ v="${fpbxDirs[$k]}"
|
|
|
+ eval fpbxDirs[$k]=${APP_DATA}$v
|
|
|
+ [ ! -e "$v" ] && mkdir -p "$v"
|
|
|
+ if [ "$(stat -c "%U %G" "$v" 2>/dev/null)" != "${APP_USR} ${APP_GRP}" ];then
|
|
|
+ echo "---> fixing permissions for: $k=$v"
|
|
|
+ chown ${APP_USR}:${APP_GRP} "$v"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ for k in ${!fpbxFilesLog[@]}; do
|
|
|
+ v="${fpbxFilesLog[$k]}"
|
|
|
+ eval fpbxFilesLog[$k]=${APP_DATA}$v
|
|
|
+ [ ! -e "$v" ] && touch "$v"
|
|
|
+ if [ "$(stat -c "%U %G" "$v" 2>/dev/null)" != "${APP_USR} ${APP_GRP}" ];then
|
|
|
+ echo "---> fixing permissions for: $k=$v"
|
|
|
+ chown ${APP_USR}:${APP_GRP} "$v"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+ fi
|
|
|
+ echo "[MySQL-asteriskcdrdb]
|
|
|
+Description = MariaDB connection to 'asteriskcdrdb' database
|
|
|
+driver = MySQL
|
|
|
+server = ${MYSQL_SERVER}
|
|
|
+database = asteriskcdrdb
|
|
|
+Port = ${APP_PORT_MYSQL}
|
|
|
+option = 3
|
|
|
+Charset=utf8" > /etc/odbc.ini
|
|
|
+
|
|
|
+ if [[ -e "${appFilesConf[FPBXCFGFILE]}" && ! -e ${APP_DATA}/.initialized ]]; then
|
|
|
+ echo "--> INFO: found '${appFilesConf[FPBXCFGFILE]}' configuration file but missing '${APP_DATA}/.initialized'... creating it right now"
|
|
|
+ echo "--> NOTE: if you want make an initial install, remove '${appFilesConf[FPBXCFGFILE]}' and '${APP_DATA}/.initialized' file"
|
|
|
+ touch "${APP_DATA}/.initialized"
|
|
|
+ fi
|
|
|
+ if [ ! -e ${APP_DATA}/.initialized ]; then
|
|
|
+ cfgService_freepbx_install
|
|
|
+ else
|
|
|
+ echo "--> INFO: FreePBX installation DETECTED! found '${APP_DATA}/.initialized' file"
|
|
|
+ [ ! -e "${appFilesConf[FPBXCFGFILE]}" ] && echo "---> WARNING: missing configuration file: ${appFilesConf[FPBXCFGFILE]}"
|
|
|
+ echo "---> reconfiguring '${appFilesConf[FPBXCFGFILE]}'..."
|
|
|
+ [[ ! -z "${APP_PORT_MYSQL}" && ${APP_PORT_MYSQL} -ne 3306 ]] && export MYSQL_SERVER="${MYSQL_SERVER}:${APP_PORT_MYSQL}"
|
|
|
+ sed "s/^\$amp_conf\['AMPDBUSER'\] =.*/\$amp_conf\['AMPDBUSER'\] = '${MYSQL_USER}';/" -i "${appFilesConf[FPBXCFGFILE]}"
|
|
|
+ sed "s/^\$amp_conf\['AMPDBPASS'\] =.*/\$amp_conf\['AMPDBPASS'\] = '${MYSQL_PASSWORD}';/" -i "${appFilesConf[FPBXCFGFILE]}"
|
|
|
+ sed "s/^\$amp_conf\['AMPDBHOST'\] =.*/\$amp_conf\['AMPDBHOST'\] = '${MYSQL_SERVER}';/" -i "${appFilesConf[FPBXCFGFILE]}"
|
|
|
+ sed "s/^\$amp_conf\['AMPDBNAME'\] =.*/\$amp_conf\['AMPDBNAME'\] = '${MYSQL_DATABASE}';/" -i "${appFilesConf[FPBXCFGFILE]}"
|
|
|
+ fi
|
|
|
+ echo "---> applying workarounds for FreePBX and Asterisk..."
|
|
|
+ [ ! -e "${fpbxDirs[ASTLOGDIR]}/full" ] && touch "${fpbxDirs[ASTLOGDIR]}/full" && chown ${APP_USR}:${APP_GRP} "${file}" "${fpbxDirs[ASTLOGDIR]}/full"
|
|
|
+ [ ! -e "/usr/sbin/fwconsole" ] && ln -s ${fpbxDirs[AMPBIN]}/fwconsole /usr/sbin/fwconsole
|
|
|
+ [ ! -e "/usr/sbin/amportal" ] && ln -s ${fpbxDirs[AMPBIN]}/amportal /usr/sbin/amportal
|
|
|
+ echo "---> reconfiguring FreePBX Advanced Settings if needed..."
|
|
|
+ set | grep ^"FREEPBX_" | grep -v -e ^"FREEPBX_MODULES_" -e ^"FREEPBX_VER=" | sed -e 's/^FREEPBX_//' -e 's/=/ /' | while read setting ; do
|
|
|
+ k="$(echo $setting | awk '{print $1}')"
|
|
|
+ v="$(echo $setting | awk '{print $2}')"
|
|
|
+ currentVal=$(fwconsole setting $k | awk -F"[][{}]" '{print $2}')
|
|
|
+ [ "$currentVal" = "true" ] && currentVal="1"
|
|
|
+ [ "$currentVal" = "false" ] && currentVal="0"
|
|
|
+ if [ "$currentVal" != "$v" ]; then
|
|
|
+ echo "---> reconfiguring advanced setting: ${k}=${v}"
|
|
|
+ fwconsole setting $k $v
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ if [[ ! -z "${APP_AMI_USERNAME}" && ! -z "${APP_AMI_SECRET}" ]]; then
|
|
|
+ echo "---> adding asterisk manager user ${APP_AMI_USERNAME}..."
|
|
|
+ set +H
|
|
|
+ echo "[${APP_AMI_USERNAME}]
|
|
|
+secret = ${APP_AMI_SECRET}
|
|
|
+deny=0.0.0.0/0.0.0.0
|
|
|
+permit=127.0.0.1/255.255.255.0
|
|
|
+permit=172.16.0.0/255.240.0.0
|
|
|
+read = all
|
|
|
+write = all
|
|
|
+writetimeout = 100
|
|
|
+eventfilter=!Event: SuccessfulAuth
|
|
|
+eventfilter=!Event: ChallengeSent
|
|
|
+eventfilter=!Event: Registry
|
|
|
+eventfilter=!Event: InvalidPassword" > /etc/asterisk/manager_custom.conf
|
|
|
+ set -H
|
|
|
+ fi
|
|
|
+ echo "---> reconfiguring FreePBX SIP Settings if needed..."
|
|
|
+ for k in ${!fpbxSipSettings[@]}; do
|
|
|
+ v="${fpbxSipSettings[$k]}"
|
|
|
+ cVal=$(echo "<?php include '/etc/freepbx.conf'; \$FreePBX = FreePBX::Create(); echo \$FreePBX->sipsettings->getConfig('${k}');?>" | php)
|
|
|
+ if [ "$cVal" != "${v}" ];then
|
|
|
+ echo "---> reconfiguring sip setting: ${k}=${v}"
|
|
|
+ echo "<?php include '/etc/freepbx.conf'; \$FreePBX = FreePBX::Create(); \$FreePBX->sipsettings->setConfig('${k}',${v}); needreload();?>" | php
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ echo "---> FIXME: temporary workarounds for FreePBX broken modules and configs..."
|
|
|
+ sed 's/^preload = chan_local.so/;preload = chan_local.so/' -i ${fpbxDirs[ASTETCDIR]}/modules.conf
|
|
|
+ sed 's/^enabled =.*/enabled = yes/' -i ${fpbxDirs[ASTETCDIR]}/hep.conf
|
|
|
+ sed 's/!count(\$dsn)/!@count(\$dsn)/' -i ${fpbxDirs[AMPWEBROOT]}/admin/libraries/DB.class.php
|
|
|
+}
|
|
|
+
|
|
|
+cfgService_freepbx_install() {
|
|
|
+ n=1 ; t=5
|
|
|
+
|
|
|
+ until [ $n -eq $t ]; do
|
|
|
+ echo "=> !!! FreePBX IS NOT INITIALIZED :: NEW INSTALLATION DETECTED !!!"
|
|
|
+ echo "--> missing '${APP_DATA}/.initialized' file... initializing FreePBX right now... try:[$n/$t]"
|
|
|
+ cd /usr/src/freepbx
|
|
|
+ if ! asterisk -r -x "core show version" 2>/dev/null ; then ./start_asterisk start ; fi
|
|
|
+ myn=1 ; myt=10
|
|
|
+ until [ $myn -eq $myt ]; do
|
|
|
+ mysql -h ${MYSQL_SERVER} -P ${APP_PORT_MYSQL} -u root --password=${MYSQL_ROOT_PASSWORD} -B -e "SELECT 1;" >/dev/null
|
|
|
+ RETVAL=$?
|
|
|
+ if [ $RETVAL = 0 ]; then
|
|
|
+ myn=$myt
|
|
|
+ else
|
|
|
+ let myn+=1
|
|
|
+ echo "--> WARNING: cannot connect to MySQL database '${MYSQL_SERVER}'... waiting database to become ready... retrying in 10 seconds... try:[$myn/$myt]"
|
|
|
+ sleep 10
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ mysql -h ${MYSQL_SERVER} -P ${APP_PORT_MYSQL} -u root --password=${MYSQL_ROOT_PASSWORD} -B -e "CREATE DATABASE IF NOT EXISTS asteriskcdrdb;"
|
|
|
+ mysql -h ${MYSQL_SERVER} -P ${APP_PORT_MYSQL} -u root --password=${MYSQL_ROOT_PASSWORD} -B -e "GRANT ALL PRIVILEGES ON asteriskcdrdb.* TO 'asterisk'@'%' WITH GRANT OPTION;"
|
|
|
+ mysql -h ${MYSQL_SERVER} -P ${APP_PORT_MYSQL} -u root --password=${MYSQL_ROOT_PASSWORD} -B -e \
|
|
|
+ "CREATE TABLE IF NOT EXISTS asteriskcdrdb.voicemessages \
|
|
|
+ (msgnum INT(11) NULL DEFAULT NULL, \
|
|
|
+ dir VARCHAR(80) NOT NULL, \
|
|
|
+ context VARCHAR(80) NULL DEFAULT NULL, \
|
|
|
+ macrocontext VARCHAR(80) NULL DEFAULT NULL, \
|
|
|
+ callerid VARCHAR(40) NULL DEFAULT NULL, \
|
|
|
+ origtime VARCHAR(40) NULL DEFAULT NULL, \
|
|
|
+ duration VARCHAR(20) NULL DEFAULT NULL, \
|
|
|
+ flag VARCHAR(8) NULL DEFAULT NULL, \
|
|
|
+ mailboxuser VARCHAR(80) NULL DEFAULT NULL, \
|
|
|
+ mailboxcontext VARCHAR(80) NULL DEFAULT NULL, \
|
|
|
+ recording LONGBLOB NULL DEFAULT NULL, \
|
|
|
+ msg_id VARCHAR(40) NULL DEFAULT NULL) ENGINE = InnoDB;"
|
|
|
+ mysql -h ${MYSQL_SERVER} -P ${APP_PORT_MYSQL} -u root --password=${MYSQL_ROOT_PASSWORD} -B -e \
|
|
|
+ "CREATE TABLE IF NOT EXISTS asteriskcdrdb.cdr \
|
|
|
+ (calldate datetime NOT NULL DEFAULT '1000-01-01 00:00:00', \
|
|
|
+ clid varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ src varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ dst varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ dcontext varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ channel varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ dstchannel varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ lastapp varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ lastdata varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ duration int(11) NOT NULL DEFAULT 0, \
|
|
|
+ billsec int(11) NOT NULL DEFAULT 0, \
|
|
|
+ disposition varchar(45) NOT NULL DEFAULT '', \
|
|
|
+ amaflags int(11) NOT NULL DEFAULT 0, \
|
|
|
+ accountcode varchar(20) NOT NULL DEFAULT '', \
|
|
|
+ uniqueid varchar(32) NOT NULL DEFAULT '', \
|
|
|
+ userfield varchar(255) NOT NULL DEFAULT '', \
|
|
|
+ did varchar(50) NOT NULL DEFAULT '', \
|
|
|
+ recordingfile varchar(255) NOT NULL DEFAULT '', \
|
|
|
+ cnum varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ cnam varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ outbound_cnum varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ outbound_cnam varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ dst_cnam varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ linkedid varchar(32) NOT NULL DEFAULT '', \
|
|
|
+ peeraccount varchar(80) NOT NULL DEFAULT '', \
|
|
|
+ sequence int(11) NOT NULL DEFAULT 0, \
|
|
|
+ KEY calldate (calldate), \
|
|
|
+ KEY dst (dst), \
|
|
|
+ KEY accountcode (accountcode), \
|
|
|
+ KEY uniqueid (uniqueid), \
|
|
|
+ KEY did (did), \
|
|
|
+ KEY recordingfile (recordingfile)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
|
|
|
+
|
|
|
+ FPBX_OPTS+=" --webroot=${fpbxDirs[AMPWEBROOT]}"
|
|
|
+ FPBX_OPTS+=" --astetcdir=${fpbxDirs[ASTETCDIR]}"
|
|
|
+ FPBX_OPTS+=" --astmoddir=${fpbxDirs[ASTMODDIR]}"
|
|
|
+ FPBX_OPTS+=" --astvarlibdir=${fpbxDirs[ASTVARLIBDIR]}"
|
|
|
+ FPBX_OPTS+=" --astagidir=${fpbxDirs[ASTAGIDIR]}"
|
|
|
+ FPBX_OPTS+=" --astspooldir=${fpbxDirs[ASTSPOOLDIR]}"
|
|
|
+ FPBX_OPTS+=" --astrundir=${fpbxDirs[ASTRUNDIR]}"
|
|
|
+ FPBX_OPTS+=" --astlogdir=${fpbxDirs[ASTLOGDIR]}"
|
|
|
+ FPBX_OPTS+=" --ampbin=${fpbxDirs[AMPBIN]}"
|
|
|
+ FPBX_OPTS+=" --ampsbin=${fpbxDirs[AMPSBIN]}"
|
|
|
+ FPBX_OPTS+=" --ampcgibin=${fpbxDirs[AMPCGIBIN]}"
|
|
|
+ FPBX_OPTS+=" --ampplayback=${fpbxDirs[AMPPLAYBACK]}"
|
|
|
+
|
|
|
+ echo "--> installing FreePBX in '${fpbxDirs[AMPWEBROOT]}'"
|
|
|
+ echo "---> START install FreePBX @ $(date)"
|
|
|
+ [[ ! -z "${APP_PORT_MYSQL}" && ${APP_PORT_MYSQL} -ne 3306 ]] && export MYSQL_SERVER="${MYSQL_SERVER}:${APP_PORT_MYSQL}"
|
|
|
+ set -x
|
|
|
+ ./install -n --skip-install --no-ansi --dbhost=${MYSQL_SERVER} --dbuser=${MYSQL_USER} --dbpass=${MYSQL_PASSWORD} ${FPBX_OPTS}
|
|
|
+ RETVAL=$?
|
|
|
+ set +x
|
|
|
+ echo "---> END install FreePBX @ $(date)"
|
|
|
+ unset FPBX_OPTS
|
|
|
+
|
|
|
+ if [ $RETVAL = 0 ]; then
|
|
|
+ [ ! -e "/usr/sbin/fwconsole" ] && ln -s ${fpbxDirs[ASTVARLIBDIR]}/bin/fwconsole /usr/sbin/fwconsole
|
|
|
+ [ ! -e "/usr/sbin/amportal" ] && ln -s ${fpbxDirs[ASTVARLIBDIR]}/bin/amportal /usr/sbin/amportal
|
|
|
+
|
|
|
+ if [ ! -z "${APP_DATA}" ]; then
|
|
|
+ for file in ${appFilesConf[@]}; do
|
|
|
+ chown ${APP_USR}:${APP_GRP} "${file}"
|
|
|
+ done
|
|
|
+ echo "--> fixing directory system paths in db configuration..."
|
|
|
+ for k in ${!fpbxDirs[@]} ${!fpbxFilesLog[@]}; do
|
|
|
+ fwconsole setting ${k} ${fpbxDirs[$k]}
|
|
|
+ done
|
|
|
+ fi
|
|
|
+
|
|
|
+ : ${FREEPBX_MODULES_CORE="
|
|
|
+ framework
|
|
|
+ core
|
|
|
+ dashboard
|
|
|
+ sipsettings
|
|
|
+ voicemail
|
|
|
+ "}
|
|
|
+
|
|
|
+ : ${FREEPBX_MODULES_PRE:="
|
|
|
+ pm2
|
|
|
+ userman
|
|
|
+ "}
|
|
|
+
|
|
|
+ : ${FREEPBX_MODULES_EXTRA:="
|
|
|
+ soundlang
|
|
|
+ callrecording
|
|
|
+ cdr
|
|
|
+ conferences
|
|
|
+ customappsreg
|
|
|
+ featurecodeadmin
|
|
|
+ infoservices
|
|
|
+ logfiles
|
|
|
+ music
|
|
|
+ manager
|
|
|
+ arimanager
|
|
|
+ filestore
|
|
|
+ recordings
|
|
|
+ announcement
|
|
|
+ asteriskinfo
|
|
|
+ backup
|
|
|
+ callforward
|
|
|
+ callwaiting
|
|
|
+ daynight
|
|
|
+ calendar
|
|
|
+ certman
|
|
|
+ cidlookup
|
|
|
+ contactmanager
|
|
|
+ donotdisturb
|
|
|
+ fax
|
|
|
+ findmefollow
|
|
|
+ iaxsettings
|
|
|
+ miscapps
|
|
|
+ miscdests
|
|
|
+ ivr
|
|
|
+ parking
|
|
|
+ phonebook
|
|
|
+ presencestate
|
|
|
+ printextensions
|
|
|
+ queues
|
|
|
+ cel
|
|
|
+ timeconditions
|
|
|
+ asterisk-cli
|
|
|
+ blacklist
|
|
|
+ configedit
|
|
|
+ "}
|
|
|
+
|
|
|
+ : ${FREEPBX_MODULES_DISABLED="
|
|
|
+ bulkhandler
|
|
|
+ speeddial
|
|
|
+ weakpasswords
|
|
|
+ ucp
|
|
|
+ "}
|
|
|
+ echo "--> enabling EXTENDED FreePBX repo..."
|
|
|
+ su - ${APP_USR} -s /bin/bash -c "fwconsole ma enablerepo extended"
|
|
|
+ su - ${APP_USR} -s /bin/bash -c "fwconsole ma enablerepo unsupported"
|
|
|
+ echo "--> starting cron to avoid crontab checks error..."
|
|
|
+ cron
|
|
|
+ echo "--> installing prerequisite FreePBX modules from local install into '${fpbxDirs[AMPWEBROOT]}/admin/modules'"
|
|
|
+ for module in ${FREEPBX_MODULES_PRE}; do
|
|
|
+ su - ${APP_USR} -s /bin/bash -c "echo \"---> installing module: ${module}\" && fwconsole ma install ${module}"
|
|
|
+ done
|
|
|
+ echo "--> fixing FreePBX permissions..."
|
|
|
+ fwconsole chown
|
|
|
+ echo "--> enabling pm2 module..."
|
|
|
+ fwconsole ma enable pm2
|
|
|
+ freepbx_reload
|
|
|
+ echo "--> installing Extra FreePBX modules from local install into '${fpbxDirs[AMPWEBROOT]}/admin/modules'"
|
|
|
+ for module in ${FREEPBX_MODULES_EXTRA}; do
|
|
|
+ su - ${APP_USR} -s /bin/bash -c "echo \"---> installing module: ${module}\" && fwconsole ma install ${module}"
|
|
|
+ done
|
|
|
+ echo "--> fixing FreePBX permissions..."
|
|
|
+ fwconsole chown
|
|
|
+ freepbx_reload
|
|
|
+ echo "--> upgrading modules..."
|
|
|
+ fwconsole ma upgradeall
|
|
|
+ echo "--> fixing FreePBX permissions..."
|
|
|
+ fwconsole chown
|
|
|
+ freepbx_reload
|
|
|
+ echo "--> stopping cron..."
|
|
|
+ killall -9 cron
|
|
|
+ touch "${APP_DATA}/.initialized"
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [ $RETVAL = 0 ]; then
|
|
|
+ n=$t
|
|
|
+ else
|
|
|
+ let n+=1
|
|
|
+ echo "--> problem detected... restarting in 10 seconds... try:[$n/$t]"
|
|
|
+ sleep 10
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ if asterisk -r -x "core show version" 2>/dev/null ; then
|
|
|
+ echo "--> stopping Asterisk"
|
|
|
+ asterisk -r -x "core stop now"
|
|
|
+ echo "=> Finished installing FreePBX"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+runHooks() {
|
|
|
+ mkdir -p /var/log/supervisor /var/log/dbconfig-common /var/log/apt /var/log/apache2 /var/log/asterisk/cdr-csv
|
|
|
+ touch /var/log/wtmp /var/log/lastlog
|
|
|
+ [ ! -e /sbin/nologin ] && ln -s /usr/sbin/nologin /sbin/nologin
|
|
|
+
|
|
|
+ if [ ! -z "${APP_DATA}" ]; then
|
|
|
+ echo "=> Persistent storage path detected... relocating and reconfiguring system data and configuration files using base: ${APP_DATA}"
|
|
|
+ for dir in ${appDataDirs[@]}
|
|
|
+ do
|
|
|
+ dir="${APP_DATA}${dir}"
|
|
|
+ if [ ! -e "${dir}" ];then
|
|
|
+ echo "--> creating missing dir: '$dir'"
|
|
|
+ mkdir -p "${dir}"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ for dir in ${appDataDirs[@]}; do
|
|
|
+ symlinkDir "${dir}" "${APP_DATA}${dir}"
|
|
|
+ done
|
|
|
+
|
|
|
+ for file in ${appFilesConf[@]}; do
|
|
|
+ symlinkFile "${file}" "${APP_DATA}${file}"
|
|
|
+ done
|
|
|
+ else
|
|
|
+ echo "=> WARNING: No Persistent storage path detected... the configurations will be lost on container restart"
|
|
|
+ fi
|
|
|
+
|
|
|
+ chkService POSTFIX_ENABLED
|
|
|
+ chkService CRON_ENABLED
|
|
|
+ chkService FAIL2BAN_ENABLED
|
|
|
+ chkService HTTPD_ENABLED
|
|
|
+ chkService ASTERISK_ENABLED
|
|
|
+ chkService ICZRPBX_ENABLED
|
|
|
+ [[ ! -z "${APP_FQDN}" && "${LETSENCRYPT_ENABLED}" = "true" ]] && cfgService_letsencrypt
|
|
|
+}
|
|
|
+
|
|
|
+runHooks
|