Explorar o código

IPV6: Manual merge after #3605 and update from upstream

asmcc %!s(int64=2) %!d(string=hai) anos
pai
achega
b2c3d0bfd9

+ 67 - 61
bin/v-add-sys-ip

@@ -1,5 +1,5 @@
 #!/bin/bash
-# info: add system ip address
+# info: add system IP address
 # options: IP [NETMASK] [INTERFACE] [USER] [IP_STATUS] [IP_NAME] [NAT_IP]
 #
 # example: v-add-sys-ip 216.239.32.21 255.255.255.0
@@ -8,11 +8,11 @@
 # example: v-add-sys-ip 1234:55:66::1 /64
 # example: v-add-sys-ip 1234:55:66::1/64
 #
-# This function adds ip address into a system. It also creates rc scripts. You
-# can specify ip name which will be used as root domain for temporary aliases.
+# This function adds IP address into a system. It also creates rc scripts. You
+# can specify IP name which will be used as root domain for temporary aliases.
 # For example, if you set a1.myhosting.com as name, each new domain created on
-# this ip will automatically receive alias $domain.a1.myhosting.com. Of course
-# you must have wildcard record *.a1.myhosting.com pointed to ip. This feature
+# this IP will automatically receive alias $domain.a1.myhosting.com. Of course
+# you must have wildcard record *.a1.myhosting.com pointed to IP. This feature
 # is very handy when customer wants to test domain before dns migration.
 
 #----------------------------------------------------------#
@@ -20,11 +20,19 @@
 #----------------------------------------------------------#
 
 # Argument definition
-first_parameter=${1// /}										# conventional delete of spaces
-ip46=${1%/*}													# clean ip address without cidr/prefix_length
-[ -n "$ip46" ] && [ "$ip46" = "${1}" ] || ip_cidr=${1#$ip46}	# extract cidr/prefix from first parameter
-second_parameter=${2}											# second parameter can be netmask, cidr or prefix_length
-iface="${3}"
+first_parameter=${1// /}                                     # conventional delete of spaces
+ip46=${1%/*}                                                 # clean ip address without cidr/prefix_length
+[ -n "$ip46" ] && [ "$ip46" = "${1}" ] || ip_cidr=${1#$ip46} # extract cidr/prefix from first parameter
+second_parameter=${2}                                        # second parameter can be netmask, cidr or prefix_length
+# Get interface name
+# First try to detect which interface the IP address resides on
+iface="$(ip -d -j addr show | jq --arg IP "$ip46" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')"
+# If that fails, detect the default interface as a fallback
+if [ -z "$iface" ]; then
+	iface="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')"
+fi
+
+iface="${3-$iface}"
 user="${4-admin}"
 ip_status="${5-shared}"
 ip_name="${6}"
@@ -48,15 +56,15 @@ source_conf "$HESTIA/conf/hestia.conf"
 
 check_args '1' "$#" 'IP [NETMASK] [INTERFACE] [USER] [STATUS] [NAME] [NATED_IP]'
 
-ip_format="$(get_ip_format ${ip46})"	#	ip verification and format identification
+ip_format="$(get_ip_format ${ip46})" #	ip verification and format identification
 if [ -n "$second_parameter" -a -n "$ip_format" ]; then
-	[ -n "$ip_cidr" ] && check_result 1 "cidr / prefix length double defined as IP address suffix and as separate argument!"	# wrong parameters
-	netmask="$(echo ${second_parameter} | sed -nr ''/$REGEX_IPV4/p'')"				# extract netmask from second parameter if available
-	cidr_prefixlen="$(echo ${second_parameter} | sed -ne '/^\/[0-9]\{1,3\}$/p')"	# extract cidr/prefix_length from second parameter if available
-	[ -z "$netmask" -a -z "$cidr_prefixlen" ] && check_result 2 "Wrong netmask / cidr / prefix length definition!"	# wrong parameters
-	[ -n "$netmask" -a $ip_format -ne 4 ] && check_result 3 "Netmask definition for a not IPV4 address! Define a prefix lenght instead of netmask!"	# wrong parameters
+	[ -n "$ip_cidr" ] && check_result 1 "cidr / prefix length double defined as IP address suffix and as separate argument!"                        # wrong parameters
+	netmask="$(echo ${second_parameter} | sed -nr ''/$REGEX_IPV4/p'')"                                                                              # extract netmask from second parameter if available
+	cidr_prefixlen="$(echo ${second_parameter} | sed -ne '/^\/[0-9]\{1,3\}$/p')"                                                                    # extract cidr/prefix_length from second parameter if available
+	[ -z "$netmask" -a -z "$cidr_prefixlen" ] && check_result 2 "Wrong netmask / cidr / prefix length definition!"                                  # wrong parameters
+	[ -n "$netmask" -a $ip_format -ne 4 ] && check_result 3 "Netmask definition for a not IPV4 address! Define a prefix lenght instead of netmask!" # wrong parameters
 fi
-# is_ip_format_valid 'ip46'	# check for correct ipv4 or ipv6 format 
+# is_ip_format_valid 'ip46'	# check for correct ipv4 or ipv6 format
 add_string_ipv6=""
 add_cap_string_ipv6=""
 full_ip46=""
@@ -67,8 +75,8 @@ if [ -n "$ip_format" ]; then
 		ip=${ip46}
 		ipv6=''
 		if [ -n "$netmask" ]; then
-			is_ip_format_valid "${netmask}" 'netmask'	# check for correct netmask
-			cidr="$(convert_netmask $netmask)"			# convert netmask to cidr
+			is_ip_format_valid "${netmask}" 'netmask' # check for correct netmask
+			cidr="$(convert_netmask $netmask)"        # convert netmask to cidr
 		fi
 		if [ -n "$cidr_prefixlen" ]; then
 			cidr=${cidr_prefixlen}
@@ -78,11 +86,11 @@ if [ -n "$ip_format" ]; then
 		else
 			[ -z "$cidr" ] && cidr="/32"
 		fi
-		if [ -z "$netmask" ]; then 
-			is_ip_format_valid "${cidr}" 'cidr'	# check for correct cidr
-			netmask=$(convert_cidr ${cidr})	# convert cidr to netmask
+		if [ -z "$netmask" ]; then
+			is_ip_format_valid "${cidr}" 'cidr' # check for correct cidr
+			netmask=$(convert_cidr ${cidr})     # convert cidr to netmask
 		fi
-		is_ip_format_valid "${ip}" 'ipv4'	# check for correct ipv4 format 
+		is_ip_format_valid "${ip}" 'ipv4'       # check for correct ipv4 format
 		broadcast=$(get_broadcast $ip $netmask) # generate broadcast
 		full_ip46="$ip$cidr"
 		netmask_prelen="${netmask}"
@@ -98,8 +106,8 @@ if [ -n "$ip_format" ]; then
 		else
 			[ -z "$prefix_length" ] && prefix_length="/64"
 		fi
-		is_ip_format_valid "${ipv6}" 'ipv6'	# check for correct ipv6 format 
-		broadcast="" 				# reset broadcast
+		is_ip_format_valid "${ipv6}" 'ipv6' # check for correct ipv6 format
+		broadcast=""                        # reset broadcast
 		full_ip46="$ipv6$prefix_length"
 		netmask_prelen="${prefix_length}"
 		closed_ip="[${ipv6}]"
@@ -107,8 +115,8 @@ if [ -n "$ip_format" ]; then
 	fi
 fi
 
-[ -z "$iface" ] && iface="$($BIN/v-list-sys-interfaces plain | head -n 1)" 			# Get first available system interface, if none defined
-[ -z "$iface" ] && iface='eth0' # eth0, if still not defined
+[ -z "$iface" ] && iface="$($BIN/v-list-sys-interfaces plain | head -n 1)" # Get first available system interface, if none defined
+[ -z "$iface" ] && iface='eth0'                                            # eth0, if still not defined
 
 is_format_valid 'netmask' 'cidr' 'prefix_length' 'iface' 'user' 'ip_status'
 is_ip_free ${ip46}
@@ -133,32 +141,32 @@ check_hestia_demo_mode
 
 check_ip_par=""
 [ -n "$ip_format" ] && [ $ip_format -eq 4 -o $ip_format -eq 6 ] && check_ip_par=" -${ip_format}"
-sys_ip_check=$(/sbin/ip$check_ip_par addr | sed -ne "/inet[6]*[ \t]${ip46}\//p")
+sys_ip_check=$(ip$check_ip_par addr | sed -ne "/inet[6]*[ \t]${ip46}\//p")
 if [ -z "$sys_ip_check" ]; then
-	# Adding sys ip
+	# Adding system IP
 	if [ -n "$ip_format" ] && [ $ip_format -eq 6 ]; then
 		/sbin/ip addr add ${full_ip46} dev ${iface%:*} label ${iface}
 	else
-		/sbin/ip addr add ${full_ip46} dev ${iface} broadcast $broadcast label ${iface}
+		ip addr add ${full_ip46} dev ${iface} broadcast ${broadcast} label ${iface}
 	fi
-	sleep 2	# wait to avoid issues with apache and nginx port binding								 
+	sleep 2 # wait to avoid issues with apache and nginx port binding
 
 	# Check if netplan is in use and generate configuration file
 	if [ -n "$(which netplan)" ]; then
-		if [ -n "$(netplan generate --mapping "${iface}" | grep networkd)" ]; then
-			netplan=1
+		if [ -n "$(netplan generate --mapping "${iface}" 2> /dev/null | grep networkd)" ]; then
+			netplan="true"
 		else
-			netplan=0
+			netplan="false"
 		fi
 	else
-		netplan=0
+		netplan="false"
 	fi
 
-	if [ "$netplan" == "1" ]; then
+	if [ "$netplan" = "true" ]; then
 		if [ -f "/etc/netplan/60-hestia.yaml" ]; then
 			sys_ip="        - ${full_ip46}"
 		else
-			sys_ip="# Added by hestia, please do not edit the file manually!"
+			sys_ip="# Added by Hestia, please do not edit the file manually!"
 			sys_ip="$sys_ip\nnetwork:"
 			sys_ip="$sys_ip\n  version: 2"
 			sys_ip="$sys_ip\n  renderer: networkd"
@@ -185,11 +193,9 @@ if [ -z "$sys_ip_check" ]; then
 fi
 
 # Generating timestamp
-time_n_date=$(date +'%T %F')
-time=$(echo "$time_n_date" | cut -f 1 -d \ )
-date=$(echo "$time_n_date" | cut -f 2 -d \ )
+new_timestamp
 
-# Adding hestia ip
+# Adding Hestia IP
 echo "OWNER='$user'
 STATUS='$ip_status'
 NAME='$ip_name'
@@ -204,31 +210,31 @@ VERSION='${ip_format}'" > $HESTIA/data/ips/${ip46}
 chmod 660 $HESTIA/data/ips/${ip46}
 
 # WEB support
-if [ ! -z "$WEB_SYSTEM" ]; then
+if [ -n "$WEB_SYSTEM" ]; then
 	web_conf="/etc/$WEB_SYSTEM/conf.d/${ip46}.conf"
-	rm -f $web_conf
+	rm -f ${web_conf}
 
 	if [ "$WEB_SYSTEM" = 'httpd' ] || [ "$WEB_SYSTEM" = 'apache2' ]; then
 		if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then
-			echo "NameVirtualHost ${closed_ip}:$WEB_PORT" > $web_conf
+			echo "NameVirtualHost ${closed_ip}:$WEB_PORT" > ${web_conf}
 		fi
-		echo "Listen ${closed_ip}:$WEB_PORT" >> $web_conf
-		cat $HESTIA_INSTALL_DIR/apache2/unassigned.conf >> $web_conf
-        [ -n "$ip_format" ] && [ $ip_format -eq 6 ] && sed -i 's/\(VirtualHost \)directIP/\1'${closed_ip}'/g' $web_conf														   
-		sed -i 's/directIP/'${ip46}'/g' $web_conf
-		sed -i 's/directPORT/'$WEB_PORT'/g' $web_conf
+		echo "Listen ${closed_ip}:$WEB_PORT" >> ${web_conf}
+		cat $HESTIA_INSTALL_DIR/apache2/unassigned.conf >> ${web_conf}
+		[ -n "$ip_format" ] && [ $ip_format -eq 6 ] && sed -i 's/\(VirtualHost \)directIP/\1'${closed_ip}'/g' ${web_conf}
+		sed -i 's/directIP/'${ip46}'/g' ${web_conf}
+		sed -i 's/directPORT/'$WEB_PORT'/g' ${web_conf}
 
 	elif [ "$WEB_SYSTEM" = 'nginx' ]; then
-		cp -f $HESTIA_INSTALL_DIR/nginx/unassigned.inc $web_conf
-		sed -i 's/directIP/'${closed_ip}'/g' $web_conf
+		cp -f $HESTIA_INSTALL_DIR/nginx/unassigned.inc ${web_conf}
+		sed -i 's/directIP/'${closed_ip}'/g' ${web_conf}
 	fi
 
 	if [ "$WEB_SSL" = 'mod_ssl' ]; then
 		if [ -z "$(/usr/sbin/apachectl -v | grep Apache/2.4)" ]; then
-			sed -i "1s/^/NameVirtualHost ${closed_ip}:$WEB_SSL_PORT\n/" $web_conf
+			sed -i "1s/^/NameVirtualHost ${closed_ip}:$WEB_SSL_PORT\n/" ${web_conf}
 		fi
-		sed -i "1s/^/Listen ${closed_ip}:$WEB_SSL_PORT\n/" $web_conf
-		sed -i 's/directSSLPORT/'$WEB_SSL_PORT'/g' $web_conf
+		sed -i "1s/^/Listen ${closed_ip}:$WEB_SSL_PORT\n/" ${web_conf}
+		sed -i 's/directSSLPORT/'$WEB_SSL_PORT'/g' ${web_conf}
 	fi
 fi
 
@@ -244,24 +250,24 @@ if [ -n "$PROXY_SYSTEM" ]; then
 	# mod_extract_forwarded
 	fw_conf="/etc/$WEB_SYSTEM/conf.d/mod_extract_forwarded.conf"
 	if [ -e "$fw_conf" ]; then
-		ips=$(grep 'MEFaccept ' $fw_conf | grep -v '#' | head -n1)
-		sed -i "s/$ips/$ips $ip46/g" $fw_conf
+		ips=$(grep 'MEFaccept ' ${fw_conf} | grep -v '#' | head -n1)
+		sed -i "s/$ips/$ips $ip46/g" ${fw_conf}
 	fi
 
 	# mod_rpaf
 	rpaf_conf="/etc/$WEB_SYSTEM/mods-enabled/rpaf.conf"
 	if [ -e "$rpaf_conf" ]; then
-		rpaf_str=$(grep RPAFproxy_ips $rpaf_conf)
-		[ -z "$rpaf_str" ] && sed -i 's|</IfModule>|RPAFproxy_ips\n</IfModule>|' $rpaf_conf && rpaf_str='RPAFproxy_ips'
+		rpaf_str=$(grep RPAFproxy_ips ${rpaf_conf})
+		[ -z "$rpaf_str" ] && sed -i 's|</IfModule>|RPAFproxy_ips\n</IfModule>|' ${rpaf_conf} && rpaf_str='RPAFproxy_ips'
 		rpaf_str="$rpaf_str ${ip46}"
-		sed -i "s/.*RPAFproxy_ips.*/$rpaf_str/" $rpaf_conf
+		sed -i "s/.*RPAFproxy_ips.*/$rpaf_str/" ${rpaf_conf}
 	fi
 
 	#mod_remoteip
 	remoteip_conf="/etc/$WEB_SYSTEM/mods-enabled/remoteip.conf"
 	if [ -e "$remoteip_conf" ]; then
-		if [ $( grep -ic "${ip46}" $remoteip_conf ) -eq 0 ]; then
-			sed -i "s/<\/IfModule>/RemoteIPInternalProxy $ip46\n<\/IfModule>/g" $remoteip_conf
+		if [ $(grep -ic "${ip46}" ${remoteip_conf}) -eq 0 ]; then
+			sed -i "s/<\/IfModule>/RemoteIPInternalProxy $ip46\n<\/IfModule>/g" ${remoteip_conf}
 		fi
 	fi
 fi

+ 4 - 4
bin/v-change-sys-ip-name

@@ -1,11 +1,11 @@
 #!/bin/bash
-# info: change ip name
+# info: change IP name
 # options: IP NAME
 #
 # example: v-change-sys-ip-name 80.122.52.70 acme.com
 # example: v-change-sys-ip-name 1111:2222:3333::1 acme.com
 #
-# This function for changing dns domain associated with ip.
+# This function for changing dns domain associated with IP.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
@@ -30,7 +30,7 @@ source_conf "$HESTIA/conf/hestia.conf"
 #----------------------------------------------------------#
 
 check_args '2' "$#" 'IP IP_NAME'
-ip_format="$(get_ip_format ${ip46})"	#	ip verification and format identification
+ip_format="$(get_ip_format ${ip46})" #	ip verification and format identification
 if [ -n "$ip_format" ]; then
 	if [ $ip_format -eq 6 ]; then
 		ip=""
@@ -53,7 +53,7 @@ check_hestia_demo_mode
 #                       Action                             #
 #----------------------------------------------------------#
 
-# Changing ip name
+# Changing IP name
 update_ip_value '$NAME' "$ip_name" "${ip46}"
 
 #----------------------------------------------------------#

+ 32 - 32
bin/v-change-sys-ip-nat

@@ -1,11 +1,11 @@
 #!/bin/bash
-# info: change ip nat address
+# info: change NAT IP address
 # options: IP NAT_IP [RESTART]
 #
-# example: v-change-sys-ip-nat 185.209.50.140 10.110.104.205
+# example: v-change-sys-ip-nat 10.0.0.1 203.0.113.1
 # example: v-change-sys-ip-nat 1111:2222:3333::1 ''
 #
-# This function for changing nat ip associated with ip.
+# This function for changing NAT IP associated with IP.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
@@ -31,7 +31,7 @@ source_conf "$HESTIA/conf/hestia.conf"
 #----------------------------------------------------------#
 
 check_args '2' "$#" 'IP NAT_IP [RESTART]'
-ip_format="$(get_ip_format ${ip46})"	#	ip verification and format identification
+ip_format="$(get_ip_format ${ip46})" #	ip verification and format identification
 if [ -n "$ip_format" ]; then
 	if [ $ip_format -eq 6 ]; then
 		ip=""
@@ -59,11 +59,11 @@ check_hestia_demo_mode
 if [ -z "$(grep NAT= $HESTIA/data/ips/${ip46})" ]; then
 	sed -i "s/^TIME/NAT='$nat_ip'\nTIME/g" $HESTIA/data/ips/${ip46}
 	old=''
-	new=$nat_ip
+	new=${nat_ip}
 else
-	old=$(get_ip_value '$NAT')
-	new=$nat_ip
-	sed -i "s/NAT=.*/NAT='$new'/" $HESTIA/data/ips/${ip46}
+	old="$(get_ip_value '$NAT')"
+	new=${nat_ip}
+	sed -i "s/NAT=.*/NAT='$new'/" ${HESTIA}/data/ips/${ip46}
 	if [ -z "$nat_ip" ]; then
 		new=${ip46}
 	fi
@@ -72,54 +72,54 @@ fi
 # Updating WEB configs
 if [ -n "$old" ] && [ -n "$WEB_SYSTEM" ]; then
 	for user in $($BIN/v-list-sys-users plain); do
-		sed -i "s/$old/$new/" $HESTIA/data/users/$user/web.conf
-		$BIN/v-rebuild-web-domains $user no
+		sed -i "s/$old/$new/" ${HESTIA}/data/users/${user}/web.conf
+		${BIN}/v-rebuild-web-domains ${user} no
 	done
-	$BIN/v-restart-dns "$restart"
+	${BIN}/v-restart-dns "$restart"
 fi
 
 # Updating DNS configs
 if [ -n "$old" ] && [ -n "$DNS_SYSTEM" ]; then
-	for user in $($BIN/v-list-sys-users plain); do
-		sed -i "s/$old/$new/" $HESTIA/data/users/$user/dns.conf
-		if ls $HESTIA/data/users/$user/dns/*.conf 1> /dev/null 2>&1; then
-			sed -i "s/$old/$new/" $HESTIA/data/users/$user/dns/*.conf
+	for user in $(${BIN}/v-list-sys-users plain); do
+		sed -i "s/$old/$new/" ${HESTIA}/data/users/${user}/dns.conf
+		if ls ${HESTIA}/data/users/${user}/dns/*.conf 1> /dev/null 2>&1; then
+			sed -i "s/$old/$new/" ${HESTIA}/data/users/${user}/dns/*.conf
 		fi
-		$BIN/v-rebuild-dns-domains $user no
+		${BIN}/v-rebuild-dns-domains ${user} no
 	done
-	$BIN/v-restart-dns "$restart"
+	${BIN}/v-restart-dns "$restart"
 fi
 
 # Updating FTP
 if [ -n "$old" ] && [ -n "$FTP_SYSTEM" ]; then
-	conf=$(find /etc -name $FTP_SYSTEM.conf)
-	if [ -e "$conf" ]; then
-		sed -i "s/$old/$new/g" $conf
+	ftp_conf="$(find /etc -maxdepth 2 -name ${FTP_SYSTEM}.conf)"
+	if [ -e "$ftp_conf" ]; then
+		sed -i "s/$old/$new/g" ${ftp_conf}
 		if [ "$FTP_SYSTEM" = 'vsftpd' ]; then
-			check_pasv=$(grep pasv_address $conf)
+			check_pasv="$(grep pasv_address ${ftp_conf})"
 			if [ -z "$check_pasv" ] && [ -n "$nat_ip" ]; then
-				echo "pasv_address=$nat_ip" >> $conf
+				echo "pasv_address=$nat_ip" >> ${ftp_conf}
 			fi
 			if [ -n "$check_pasv" ] && [ -z "$nat_ip" ]; then
-				sed -i "/pasv_address/d" $conf
+				sed -i "/pasv_address/d" ${ftp_conf}
 			fi
 			if [ -n "$check_pasv" ] && [ -n "$nat_ip" ]; then
-				sed -i "s/pasv_address=.*/pasv_address='$nat_ip'/g" $conf
+				sed -i "s/pasv_address=.*/pasv_address='$nat_ip'/g" ${ftp_conf}
 			fi
 		fi
 	fi
 	if [ "$FTP_SYSTEM" = 'proftpd' ]; then
-        	conf="/etc/$FTP_SYSTEM/conf.d/external_ip.conf"
-        	content="MasqueradeAddress ${nat_ip}"
-        	echo "$content" > $conf
-    	fi
-	$BIN/v-restart-ftp "$restart"
+		ext_ip_conf="/etc/$FTP_SYSTEM/conf.d/external_ip.conf"
+		content="MasqueradeAddress ${nat_ip}"
+		echo "$content" > ${ext_ip_conf}
+	fi
+	${BIN}/v-restart-ftp "$restart"
 fi
 
 # Updating firewall
 if [ -n "$old" ] && [ -n "$FIREWALL_SYSTEM" ]; then
-	sed -i "s/$old/$new/g" $HESTIA/data/firewall/*.conf
-	$BIN/v-update-firewall
+	sed -i "s/$old/$new/g" ${HESTIA}/data/firewall/*.conf
+	${BIN}/v-update-firewall
 fi
 
 #----------------------------------------------------------#
@@ -127,7 +127,7 @@ fi
 #----------------------------------------------------------#
 
 # Logging
-$BIN/v-log-action "system" "Info" "System" "IP NAT address changed (IP: ${ip46}, NAT IP: $nat_ip)."
+${BIN}/v-log-action "system" "Info" "System" "IP NAT address changed (IP: ${ip46}, NAT IP: $nat_ip)."
 log_event "$OK" "$ARGUMENTS"
 
 exit

+ 11 - 11
bin/v-change-sys-ip-owner

@@ -1,26 +1,26 @@
 #!/bin/bash
-# info: change ip owner
+# info: change IP owner
 # options: IP USER
 #
 # example: v-change-sys-ip-owner 91.198.136.14 admin
 # example: v-change-sys-ip-owner 1111:2222:3333::1 admin
 #
-# This function of changing ip address ownership.
+# This function of changing IP address ownership.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
 #----------------------------------------------------------#
 
 # Argument definition
-ip46=$1
-user=$2
+ip46=${1}
+user=${2}
 
 # shellcheck source=/etc/hestiacp/hestia.conf
 source /etc/hestiacp/hestia.conf
 # shellcheck source=/usr/local/hestia/func/main.sh
-source $HESTIA/func/main.sh
+source ${HESTIA}/func/main.sh
 # shellcheck source=/usr/local/hestia/func/ip.sh
-source $HESTIA/func/ip.sh
+source ${HESTIA}/func/ip.sh
 # load config file
 source_conf "$HESTIA/conf/hestia.conf"
 
@@ -29,7 +29,7 @@ source_conf "$HESTIA/conf/hestia.conf"
 #----------------------------------------------------------#
 
 check_args '2' "$#" 'IP USER'
-ip_format="$(get_ip_format ${ip46})"	#	ip verification and format identification
+ip_format="$(get_ip_format ${ip46})" #	ip verification and format identification
 if [ -n "$ip_format" ]; then
 	if [ $ip_format -eq 6 ]; then
 		ip=""
@@ -58,7 +58,7 @@ check_hestia_demo_mode
 #                       Action                             #
 #----------------------------------------------------------#
 
-# Changing ip owner
+# Changing IP owner
 ip_owner=$(get_ip_value '$OWNER')
 if [ "$ip_owner" != "$user" ]; then
 	update_ip_value '$OWNER' "$user" "${ip46}"
@@ -93,8 +93,8 @@ fi
 
 # Set status to dedicated if owner is not admin
 ip_status="$(get_ip_value '$STATUS')"
-if [ "$user" != 'admin' ] && [ "$ip_status" == 'shared' ]; then
-	$BIN/v-change-sys-ip-status "${ip46}" 'dedicated'
+if [ "$user" != 'admin' ] && [ "$ip_status" = 'shared' ]; then
+	${BIN}/v-change-sys-ip-status "${ip46}" 'dedicated'
 fi
 
 #----------------------------------------------------------#
@@ -102,7 +102,7 @@ fi
 #----------------------------------------------------------#
 
 # Logging
-$BIN/v-log-action "system" "Info" "System" "IP address owner changed (IP: ${ip46}, Owner: $user)"
+${BIN}/v-log-action "system" "Info" "System" "IP address owner changed (IP: ${ip46}, Owner: $user)"
 log_event "$OK" "$ARGUMENTS"
 
 exit

+ 11 - 11
bin/v-change-sys-ip-status

@@ -1,11 +1,11 @@
 #!/bin/bash
-# info: change ip status
+# info: change IP status
 # options: IP IP_STATUS
 #
-# example: v-change-sys-ip-status 91.198.136.14 yourstatus
+# example: v-change-sys-ip-status 203.0.113.1 yourstatus
 # example: v-change-sys-ip-status 1111:2222:3333::1 yourstatus
 #
-# This function of changing an ip address's status.
+# This function of changing an IP address's status.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
@@ -19,9 +19,9 @@ ip_status=${2}
 # shellcheck source=/etc/hestiacp/hestia.conf
 source /etc/hestiacp/hestia.conf
 # shellcheck source=/usr/local/hestia/func/main.sh
-source $HESTIA/func/main.sh
+source ${HESTIA}/func/main.sh
 # shellcheck source=/usr/local/hestia/func/ip.sh
-source $HESTIA/func/ip.sh
+source ${HESTIA}/func/ip.sh
 # load config file
 source_conf "$HESTIA/conf/hestia.conf"
 
@@ -30,7 +30,7 @@ source_conf "$HESTIA/conf/hestia.conf"
 #----------------------------------------------------------#
 
 check_args '2' "$#" 'IP IP_STATUS'
-ip_format="$(get_ip_format ${ip46})"	#	ip verification and format identification
+ip_format="$(get_ip_format ${ip46})" #	ip verification and format identification
 if [ -n "$ip_format" ]; then
 	if [ $ip_format -eq 6 ]; then
 		ip=""
@@ -52,10 +52,10 @@ web_domains=$(get_ip_value '$U_WEB_DOMAINS')
 sys_user=$(get_ip_value '$U_SYS_USERS')
 ip_owner=$(get_ip_value '$OWNER')
 if [ "$web_domains" -ne '0' ] && [ "$sys_user" != "$ip_owner" ]; then
-	check_result "$E_INUSE" "ip ${ip46} is used"
+	check_result "$E_INUSE" "IP ${ip46} is used"
 fi
-if [ "$ip_owner" != "admin" ] && [ "$ip_status" == "shared" ]; then
-	$BIN/v-change-sys-ip-owner "${ip46}" "admin"
+if [ "$ip_owner" != "admin" ] && [ "$ip_status" = "shared" ]; then
+	${BIN}/v-change-sys-ip-owner "${ip46}" "admin"
 fi
 
 # Perform verification if read-only mode is enabled
@@ -65,7 +65,7 @@ check_hestia_demo_mode
 #                       Action                             #
 #----------------------------------------------------------#
 
-# Changing ip name
+# Changing IP status
 update_ip_value '$STATUS' "$ip_status" "${ip46}"
 
 #----------------------------------------------------------#
@@ -73,7 +73,7 @@ update_ip_value '$STATUS' "$ip_status" "${ip46}"
 #----------------------------------------------------------#
 
 # Logging
-$BIN/v-log-action "system" "Info" "System" "IP address status changed (Status: $ip_status, IP: ${ip46})."
+${BIN}/v-log-action "system" "Info" "System" "IP address status changed (Status: $ip_status, IP: ${ip46})."
 log_event "$OK" "$ARGUMENTS"
 
 exit

+ 39 - 38
bin/v-delete-sys-ip

@@ -1,30 +1,30 @@
 #!/bin/bash
-# info: delete system ip
+# info: delete system IP
 #       both kind of IP addresses, ipv4 and ipv6 are allowed
 # options: IP
 #
-# example: v-delete-sys-ip 212.42.76.210
+# example: v-delete-sys-ip 203.0.113.1
 # example: v-delete-sys-ip 1234:5678:abcd:ef90::1
 #
-# This function for deleting a system ip. It does not allow to delete first ip
-# on interface and do not allow to delete ip which is used by a web domain.
+# This function for deleting a system IP. It does not allow to delete first IP
+# on interface and do not allow to delete IP which is used by a web domain.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
 #----------------------------------------------------------#
 
 # Argument definition
-ip46=${1%/*}	# clean ip address without cidr/prefix_length
+ip46=${1%/*} # clean ip address without cidr/prefix_length
 
 # Includes
 # shellcheck source=/etc/hestiacp/hestia.conf
 source /etc/hestiacp/hestia.conf
 # shellcheck source=/usr/local/hestia/func/main.sh
-source $HESTIA/func/main.sh
+source ${HESTIA}/func/main.sh
 # shellcheck source=/usr/local/hestia/func/ip.sh
-source $HESTIA/func/ip.sh
+source ${HESTIA}/func/ip.sh
 # shellcheck source=/usr/local/hestia/func/domain.sh
-source $HESTIA/func/domain.sh
+source ${HESTIA}/func/domain.sh
 # load config file
 source_conf "$HESTIA/conf/hestia.conf"
 
@@ -33,7 +33,7 @@ source_conf "$HESTIA/conf/hestia.conf"
 #----------------------------------------------------------#
 
 check_args '1' "$#" 'IP'
-ip_format="$(get_ip_format ${ip46})"	#	ip verification and format identification
+ip_format="$(get_ip_format ${ip46})" #	ip verification and format identification
 retval=$?
 check_ip_par=""
 add_cap_string_ipv6=""
@@ -64,8 +64,8 @@ check_hestia_demo_mode
 #                       Action                             #
 #----------------------------------------------------------#
 
-# Import ip variables
-source $HESTIA/data/ips/${ip46}
+# Import IP variables
+source ${HESTIA}/data/ips/${ip46}
 if [ $ip_format -eq 6 ]; then
 	prefix_length=${NETMASK}
 	is_format_valid 'prefix_length'
@@ -76,27 +76,28 @@ else
 	cidr_prefixlen=$(convert_netmask "$netmask")
 fi
 
-host_ip_check=$(hostname -i | sed -ne "/$ip46/p") # check, if IP address is main (listed in /etc/hosts)
+host_ip_check=$(hostname -i | sed -ne "/$ip46/p")                                                # check, if IP address is primary (listed in /etc/hosts)
 interface=$($BIN/v-list-network plain | sed -ne "/$ip46/s/$ip46[ \t]*\/[0-9]*[ \t]*\(.*\)/\1/p") # interface for IP address
-number_of_ips=$(/sbin/ip${check_ip_par} addr | grep -c global) # number of global system IP addresses
+number_of_ips=$(/sbin/ip${check_ip_par} addr | grep -c global)                                   # number of global system IP addresses
 
-if [[ ( -n "$host_ip_check" && -n "$interface" ) || ( $number_of_ips -eq 1 ) ]]; then
-	echo "Error: can't delete main IP address"
+if [[ (-n "$host_ip_check" && -n "$interface") || ($number_of_ips -eq 1) ]]; then
+	echo "Error: can't delete primary IP address"
 	log_event "$E_FORBIDEN" "$ARGUMENTS"
 	exit "$E_FORBIDEN"
 fi
 
-# Deleting system ip
+# Deleting system IP
 if [ -n "$interface" ]; then
-	/sbin/ip addr del "$ip46$cidr_prefixlen" dev ${INTERFACE%:*}
+	ip addr del "$ip46$cidr_prefixlen" dev ${INTERFACE%:*}
 	if [ "$?" -ne 0 ]; then
-		echo "Error: can't delete system ip"
+		echo "Error: can't delete system IP address"
 		log_event "$E_FORBIDEN" "$ARGUMENTS"
-		exit $E_FORBIDEN
+		exit "$E_FORBIDEN"
 	fi
 fi
 
 # Deleting startup conf on RHEL/CentOS/Fedora
+# Need RHEL experts to fix me
 if [ -e "/etc/sysconfig/network-scripts/ifcfg-$interface" ]; then
 	rm -f /etc/sysconfig/network-scripts/ifcfg-$interface
 fi
@@ -110,10 +111,10 @@ if [ -f "/etc/netplan/60-hestia.yaml" ]; then
 elif [ -e "/etc/network/interfaces" ]; then
 	if [ $ip_format -eq 6 ]; then
 		filter_ip="${ip46}${cidr_prefixlen}"
-		lines_after=0	# ipv6 is defined using prefix length in one line
+		lines_after=0 # ipv6 is defined using prefix length in one line
 	else
 		filter_ip="${ip46}"
-		lines_after=1	# ipv4 is defined using netmask in a separate line
+		lines_after=1 # ipv4 is defined using netmask in a separate line
 	fi
 	ip_str=$(grep -n $filter_ip$ /etc/network/interfaces | cut -f1 -d:)
 	if [ -n "$ip_str" ]; then
@@ -123,38 +124,38 @@ elif [ -e "/etc/network/interfaces" ]; then
 	fi
 fi
 
-# Deleting hestia ip
-rm -f $HESTIA/data/ips/${ip46}
+# Deleting Hestia IP
+rm -f ${HESTIA}/data/ips/${ip46}
 
 # Deleting web config
 if [ -n "$WEB_SYSTEM" ]; then
-	rm -f /etc/$WEB_SYSTEM/conf.d/${ip46}.conf
+	rm -f /etc/${WEB_SYSTEM}/conf.d/${ip46}.conf
 fi
 
 # Deleting proxy config
 if [ -n "$PROXY_SYSTEM" ]; then
-	rm -f /etc/$PROXY_SYSTEM/conf.d/${ip46}.conf
+	rm -f /etc/${PROXY_SYSTEM}/conf.d/${ip46}.conf
 
 	# mod_extract_forwarded
 	fw_conf="/etc/$WEB_SYSTEM/conf.d/mod_extract_forwarded.conf"
 	if [ -e "$fw_conf" ]; then
-		ips=$(grep 'MEFaccept 127.0.0.1' $fw_conf)
-		new_ips=$(echo "$ips" | sed "s/$ip46//")
-		sed -i "s/$ips/$new_ips/g" $fw_conf
+		ips="$(grep 'MEFaccept 127.0.0.1' ${fw_conf})"
+		new_ips="$(echo "$ips" | sed "s/$ip46//")"
+		sed -i "s/$ips/$new_ips/g" ${fw_conf}
 	fi
 
 	# mod_rpaf
 	rpaf_conf="/etc/$WEB_SYSTEM/mods-enabled/rpaf.conf"
 	if [ -e "$rpaf_conf" ]; then
-		ips=$(grep RPAFproxy_ips "$rpaf_conf")
-		new_ips=$(echo "$ips" | sed "s/ $ip46//")
-		sed -i "s/$ips/$new_ips/g" "$rpaf_conf"
+		ips="$(grep RPAFproxy_ips ${rpaf_conf})"
+		new_ips="$(echo "$ips" | sed "s/ $ip46//")"
+		sed -i "s/$ips/$new_ips/g" ${rpaf_conf}
 
 		# Remove RPAFproxy_ips line when ip list is empty
-		[ "$(grep RPAFproxy_ips $rpaf_conf | sed 's/^[[:space:]]*//g')" = "RPAFproxy_ips" ] && sed -i "/RPAFproxy_ips/d" $rpaf_conf
+		[ "$(grep RPAFproxy_ips ${rpaf_conf} | sed 's/^[[:space:]]*//g')" = "RPAFproxy_ips" ] && sed -i "/RPAFproxy_ips/d" ${rpaf_conf}
 	fi
 
-	#mod_remoteip
+	# mod_remoteip
 	remoteip_conf="/etc/$WEB_SYSTEM/mods-enabled/remoteip.conf"
 	if [ -e "$remoteip_conf" ]; then
 		sed -i "/RemoteIPInternalProxy $ip46\$/d" "$remoteip_conf"
@@ -172,7 +173,7 @@ fi
 
 if [ "$OWNER" = 'admin' ]; then
 	if [ "$STATUS" = 'shared' ]; then
-		for hestia_user in $($BIN/v-list-sys-users plain); do
+		for hestia_user in $(${BIN}/v-list-sys-users plain); do
 			decrease_user_value "$hestia_user" '$IP'$add_cap_string_ipv6'_AVAIL'
 		done
 	else
@@ -183,22 +184,22 @@ else
 fi
 
 # Restarting web server
-$BIN/v-restart-web
+${BIN}/v-restart-web
 check_result $? "Web restart failed" > /dev/null
 
 # Restarting proxy server
 if [ -n "$PROXY_SYSTEM" ]; then
-	$BIN/v-restart-proxy
+	${BIN}/v-restart-proxy
 	check_result $? "Proxy restart failed" > /dev/null
 fi
 
 # Restarting firewall
 if [ -n "$FIREWALL_SYSTEM" ]; then
-	$BIN/v-update-firewall
+	${BIN}/v-update-firewall
 fi
 
 # Logging
-$BIN/v-log-action "system" "Info" "System" "IP address deleted (IP: $ip46)."
+${BIN}/v-log-action "system" "Info" "System" "IP address deleted (IP: $ip46)."
 log_event "$OK" "$ARGUMENTS"
 
 exit

+ 8 - 8
bin/v-list-sys-ip

@@ -1,11 +1,11 @@
 #!/bin/bash
-# info: list system ip
+# info: list system IP
 # options: IP [FORMAT]
 #
-# example: v-list-sys-ip 116.203.78.202
+# example: v-list-sys-ip 203.0.113.1
 # example: v-list-sys-ip 1234:55:66::1
 #
-# This function for getting the list of system ip parameters.
+# This function for getting the list of system IP parameters.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
@@ -19,9 +19,9 @@ format=${2-shell}
 # shellcheck source=/etc/hestiacp/hestia.conf
 source /etc/hestiacp/hestia.conf
 # shellcheck source=/usr/local/hestia/func/main.sh
-source $HESTIA/func/main.sh
+source ${HESTIA}/func/main.sh
 # shellcheck source=/usr/local/hestia/func/ip.sh
-source $HESTIA/func/ip.sh
+source ${HESTIA}/func/ip.sh
 # load config file
 source_conf "$HESTIA/conf/hestia.conf"
 
@@ -77,7 +77,7 @@ csv_list() {
 #----------------------------------------------------------#
 
 check_args '1' "$#" 'IP [FORMAT]'
-ip_format="$(get_ip_format ${ip46})"	#	ip verification and format identification
+ip_format="$(get_ip_format ${ip46})" #	ip verification and format identification
 if [ -n "$ip_format" ]; then
 	if [ $ip_format -eq 6 ]; then
 		ip=""
@@ -90,14 +90,14 @@ if [ -n "$ip_format" ]; then
 	fi
 fi
 if [ ! -e "$HESTIA/data/ips/${ip46}" ]; then
-	check_result $E_NOTEXIST "ip ${ip46} doesn't exist"
+	check_result $E_NOTEXIST "IP ${ip46} doesn't exist"
 fi
 
 #----------------------------------------------------------#
 #                       Action                             #
 #----------------------------------------------------------#
 
-# Parsing ip
+# Parsing IP
 source_conf "$HESTIA/data/ips/${ip46}"
 
 # Listing data

+ 8 - 9
bin/v-list-sys-ips

@@ -1,10 +1,10 @@
 #!/bin/bash
-# info: list system ips
+# info: list system IPs
 # options: [FORMAT]
 #
 # example: v-list-sys-ips
 #
-# This function for obtaining the list of system ip addresses.
+# This function for obtaining the list of system IP addresses.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
@@ -17,17 +17,17 @@ format=${1-shell}
 # shellcheck source=/etc/hestiacp/hestia.conf
 source /etc/hestiacp/hestia.conf
 # shellcheck source=/usr/local/hestia/func/main.sh
-source $HESTIA/func/main.sh
+source ${HESTIA}/func/main.sh
 # shellcheck source=/usr/local/hestia/func/ip.sh
-source $HESTIA/func/ip.sh
+source ${HESTIA}/func/ip.sh
 # load config file
 source_conf "$HESTIA/conf/hestia.conf"
 
 # ONLY IP list function
 only_ip_list() {
-	ls $HESTIA/data/ips/ | while read IP; do
+	ls ${HESTIA}/data/ips/ | while read IP; do
 		ip_format="$(get_ip_format ${IP})"
-		if [ -n "$ip_format" ]; then 
+		if [ -n "$ip_format" ]; then
 			echo "$IP"
 		fi
 	done
@@ -99,9 +99,8 @@ csv_list() {
 #----------------------------------------------------------#
 
 # Read IPs from IP configuration directory
-IPS="$(only_ip_list)"			# IP Listing
-IPN=$(echo "$IPS" | wc -l)		# Number of IPs
-
+IPS="$(only_ip_list)"      # IP Listing
+IPN=$(echo "$IPS" | wc -l) # Number of IPs
 
 # Listing data
 case $format in

+ 6 - 6
bin/v-list-user-ips

@@ -1,31 +1,31 @@
 #!/bin/bash
-# info: list user ips
+# info: list user IPs
 # options: USER [FORMAT]
 #
 # example: v-list-user-ips admin
 #
-# This function for obtaining the list of available ip addresses.
+# This function for obtaining the list of available IP addresses.
 
 #----------------------------------------------------------#
 #                Variables & Functions                     #
 #----------------------------------------------------------#
 
 # Argument definition
-user=$1
+user=${1}
 format=${2-shell}
 
 # Includes
 # shellcheck source=/etc/hestiacp/hestia.conf
 source /etc/hestiacp/hestia.conf
 # shellcheck source=/usr/local/hestia/func/main.sh
-source $HESTIA/func/main.sh
+source ${HESTIA}/func/main.sh
 # load config file
 source_conf "$HESTIA/conf/hestia.conf"
 
 # Read and filter IP config file
 read_ip_config() {
 	VERSION=""
-	source_conf "$HESTIA/data/ips/$1"
+	source_conf "${HESTIA}/data/ips/$1"
 	if [ -z "$VERSION" ]; then
 		VERSION=4
 	fi
@@ -105,7 +105,7 @@ is_object_valid 'user' 'USER' "$user"
 owner='admin'
 owner_ips="$(grep -A 1 -H "OWNER='$owner'" $HESTIA/data/ips/* | grep "STATUS='shared'" | sed 's/.*\/\([^\/*]\)/\1/;s/-STATUS.*//')"
 user_ips="$(grep -l "OWNER='$user'" $HESTIA/data/ips/* | sed 's/.*\/\([^\/*]\)/\1/')"
-ips=$(echo -e "$user_ips\n$owner_ips" | sort -u | sed "/^$/d")
+ips="$(echo -e "$user_ips\n$owner_ips" | sort -u | sed "/^$/d")"
 fields='$IP $OWNER $STATUS $NAME $NAT'
 
 # Listing data

+ 70 - 52
bin/v-update-sys-ip

@@ -1,12 +1,12 @@
 #!/bin/bash
-# info: update system ip
+# info: update system IP
 # options: NONE
 #
 # example: v-update-sys-ip
 #          # Intended for internal usage
 #
-# This function scans configured ip in the system and register them with hestia
-# internal database. This call is intended for use on vps servers, where ip is
+# This function scans configured IP in the system and register them with Hestia
+# internal database. This call is intended for use on vps servers, where IP is
 # set by hypervisor.
 
 #----------------------------------------------------------#
@@ -17,9 +17,9 @@
 # shellcheck source=/etc/hestiacp/hestia.conf
 source /etc/hestiacp/hestia.conf
 # shellcheck source=/usr/local/hestia/func/main.sh
-source $HESTIA/func/main.sh
+source ${HESTIA}/func/main.sh
 # shellcheck source=/usr/local/hestia/func/ip.sh
-source $HESTIA/func/ip.sh
+source ${HESTIA}/func/ip.sh
 # load config file
 source_conf "$HESTIA/conf/hestia.conf"
 
@@ -34,10 +34,10 @@ check_hestia_demo_mode
 #                       Action                             #
 #----------------------------------------------------------#
 
-# Listing system ip addresses
-ips=$(/sbin/ip -4 addr | sed -ne '/inet.*global/s/[ \t]*inet[ \t]*\([^ ^\t^\/]*\)\/[ \t]*.*/\1/p')
-ipv6s=$(/sbin/ip -6 addr | sed -ne '/inet6.*global/s/[ \t]*inet6[ \t]*\([^ ^\t^\/]*\)\/[ \t]*.*/\1/p')
-v_ips="$($HESTIA/bin/v-list-sys-ips list)"
+# Listing system IP addresses
+ips=$(ip -4 addr | sed -ne '/inet.*global/s/[ \t]*inet[ \t]*\([^ ^\t^\/]*\)\/[ \t]*.*/\1/p')
+ipv6s=$(ip -6 addr | sed -ne '/inet6.*global/s/[ \t]*inet6[ \t]*\([^ ^\t^\/]*\)\/[ \t]*.*/\1/p')
+v_ips="$(${HESTIA}/bin/v-list-sys-ips list)"
 ip_num=$(echo "$ips" | wc -l)
 ipv6_num=$(echo "$ipv6s" | wc -l)
 v_ip_num=$(echo "$v_ips" | wc -l)
@@ -45,103 +45,121 @@ v_ip_num=$(echo "$v_ips" | wc -l)
 # Checking primary IP change
 if [ "$ip_num" -eq 1 -a "$ipv6_num" -eq 0 -a "$v_ip_num" -eq 1 ]; then
 	if [ "$ips" != "$v_ips" ]; then
-		new=$ips
-		old=$v_ips
+		new_ip=$ips
+		old_ip=$v_ips
 	fi
 fi
 
 if [ "$ipv6_num" -eq 1 -a "$ip_num" -eq 0 -a "$v_ip_num" -eq 1 ]; then
 	if [ "$ipv6s" != "$v_ips" ]; then
-		new=$ipv6s
-		old=$v_ips
+		new_ip=${ipv6s}
+		old_ip=${v_ips}
 	fi
 fi
 
 # Updating configs
-if [ -n "$new" ]; then
-	mv $HESTIA/data/ips/$old $HESTIA/data/ips/$new
+if [ -n "$old_ip" ]; then
+	mv ${HESTIA}/data/ips/${old_ip} ${HESTIA}/data/ips/${new_ip}
+
+	# Generating timestamp
+	new_timestamp
+
+	# Updating IP's values
+	ip="$new_ip"
+	interface="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[] | if .addr_info[].local == $IP then .ifname else empty end')"
+	prefixlen="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[].addr_info[] | if .local == $IP then .prefixlen else empty end')"
+	netmask="$(convert_cidr "$prefixlen")"
+	update_ip_value '$INTERFACE' "$interface"
+	update_ip_value '$NETMASK' "$netmask"
+	update_ip_value '$TIME' "$time"
+	update_ip_value '$DATE' "$date"
 
 	# Updating PROXY
 	if [ -n "$PROXY_SYSTEM" ]; then
-		cd /etc/$PROXY_SYSTEM/conf.d
-		if [ -e "$old.conf" ]; then
-			mv $old.conf $new.conf
-			sed -i "s/$old/$new/g" $new.conf
+		cd /etc/${PROXY_SYSTEM}/conf.d
+		if [ -e "$old_ip.conf" ]; then
+			mv $old_ip.conf $new_ip.conf
+			sed -i "s/$old_ip/$new_ip/g" $new_ip.conf
 		fi
 	fi
 
 	# Updating WEB
 	if [ -n "$WEB_SYSTEM" ]; then
-		cd /etc/$WEB_SYSTEM/conf.d
-		if [ -e "$old.conf" ]; then
-			mv $old.conf $new.conf
-			sed -i "s/$old/$new/g" $new.conf
+		cd /etc/${WEB_SYSTEM}/conf.d
+		if [ -e "$old_ip.conf" ]; then
+			mv $old_ip.conf $new_ip.conf
+			sed -i "s/$old_ip/$new_ip/g" $new_ip.conf
 		fi
-		for user in $($BIN/v-list-sys-users plain); do
-			sed -i "s/$old/$new/g" $HESTIA/data/users/$user/web.conf
-			$BIN/v-rebuild-web-domains "$user" no
+		for user in $(${BIN}/v-list-sys-users plain); do
+			sed -i "s/$old_ip/$new_ip/g" ${HESTIA}/data/users/${user}/web.conf
+			${BIN}/v-rebuild-web-domains "$user" no
 		done
 
 		if [ -e "/etc/apache2/mods-available/remoteip.conf" ]; then
-			sed -i "s/$old/$new/g" /etc/apache2/mods-available/remoteip.conf
+			sed -i "s/$old_ip/$new_ip/g" /etc/apache2/mods-available/remoteip.conf
 		fi
 
 		if [ -e "/etc/apache2/mods-enabled/rpaf.conf" ]; then
-			sed -i "s/$old/$new/g" /etc/apache2/mods-enabled/rpaf.conf
+			sed -i "s/$old_ip/$new_ip/g" /etc/apache2/mods-enabled/rpaf.conf
 		fi
 
-		$BIN/v-restart-proxy
-		$BIN/v-restart-web
+		${BIN}/v-restart-proxy
+		${BIN}/v-restart-web
 	fi
 
+	# Updating MAIL
 	if [ -n "$IMAP_SYSTEM" ]; then
-		for user in $($BIN/v-list-sys-users plain); do
-			$BIN/v-rebuild-mail-domains "$user" no
+		for user in $(${BIN}/v-list-sys-users plain); do
+			${BIN}/v-rebuild-mail-domains "$user" no
 		done
+		${BIN}/v-restart-mail
 	fi
 
 	# Updating DNS
-	if [ ! -z "$DNS_SYSTEM" ]; then
-		for user in $($BIN/v-list-sys-users plain); do
-			sed -i "s/$old/$new/g" $HESTIA/data/users/$user/dns.conf
-			sed -i "s/$old/$new/g" $HESTIA/data/users/$user/dns/*.conf
-			$BIN/v-rebuild-dns-domains "$user" no
+	if [ -n "$DNS_SYSTEM" ]; then
+		for user in $(${BIN}/v-list-sys-users plain); do
+			sed -i "s/$old_ip/$new_ip/g" ${HESTIA}/data/users/${user}/dns.conf
+			sed -i "s/$old_ip/$new_ip/g" ${HESTIA}/data/users/${user}/dns/*.conf
+			${BIN}/v-rebuild-dns-domains "$user" no
 		done
-		$BIN/v-restart-dns
+		${BIN}/v-restart-dns
 	fi
 
 	# Updating FTP
-	if [ ! -z "$FTP_SYSTEM" ] && [ "$FTP_SYSTEM" = 'vsftpd' ]; then
-		conf=$(find /etc/ -maxdepth 2 -name $FTP_SYSTEM.conf)
-		if [ ! -z "$conf" ]; then
-			sed -i "s/$old/$new/g" $conf
-			$BIN/v-restart-ftp
+	if [ -n "$FTP_SYSTEM" ] && [ "$FTP_SYSTEM" = 'vsftpd' ]; then
+		ftp_conf="$(find /etc/ -maxdepth 2 -name $FTP_SYSTEM.conf)"
+		if [ -n "$ftp_conf" ]; then
+			sed -i "s/$old_ip/$new_ip/g" ${ftp_conf}
+			${BIN}/v-restart-ftp
 		fi
 	fi
 
 	# Updating firewall
-	if [ ! -z "$FIREWALL_SYSTEM" ]; then
-		sed -i "s/$old/$new/g" $HESTIA/data/firewall/*.conf
-		$BIN/v-update-firewall
+	if [ -n "$FIREWALL_SYSTEM" ]; then
+		sed -i "s/$old_ip/$new_ip/g" $HESTIA/data/firewall/*.conf
+		${BIN}/v-update-firewall
 	fi
 fi
 
 # Adding system IP
-$BIN/v-list-network plain | while read listed_ip listed_mask listed_iface; do
+${BIN}/v-list-network plain | while read listed_ip listed_mask listed_iface; do
 	if [ ! -e "$HESTIA/data/ips/${listed_ip}" ]; then
-		$BIN/v-add-sys-ip ${listed_ip} ${listed_mask} ${listed_iface}
+		${BIN}/v-add-sys-ip ${listed_ip} ${listed_mask} ${listed_iface}
 	fi
 done
 
 # Updating NAT
-pub_ip=$(curl --ipv4 -s https://ip.hestiacp.com/)
+pub_ipv4="$(curl -fsLm5 --retry 2 --ipv4 https://ip.hestiacp.com/)"
 if [ ! -e "$HESTIA/data/ips/$pub_ip" ]; then
-	if [ -z "$(grep -R "$pub_ip" $HESTIA/data/ips/)" ]; then
-		ip=$(ls -t $HESTIA/data/ips/ | head -n1)
-		$BIN/v-change-sys-ip-nat "$ip" "$pub_ip"
+	if [ -z "$(grep -R "$pub_ip" ${HESTIA}/data/ips/)" ]; then
+		ip="$(ls -t ${HESTIA}/data/ips/ | head -n1)"
+		${BIN}/v-change-sys-ip-nat "$ip" "$pub_ipv4"
 	fi
 fi
 
+# Updating IP usage counters
+${BIN}/v-update-sys-ip-counters
+
 #----------------------------------------------------------#
 #                       Hestia                             #
 #----------------------------------------------------------#

+ 4 - 3
func/main.sh

@@ -1102,15 +1102,16 @@ is_int_format_valid() {
 
 # Interface validator
 is_interface_format_valid() {
-	netdevices=$(cat /proc/net/dev | grep : | cut -f 1 -d : | tr -d ' ')
-	if [ -z $(echo "$netdevices" | grep -x ${1%:*}) ]; then
+	# Detect "physical" NICs only (virtual NICs created by Docker, WireGuard etc. are excluded)
+	nic_names="$(ip -d -j link show | jq -r '.[] | if .link_type == "loopback" // .linkinfo.info_kind then empty else .ifname, if .altnames then .altnames[] else empty end end')"
+	if [ -z "$(echo "$nic_names" | grep -x ${1%:*})" ]; then
 		check_result "$E_INVALID" "invalid interface format :: $1"
 	fi
 }
 
 # IP status validator
 is_ip_status_format_valid() {
-	if [ -z "$(echo shared,dedicated | grep -w $1)" ]; then
+	if [ -z "$(echo shared,dedicated | grep -w ${1})" ]; then
 		check_result "$E_INVALID" "invalid status format :: $1"
 	fi
 }

+ 163 - 140
install/hst-install-debian.sh

@@ -49,7 +49,7 @@ software="acl apache2 apache2-suexec-custom apache2-suexec-pristine apache2-util
   php$fpm_v-pgsql php$fpm_v-pspell php$fpm_v-readline php$fpm_v-xml php$fpm_v-zip postgresql postgresql-contrib
   proftpd-basic quota rrdtool rsyslog spamassassin sudo sysstat unrar-free unzip util-linux vim-common vsftpd whois zip zstd"
 
-installer_dependencies="apt-transport-https ca-certificates curl dirmngr gnupg wget"
+installer_dependencies="apt-transport-https ca-certificates curl dirmngr gnupg openssl wget"
 
 # Defining help function
 help() {
@@ -147,21 +147,21 @@ set_default_port() {
 write_config_value() {
 	local key="$1"
 	local value="$2"
-	echo "$key='$value'" >> $HESTIA/conf/hestia.conf
+	echo "$key='$value'" >> ${HESTIA}/conf/hestia.conf
 }
 
 # Sort configuration file values
 # Write final copy to $HESTIA/conf/hestia.conf for active usage
 # Duplicate file to $HESTIA/conf/defaults/hestia.conf to restore known good installation values
 sort_config_file() {
-	sort $HESTIA/conf/hestia.conf -o /tmp/updconf
-	mv $HESTIA/conf/hestia.conf $HESTIA/conf/hestia.conf.bak
-	mv /tmp/updconf $HESTIA/conf/hestia.conf
-	rm -f $HESTIA/conf/hestia.conf.bak
+	sort ${HESTIA}/conf/hestia.conf -o /tmp/updconf
+	mv ${HESTIA}/conf/hestia.conf ${HESTIA}/conf/hestia.conf.bak
+	mv /tmp/updconf ${HESTIA}/conf/hestia.conf
+	rm -f ${HESTIA}/conf/hestia.conf.bak
 	if [ ! -d "$HESTIA/conf/defaults/" ]; then
-		mkdir -p "$HESTIA/conf/defaults/"
+		mkdir -p "${HESTIA}/conf/defaults/"
 	fi
-	cp $HESTIA/conf/hestia.conf $HESTIA/conf/defaults/hestia.conf
+	cp ${HESTIA}/conf/hestia.conf ${HESTIA}/conf/defaults/hestia.conf
 }
 
 # Validate hostname according to RFC1178
@@ -698,7 +698,7 @@ if [ -z "$(swapon -s)" ] && [ "$memory" -lt 1000000 ]; then
 	chmod 600 /swapfile
 	mkswap /swapfile
 	swapon /swapfile
-	echo "/swapfile   none    swap    sw    0   0" >> /etc/fstab
+	echo "/swapfile	none	swap	sw	0	0" >> /etc/fstab
 fi
 
 #----------------------------------------------------------#
@@ -799,7 +799,10 @@ check_result $? 'apt-get upgrade failed'
 mkdir -p $hst_backups
 cd $hst_backups
 mkdir nginx apache2 php vsftpd proftpd bind exim4 dovecot clamd
-mkdir spamassassin mysql postgresql hestia
+mkdir spamassassin mysql postgresql openssl hestia
+
+# Backup OpenSSL configuration
+cp /etc/ssl/openssl.cnf $hst_backups/openssl > /dev/null 2>&1
 
 # Backup nginx configuration
 systemctl stop nginx > /dev/null 2>&1
@@ -812,7 +815,7 @@ rm -f /etc/apache2/conf.d/* > /dev/null 2>&1
 
 # Backup PHP-FPM configuration
 systemctl stop php*-fpm > /dev/null 2>&1
-cp -r /etc/php/* $hst_backups/php/ > /dev/null 2>&1
+cp -r /etc/php/* $hst_backups/php > /dev/null 2>&1
 
 # Backup Bind configuration
 systemctl stop bind9 > /dev/null 2>&1
@@ -852,9 +855,9 @@ mv -f /root/.my.cnf $hst_backups/mysql > /dev/null 2>&1
 
 # Backup Hestia
 systemctl stop hestia > /dev/null 2>&1
-cp -r $HESTIA/* $hst_backups/hestia > /dev/null 2>&1
+cp -r ${HESTIA}/* $hst_backups/hestia > /dev/null 2>&1
 apt-get -y purge hestia hestia-nginx hestia-php > /dev/null 2>&1
-rm -rf $HESTIA > /dev/null 2>&1
+rm -rf ${HESTIA} > /dev/null 2>&1
 
 #----------------------------------------------------------#
 #                     Package Includes                     #
@@ -1047,7 +1050,7 @@ systemctl restart ssh
 # Disable AWStats cron
 rm -f /etc/cron.d/awstats
 # Replace awstatst function
-cp -f $HESTIA_INSTALL_DIR/logrotate/httpd-prerotate/* /etc/logrotate.d/httpd-prerotate/
+cp -f ${HESTIA_INSTALL_DIR}/logrotate/httpd-prerotate/* /etc/logrotate.d/httpd-prerotate/
 
 # Set directory color
 if [ -z "$(grep 'LS_COLORS="$LS_COLORS:di=00;33"' /etc/profile)" ]; then
@@ -1084,7 +1087,7 @@ fi
 echo "[ * ] Configuring Hestia Control Panel..."
 # Installing sudo configuration
 mkdir -p /etc/sudoers.d
-cp -f $HESTIA_INSTALL_DIR/sudo/admin /etc/sudoers.d/
+cp -f ${HESTIA_INSTALL_DIR}/sudo/admin /etc/sudoers.d/
 chmod 440 /etc/sudoers.d/admin
 
 # Add Hestia global config
@@ -1101,30 +1104,30 @@ chmod 755 /etc/profile.d/hestia.sh
 source /etc/profile.d/hestia.sh
 
 # Configuring logrotate for Hestia logs
-cp -f $HESTIA_INSTALL_DIR/logrotate/hestia /etc/logrotate.d/hestia
+cp -f ${HESTIA_INSTALL_DIR}/logrotate/hestia /etc/logrotate.d/hestia
 
 # Create log path and symbolic link
 rm -f /var/log/hestia
 mkdir -p /var/log/hestia
-ln -s /var/log/hestia $HESTIA/log
+ln -s /var/log/hestia ${HESTIA}/log
 
 # Building directory tree and creating some blank files for Hestia
-mkdir -p $HESTIA/conf $HESTIA/ssl $HESTIA/data/ips \
-	$HESTIA/data/queue $HESTIA/data/users $HESTIA/data/firewall \
-	$HESTIA/data/sessions
-touch $HESTIA/data/queue/backup.pipe $HESTIA/data/queue/disk.pipe \
-	$HESTIA/data/queue/webstats.pipe $HESTIA/data/queue/restart.pipe \
-	$HESTIA/data/queue/traffic.pipe $HESTIA/data/queue/daily.pipe $HESTIA/log/system.log \
-	$HESTIA/log/nginx-error.log $HESTIA/log/auth.log $HESTIA/log/backup.log
-chmod 750 $HESTIA/conf $HESTIA/data/users $HESTIA/data/ips $HESTIA/log
-chmod -R 750 $HESTIA/data/queue
+mkdir -p ${HESTIA}/conf ${HESTIA}/ssl ${HESTIA}/data/ips \
+	${HESTIA}/data/queue ${HESTIA}/data/users ${HESTIA}/data/firewall \
+	${HESTIA}/data/sessions
+touch ${HESTIA}/data/queue/backup.pipe ${HESTIA}/data/queue/disk.pipe \
+	${HESTIA}/data/queue/webstats.pipe ${HESTIA}/data/queue/restart.pipe \
+	${HESTIA}/data/queue/traffic.pipe ${HESTIA}/data/queue/daily.pipe ${HESTIA}/log/system.log \
+	${HESTIA}/log/nginx-error.log ${HESTIA}/log/auth.log ${HESTIA}/log/backup.log
+chmod 750 ${HESTIA}/conf ${HESTIA}/data/users ${HESTIA}/data/ips ${HESTIA}/log
+chmod -R 750 ${HESTIA}/data/queue
 chmod 660 /var/log/hestia/*
-chmod 770 $HESTIA/data/sessions
+chmod 770 ${HESTIA}/data/sessions
 
 # Generating Hestia configuration
-rm -f $HESTIA/conf/hestia.conf > /dev/null 2>&1
-touch $HESTIA/conf/hestia.conf
-chmod 660 $HESTIA/conf/hestia.conf
+rm -f ${HESTIA}/conf/hestia.conf > /dev/null 2>&1
+touch ${HESTIA}/conf/hestia.conf
+chmod 660 ${HESTIA}/conf/hestia.conf
 
 # Write default port value to hestia.conf
 # If a custom port is specified it will be set at the end of the installation process.
@@ -1243,40 +1246,56 @@ write_config_value "UPGRADE_SEND_EMAIL" "true"
 write_config_value "UPGRADE_SEND_EMAIL_LOG" "false"
 
 # Installing hosting packages
-cp -rf $HESTIA_COMMON_DIR/packages $HESTIA/data/
+cp -rf ${HESTIA_COMMON_DIR}/packages ${HESTIA}/data/
 
 # Update nameservers in hosting package
 IFS='.' read -r -a domain_elements <<< "$servername"
 if [ -n "${domain_elements[-2]}" ] && [ -n "${domain_elements[-1]}" ]; then
 	serverdomain="${domain_elements[-2]}.${domain_elements[-1]}"
-	sed -i s/"domain.tld"/"$serverdomain"/g $HESTIA/data/packages/*.pkg
+	sed -i s/"domain.tld"/"$serverdomain"/g ${HESTIA}/data/packages/*.pkg
 fi
 
 # Installing templates
-cp -rf $HESTIA_INSTALL_DIR/templates $HESTIA/data/
-cp -rf $HESTIA_COMMON_DIR/templates/web/ $HESTIA/data/templates
-cp -rf $HESTIA_COMMON_DIR/templates/dns/ $HESTIA/data/templates
+cp -rf ${HESTIA_INSTALL_DIR}/templates ${HESTIA}/data/
+cp -rf ${HESTIA_COMMON_DIR}/templates/web/ ${HESTIA}/data/templates
+cp -rf ${HESTIA_COMMON_DIR}/templates/dns/ ${HESTIA}/data/templates
 
 mkdir -p /var/www/html
 mkdir -p /var/www/document_errors
 
 # Install default success page
-cp -rf $HESTIA_COMMON_DIR/templates/web/unassigned/index.html /var/www/html/
-cp -rf $HESTIA_COMMON_DIR/templates/web/skel/document_errors/* /var/www/document_errors/
+cp -rf ${HESTIA_COMMON_DIR}/templates/web/unassigned/index.html /var/www/html/
+cp -rf ${HESTIA_COMMON_DIR}/templates/web/skel/document_errors/* /var/www/document_errors/
 
 # Installing firewall rules
-cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/
-rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh
+cp -rf ${HESTIA_COMMON_DIR}/firewall ${HESTIA}/data/
+rm -f ${HESTIA}/data/firewall/ipset/blacklist.sh ${HESTIA}/data/firewall/ipset/blacklist.ipv6.sh
 
 # Installing apis
-cp -rf $HESTIA_COMMON_DIR/api $HESTIA/data/
+cp -rf ${HESTIA_COMMON_DIR}/api ${HESTIA}/data/
 
 # Configuring server hostname
-$HESTIA/bin/v-change-sys-hostname $servername > /dev/null 2>&1
+${HESTIA}/bin/v-change-sys-hostname $servername > /dev/null 2>&1
+
+# Configuring global OpenSSL options
+echo "[ * ] Configuring OpenSSL to improve TLS performance..."
+tls13_ciphers="TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
+if [ "$release" = "10" ] || [ "$release" = "11" ]; then
+	sed -i '/^system_default = system_default_sect$/a system_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
+elif [ "$release" = "12" ]; then
+	if ! grep -qw "^ssl_conf = ssl_sect$" /etc/ssl/openssl.cnf 2> /dev/null; then
+		sed -i '/providers = provider_sect$/a ssl_conf = ssl_sect' /etc/ssl/openssl.cnf
+	fi
+	if ! grep -qw "^[ssl_sect]$" /etc/ssl/openssl.cnf 2> /dev/null; then
+		sed -i '$a \\n[ssl_sect]\nsystem_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
+	elif grep -qw "^system_default = system_default_sect$" /etc/ssl/openssl.cnf 2> /dev/null; then
+		sed -i '/^system_default = system_default_sect$/a system_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
+	fi
+fi
 
 # Generating SSL certificate
 echo "[ * ] Generating default self-signed SSL certificate..."
-$HESTIA/bin/v-generate-ssl-cert $(hostname) '' 'US' 'California' \
+${HESTIA}/bin/v-generate-ssl-cert $(hostname) '' 'US' 'California' \
 	'San Francisco' 'Hestia Control Panel' 'IT' > /tmp/hst.pem
 
 # Parsing certificate file
@@ -1286,15 +1305,15 @@ key_end=$(grep -n "END RSA" /tmp/hst.pem | cut -f 1 -d:)
 
 # Adding SSL certificate
 echo "[ * ] Adding SSL certificate to Hestia Control Panel..."
-cd $HESTIA/ssl
+cd ${HESTIA}/ssl
 sed -n "1,${crt_end}p" /tmp/hst.pem > certificate.crt
 sed -n "$key_start,${key_end}p" /tmp/hst.pem > certificate.key
-chown root:mail $HESTIA/ssl/*
-chmod 660 $HESTIA/ssl/*
+chown root:mail ${HESTIA}/ssl/*
+chmod 660 ${HESTIA}/ssl/*
 rm /tmp/hst.pem
 
 # Install dhparam.pem
-cp -f $HESTIA_INSTALL_DIR/ssl/dhparam.pem /etc/ssl
+cp -f ${HESTIA_INSTALL_DIR}/ssl/dhparam.pem /etc/ssl
 
 # Deleting old admin user
 if [ -n "$(grep ^admin: /etc/passwd)" ] && [ "$force" = 'yes' ]; then
@@ -1310,17 +1329,17 @@ fi
 
 # Enable sftp jail
 echo "[ * ] Enable SFTP jail..."
-$HESTIA/bin/v-add-sys-sftp-jail > /dev/null 2>&1
+${HESTIA}/bin/v-add-sys-sftp-jail > /dev/null 2>&1
 check_result $? "can't enable sftp jail"
 
 # Adding Hestia admin account
 echo "[ * ] Create admin account..."
-$HESTIA/bin/v-add-user admin $vpass $email "system" "System Administrator"
+${HESTIA}/bin/v-add-user admin $vpass $email "system" "System Administrator"
 check_result $? "can't create admin user"
-$HESTIA/bin/v-change-user-shell admin nologin
-$HESTIA/bin/v-change-user-role admin admin
-$HESTIA/bin/v-change-user-language admin $lang
-$HESTIA/bin/v-change-sys-config-value 'POLICY_SYSTEM_PROTECTED_ADMIN' 'yes'
+${HESTIA}/bin/v-change-user-shell admin nologin
+${HESTIA}/bin/v-change-user-role admin admin
+${HESTIA}/bin/v-change-user-language admin $lang
+${HESTIA}/bin/v-change-sys-config-value 'POLICY_SYSTEM_PROTECTED_ADMIN' 'yes'
 
 locale-gen "en_US.utf8" > /dev/null 2>&1
 
@@ -1330,15 +1349,15 @@ locale-gen "en_US.utf8" > /dev/null 2>&1
 
 echo "[ * ] Configuring NGINX..."
 rm -f /etc/nginx/conf.d/*.conf
-cp -f $HESTIA_INSTALL_DIR/nginx/nginx.conf /etc/nginx/
-cp -f $HESTIA_INSTALL_DIR/nginx/status.conf /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/nginx/agents.conf /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/nginx/phpmyadmin.inc /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/nginx/phppgadmin.inc /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/logrotate/nginx /etc/logrotate.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/nginx.conf /etc/nginx/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/status.conf /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/agents.conf /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/phpmyadmin.inc /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/phppgadmin.inc /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/logrotate/nginx /etc/logrotate.d/
 if [ "$ipv6" = 'yes' ]; then
-	cp -f $HESTIA_INSTALL_DIR/nginx/nginx-ipv6.conf /etc/nginx/nginx.conf
-	cp -f $HESTIA_INSTALL_DIR/nginx/status-ipv6.conf /etc/nginx/conf.d/status.conf
+	cp -f ${HESTIA_INSTALL_DIR}/nginx/nginx-ipv6.conf /etc/nginx/nginx.conf
+	cp -f ${HESTIA_INSTALL_DIR}/nginx/status-ipv6.conf /etc/nginx/conf.d/status.conf
 fi
 mkdir -p /etc/nginx/conf.d/domains
 mkdir -p /etc/nginx/modules-enabled
@@ -1367,7 +1386,7 @@ if [ -n "$resolver" ]; then
 fi
 
 # https://github.com/ergin/nginx-cloudflare-real-ip/
-cf_ips="$(curl -fsLm2 --retry 1 https://api.cloudflare.com/client/v4/ips)"
+cf_ips="$(curl -fsLm5 --retry 2 https://api.cloudflare.com/client/v4/ips)"
 
 if [ -n "$cf_ips" ] && [ "$(echo "$cf_ips" | jq -r '.success//""')" = "true" ]; then
 	cf_inc="/etc/nginx/conf.d/cloudflare.inc"
@@ -1403,12 +1422,12 @@ if [ "$apache" = 'yes' ]; then
 	mkdir -p /etc/apache2/conf.d/domains
 
 	# Copy configuration files
-	cp -f $HESTIA_INSTALL_DIR/apache2/apache2.conf /etc/apache2/
-	cp -f $HESTIA_INSTALL_DIR/apache2/status.conf /etc/apache2/mods-available/hestia-status.conf
+	cp -f ${HESTIA_INSTALL_DIR}/apache2/apache2.conf /etc/apache2/
+	cp -f ${HESTIA_INSTALL_DIR}/apache2/status.conf /etc/apache2/mods-available/hestia-status.conf
 	cp -f /etc/apache2/mods-available/status.load /etc/apache2/mods-available/hestia-status.load
-	cp -f $HESTIA_INSTALL_DIR/logrotate/apache2 /etc/logrotate.d/
+	cp -f ${HESTIA_INSTALL_DIR}/logrotate/apache2 /etc/logrotate.d/
 	if [ "$ipv6" = 'yes' ]; then
-		cp -f $HESTIA_INSTALL_DIR/apache2/status-ipv6.conf /etc/apache2/mods-available/hestia-status.conf
+		cp -f ${HESTIA_INSTALL_DIR}/apache2/status-ipv6.conf /etc/apache2/mods-available/hestia-status.conf
 	fi
 	# Enable needed modules
 	a2enmod rewrite > /dev/null 2>&1
@@ -1424,7 +1443,7 @@ if [ "$apache" = 'yes' ]; then
 		a2dismod php$fpm_v > /dev/null 2>&1
 		a2dismod mpm_prefork > /dev/null 2>&1
 		a2enmod mpm_event > /dev/null 2>&1
-		cp -f $HESTIA_INSTALL_DIR/apache2/hestia-event.conf /etc/apache2/conf.d/
+		cp -f ${HESTIA_INSTALL_DIR}/apache2/hestia-event.conf /etc/apache2/conf.d/
 	else
 		a2enmod mpm_itk > /dev/null 2>&1
 	fi
@@ -1458,16 +1477,16 @@ if [ "$phpfpm" = "yes" ]; then
 	if [ "$multiphp" = 'yes' ]; then
 		for v in "${multiphp_v[@]}"; do
 			echo "[ * ] Install PHP $v..."
-			$HESTIA/bin/v-add-web-php "$v" > /dev/null 2>&1
+			${HESTIA}/bin/v-add-web-php "$v" > /dev/null 2>&1
 		done
 	else
 		echo "[ * ] Install  PHP $fpm_v..."
-		$HESTIA/bin/v-add-web-php "$fpm_v" > /dev/null 2>&1
+		${HESTIA}/bin/v-add-web-php "$fpm_v" > /dev/null 2>&1
 	fi
 
 	echo "[ * ] Configuring PHP $fpm_v..."
 	# Create www.conf for webmail and php(*)admin
-	cp -f $HESTIA_INSTALL_DIR/php-fpm/www.conf /etc/php/$fpm_v/fpm/pool.d/www.conf
+	cp -f ${HESTIA_INSTALL_DIR}/php-fpm/www.conf /etc/php/$fpm_v/fpm/pool.d/www.conf
 	update-rc.d php$fpm_v-fpm defaults > /dev/null 2>&1
 	systemctl start php$fpm_v-fpm >> $LOG
 	check_result $? "php-fpm start failed"
@@ -1501,9 +1520,9 @@ chmod 755 /etc/cron.daily/php-session-cleanup
 
 if [ "$vsftpd" = 'yes' ]; then
 	echo "[ * ] Configuring Vsftpd server..."
-	cp -f $HESTIA_INSTALL_DIR/vsftpd/vsftpd.conf /etc/
+	cp -f ${HESTIA_INSTALL_DIR}/vsftpd/vsftpd.conf /etc/
 	if [ "$ipv6" = 'yes' ]; then
-		cp -f $HESTIA_INSTALL_DIR/vsftpd/vsftpd-ipv6.conf /etc/vsftpd.conf
+		cp -f ${HESTIA_INSTALL_DIR}/vsftpd/vsftpd-ipv6.conf /etc/vsftpd.conf
 	fi
 	touch /var/log/vsftpd.log
 	chown root:adm /var/log/vsftpd.log
@@ -1523,8 +1542,8 @@ fi
 if [ "$proftpd" = 'yes' ]; then
 	echo "[ * ] Configuring ProFTPD server..."
 	echo "127.0.0.1 $servername" >> /etc/hosts
-	cp -f $HESTIA_INSTALL_DIR/proftpd/proftpd.conf /etc/proftpd/
-	cp -f $HESTIA_INSTALL_DIR/proftpd/tls.conf /etc/proftpd/
+	cp -f ${HESTIA_INSTALL_DIR}/proftpd/proftpd.conf /etc/proftpd/
+	cp -f ${HESTIA_INSTALL_DIR}/proftpd/tls.conf /etc/proftpd/
 
 	if [ "$release" -eq 11 ]; then
 		sed -i 's|IdentLookups                  off|#IdentLookups                  off|g' /etc/proftpd/proftpd.conf
@@ -1565,7 +1584,7 @@ if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	# Remove symbolic link
 	rm -f /etc/mysql/my.cnf
 	# Configuring MariaDB
-	cp -f $HESTIA_INSTALL_DIR/mysql/$mycnf /etc/mysql/my.cnf
+	cp -f ${HESTIA_INSTALL_DIR}/mysql/$mycnf /etc/mysql/my.cnf
 
 	# Switch MariaDB inclusions to the MySQL
 	if [ "$mysql_type" = 'MySQL' ]; then
@@ -1622,7 +1641,7 @@ fi
 
 # Source upgrade.conf with phpmyadmin versions
 # shellcheck source=/usr/local/hestia/install/upgrade/upgrade.conf
-source $HESTIA/install/upgrade/upgrade.conf
+source ${HESTIA}/install/upgrade/upgrade.conf
 
 if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	# Display upgrade information
@@ -1649,7 +1668,7 @@ if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	cp -rf phpMyAdmin-$pma_v-all-languages/* /usr/share/phpmyadmin
 
 	# Create copy of config file
-	cp -f $HESTIA_INSTALL_DIR/phpmyadmin/config.inc.php /etc/phpmyadmin/
+	cp -f ${HESTIA_INSTALL_DIR}/phpmyadmin/config.inc.php /etc/phpmyadmin/
 	mkdir -p /var/lib/phpmyadmin/tmp
 	chmod 770 /var/lib/phpmyadmin/tmp
 	chown root:www-data /usr/share/phpmyadmin/tmp
@@ -1670,12 +1689,12 @@ if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	rm -f phpMyAdmin-$pma_v-all-languages.tar.gz
 
 	write_config_value "DB_PMA_ALIAS" "phpmyadmin"
-	$HESTIA/bin/v-change-sys-db-alias 'pma' "phpmyadmin"
+	${HESTIA}/bin/v-change-sys-db-alias 'pma' "phpmyadmin"
 
 	# Special thanks to Pavel Galkin (https://skurudo.ru)
 	# https://github.com/skurudo/phpmyadmin-fixer
 	# shellcheck source=/usr/local/hestia/install/deb/phpmyadmin/pma.sh
-	source $HESTIA_INSTALL_DIR/phpmyadmin/pma.sh > /dev/null 2>&1
+	source ${HESTIA_INSTALL_DIR}/phpmyadmin/pma.sh > /dev/null 2>&1
 
 	# limit access to /etc/phpmyadmin/
 	chown -R root:www-data /etc/phpmyadmin/
@@ -1690,7 +1709,7 @@ fi
 if [ "$postgresql" = 'yes' ]; then
 	echo "[ * ] Configuring PostgreSQL database server..."
 	ppass=$(gen_pass)
-	cp -f $HESTIA_INSTALL_DIR/postgresql/pg_hba.conf /etc/postgresql/*/main/
+	cp -f ${HESTIA_INSTALL_DIR}/postgresql/pg_hba.conf /etc/postgresql/*/main/
 	systemctl restart postgresql
 	sudo -iu postgres psql -c "ALTER USER postgres WITH PASSWORD '$ppass'" > /dev/null 2>&1
 
@@ -1700,18 +1719,18 @@ if [ "$postgresql" = 'yes' ]; then
 	wget --retry-connrefused --quiet https://github.com/hestiacp/phppgadmin/releases/download/v$pga_v/phppgadmin-v$pga_v.tar.gz
 	tar xzf phppgadmin-v$pga_v.tar.gz -C /usr/share/phppgadmin/
 
-	cp -f $HESTIA_INSTALL_DIR/pga/config.inc.php /etc/phppgadmin/
+	cp -f ${HESTIA_INSTALL_DIR}/pga/config.inc.php /etc/phppgadmin/
 
 	ln -s /etc/phppgadmin/config.inc.php /usr/share/phppgadmin/conf/
 
 	# Configuring phpPgAdmin
 	if [ "$apache" = 'yes' ]; then
-		cp -f $HESTIA_INSTALL_DIR/pga/phppgadmin.conf /etc/apache2/conf.d/phppgadmin.inc
+		cp -f ${HESTIA_INSTALL_DIR}/pga/phppgadmin.conf /etc/apache2/conf.d/phppgadmin.inc
 	fi
 
 	rm phppgadmin-v$pga_v.tar.gz
 	write_config_value "DB_PGA_ALIAS" "phppgadmin"
-	$HESTIA/bin/v-change-sys-db-alias 'pga' "phppgadmin"
+	${HESTIA}/bin/v-change-sys-db-alias 'pga' "phppgadmin"
 fi
 
 #----------------------------------------------------------#
@@ -1720,8 +1739,8 @@ fi
 
 if [ "$named" = 'yes' ]; then
 	echo "[ * ] Configuring Bind DNS server..."
-	cp -f $HESTIA_INSTALL_DIR/bind/named.conf /etc/bind/
-	cp -f $HESTIA_INSTALL_DIR/bind/named.conf.options /etc/bind/
+	cp -f ${HESTIA_INSTALL_DIR}/bind/named.conf /etc/bind/
+	cp -f ${HESTIA_INSTALL_DIR}/bind/named.conf.options /etc/bind/
 	chown root:bind /etc/bind/named.conf
 	chown root:bind /etc/bind/named.conf.options
 	chown bind:bind /var/cache/bind
@@ -1754,14 +1773,14 @@ if [ "$exim" = 'yes' ]; then
 	gpasswd -a Debian-exim mail > /dev/null 2>&1
 	exim_version=$(exim4 --version | head -1 | awk '{print $3}' | cut -f -2 -d .)
 	if [ "$exim_version" = "4.94" ]; then
-		cp -f $HESTIA_INSTALL_DIR/exim/exim4.conf.4.94.template /etc/exim4/exim4.conf.template
+		cp -f ${HESTIA_INSTALL_DIR}/exim/exim4.conf.4.94.template /etc/exim4/exim4.conf.template
 	else
-		cp -f $HESTIA_INSTALL_DIR/exim/exim4.conf.template /etc/exim4/
+		cp -f ${HESTIA_INSTALL_DIR}/exim/exim4.conf.template /etc/exim4/
 	fi
-	cp -f $HESTIA_INSTALL_DIR/exim/dnsbl.conf /etc/exim4/
-	cp -f $HESTIA_INSTALL_DIR/exim/spam-blocks.conf /etc/exim4/
-	cp -f $HESTIA_INSTALL_DIR/exim/limit.conf /etc/exim4/
-	cp -f $HESTIA_INSTALL_DIR/exim/system.filter /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/dnsbl.conf /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/spam-blocks.conf /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/limit.conf /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/system.filter /etc/exim4/
 	touch /etc/exim4/white-blocks.conf
 
 	if [ "$spamd" = 'yes' ]; then
@@ -1793,8 +1812,8 @@ fi
 if [ "$dovecot" = 'yes' ]; then
 	echo "[ * ] Configuring Dovecot POP/IMAP mail server..."
 	gpasswd -a dovecot mail > /dev/null 2>&1
-	cp -rf $HESTIA_COMMON_DIR/dovecot /etc/
-	cp -f $HESTIA_INSTALL_DIR/logrotate/dovecot /etc/logrotate.d/
+	cp -rf ${HESTIA_COMMON_DIR}/dovecot /etc/
+	cp -f ${HESTIA_INSTALL_DIR}/logrotate/dovecot /etc/logrotate.d/
 	rm -f /etc/dovecot/conf.d/15-mailboxes.conf
 	chown -R root:root /etc/dovecot*
 
@@ -1819,7 +1838,7 @@ fi
 if [ "$clamd" = 'yes' ]; then
 	gpasswd -a clamav mail > /dev/null 2>&1
 	gpasswd -a clamav Debian-exim > /dev/null 2>&1
-	cp -f $HESTIA_INSTALL_DIR/clamav/clamd.conf /etc/clamav/
+	cp -f ${HESTIA_INSTALL_DIR}/clamav/clamd.conf /etc/clamav/
 	update-rc.d clamav-daemon defaults
 	if [ ! -d "/run/clamav" ]; then
 		mkdir /run/clamav
@@ -1868,7 +1887,7 @@ fi
 
 if [ "$fail2ban" = 'yes' ]; then
 	echo "[ * ] Configuring fail2ban access monitor..."
-	cp -rf $HESTIA_INSTALL_DIR/fail2ban /etc/
+	cp -rf ${HESTIA_INSTALL_DIR}/fail2ban /etc/
 	if [ "$dovecot" = 'no' ]; then
 		fline=$(cat /etc/fail2ban/jail.local | grep -n dovecot-iptables -A 2)
 		fline=$(echo "$fline" | grep enabled | tail -n1 | cut -f 1 -d -)
@@ -1905,12 +1924,12 @@ fi
 
 # Configuring MariaDB/MySQL host
 if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
-	$HESTIA/bin/v-add-database-host mysql localhost root $mpass
+	${HESTIA}/bin/v-add-database-host mysql localhost root $mpass
 fi
 
 # Configuring PostgreSQL host
 if [ "$postgresql" = 'yes' ]; then
-	$HESTIA/bin/v-add-database-host pgsql localhost postgres $ppass
+	${HESTIA}/bin/v-add-database-host pgsql localhost postgres $ppass
 fi
 
 #----------------------------------------------------------#
@@ -1920,7 +1939,7 @@ fi
 # Min requirements Dovecot + Exim + Mysql
 if ([ "$mysql" == 'yes' ] || [ "$mysql8" == 'yes' ]) && [ "$dovecot" == "yes" ]; then
 	echo "[ * ] Install Roundcube..."
-	$HESTIA/bin/v-add-sys-roundcube
+	${HESTIA}/bin/v-add-sys-roundcube
 	write_config_value "WEBMAIL_ALIAS" "webmail"
 else
 	write_config_value "WEBMAIL_ALIAS" ""
@@ -1951,7 +1970,7 @@ if [ "$sieve" = 'yes' ]; then
 	sed -i "s/mail_plugins = quota imap_quota/mail_plugins = quota imap_quota imap_sieve/g" /etc/dovecot/conf.d/20-imap.conf
 
 	# Replace dovecot-sieve config files
-	cp -f $HESTIA_COMMON_DIR/dovecot/sieve/* /etc/dovecot/conf.d
+	cp -f ${HESTIA_COMMON_DIR}/dovecot/sieve/* /etc/dovecot/conf.d
 
 	# Dovecot default file install
 	echo -e "require [\"fileinto\"];\n# rule:[SPAM]\nif header :contains \"X-Spam-Flag\" \"YES\" {\n    fileinto \"INBOX.Spam\";\n}\n" > /etc/dovecot/sieve/default
@@ -1967,7 +1986,7 @@ if [ "$sieve" = 'yes' ]; then
 	if [ -d "/var/lib/roundcube" ]; then
 		# Modify Roundcube config
 		mkdir -p $RC_CONFIG_DIR/plugins/managesieve
-		cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_managesieve.inc.php $RC_CONFIG_DIR/plugins/managesieve/config.inc.php
+		cp -f ${HESTIA_COMMON_DIR}/roundcube/plugins/config_managesieve.inc.php $RC_CONFIG_DIR/plugins/managesieve/config.inc.php
 		ln -s $RC_CONFIG_DIR/plugins/managesieve/config.inc.php $RC_INSTALL_DIR/plugins/managesieve/config.inc.php
 		chown -R root:www-data $RC_CONFIG_DIR/
 		chmod 751 -R $RC_CONFIG_DIR
@@ -1994,7 +2013,7 @@ else
 	write_config_value "API" "no"
 	write_config_value "API_SYSTEM" "0"
 	write_config_value "API_ALLOWED_IP" ""
-	$HESTIA/bin/v-change-sys-api disable
+	${HESTIA}/bin/v-change-sys-api disable
 fi
 
 #----------------------------------------------------------#
@@ -2002,14 +2021,14 @@ fi
 #----------------------------------------------------------#
 
 echo "[ * ] Configuring File Manager..."
-$HESTIA/bin/v-add-sys-filemanager quiet
+${HESTIA}/bin/v-add-sys-filemanager quiet
 
 #----------------------------------------------------------#
 #                  Configure dependencies                  #
 #----------------------------------------------------------#
 
 echo "[ * ] Configuring PHP dependencies..."
-$HESTIA/bin/v-add-sys-dependencies quiet
+${HESTIA}/bin/v-add-sys-dependencies quiet
 
 echo "[ * ] Install Rclone"
 curl -s https://rclone.org/install.sh | bash > /dev/null 2>&1
@@ -2020,26 +2039,30 @@ curl -s https://rclone.org/install.sh | bash > /dev/null 2>&1
 
 # Configuring system IPs
 echo "[ * ] Configuring System IP..."
-$HESTIA/bin/v-update-sys-ip > /dev/null 2>&1
-
-# Get main IP
-ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/)
-ipv6=$(ip addr | grep 'inet6 ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/)
-local_ip=$ip
-local_ipv6=$ipv6
+${HESTIA}/bin/v-update-sys-ip > /dev/null 2>&1
+
+# Get primary IP
+default_nic="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')"
+# IPv4
+primary_ipv4="$(ip -4 -d -j addr show "$default_nic" | jq -r '.[].addr_info[] | if .scope == "global" then .local else empty end' | head -n1)"
+# IPv6
+primary_ipv6="$(ip -6 -d -j addr show "$default_nic" | jq -r '.[].addr_info[] | if .scope == "global" then .local else empty end' | head -n1)"
+ip="$primary_ipv4"
+local_ip=${primary_ipv4}
+local_ipv6=${primary_ipv6}
 
 # Configuring firewall
 if [ "$iptables" = 'yes' ]; then
-	$HESTIA/bin/v-update-firewall
+	${HESTIA}/bin/v-update-firewall
 fi
 
 # Get public IP
-pub_ip=$(curl --ipv4 -s https://ip.hestiacp.com/)
-pub_ipv6=$(curl --ipv6 -s https://ip.hestiacp.com/)
+pub_ipv4="$(curl -fsLm5 --retry 2 --ipv4 https://ip.hestiacp.com/)"
+pub_ipv6="$(curl -fsLm5 --retry 2 --ipv6 https://ip.hestiacp.com/)"
 
-if [ -n "$pub_ip" ] && [ "$pub_ip" != "$ip" ]; then
-	$HESTIA/bin/v-change-sys-ip-nat $ip $pub_ip > /dev/null 2>&1
-	ip=$pub_ip
+if [ -n "$pub_ipv4" ] && [ "$pub_ipv4" != "$ip" ]; then
+	${HESTIA}/bin/v-change-sys-ip-nat ${ip} ${pub_ipv4} > /dev/null 2>&1
+	ip=${pub_ipv4}
 fi
 
 # Configuring libapache2-mod-remoteip
@@ -2047,14 +2070,14 @@ if [ "$apache" = 'yes' ] && [ "$nginx" = 'yes' ]; then
 	cd /etc/apache2/mods-available
 	echo "<IfModule mod_remoteip.c>" > remoteip.conf
 	echo "  RemoteIPHeader X-Real-IP" >> remoteip.conf
-	if [ "$local_ip" != "127.0.0.1" ] && [ "$pub_ip" != "127.0.0.1" ]; then
+	if [ "$local_ip" != "127.0.0.1" ] && [ "$pub_ipv4" != "127.0.0.1" ]; then
 		echo "  RemoteIPInternalProxy 127.0.0.1" >> remoteip.conf
 	fi
-	if [ -n "$local_ip" ] && [ "$local_ip" != "$pub_ip" ]; then
+	if [ -n "$local_ip" ] && [ "$local_ip" != "$pub_ipv4" ]; then
 		echo "  RemoteIPInternalProxy $local_ip" >> remoteip.conf
 	fi
-	if [ -n "$pub_ip" ]; then
-		echo "  RemoteIPInternalProxy $pub_ip" >> remoteip.conf
+	if [ -n "$pub_ipv4" ]; then
+		echo "  RemoteIPInternalProxy $pub_ipv4" >> remoteip.conf
 	fi
 	echo "</IfModule>" >> remoteip.conf
 	sed -i "s/LogFormat \"%h/LogFormat \"%a/g" /etc/apache2/apache2.conf
@@ -2065,13 +2088,13 @@ fi
 # Adding default domain
 if [ -n "$ip" ]; then
 	if [ -n "ipv6" ]; then
-		$HESTIA/bin/v-add-web-domain admin $servername $ip $ipv6
+		${HESTIA}/bin/v-add-web-domain admin ${servername} ${ip} ${ipv6}
 	else
-		$HESTIA/bin/v-add-web-domain admin $servername $ip
+		${HESTIA}/bin/v-add-web-domain admin ${servername} ${ip}
 	fi
 else
 	if [ -n "ipv6" ]; then
-		$HESTIA/bin/v-add-web-domain admin $servername "" $ipv6
+		${HESTIA}/bin/v-add-web-domain admin ${servername} "" ${ipv6}
 	fi
 fi
 
@@ -2080,46 +2103,46 @@ check_result $? "can't create $servername domain"
 # Adding cron jobs
 export SCHEDULED_RESTART="yes"
 command="sudo $HESTIA/bin/v-update-sys-queue restart"
-$HESTIA/bin/v-add-cron-job 'admin' '*/2' '*' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '*/2' '*' '*' '*' '*' "$command"
 systemctl restart cron
 
 command="sudo $HESTIA/bin/v-update-sys-queue daily"
-$HESTIA/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue disk"
-$HESTIA/bin/v-add-cron-job 'admin' '15' '02' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '15' '02' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue traffic"
-$HESTIA/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue webstats"
-$HESTIA/bin/v-add-cron-job 'admin' '30' '03' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '30' '03' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue backup"
-$HESTIA/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-backup-users"
-$HESTIA/bin/v-add-cron-job 'admin' '10' '05' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '10' '05' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-user-stats"
-$HESTIA/bin/v-add-cron-job 'admin' '20' '00' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '20' '00' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-rrd"
-$HESTIA/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-letsencrypt-ssl"
 min=$(gen_pass '012345' '2')
 hour=$(gen_pass '1234567' '1')
-$HESTIA/bin/v-add-cron-job 'admin' "$min" "$hour" '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' "$min" "$hour" '*' '*' '*' "$command"
 
 # Enable automatic updates
-$HESTIA/bin/v-add-cron-hestia-autoupdate apt
+${HESTIA}/bin/v-add-cron-hestia-autoupdate apt
 
 # Building initital rrd images
-$HESTIA/bin/v-update-sys-rrd
+${HESTIA}/bin/v-update-sys-rrd
 
 # Enabling file system quota
 if [ "$quota" = 'yes' ]; then
-	$HESTIA/bin/v-add-sys-quota
+	${HESTIA}/bin/v-add-sys-quota
 fi
 
 # Set backend port
-$HESTIA/bin/v-change-sys-port $port > /dev/null 2>&1
+${HESTIA}/bin/v-change-sys-port $port > /dev/null 2>&1
 
 # Create default configuration files
-$HESTIA/bin/v-update-sys-defaults
+${HESTIA}/bin/v-update-sys-defaults
 
 # Update remaining packages since repositories have changed
 echo -ne "[ * ] Installing remaining software updates..."
@@ -2132,7 +2155,7 @@ echo
 update-rc.d hestia defaults
 systemctl start hestia
 check_result $? "hestia start failed"
-chown admin:admin $HESTIA/data/sessions
+chown admin:admin ${HESTIA}/data/sessions
 
 # Create backup folder and set correct permission
 mkdir -p /backup/
@@ -2148,7 +2171,7 @@ echo "@reboot root sleep 10 && rm /etc/cron.d/hestia-ssl && PATH='/usr/local/sbi
 echo "[ * ] Updating configuration files..."
 
 BIN="$HESTIA/bin"
-source $HESTIA/func/syshealth.sh
+source ${HESTIA}/func/syshealth.sh
 syshealth_repair_system_config
 
 # Add /usr/local/hestia/bin/ to path variable
@@ -2222,7 +2245,7 @@ cat $tmpfile
 rm -f $tmpfile
 
 # Add welcome message to notification panel
-$HESTIA/bin/v-add-user-notification admin 'Welcome to Hestia Control Panel!' '<br>You are now ready to begin <a href="/add/user/">adding user accounts</a> and <a href="/add/web/">domains</a>. For help and assistance, <a href="https://hestiacp.com/docs/" target="_blank">view the documentation</a> or <a href="https://forum.hestiacp.com/" target="_blank">visit our forum</a>.<br><br>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">report any issues via GitHub</a>.<br><br><b>Have a wonderful day!</b><br><br><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team'
+${HESTIA}/bin/v-add-user-notification admin 'Welcome to Hestia Control Panel!' '<br>You are now ready to begin <a href="/add/user/">adding user accounts</a> and <a href="/add/web/">domains</a>. For help and assistance, <a href="https://hestiacp.com/docs/" target="_blank">view the documentation</a> or <a href="https://forum.hestiacp.com/" target="_blank">visit our forum</a>.<br><br>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">report any issues via GitHub</a>.<br><br><b>Have a wonderful day!</b><br><br><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team'
 
 # Clean-up
 # Sort final configuration file

+ 162 - 138
install/hst-install-ubuntu.sh

@@ -49,7 +49,7 @@ software="acl apache2 apache2.2-common apache2-suexec-custom apache2-utils appar
   php$fpm_v-pgsql php$fpm_v-pspell php$fpm_v-readline php$fpm_v-xml php$fpm_v-zip postgresql postgresql-contrib
   proftpd-basic quota rrdtool rsyslog setpriv spamassassin sudo sysstat unzip vim-common vsftpd whois zip zstd"
 
-installer_dependencies="apt-transport-https ca-certificates curl dirmngr gnupg software-properties-common wget"
+installer_dependencies="apt-transport-https ca-certificates curl dirmngr gnupg openssl software-properties-common wget"
 
 # Defining help function
 help() {
@@ -147,21 +147,21 @@ set_default_port() {
 write_config_value() {
 	local key="$1"
 	local value="$2"
-	echo "$key='$value'" >> $HESTIA/conf/hestia.conf
+	echo "$key='$value'" >> ${HESTIA}/conf/hestia.conf
 }
 
 # Sort configuration file values
 # Write final copy to $HESTIA/conf/hestia.conf for active usage
 # Duplicate file to $HESTIA/conf/defaults/hestia.conf to restore known good installation values
 sort_config_file() {
-	sort $HESTIA/conf/hestia.conf -o /tmp/updconf
-	mv $HESTIA/conf/hestia.conf $HESTIA/conf/hestia.conf.bak
-	mv /tmp/updconf $HESTIA/conf/hestia.conf
-	rm -f $HESTIA/conf/hestia.conf.bak
+	sort ${HESTIA}/conf/hestia.conf -o /tmp/updconf
+	mv ${HESTIA}/conf/hestia.conf ${HESTIA}/conf/hestia.conf.bak
+	mv /tmp/updconf ${HESTIA}/conf/hestia.conf
+	rm -f ${HESTIA}/conf/hestia.conf.bak
 	if [ ! -d "$HESTIA/conf/defaults/" ]; then
 		mkdir -p "$HESTIA/conf/defaults/"
 	fi
-	cp $HESTIA/conf/hestia.conf $HESTIA/conf/defaults/hestia.conf
+	cp ${HESTIA}/conf/hestia.conf ${HESTIA}/conf/defaults/hestia.conf
 }
 
 # Validate hostname according to RFC1178
@@ -684,7 +684,7 @@ if [ -z "$(swapon -s)" ] && [ "$memory" -lt 1000000 ]; then
 	chmod 600 /swapfile
 	mkswap /swapfile
 	swapon /swapfile
-	echo "/swapfile   none    swap    sw    0   0" >> /etc/fstab
+	echo "/swapfile	none	swap	sw	0	0" >> /etc/fstab
 fi
 
 #----------------------------------------------------------#
@@ -768,7 +768,10 @@ check_result $? 'apt-get upgrade failed'
 mkdir -p $hst_backups
 cd $hst_backups
 mkdir nginx apache2 php vsftpd proftpd bind exim4 dovecot clamd
-mkdir spamassassin mysql postgresql hestia
+mkdir spamassassin mysql postgresql openssl hestia
+
+# Backup OpenSSL configuration
+cp /etc/ssl/openssl.cnf $hst_backups/openssl > /dev/null 2>&1
 
 # Backup nginx configuration
 systemctl stop nginx > /dev/null 2>&1
@@ -781,7 +784,7 @@ rm -f /etc/apache2/conf.d/* > /dev/null 2>&1
 
 # Backup PHP-FPM configuration
 systemctl stop php*-fpm > /dev/null 2>&1
-cp -r /etc/php/* $hst_backups/php/ > /dev/null 2>&1
+cp -r /etc/php/* $hst_backups/php > /dev/null 2>&1
 
 # Backup Bind configuration
 systemctl stop bind9 > /dev/null 2>&1
@@ -821,9 +824,9 @@ mv -f /root/.my.cnf $hst_backups/mysql > /dev/null 2>&1
 
 # Backup Hestia
 systemctl stop hestia > /dev/null 2>&1
-cp -r $HESTIA/* $hst_backups/hestia > /dev/null 2>&1
+cp -r ${HESTIA}/* $hst_backups/hestia > /dev/null 2>&1
 apt-get -y purge hestia hestia-nginx hestia-php > /dev/null 2>&1
-rm -rf $HESTIA > /dev/null 2>&1
+rm -rf ${HESTIA} > /dev/null 2>&1
 
 #----------------------------------------------------------#
 #                     Package Includes                     #
@@ -1039,7 +1042,7 @@ systemctl restart ssh
 # Disable AWStats cron
 rm -f /etc/cron.d/awstats
 # Replace awstatst function
-cp -f $HESTIA_INSTALL_DIR/logrotate/httpd-prerotate/* /etc/logrotate.d/httpd-prerotate/
+cp -f ${HESTIA_INSTALL_DIR}/logrotate/httpd-prerotate/* /etc/logrotate.d/httpd-prerotate/
 
 # Set directory color
 if [ -z "$(grep 'LS_COLORS="$LS_COLORS:di=00;33"' /etc/profile)" ]; then
@@ -1148,7 +1151,7 @@ fi
 echo "[ * ] Configuring Hestia Control Panel..."
 # Installing sudo configuration
 mkdir -p /etc/sudoers.d
-cp -f $HESTIA_INSTALL_DIR/sudo/admin /etc/sudoers.d/
+cp -f ${HESTIA_INSTALL_DIR}/sudo/admin /etc/sudoers.d/
 chmod 440 /etc/sudoers.d/admin
 
 # Add Hestia global config
@@ -1165,30 +1168,30 @@ chmod 755 /etc/profile.d/hestia.sh
 source /etc/profile.d/hestia.sh
 
 # Configuring logrotate for Hestia logs
-cp -f $HESTIA_INSTALL_DIR/logrotate/hestia /etc/logrotate.d/hestia
+cp -f ${HESTIA_INSTALL_DIR}/logrotate/hestia /etc/logrotate.d/hestia
 
 # Create log path and symbolic link
 rm -f /var/log/hestia
 mkdir -p /var/log/hestia
-ln -s /var/log/hestia $HESTIA/log
+ln -s /var/log/hestia ${HESTIA}/log
 
 # Building directory tree and creating some blank files for Hestia
-mkdir -p $HESTIA/conf $HESTIA/ssl $HESTIA/data/ips \
-	$HESTIA/data/queue $HESTIA/data/users $HESTIA/data/firewall \
-	$HESTIA/data/sessions
-touch $HESTIA/data/queue/backup.pipe $HESTIA/data/queue/disk.pipe \
-	$HESTIA/data/queue/webstats.pipe $HESTIA/data/queue/restart.pipe \
-	$HESTIA/data/queue/traffic.pipe $HESTIA/data/queue/daily.pipe $HESTIA/log/system.log \
-	$HESTIA/log/nginx-error.log $HESTIA/log/auth.log $HESTIA/log/backup.log
-chmod 750 $HESTIA/conf $HESTIA/data/users $HESTIA/data/ips $HESTIA/log
-chmod -R 750 $HESTIA/data/queue
+mkdir -p ${HESTIA}/conf ${HESTIA}/ssl ${HESTIA}/data/ips \
+	${HESTIA}/data/queue ${HESTIA}/data/users ${HESTIA}/data/firewall \
+	${HESTIA}/data/sessions
+touch ${HESTIA}/data/queue/backup.pipe ${HESTIA}/data/queue/disk.pipe \
+	${HESTIA}/data/queue/webstats.pipe ${HESTIA}/data/queue/restart.pipe \
+	${HESTIA}/data/queue/traffic.pipe ${HESTIA}/data/queue/daily.pipe ${HESTIA}/log/system.log \
+	${HESTIA}/log/nginx-error.log ${HESTIA}/log/auth.log ${HESTIA}/log/backup.log
+chmod 750 ${HESTIA}/conf ${HESTIA}/data/users ${HESTIA}/data/ips ${HESTIA}/log
+chmod -R 750 ${HESTIA}/data/queue
 chmod 660 /var/log/hestia/*
-chmod 770 $HESTIA/data/sessions
+chmod 770 ${HESTIA}/data/sessions
 
 # Generating Hestia configuration
-rm -f $HESTIA/conf/hestia.conf > /dev/null 2>&1
-touch $HESTIA/conf/hestia.conf
-chmod 660 $HESTIA/conf/hestia.conf
+rm -f ${HESTIA}/conf/hestia.conf > /dev/null 2>&1
+touch ${HESTIA}/conf/hestia.conf
+chmod 660 ${HESTIA}/conf/hestia.conf
 
 # Write default port value to hestia.conf
 # If a custom port is specified it will be set at the end of the installation process.
@@ -1307,40 +1310,56 @@ write_config_value "UPGRADE_SEND_EMAIL" "true"
 write_config_value "UPGRADE_SEND_EMAIL_LOG" "false"
 
 # Installing hosting packages
-cp -rf $HESTIA_COMMON_DIR/packages $HESTIA/data/
+cp -rf ${HESTIA_COMMON_DIR}/packages ${HESTIA}/data/
 
 # Update nameservers in hosting package
 IFS='.' read -r -a domain_elements <<< "$servername"
 if [ -n "${domain_elements[-2]}" ] && [ -n "${domain_elements[-1]}" ]; then
 	serverdomain="${domain_elements[-2]}.${domain_elements[-1]}"
-	sed -i s/"domain.tld"/"$serverdomain"/g $HESTIA/data/packages/*.pkg
+	sed -i s/"domain.tld"/"$serverdomain"/g ${HESTIA}/data/packages/*.pkg
 fi
 
 # Installing templates
-cp -rf $HESTIA_INSTALL_DIR/templates $HESTIA/data/
-cp -rf $HESTIA_COMMON_DIR/templates/web/ $HESTIA/data/templates
-cp -rf $HESTIA_COMMON_DIR/templates/dns/ $HESTIA/data/templates
+cp -rf ${HESTIA_INSTALL_DIR}/templates ${HESTIA}/data/
+cp -rf ${HESTIA_COMMON_DIR}/templates/web/ ${HESTIA}/data/templates
+cp -rf ${HESTIA_COMMON_DIR}/templates/dns/ ${HESTIA}/data/templates
 
 mkdir -p /var/www/html
 mkdir -p /var/www/document_errors
 
 # Install default success page
-cp -rf $HESTIA_COMMON_DIR/templates/web/unassigned/index.html /var/www/html/
-cp -rf $HESTIA_COMMON_DIR/templates/web/skel/document_errors/* /var/www/document_errors/
+cp -rf ${HESTIA_COMMON_DIR}/templates/web/unassigned/index.html /var/www/html/
+cp -rf ${HESTIA_COMMON_DIR}/templates/web/skel/document_errors/* /var/www/document_errors/
 
 # Installing firewall rules
-cp -rf $HESTIA_COMMON_DIR/firewall $HESTIA/data/
-rm -f $HESTIA/data/firewall/ipset/blacklist.sh $HESTIA/data/firewall/ipset/blacklist.ipv6.sh
+cp -rf ${HESTIA_COMMON_DIR}/firewall ${HESTIA}/data/
+rm -f ${HESTIA}/data/firewall/ipset/blacklist.sh ${HESTIA}/data/firewall/ipset/blacklist.ipv6.sh
 
 # Installing apis
-cp -rf $HESTIA_COMMON_DIR/api $HESTIA/data/
+cp -rf ${HESTIA_COMMON_DIR}/api ${HESTIA}/data/
 
 # Configuring server hostname
-$HESTIA/bin/v-change-sys-hostname $servername > /dev/null 2>&1
+${HESTIA}/bin/v-change-sys-hostname $servername > /dev/null 2>&1
+
+# Configuring global OpenSSL options
+echo "[ * ] Configuring OpenSSL to improve TLS performance..."
+tls13_ciphers="TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
+if [ "$release" = "20.04" ]; then
+	if ! grep -qw "^openssl_conf = default_conf$" /etc/ssl/openssl.cnf 2> /dev/null; then
+		sed -i '/^oid_section		= new_oids$/a \\n# System default\nopenssl_conf = default_conf' /etc/ssl/openssl.cnf
+	fi
+	if ! grep -qw "^[default_conf]$" /etc/ssl/openssl.cnf 2> /dev/null; then
+		sed -i '$a [default_conf]\nssl_conf = ssl_sect\n\n[ssl_sect]\nsystem_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
+	elif grep -qw "^system_default = system_default_sect$" /etc/ssl/openssl.cnf 2> /dev/null; then
+		sed -i '/^system_default = system_default_sect$/a system_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
+	fi
+elif [ "$release" = "22.04" ]; then
+	sed -i '/^system_default = system_default_sect$/a system_default = hestia_openssl_sect\n\n[hestia_openssl_sect]\nCiphersuites = '"$tls13_ciphers"'\nOptions = PrioritizeChaCha' /etc/ssl/openssl.cnf
+fi
 
 # Generating SSL certificate
 echo "[ * ] Generating default self-signed SSL certificate..."
-$HESTIA/bin/v-generate-ssl-cert $(hostname) '' 'US' 'California' \
+${HESTIA}/bin/v-generate-ssl-cert $(hostname) '' 'US' 'California' \
 	'San Francisco' 'Hestia Control Panel' 'IT' > /tmp/hst.pem
 
 # Parsing certificate file
@@ -1355,15 +1374,15 @@ fi
 
 # Adding SSL certificate
 echo "[ * ] Adding SSL certificate to Hestia Control Panel..."
-cd $HESTIA/ssl
+cd ${HESTIA}/ssl
 sed -n "1,${crt_end}p" /tmp/hst.pem > certificate.crt
 sed -n "$key_start,${key_end}p" /tmp/hst.pem > certificate.key
-chown root:mail $HESTIA/ssl/*
-chmod 660 $HESTIA/ssl/*
+chown root:mail ${HESTIA}/ssl/*
+chmod 660 ${HESTIA}/ssl/*
 rm /tmp/hst.pem
 
 # Install dhparam.pem
-cp -f $HESTIA_INSTALL_DIR/ssl/dhparam.pem /etc/ssl
+cp -f ${HESTIA_INSTALL_DIR}/ssl/dhparam.pem /etc/ssl
 
 # Deleting old admin user
 if [ -n "$(grep ^admin: /etc/passwd)" ] && [ "$force" = 'yes' ]; then
@@ -1382,17 +1401,17 @@ sed -i "s/%admin ALL=(ALL) ALL/#%admin ALL=(ALL) ALL/g" /etc/sudoers
 
 # Enable sftp jail
 echo "[ * ] Enable SFTP jail..."
-$HESTIA/bin/v-add-sys-sftp-jail > /dev/null 2>&1
+${HESTIA}/bin/v-add-sys-sftp-jail > /dev/null 2>&1
 check_result $? "can't enable sftp jail"
 
 # Adding Hestia admin account
 echo "[ * ] Create admin account..."
-$HESTIA/bin/v-add-user admin $vpass $email "system" "System Administrator"
+${HESTIA}/bin/v-add-user admin $vpass $email "system" "System Administrator"
 check_result $? "can't create admin user"
-$HESTIA/bin/v-change-user-shell admin nologin
-$HESTIA/bin/v-change-user-role admin admin
-$HESTIA/bin/v-change-user-language admin $lang
-$HESTIA/bin/v-change-sys-config-value 'POLICY_SYSTEM_PROTECTED_ADMIN' 'yes'
+${HESTIA}/bin/v-change-user-shell admin nologin
+${HESTIA}/bin/v-change-user-role admin admin
+${HESTIA}/bin/v-change-user-language admin $lang
+${HESTIA}/bin/v-change-sys-config-value 'POLICY_SYSTEM_PROTECTED_ADMIN' 'yes'
 
 locale-gen "en_US.utf8" > /dev/null 2>&1
 
@@ -1402,15 +1421,15 @@ locale-gen "en_US.utf8" > /dev/null 2>&1
 
 echo "[ * ] Configuring NGINX..."
 rm -f /etc/nginx/conf.d/*.conf
-cp -f $HESTIA_INSTALL_DIR/nginx/nginx.conf /etc/nginx/
-cp -f $HESTIA_INSTALL_DIR/nginx/status.conf /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/nginx/agents.conf /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/nginx/phpmyadmin.inc /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/nginx/phppgadmin.inc /etc/nginx/conf.d/
-cp -f $HESTIA_INSTALL_DIR/logrotate/nginx /etc/logrotate.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/nginx.conf /etc/nginx/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/status.conf /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/agents.conf /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/phpmyadmin.inc /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/nginx/phppgadmin.inc /etc/nginx/conf.d/
+cp -f ${HESTIA_INSTALL_DIR}/logrotate/nginx /etc/logrotate.d/
 if [ "$ipv6" = 'yes' ]; then
-	cp -f $HESTIA_INSTALL_DIR/nginx/nginx-ipv6.conf /etc/nginx/nginx.conf
-	cp -f $HESTIA_INSTALL_DIR/nginx/status-ipv6.conf /etc/nginx/conf.d/status.conf
+	cp -f ${HESTIA_INSTALL_DIR}/nginx/nginx-ipv6.conf /etc/nginx/nginx.conf
+	cp -f ${HESTIA_INSTALL_DIR}/nginx/status-ipv6.conf /etc/nginx/conf.d/status.conf
 fi
 mkdir -p /etc/nginx/conf.d/domains
 mkdir -p /etc/nginx/modules-enabled
@@ -1439,7 +1458,7 @@ if [ -n "$resolver" ]; then
 fi
 
 # https://github.com/ergin/nginx-cloudflare-real-ip/
-cf_ips="$(curl -fsLm2 --retry 1 https://api.cloudflare.com/client/v4/ips)"
+cf_ips="$(curl -fsLm5 --retry 2 https://api.cloudflare.com/client/v4/ips)"
 
 if [ -n "$cf_ips" ] && [ "$(echo "$cf_ips" | jq -r '.success//""')" = "true" ]; then
 	cf_inc="/etc/nginx/conf.d/cloudflare.inc"
@@ -1475,13 +1494,13 @@ if [ "$apache" = 'yes' ]; then
 	mkdir -p /etc/apache2/conf.d/domains
 
 	# Copy configuration files
-	cp -f $HESTIA_INSTALL_DIR/apache2/apache2.conf /etc/apache2/
-	cp -f $HESTIA_INSTALL_DIR/apache2/status.conf /etc/apache2/mods-available/hestia-status.conf
+	cp -f ${HESTIA_INSTALL_DIR}/apache2/apache2.conf /etc/apache2/
+	cp -f ${HESTIA_INSTALL_DIR}/apache2/status.conf /etc/apache2/mods-available/hestia-status.conf
 	cp -f /etc/apache2/mods-available/status.load /etc/apache2/mods-available/hestia-status.load
-	cp -f $HESTIA_INSTALL_DIR/logrotate/apache2 /etc/logrotate.d/
+	cp -f ${HESTIA_INSTALL_DIR}/logrotate/apache2 /etc/logrotate.d/
 
 	if [ "$ipv6" = 'yes' ]; then
-		cp -f $HESTIA_INSTALL_DIR/apache2/status-ipv6.conf /etc/apache2/mods-available/hestia-status.conf
+		cp -f ${HESTIA_INSTALL_DIR}/apache2/status-ipv6.conf /etc/apache2/mods-available/hestia-status.conf
 	fi
 
 	# Enable needed modules
@@ -1498,7 +1517,7 @@ if [ "$apache" = 'yes' ]; then
 		a2dismod php$fpm_v > /dev/null 2>&1
 		a2dismod mpm_prefork > /dev/null 2>&1
 		a2enmod mpm_event > /dev/null 2>&1
-		cp -f $HESTIA_INSTALL_DIR/apache2/hestia-event.conf /etc/apache2/conf.d/
+		cp -f ${HESTIA_INSTALL_DIR}/apache2/hestia-event.conf /etc/apache2/conf.d/
 	else
 		a2enmod ruid2 > /dev/null 2>&1
 	fi
@@ -1532,16 +1551,16 @@ if [ "$phpfpm" = "yes" ]; then
 	if [ "$multiphp" = 'yes' ]; then
 		for v in "${multiphp_v[@]}"; do
 			echo "[ * ] Install PHP $v..."
-			$HESTIA/bin/v-add-web-php "$v" > /dev/null 2>&1
+			${HESTIA}/bin/v-add-web-php "$v" > /dev/null 2>&1
 		done
 	else
 		echo "[ * ] Install  PHP $fpm_v..."
-		$HESTIA/bin/v-add-web-php "$fpm_v" > /dev/null 2>&1
+		${HESTIA}/bin/v-add-web-php "$fpm_v" > /dev/null 2>&1
 	fi
 
 	echo "[ * ] Configuring PHP-FPM $fpm_v..."
 	# Create www.conf for webmail and php(*)admin
-	cp -f $HESTIA_INSTALL_DIR/php-fpm/www.conf /etc/php/$fpm_v/fpm/pool.d/www.conf
+	cp -f ${HESTIA_INSTALL_DIR}/php-fpm/www.conf /etc/php/$fpm_v/fpm/pool.d/www.conf
 	update-rc.d php$fpm_v-fpm defaults > /dev/null 2>&1
 	systemctl start php$fpm_v-fpm >> $LOG
 	check_result $? "php-fpm start failed"
@@ -1575,9 +1594,9 @@ chmod 755 /etc/cron.daily/php-session-cleanup
 
 if [ "$vsftpd" = 'yes' ]; then
 	echo "[ * ] Configuring Vsftpd server..."
-	cp -f $HESTIA_INSTALL_DIR/vsftpd/vsftpd.conf /etc/
+	cp -f ${HESTIA_INSTALL_DIR}/vsftpd/vsftpd.conf /etc/
 	if [ "$ipv6" = 'yes' ]; then
-		cp -f $HESTIA_INSTALL_DIR/vsftpd/vsftpd-ipv6.conf /etc/vsftpd.conf
+		cp -f ${HESTIA_INSTALL_DIR}/vsftpd/vsftpd-ipv6.conf /etc/vsftpd.conf
 	fi
 	touch /var/log/vsftpd.log
 	chown root:adm /var/log/vsftpd.log
@@ -1585,7 +1604,7 @@ if [ "$vsftpd" = 'yes' ]; then
 	touch /var/log/xferlog
 	chown root:adm /var/log/xferlog
 	chmod 640 /var/log/xferlog
-	update-rc.d vsftpd defaults
+	update-rc.d vsftpd defaults > /dev/null 2>&1
 	systemctl start vsftpd >> $LOG
 	check_result $? "vsftpd start failed"
 fi
@@ -1597,8 +1616,8 @@ fi
 if [ "$proftpd" = 'yes' ]; then
 	echo "[ * ] Configuring ProFTPD server..."
 	echo "127.0.0.1 $servername" >> /etc/hosts
-	cp -f $HESTIA_INSTALL_DIR/proftpd/proftpd.conf /etc/proftpd/
-	cp -f $HESTIA_INSTALL_DIR/proftpd/tls.conf /etc/proftpd/
+	cp -f ${HESTIA_INSTALL_DIR}/proftpd/proftpd.conf /etc/proftpd/
+	cp -f ${HESTIA_INSTALL_DIR}/proftpd/tls.conf /etc/proftpd/
 
 	if [ "$release" = '22.04' ]; then
 		sed -i 's|IdentLookups                  off|#IdentLookups                  off|g' /etc/proftpd/proftpd.conf
@@ -1639,7 +1658,7 @@ if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	# Remove symbolic link
 	rm -f /etc/mysql/my.cnf
 	# Configuring MariaDB
-	cp -f $HESTIA_INSTALL_DIR/mysql/$mycnf /etc/mysql/my.cnf
+	cp -f ${HESTIA_INSTALL_DIR}/mysql/$mycnf /etc/mysql/my.cnf
 
 	# Switch MariaDB inclusions to the MySQL
 	if [ "$mysql_type" = 'MySQL' ]; then
@@ -1696,7 +1715,7 @@ fi
 
 # Source upgrade.conf with phpmyadmin versions
 # shellcheck source=/usr/local/hestia/install/upgrade/upgrade.conf
-source $HESTIA/install/upgrade/upgrade.conf
+source ${HESTIA}/install/upgrade/upgrade.conf
 
 if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	# Display upgrade information
@@ -1723,7 +1742,7 @@ if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	cp -rf phpMyAdmin-$pma_v-all-languages/* /usr/share/phpmyadmin
 
 	# Create copy of config file
-	cp -f $HESTIA_INSTALL_DIR/phpmyadmin/config.inc.php /etc/phpmyadmin/
+	cp -f ${HESTIA_INSTALL_DIR}/phpmyadmin/config.inc.php /etc/phpmyadmin/
 	mkdir -p /var/lib/phpmyadmin/tmp
 	chmod 770 /var/lib/phpmyadmin/tmp
 	chown root:www-data /usr/share/phpmyadmin/tmp
@@ -1744,12 +1763,12 @@ if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
 	rm -f phpMyAdmin-$pma_v-all-languages.tar.gz
 
 	write_config_value "DB_PMA_ALIAS" "phpmyadmin"
-	$HESTIA/bin/v-change-sys-db-alias 'pma' "phpmyadmin"
+	${HESTIA}/bin/v-change-sys-db-alias 'pma' "phpmyadmin"
 
 	# Special thanks to Pavel Galkin (https://skurudo.ru)
 	# https://github.com/skurudo/phpmyadmin-fixer
 	# shellcheck source=/usr/local/hestia/install/deb/phpmyadmin/pma.sh
-	source $HESTIA_INSTALL_DIR/phpmyadmin/pma.sh > /dev/null 2>&1
+	source ${HESTIA_INSTALL_DIR}/phpmyadmin/pma.sh > /dev/null 2>&1
 
 	# limit access to /etc/phpmyadmin/
 	chown -R root:www-data /etc/phpmyadmin/
@@ -1764,7 +1783,7 @@ fi
 if [ "$postgresql" = 'yes' ]; then
 	echo "[ * ] Configuring PostgreSQL database server..."
 	ppass=$(gen_pass)
-	cp -f $HESTIA_INSTALL_DIR/postgresql/pg_hba.conf /etc/postgresql/*/main/
+	cp -f ${HESTIA_INSTALL_DIR}/postgresql/pg_hba.conf /etc/postgresql/*/main/
 	systemctl restart postgresql
 	sudo -iu postgres psql -c "ALTER USER postgres WITH PASSWORD '$ppass'" > /dev/null 2>&1
 
@@ -1774,18 +1793,18 @@ if [ "$postgresql" = 'yes' ]; then
 	wget --retry-connrefused --quiet https://github.com/hestiacp/phppgadmin/releases/download/v$pga_v/phppgadmin-v$pga_v.tar.gz
 	tar xzf phppgadmin-v$pga_v.tar.gz -C /usr/share/phppgadmin/
 
-	cp -f $HESTIA_INSTALL_DIR/pga/config.inc.php /etc/phppgadmin/
+	cp -f ${HESTIA_INSTALL_DIR}/pga/config.inc.php /etc/phppgadmin/
 
 	ln -s /etc/phppgadmin/config.inc.php /usr/share/phppgadmin/conf/
 
 	# Configuring phpPgAdmin
 	if [ "$apache" = 'yes' ]; then
-		cp -f $HESTIA_INSTALL_DIR/pga/phppgadmin.conf /etc/apache2/conf.d/phppgadmin.inc
+		cp -f ${HESTIA_INSTALL_DIR}/pga/phppgadmin.conf /etc/apache2/conf.d/phppgadmin.inc
 	fi
 
 	rm phppgadmin-v$pga_v.tar.gz
 	write_config_value "DB_PGA_ALIAS" "phppgadmin"
-	$HESTIA/bin/v-change-sys-db-alias 'pga' "phppgadmin"
+	${HESTIA}/bin/v-change-sys-db-alias 'pga' "phppgadmin"
 fi
 
 #----------------------------------------------------------#
@@ -1794,8 +1813,8 @@ fi
 
 if [ "$named" = 'yes' ]; then
 	echo "[ * ] Configuring Bind DNS server..."
-	cp -f $HESTIA_INSTALL_DIR/bind/named.conf /etc/bind/
-	cp -f $HESTIA_INSTALL_DIR/bind/named.conf.options /etc/bind/
+	cp -f ${HESTIA_INSTALL_DIR}/bind/named.conf /etc/bind/
+	cp -f ${HESTIA_INSTALL_DIR}/bind/named.conf.options /etc/bind/
 	chown root:bind /etc/bind/named.conf
 	chown root:bind /etc/bind/named.conf.options
 	chown bind:bind /var/cache/bind
@@ -1828,14 +1847,14 @@ if [ "$exim" = 'yes' ]; then
 	gpasswd -a Debian-exim mail > /dev/null 2>&1
 	if [ "$release" = "22.04" ]; then
 		# Jammyy uses Exim 4.95 instead but config works with Exim4.94
-		cp -f $HESTIA_INSTALL_DIR/exim/exim4.conf.4.94.template /etc/exim4/exim4.conf.template
+		cp -f ${HESTIA_INSTALL_DIR}/exim/exim4.conf.4.94.template /etc/exim4/exim4.conf.template
 	else
-		cp -f $HESTIA_INSTALL_DIR/exim/exim4.conf.template /etc/exim4/
+		cp -f ${HESTIA_INSTALL_DIR}/exim/exim4.conf.template /etc/exim4/
 	fi
-	cp -f $HESTIA_INSTALL_DIR/exim/dnsbl.conf /etc/exim4/
-	cp -f $HESTIA_INSTALL_DIR/exim/spam-blocks.conf /etc/exim4/
-	cp -f $HESTIA_INSTALL_DIR/exim/limit.conf /etc/exim4/
-	cp -f $HESTIA_INSTALL_DIR/exim/system.filter /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/dnsbl.conf /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/spam-blocks.conf /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/limit.conf /etc/exim4/
+	cp -f ${HESTIA_INSTALL_DIR}/exim/system.filter /etc/exim4/
 	touch /etc/exim4/white-blocks.conf
 
 	if [ "$spamd" = 'yes' ]; then
@@ -1867,8 +1886,8 @@ fi
 if [ "$dovecot" = 'yes' ]; then
 	echo "[ * ] Configuring Dovecot POP/IMAP mail server..."
 	gpasswd -a dovecot mail > /dev/null 2>&1
-	cp -rf $HESTIA_COMMON_DIR/dovecot /etc/
-	cp -f $HESTIA_INSTALL_DIR/logrotate/dovecot /etc/logrotate.d/
+	cp -rf ${HESTIA_COMMON_DIR}/dovecot /etc/
+	cp -f ${HESTIA_INSTALL_DIR}/logrotate/dovecot /etc/logrotate.d/
 	rm -f /etc/dovecot/conf.d/15-mailboxes.conf
 	chown -R root:root /etc/dovecot*
 
@@ -1893,7 +1912,7 @@ fi
 if [ "$clamd" = 'yes' ]; then
 	gpasswd -a clamav mail > /dev/null 2>&1
 	gpasswd -a clamav Debian-exim > /dev/null 2>&1
-	cp -f $HESTIA_INSTALL_DIR/clamav/clamd.conf /etc/clamav/
+	cp -f ${HESTIA_INSTALL_DIR}/clamav/clamd.conf /etc/clamav/
 	update-rc.d clamav-daemon defaults
 	echo -ne "[ * ] Installing ClamAV anti-virus definitions... "
 	/usr/bin/freshclam >> $LOG &
@@ -1931,7 +1950,7 @@ fi
 
 if [ "$fail2ban" = 'yes' ]; then
 	echo "[ * ] Configuring fail2ban access monitor..."
-	cp -rf $HESTIA_INSTALL_DIR/fail2ban /etc/
+	cp -rf ${HESTIA_INSTALL_DIR}/fail2ban /etc/
 	if [ "$dovecot" = 'no' ]; then
 		fline=$(cat /etc/fail2ban/jail.local | grep -n dovecot-iptables -A 2)
 		fline=$(echo "$fline" | grep enabled | tail -n1 | cut -f 1 -d -)
@@ -1964,12 +1983,12 @@ fi
 
 # Configuring MariaDB/MySQL host
 if [ "$mysql" = 'yes' ] || [ "$mysql8" = 'yes' ]; then
-	$HESTIA/bin/v-add-database-host mysql localhost root $mpass
+	${HESTIA}/bin/v-add-database-host mysql localhost root $mpass
 fi
 
 # Configuring PostgreSQL host
 if [ "$postgresql" = 'yes' ]; then
-	$HESTIA/bin/v-add-database-host pgsql localhost postgres $ppass
+	${HESTIA}/bin/v-add-database-host pgsql localhost postgres $ppass
 fi
 
 #----------------------------------------------------------#
@@ -1979,7 +1998,7 @@ fi
 # Min requirements Dovecot + Exim + Mysql
 if ([ "$mysql" == 'yes' ] || [ "$mysql8" == 'yes' ]) && [ "$dovecot" == "yes" ]; then
 	echo "[ * ] Install Roundcube..."
-	$HESTIA/bin/v-add-sys-roundcube
+	${HESTIA}/bin/v-add-sys-roundcube
 	write_config_value "WEBMAIL_ALIAS" "webmail"
 else
 	write_config_value "WEBMAIL_ALIAS" ""
@@ -2010,7 +2029,7 @@ if [ "$sieve" = 'yes' ]; then
 	sed -i "s/mail_plugins = quota imap_quota/mail_plugins = quota imap_quota imap_sieve/g" /etc/dovecot/conf.d/20-imap.conf
 
 	# Replace dovecot-sieve config files
-	cp -f $HESTIA_COMMON_DIR/dovecot/sieve/* /etc/dovecot/conf.d
+	cp -f ${HESTIA_COMMON_DIR}/dovecot/sieve/* /etc/dovecot/conf.d
 
 	# Dovecot default file install
 	echo -e "require [\"fileinto\"];\n# rule:[SPAM]\nif header :contains \"X-Spam-Flag\" \"YES\" {\n    fileinto \"INBOX.Spam\";\n}\n" > /etc/dovecot/sieve/default
@@ -2026,7 +2045,7 @@ if [ "$sieve" = 'yes' ]; then
 	if [ -d "/var/lib/roundcube" ]; then
 		# Modify Roundcube config
 		mkdir -p $RC_CONFIG_DIR/plugins/managesieve
-		cp -f $HESTIA_COMMON_DIR/roundcube/plugins/config_managesieve.inc.php $RC_CONFIG_DIR/plugins/managesieve/config.inc.php
+		cp -f ${HESTIA_COMMON_DIR}/roundcube/plugins/config_managesieve.inc.php $RC_CONFIG_DIR/plugins/managesieve/config.inc.php
 		ln -s $RC_CONFIG_DIR/plugins/managesieve/config.inc.php $RC_INSTALL_DIR/plugins/managesieve/config.inc.php
 		chown -R root:www-data $RC_CONFIG_DIR/
 		chmod 751 -R $RC_CONFIG_DIR
@@ -2053,7 +2072,7 @@ else
 	write_config_value "API" "no"
 	write_config_value "API_SYSTEM" "0"
 	write_config_value "API_ALLOWED_IP" ""
-	$HESTIA/bin/v-change-sys-api disable
+	${HESTIA}/bin/v-change-sys-api disable
 fi
 
 #----------------------------------------------------------#
@@ -2061,14 +2080,14 @@ fi
 #----------------------------------------------------------#
 
 echo "[ * ] Configuring File Manager..."
-$HESTIA/bin/v-add-sys-filemanager quiet
+${HESTIA}/bin/v-add-sys-filemanager quiet
 
 #----------------------------------------------------------#
 #                  Configure dependencies                  #
 #----------------------------------------------------------#
 
 echo "[ * ] Configuring PHP dependencies..."
-$HESTIA/bin/v-add-sys-dependencies quiet
+${HESTIA}/bin/v-add-sys-dependencies quiet
 
 echo "[ * ] Install Rclone"
 curl -s https://rclone.org/install.sh | bash > /dev/null 2>&1
@@ -2079,22 +2098,27 @@ curl -s https://rclone.org/install.sh | bash > /dev/null 2>&1
 
 # Configuring system IPs
 echo "[ * ] Configuring System IP..."
-$HESTIA/bin/v-update-sys-ip > /dev/null 2>&1
+${HESTIA}/bin/v-update-sys-ip > /dev/null 2>&1
 
-# Get main IP
-ip=$(ip addr | grep 'inet ' | grep global | head -n1 | awk '{print $2}' | cut -f1 -d/)
-local_ip=$ip
+# Get primary IP
+default_nic="$(ip -d -j route show | jq -r '.[] | if .dst == "default" then .dev else empty end')"
+# IPv4
+primary_ipv4="$(ip -4 -d -j addr show "$default_nic" | jq -r '.[].addr_info[] | if .scope == "global" then .local else empty end' | head -n1)"
+# IPv6
+primary_ipv6="$(ip -6 -d -j addr show "$default_nic" | jq -r '.[].addr_info[] | if .scope == "global" then .local else empty end' | head -n1)"
+ip="$primary_ipv4"
+local_ip="$primary_ipv4"
 
 # Configuring firewall
 if [ "$iptables" = 'yes' ]; then
-	$HESTIA/bin/v-update-firewall
+	${HESTIA}/bin/v-update-firewall
 fi
 
 # Get public IP
-pub_ip=$(curl --ipv4 -s https://ip.hestiacp.com/)
-pub_ipv6=$(curl --ipv6 -s https://ip.hestiacp.com/)
+pub_ipv4="$(curl -fsLm5 --retry 2 --ipv4 https://ip.hestiacp.com/)"
+pub_ipv6="$(curl -fsLm5 --retry 2 --ipv6 https://ip.hestiacp.com/)"
 
-if [ -n "$pub_ip" ] && [ "$pub_ip" != "$ip" ]; then
+if [ -n "$pub_ipv4" ] && [ "$pub_ipv4" != "$ip" ]; then
 	if [ -e /etc/rc.local ]; then
 		sed -i '/exit 0/d' /etc/rc.local
 	else
@@ -2110,8 +2134,8 @@ if [ -n "$pub_ip" ] && [ "$pub_ip" != "$ip" ]; then
 	echo "exit 0" >> /etc/rc.local
 	chmod +x /etc/rc.local
 	systemctl enable rc-local > /dev/null 2>&1
-	$HESTIA/bin/v-change-sys-ip-nat $ip $pub_ip > /dev/null 2>&1
-	ip=$pub_ip
+	${HESTIA}/bin/v-change-sys-ip-nat ${ip} ${pub_ipv4} > /dev/null 2>&1
+	ip=${pub_ipv4}
 fi
 
 # Configuring libapache2-mod-remoteip
@@ -2119,14 +2143,14 @@ if [ "$apache" = 'yes' ] && [ "$nginx" = 'yes' ]; then
 	cd /etc/apache2/mods-available
 	echo "<IfModule mod_remoteip.c>" > remoteip.conf
 	echo "  RemoteIPHeader X-Real-IP" >> remoteip.conf
-	if [ "$local_ip" != "127.0.0.1" ] && [ "$pub_ip" != "127.0.0.1" ]; then
+	if [ "$local_ip" != "127.0.0.1" ] && [ "$pub_ipv4" != "127.0.0.1" ]; then
 		echo "  RemoteIPInternalProxy 127.0.0.1" >> remoteip.conf
 	fi
-	if [ -n "$local_ip" ] && [ "$local_ip" != "$pub_ip" ]; then
+	if [ -n "$local_ip" ] && [ "$local_ip" != "$pub_ipv4" ]; then
 		echo "  RemoteIPInternalProxy $local_ip" >> remoteip.conf
 	fi
-	if [ -n "$pub_ip" ]; then
-		echo "  RemoteIPInternalProxy $pub_ip" >> remoteip.conf
+	if [ -n "$pub_ipv4" ]; then
+		echo "  RemoteIPInternalProxy $pub_ipv4" >> remoteip.conf
 	fi
 	echo "</IfModule>" >> remoteip.conf
 	sed -i "s/LogFormat \"%h/LogFormat \"%a/g" /etc/apache2/apache2.conf
@@ -2137,13 +2161,13 @@ fi
 # Adding default domain
 if [ -n "$ip" ]; then
 	if [ -n "ipv6" ]; then
-		$HESTIA/bin/v-add-web-domain admin $servername $ip $ipv6
+		${HESTIA}/bin/v-add-web-domain admin ${servername} ${ip} ${ipv6}
 	else
-		$HESTIA/bin/v-add-web-domain admin $servername $ip
+		${HESTIA}/bin/v-add-web-domain admin ${servername} ${ip}
 	fi
 else
 	if [ -n "ipv6" ]; then
-		$HESTIA/bin/v-add-web-domain admin $servername "" $ipv6
+		${HESTIA}/bin/v-add-web-domain admin ${servername} "" ${ipv6}
 	fi
 fi
 check_result $? "can't create $servername domain"
@@ -2151,46 +2175,46 @@ check_result $? "can't create $servername domain"
 # Adding cron jobs
 export SCHEDULED_RESTART="yes"
 command="sudo $HESTIA/bin/v-update-sys-queue restart"
-$HESTIA/bin/v-add-cron-job 'admin' '*/2' '*' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '*/2' '*' '*' '*' '*' "$command"
 systemctl restart cron
 
 command="sudo $HESTIA/bin/v-update-sys-queue daily"
-$HESTIA/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue disk"
-$HESTIA/bin/v-add-cron-job 'admin' '15' '02' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '15' '02' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue traffic"
-$HESTIA/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '10' '00' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue webstats"
-$HESTIA/bin/v-add-cron-job 'admin' '30' '03' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '30' '03' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-queue backup"
-$HESTIA/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-backup-users"
-$HESTIA/bin/v-add-cron-job 'admin' '10' '05' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '10' '05' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-user-stats"
-$HESTIA/bin/v-add-cron-job 'admin' '20' '00' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '20' '00' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-sys-rrd"
-$HESTIA/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' '*/5' '*' '*' '*' '*' "$command"
 command="sudo $HESTIA/bin/v-update-letsencrypt-ssl"
 min=$(gen_pass '012345' '2')
 hour=$(gen_pass '1234567' '1')
-$HESTIA/bin/v-add-cron-job 'admin' "$min" "$hour" '*' '*' '*' "$command"
+${HESTIA}/bin/v-add-cron-job 'admin' "$min" "$hour" '*' '*' '*' "$command"
 
 # Enable automatic updates
-$HESTIA/bin/v-add-cron-hestia-autoupdate apt
+${HESTIA}/bin/v-add-cron-hestia-autoupdate apt
 
 # Building initital rrd images
-$HESTIA/bin/v-update-sys-rrd
+${HESTIA}/bin/v-update-sys-rrd
 
 # Enabling file system quota
 if [ "$quota" = 'yes' ]; then
-	$HESTIA/bin/v-add-sys-quota
+	${HESTIA}/bin/v-add-sys-quota
 fi
 
 # Set backend port
-$HESTIA/bin/v-change-sys-port $port > /dev/null 2>&1
+${HESTIA}/bin/v-change-sys-port $port > /dev/null 2>&1
 
 # Create default configuration files
-$HESTIA/bin/v-update-sys-defaults
+${HESTIA}/bin/v-update-sys-defaults
 
 # Update remaining packages since repositories have changed
 echo -ne "[ * ] Installing remaining software updates..."
@@ -2203,7 +2227,7 @@ echo
 update-rc.d hestia defaults
 systemctl start hestia
 check_result $? "hestia start failed"
-chown admin:admin $HESTIA/data/sessions
+chown admin:admin ${HESTIA}/data/sessions
 
 # Create backup folder and set correct permission
 mkdir -p /backup/
@@ -2217,8 +2241,8 @@ echo "@reboot root sleep 10 && rm /etc/cron.d/hestia-ssl && PATH='/usr/local/sbi
 #----------------------------------------------------------#
 
 echo "[ * ] Updating configuration files..."
-BIN="$HESTIA/bin"
-source $HESTIA/func/syshealth.sh
+BIN="${HESTIA}/bin"
+source ${HESTIA}/func/syshealth.sh
 syshealth_repair_system_config
 
 # Add /usr/local/hestia/bin/ to path variable
@@ -2292,7 +2316,7 @@ cat $tmpfile
 rm -f $tmpfile
 
 # Add welcome message to notification panel
-$HESTIA/bin/v-add-user-notification admin 'Welcome to Hestia Control Panel!' '<br>You are now ready to begin <a href="/add/user/">adding user accounts</a> and <a href="/add/web/">domains</a>. For help and assistance, <a href="https://hestiacp.com/docs/" target="_blank">view the documentation</a> or <a href="https://forum.hestiacp.com/" target="_blank">visit our forum</a>.<br><br>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">report any issues via GitHub</a>.<br><br><b>Have a wonderful day!</b><br><br><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team'
+${HESTIA}/bin/v-add-user-notification admin 'Welcome to Hestia Control Panel!' '<br>You are now ready to begin <a href="/add/user/">adding user accounts</a> and <a href="/add/web/">domains</a>. For help and assistance, <a href="https://hestiacp.com/docs/" target="_blank">view the documentation</a> or <a href="https://forum.hestiacp.com/" target="_blank">visit our forum</a>.<br><br>Please <a href="https://github.com/hestiacp/hestiacp/issues" target="_blank">report any issues via GitHub</a>.<br><br><b>Have a wonderful day!</b><br><br><i class="fas fa-heart icon-red"></i> The Hestia Control Panel development team'
 
 # Clean-up
 # Sort final configuration file