Browse Source

Merge branch 'develop' into webui-refresh-winterfell

Kristan Kenney 6 years ago
parent
commit
8ba6ed8b52

+ 2 - 0
.gitignore

@@ -3,5 +3,7 @@
 *.gzip
 *.gz
 *.bz2
+*.deb
+
 .vscode
 .DS_Store

+ 79 - 1
bin/v-add-letsencrypt-domain

@@ -49,7 +49,11 @@ query_le_v2() {
     curl -s -i -d "$post_data" "$1" -H "$content"
 }
 
-
+# Set DNS CAA record retrieval commands
+if [ ! -z "$DNS_SYSTEM" ]; then
+    dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
+    caa_record=$($BIN/v-list-dns-records $user $domain | grep -i "CAA" | cut -d' ' -f1)
+fi
 
 #----------------------------------------------------------#
 #                    Verifications                         #
@@ -122,11 +126,33 @@ if [ "$proto" = "http-01" ]; then
     done
 fi
 
+# Ensure DNS CAA record exists for Let's Encrypt before requesting certificate
+if [ ! -z "$DNS_SYSTEM" ]; then
+    # Check for DNS zone
+    if [ "$dns_domain" = "$domain" ]; then
+        # Replace DNS domain CAA records with Let's Encrypt values
+        if [ -z "$caa_record" ]; then
+            $BIN/v-add-dns-record $user $domain '@' 'CAA' 'issue 0 "letsencrypt.org"'
+        else
+            $BIN/v-delete-dns-record $user $domain $caa_record
+            $BIN/v-add-dns-record $user $domain '@' 'CAA' 'issue 0 "letsencrypt.org"'
+        fi
+    fi
+fi
+
 # Requesting nonce / STEP 1
 answer=$(curl -s -I "$LE_API/directory")
 nonce=$(echo "$answer" |grep Nonce |cut -f2 -d \ |tr -d '\r\n')
 status=$(echo "$answer"|grep HTTP/1.1 |tail -n1 |cut -f 2 -d ' ')
 if [[ "$status" -ne 200 ]]; then
+    # Delete DNS CAA record
+    if [ ! -z "$DNS_SYSTEM" ]; then
+        if [ "$dns_domain" = "$domain" ]; then
+            if [ ! -z "$caa_record" ]; then
+                $BIN/v-delete-dns-record $user $domain $caa_record
+            fi
+        fi
+    fi
     check_result $E_CONNECT "Let's Encrypt nonce request status $status"
 fi
 
@@ -147,6 +173,14 @@ authz=$(echo "$answer" |grep "acme/authz" |cut -f2 -d '"')
 finalize=$(echo "$answer" |grep 'finalize":' |cut -f4 -d '"')
 status=$(echo "$answer" |grep HTTP/1.1 |tail -n1 |cut -f2 -d ' ')
 if [[ "$status" -ne 201 ]]; then
+    # Delete DNS CAA record
+    if [ ! -z "$DNS_SYSTEM" ]; then
+        if [ "$dns_domain" = "$domain" ]; then
+            if [ ! -z "$caa_record" ]; then
+                $BIN/v-delete-dns-record $user $domain $caa_record
+            fi
+        fi
+    fi
     check_result $E_CONNECT "Let's Encrypt new auth status $status"
 fi
 
@@ -159,6 +193,17 @@ for auth in $authz; do
     nonce=$(echo "$answer" |grep Nonce |cut -f2 -d \ |tr -d '\r\n')
     status=$(echo "$answer"|grep HTTP/1.1 |tail -n1 |cut -f 2 -d ' ')
     if [[ "$status" -ne 200 ]]; then
+        # Delete DNS CAA record
+        if [ ! -z "$DNS_SYSTEM" ]; then
+            dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
+            caa_record=$($BIN/v-list-dns-records $user $domain | grep -i "letsencrypt" | cut -d' ' -f1)
+
+            if [ "$dns_domain" = "$domain" ]; then
+                if [ ! -z "$caa_record" ]; then
+                    $BIN/v-delete-dns-record $user $domain $caa_record
+                fi
+            fi
+        fi
         check_result $E_CONNECT "Let's Encrypt acme/authz bad status $status"
     fi
 
@@ -232,16 +277,49 @@ for auth in $authz; do
         nonce=$(echo "$answer" |grep Nonce |cut -f2 -d \ |tr -d '\r\n')
         status=$(echo "$answer"|grep HTTP/1.1 |tail -n1 |cut -f 2 -d ' ')
         if [[ "$status" -ne 200 ]]; then
+            # Delete DNS CAA record
+            if [ ! -z "$DNS_SYSTEM" ]; then
+                dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
+                caa_record=$($BIN/v-list-dns-records $user $domain | grep -i "letsencrypt" | cut -d' ' -f1)
+
+                if [ "$dns_domain" = "$domain" ]; then
+                    if [ ! -z "$caa_record" ]; then
+                        $BIN/v-delete-dns-record $user $domain $caa_record
+                    fi
+                fi
+            fi
             check_result $E_CONNECT "Let's Encrypt validation status $status"
         fi
 
         i=$((i + 1))
         if [ "$i" -gt 10 ]; then
+            # Delete DNS CAA record
+            if [ ! -z "$DNS_SYSTEM" ]; then
+                dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
+                caa_record=$($BIN/v-list-dns-records $user $domain | grep -i "letsencrypt" | cut -d' ' -f1)
+
+                if [ "$dns_domain" = "$domain" ]; then
+                    if [ ! -z "$caa_record" ]; then
+                        $BIN/v-delete-dns-record $user $domain $caa_record
+                    fi
+                fi
+            fi
             check_result $E_CONNECT "Let's Encrypt domain validation timeout"
         fi
         sleep 1
     done
     if [ "$validation" = 'invalid' ]; then
+        # Delete DNS CAA record
+        if [ ! -z "$DNS_SYSTEM" ]; then
+            dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
+            caa_record=$($BIN/v-list-dns-records $user $domain | grep -i "letsencrypt" | cut -d' ' -f1)
+
+            if [ "$dns_domain" = "$domain" ]; then
+                if [ ! -z "$caa_record" ]; then
+                    $BIN/v-delete-dns-record $user $domain $caa_record
+                fi
+            fi
+        fi    
         check_result $E_CONNECT "Let's Encrypt domain verification failed"
     fi
 done

+ 12 - 0
bin/v-delete-letsencrypt-domain

@@ -46,6 +46,18 @@ fi
 #                       Action                             #
 #----------------------------------------------------------#
 
+# Delete DNS CAA record
+if [ ! -z "$DNS_SYSTEM" ]; then
+    dns_domain=$($BIN/v-list-dns-domains $user | grep $domain | cut -d' ' -f1)
+    caa_record=$($BIN/v-list-dns-records $user $domain | grep -i "letsencrypt" | cut -d' ' -f1)
+
+    if [ "$dns_domain" = "$domain" ]; then
+        if [ ! -z "$caa_record" ]; then
+            $BIN/v-delete-dns-record $user $domain $caa_record
+        fi
+    fi
+fi
+
 # Delete SSL
 if [ -z "$mail" ]; then
     $BIN/v-delete-web-domain-ssl $user $domain $restart >/dev/null 2>&1

+ 0 - 3
bin/v-rebuild-mail-domains

@@ -45,9 +45,6 @@ U_MAIL_SSL=0
 SUSPENDED_MAIL=0
 U_DISK_MAIL=0
 
-# Update mail templates
-$BIN/v-update-mail-templates
-
 # Checking mail folder
 if [ ! -d "$USER_DATA/mail" ]; then
     rm -f $USER_DATA/mail

+ 5 - 0
bin/v-update-mail-templates

@@ -40,6 +40,11 @@ fi
 # Update templates
 cp -rf $HESTIA/install/$type/templates/mail $HESTIA/data/templates/
 
+# Rebuilding mail domains
+for user in $($BIN/v-list-sys-users plain); do
+    $BIN/v-rebuild-mail-domains $user no
+done
+
 #----------------------------------------------------------#
 #                       Hestia                             #
 #----------------------------------------------------------#

+ 13 - 15
bin/v-update-web-templates

@@ -41,23 +41,21 @@ fi
 cp -rf $HESTIA/install/$type/templates/web $HESTIA/data/templates/
 
 # Update Multi-PHP templates
-if [ -d "/etc/php/*/fpm" ]; then
-    php_versions=$(ls /etc/php/*/fpm -d | wc -l)
-    if [ "$php_versions" -gt 1 ]; then
-        if [ "$WEB_SYSTEM" = "nginx" ]; then
-            for tplname in $(ls $HESTIA/data/templates/web/$WEB_SYSTEM/ | grep -v 'default'); do
-                rm -fr $HESTIA/data/templates/web/$WEB_SYSTEM/$tplname
-            done
-        fi
-        for v in $(ls /etc/php/); do
-            if [ ! -d "/etc/php/$v/fpm/pool.d/" ]; then
-                continue
-            fi
-            v_tpl=$(echo "$v" | sed -e 's/[.]//')
-            cp -f $HESTIA/install/$type/multiphp/$WEB_SYSTEM/PHP-$v_tpl.* $HESTIA/data/templates/web/$WEB_SYSTEM/
+php_versions=$(ls /etc/php/*/fpm -d 2>/dev/null | wc -l)
+if [ "$php_versions" -gt 1 ]; then
+    if [ "$WEB_SYSTEM" = "nginx" ]; then
+        for tplname in $(ls $HESTIA/data/templates/web/$WEB_SYSTEM/ | grep -v 'default'); do
+            rm -fr $HESTIA/data/templates/web/$WEB_SYSTEM/$tplname
         done
-        chmod a+x $HESTIA/data/templates/web/$WEB_SYSTEM/*.sh
     fi
+    for v in $(ls /etc/php/); do
+        if [ ! -d "/etc/php/$v/fpm/pool.d/" ]; then
+            continue
+        fi
+        v_tpl=$(echo "$v" | sed -e 's/[.]//')
+        cp -f $HESTIA/install/$type/multiphp/$WEB_SYSTEM/PHP-$v_tpl.* $HESTIA/data/templates/web/$WEB_SYSTEM/
+    done
+    chmod a+x $HESTIA/data/templates/web/$WEB_SYSTEM/*.sh
 fi
 
 # Rebuilding web domains

+ 22 - 2
install/hst-install-debian.sh

@@ -79,6 +79,7 @@ help() {
   -s, --hostname          Set hostname
   -e, --email             Set admin email
   -p, --password          Set admin password
+  -D, --with-debs         Path to Hestia debs
   -f, --force             Force installation
   -h, --help              Print this help
 
@@ -179,6 +180,7 @@ for arg; do
         --email)                args="${args}-e " ;;
         --password)             args="${args}-p " ;;
         --force)                args="${args}-f " ;;
+        --with-debs)            args="${args}-D " ;;
         --help)                 args="${args}-h " ;;
         *)                      [[ "${arg:0:1}" == "-" ]] || delim="\""
                                 args="${args}${delim}${arg}${delim} ";;
@@ -187,7 +189,7 @@ done
 eval set -- "$args"
 
 # Parsing arguments
-while getopts "a:n:w:v:j:k:m:g:d:x:z:c:t:i:b:r:o:q:l:y:s:e:p:fh" Option; do
+while getopts "a:n:w:v:j:k:m:g:d:x:z:c:t:i:b:r:o:q:l:y:s:e:p:D:fh" Option; do
     case $Option in
         a) apache=$OPTARG ;;            # Apache
         n) nginx=$OPTARG ;;             # Nginx
@@ -212,6 +214,7 @@ while getopts "a:n:w:v:j:k:m:g:d:x:z:c:t:i:b:r:o:q:l:y:s:e:p:fh" Option; do
         s) servername=$OPTARG ;;        # Hostname
         e) email=$OPTARG ;;             # Admin email
         p) vpass=$OPTARG ;;             # Admin password
+        D) withdebs=$OPTARG ;;          # Hestia debs path
         f) force='yes' ;;               # Force install
         h) help ;;                      # Help
         *) help ;;                      # Print help (default)
@@ -281,6 +284,11 @@ fi
 # Clear the screen once launch permissions have been verified
 clear
 
+# Configure apt to retry downloading on error
+if [ ! -f /etc/apt/apt.conf.d/80-retries ]; then
+    echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
+fi
+
 # Update apt repository
 echo "Please wait a moment while we update your systems APT repositories..."
 apt-get -qq update
@@ -819,6 +827,11 @@ if [ "$multiphp" = 'yes' ]; then
     software=$(echo "$software" | sed -e 's/php-phpseclib//')
     software=$(echo "$software" | sed -e 's/php-pgsql//')
 fi
+if [ -d "$withdebs" ]; then
+    software=$(echo "$software" | sed -e 's/hestia-nginx//')
+    software=$(echo "$software" | sed -e 's/hestia-php//')
+    software=$(echo "$software" | sed -e 's/hestia//')
+fi
 
 #----------------------------------------------------------#
 #                     Install packages                     #
@@ -850,6 +863,13 @@ echo
 # Check Installation result
 check_result $? "apt-get install failed"
 
+# Install Hestia packages from local folder
+if [ ! -z "$withdebs" ] && [ -d "$withdebs" ]; then
+    dpkg -i $withdebs/hestia_*.deb
+    dpkg -i $withdebs/hestia-php_*.deb
+    dpkg -i $withdebs/hestia-nginx_*.deb
+fi
+
 # Restoring autostart policy
 rm -f /usr/sbin/policy-rc.d
 
@@ -1776,7 +1796,7 @@ echo "(!) IMPORTANT: You must logout or restart the server before continuing."
 echo -n " Do you want to logout now? [Y/N] "
 read resetshell
 
-if [ $resetshell = "Y" ] || [ $resetshell = "y" ]; then
+if [ "$resetshell" = "Y" ] || [ "$resetshell" = "y" ]; then
     logout
 fi
 

+ 22 - 2
install/hst-install-ubuntu.sh

@@ -64,6 +64,7 @@ help() {
   -s, --hostname          Set hostname
   -e, --email             Set admin email
   -p, --password          Set admin password
+  -D, --with-debs         Path to Hestia debs
   -f, --force             Force installation
   -h, --help              Print this help
 
@@ -164,6 +165,7 @@ for arg; do
         --email)                args="${args}-e " ;;
         --password)             args="${args}-p " ;;
         --force)                args="${args}-f " ;;
+        --with-debs)            args="${args}-D " ;;
         --help)                 args="${args}-h " ;;
         *)                      [[ "${arg:0:1}" == "-" ]] || delim="\""
                                 args="${args}${delim}${arg}${delim} ";;
@@ -172,7 +174,7 @@ done
 eval set -- "$args"
 
 # Parsing arguments
-while getopts "a:n:w:v:j:k:m:g:d:x:z:c:t:i:b:r:o:q:l:y:s:e:p:fh" Option; do
+while getopts "a:n:w:v:j:k:m:g:d:x:z:c:t:i:b:r:o:q:l:y:s:e:p:D:fh" Option; do
     case $Option in
         a) apache=$OPTARG ;;            # Apache
         n) nginx=$OPTARG ;;             # Nginx
@@ -197,6 +199,7 @@ while getopts "a:n:w:v:j:k:m:g:d:x:z:c:t:i:b:r:o:q:l:y:s:e:p:fh" Option; do
         s) servername=$OPTARG ;;        # Hostname
         e) email=$OPTARG ;;             # Admin email
         p) vpass=$OPTARG ;;             # Admin password
+        D) withdebs=$OPTARG ;;          # Hestia debs path
         f) force='yes' ;;               # Force install
         h) help ;;                      # Help
         *) help ;;                      # Print help (default)
@@ -266,6 +269,11 @@ fi
 # Clear the screen once launch permissions have been verified
 clear
 
+# Configure apt to retry downloading on error
+if [ ! -f /etc/apt/apt.conf.d/80-retries ]; then
+    echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
+fi
+
 # Update apt repository
 echo "Please wait a moment while we update your systems APT repositories..."
 apt-get -qq update
@@ -781,6 +789,11 @@ if [ "$multiphp" = 'yes' ]; then
     software=$(echo "$software" | sed -e 's/php-phpseclib//')
     software=$(echo "$software" | sed -e 's/php-pgsql//')
 fi
+if [ -d "$withdebs" ]; then
+    software=$(echo "$software" | sed -e 's/hestia-nginx//')
+    software=$(echo "$software" | sed -e 's/hestia-php//')
+    software=$(echo "$software" | sed -e 's/hestia//')
+fi
 
 #----------------------------------------------------------#
 #                 Disable Apparmor on LXC                  #
@@ -824,6 +837,13 @@ echo
 # Check Installation result
 check_result $? "apt-get install failed"
 
+# Install Hestia packages from local folder
+if [ ! -z "$withdebs" ] && [ -d "$withdebs" ]; then
+    dpkg -i $withdebs/hestia_*.deb
+    dpkg -i $withdebs/hestia-php_*.deb
+    dpkg -i $withdebs/hestia-nginx_*.deb
+fi
+
 # Restoring autostart policy
 rm -f /usr/sbin/policy-rc.d
 
@@ -1682,7 +1702,7 @@ echo "(!) IMPORTANT: You must logout or restart the server before continuing."
 echo -n " Do you want to logout now? [Y/N] "
 read resetshell
 
-if [ $resetshell = "Y" ] || [ $resetshell = "y" ]; then
+if [ "$resetshell" = "Y" ] || [ "$resetshell" = "y" ]; then
     logout
 fi
 

+ 11 - 13
install/upgrade/0.10.0-190430.sh

@@ -191,19 +191,17 @@ if [ "$PROXY_SYSTEM" = "nginx" ]; then
 fi
 
 # Fix empty pool error message for MultiPHP
-if [ -d "/etc/php/*/fpm" ]; then
-    php_versions=$(ls /etc/php/*/fpm -d | wc -l)
-    if [ "$php_versions" -gt 1 ]; then
-        for v in $(ls /etc/php/); do
-            if [ ! -d "/etc/php/$v/fpm/pool.d/" ]; then
-                continue
-            fi
-            echo "(*) Updating Multi-PHP configuration..."
-            cp -f $hestiacp/php-fpm/dummy.conf /etc/php/$v/fpm/pool.d/
-            v1=$(echo "$v" | sed -e 's/[.]//')
-            sed -i "s/9999/99$v1/g" /etc/php/$v/fpm/pool.d/dummy.conf
-        done
-    fi
+php_versions=$(ls /etc/php/*/fpm -d 2>/dev/null |wc -l)
+if [ "$php_versions" -gt 1 ]; then
+    for v in $(ls /etc/php/); do
+        if [ ! -d "/etc/php/$v/fpm/pool.d/" ]; then
+            continue
+        fi
+        echo "(*) Updating Multi-PHP configuration..."
+        cp -f $hestiacp/php-fpm/dummy.conf /etc/php/$v/fpm/pool.d/
+        v1=$(echo "$v" | sed -e 's/[.]//')
+        sed -i "s/9999/99$v1/g" /etc/php/$v/fpm/pool.d/dummy.conf
+    done
 fi
 
 # Set Purge to false in Roundcube configuration - https://goo.gl/3Nja3u

+ 0 - 5
install/upgrade/add_notifications.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-# Add notifications
-
-rm -f /usr/local/hestia/data/users/admin/notifications.conf
-/usr/local/hestia/bin/v-add-user-notification admin "HestiaCP Beta Test"

+ 7 - 2
web/inc/i18n/ru.php

@@ -754,6 +754,11 @@ $LANG['ru'] = array(
     'Do not use encryption' => 'Не использовать шифрование',
 
     'maximum characters length, including prefix' => 'максимальное %s количество символов, включая префикс',
-
-    'Email Credentials' => 'Email Credentials',
+	
+    'Email Credentials' => 'Отправить доступы на Email',
+	'2 Factor Authentication' => 'Двухфакторная аутентификация',
+    'Enable 2FA' => 'Включить двухфакторную аутентификацию',
+    'Please scan the code below in your 2FA application:' => 'Чтобы закончить настройку 2FA, сканируйте QR-Code ниже <br /> в приложении на Вашем устройстве (например, <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Google Authenticator</a>):',
+    '2FA Reset Code:' => 'Код восстановления доступа к аккаунту:',
+	'Force SSL/HTTPS' => 'Принудительный редирект HTTP-на-HTTPS',
 );

+ 6 - 34
web/inc/i18n/ua.php

@@ -4,7 +4,6 @@
  * COLOBOCman (colobocman@gmail.com)
  * Alexandr Loskutov (alex_connor@icloud.com)
  */
-
 $LANG['ua'] = array(
     'Packages' => 'Пакети',
     'IP' => 'IP',
@@ -17,7 +16,6 @@ $LANG['ua'] = array(
     'Updates' => 'Оновлення',
     'Log in' => 'Увійти',
     'Log out' => 'Вийти',
-
     'USER' => 'USER',
     'WEB' => 'WEB',
     'DNS' => 'DNS',
@@ -25,7 +23,6 @@ $LANG['ua'] = array(
     'DB' => 'DB',
     'CRON' => 'CRON',
     'BACKUP' => 'BACKUP',
-
     'LOGIN'  => 'ВВІЙТИ',
     'RESET PASSWORD'  => 'СКИНУТИ ПАРОЛЬ',
     'SEARCH'  => 'ПОШУК',
@@ -40,9 +37,7 @@ $LANG['ua'] = array(
     'DISK'  => 'ДИСК',
     'NETWORK'  => 'МЕРЕЖА',
     'Web Log Manager'  => 'Менеджер Web журналу',
-
     'no notifications'  => 'без сповіщень',
-
     'Add User' => 'Додати користувача',
     'Add Domain' => 'Додати домен',
     'Add Web Domain' => 'Додати WEB домен',
@@ -70,7 +65,6 @@ $LANG['ua'] = array(
     'Back' => 'Назад',
     'Save' => 'Зберегти',
     'Submit' => 'Відправити',
-
     'toggle all' => 'виділити все',
     'apply to selected' => 'застосувати до вибраних',
     'rebuild' => 'перебудувати',
@@ -111,7 +105,6 @@ $LANG['ua'] = array(
     'turn on notifications' => 'увімкнути сповіщення',
     'turn off notifications' => 'вимкнути сповіщення',
     'configure' => 'configure',
-
     'Adding User' => 'Додавання користувача',
     'Editing User' => 'Редагування користувача',
     'Adding Domain' => 'Додавання домену',
@@ -139,7 +132,6 @@ $LANG['ua'] = array(
     'Adding Firewall Rule' => 'Додавання правила',
     'Editing Firewall Rule' => 'Редагування правила',
     'Adding IP Address to Banlist' => 'Додавання IP-адреси в чорний список',
-
     'active' => 'активне',
     'spnd' => 'заблоковано',
     'suspended' => 'заблокований',
@@ -147,7 +139,6 @@ $LANG['ua'] = array(
     'stopped' => 'зупинений',
     'outdated' => 'застарілий',
     'updated' => 'оновлений',
-
     'yes' => 'так',
     'no' => 'ні',
     'none' => 'нема',
@@ -398,17 +389,14 @@ $LANG['ua'] = array(
     'FTP' => 'FTP',
     'HESTIA' => 'HESTIA',
     'Add one more Name Server' => 'Додати ще один сервер імен',
-
     'web domain' => 'web домен',
     'dns domain' => 'dns домен',
     'dns record' => 'dns запис',
     'mail domain' => 'mail домен',
     'mail account' => 'mail акаунт',
     'cron job' => 'cron завдання',
-
     'cron' => 'cron',
     'user dir' => 'тека користувача',
-
     'unlimited'  => 'безлімітний',
     '1 account' => ' 1 акаунт',
     '%s accounts' => '%s акаунтів',
@@ -440,7 +428,6 @@ $LANG['ua'] = array(
     '1 rule' => '1 правило',
     '%s rules' => '%s правил',
     'There are no currently banned IP' => 'Немає заблокованих IP',
-
     'USER_CREATED_OK' => 'Аккаунт <a href="/edit/user/?user=%s"><b>%s</b></a> успішно створено',
     'WEB_DOMAIN_CREATED_OK' => 'WEB домен <a href="/edit/web/?domain=%s"><b>%s</b></a> успішно створено.',
     'DNS_DOMAIN_CREATED_OK' => 'DNS домен <a href="/list/dns/?domain=%s"><b>%s</b></a> успішно створено.',
@@ -503,26 +490,21 @@ $LANG['ua'] = array(
     'BACKUP_EXISTS'  => 'Резервне копіювання вже виконується, будь-ласка, дочекайтесь закінчення.',
     'RESTORE_SCHEDULED'  => 'Завдання успішно додано в чергу. Після виконання ви отримаєте повний звіт по пошті.',
     'RESTORE_EXISTS'  => 'Завдання вже виконується, будь-ласка, дочекайтесь закінчення.',
-
     'WEB_EXCLUSIONS' => 'Вкажіть домени по одному на рядок. Для того, щоб виключити всі, використовуйте *. Щоб виключити тільки деякі теки, використовуйте наступний формат: domain.com:public_html/cache:public_html/tmp',
     'DNS_EXCLUSIONS' => 'Вкажіть домени по одному на рядок. Для того, щоб виключити всі, використовуйте *',
     'MAIL_EXCLUSIONS' => 'Вкажіть домени по одному на рядок. Для того, щоб виключити всі, використовуйте *. Щоб виключити тільки деякі акаунти, використовуйте наступний формат: domain.com:info:support:postmaster',
     'DB_EXCLUSIONS' => 'Вкажіть бази по одній на рядок. Для того, щоб виключити всі, використовуйте *',
     'CRON_EXCLUSIONS' => 'Для того, щоб виключити всі завдання, використовуйте *',
     'USER_EXCLUSIONS' => 'Вкажіть теки по одній на рядок. Для того, щоб виключити всі, використовуйте *',
-
     'Welcome to Hestia Control Panel' => 'Вітаємо в панелі керування Hestia',
     'MAIL_FROM' => 'Hestia Control Panel <noreply@%s>',
     'GREETINGS_GORDON_FREEMAN' => "Вітаємо, %s %s,\n",
     'GREETINGS' => "Вітаємо,\n",
     'ACCOUNT_READY' => "Ваш аккаунт успішно створено і готовий до використання.\n\nhttps://%s/login/\nІм'я користувача: %s\nПароль: %s\n\n--\nПанель керування Hestia\n",
-
     'FTP login credentials' => 'Дані доступу до FTP',
     'FTP_ACCOUNT_READY' => "FTP аккаунт успішно створено і готовий до використання.\n\nХост: %s\nІм'я користувача: %s_%s\nПароль: %s\n\n--\nПанель керування Hestia\n",
-
     'Database Credentials' => 'Дані доступу до БД',
     'DATABASE_READY' => "База даних успішно створена.\n\nБаза даних: %s\nКористувач: %s\nПароль: %s\n%s\n\n--\nПанель керування Hestia\n",
-
     'forgot password' => 'нагадати пароль',
     'Confirm' => 'Підтвердити',
     'New Password' => 'Новий пароль',
@@ -533,7 +515,6 @@ $LANG['ua'] = array(
     'RESET_CODE_SENT' => 'Код для відновлення паролю успішно відправлено на вашу електронну пошту.<br>',
     'MAIL_RESET_SUBJECT' => 'Відновлення паролю %s',
     'PASSWORD_RESET_REQUEST'=>"Щоб відновити пароль, будь-ласка, перейдіть за посиланням :\nhttps://%s/reset/?action=confirm&user=%s&code=%s\n\nТакож ви можете відкрити сторінку https://%s/reset/?action=code&user=%s і вручну ввести код для відновлення:\n%s\n\nЯкщо ви не виконували процедуру відновлення паролю, будь ласка, проігноруйте цей лист і прийміть наші вибачення.\n\n--\nПанель керування Hestia\n",
-
     'Jan' => 'Січ',
     'Feb' => 'Лют',
     'Mar' => 'Бер',
@@ -546,7 +527,6 @@ $LANG['ua'] = array(
     'Oct' => 'Жовт',
     'Nov' => 'Лист',
     'Dec' => 'Груд',
-
     'Configuring Server' => 'Налаштування серверу',
     'Hostname' => "Ім'я хоста",
     'Time Zone' => 'Часовий пояс',
@@ -583,14 +563,11 @@ $LANG['ua'] = array(
     'Backup Migration Manager' => 'Менеджер міграції архівів',
     'FileManager' => 'Файл менеджер',
     'show: CPU / MEM / NET / DISK' => 'show: CPU / MEM / NET / DISK',
-
     'sort by' => 'сортувати за',
     'Date' => 'Дата',
     'Starred' => 'Вибране',
     'Name' => "Ім'я",
-
     'save to favorites' => 'зберегти до улюблених',
-
     'File Manager' => 'Файловий менеджер',
     'size' => 'розмір',
     'date' => 'дата',
@@ -653,7 +630,6 @@ $LANG['ua'] = array(
     'read by others' => 'читання для інших',
     'write by others' => 'запис для інших',
     'execute/search by others' => 'виконання/пошук для інших',
-
     'Shortcuts' => 'Скорочення',
     'Add New object' => "Додати новий об'єкт",
     'Save Form' => 'Зберегти форму',
@@ -672,7 +648,6 @@ $LANG['ua'] = array(
     'Enter focused element' => 'Перейти до активного пункту меню',
     'Move up through elements list' => 'Перейти до попереднього елементу списку',
     'Move down through elements list' => 'Перейти до наступного елементу списку',
-
     'Upload' => 'Вивантажити',
     'New File' => 'Новий файл',
     'New Folder' => 'Нова тека',
@@ -696,7 +671,6 @@ $LANG['ua'] = array(
     'Select All Files' => 'Виділити всі файли',
     'shortcuts are inspired by magnificent GNU <a href="https://www.midnight-commander.org/">Midnight Commander</a> file manager' =>
         'скорочення позичені у файлогово менеджера GNU <a href="https://www.midnight-commander.org/">Midnight Commander</a>',
-
     'Licence Key' => 'Ліцензійний ключ',
     'Enter License Key' => 'Введіть ліцензійний ключ',
     'Buy Licence' => 'Придбати ліцензію',
@@ -707,7 +681,6 @@ $LANG['ua'] = array(
     'Restrict users so that they cannot use SSH and access only their home directory.' => 'Обмежити користувачів, так що вони не можуть використовувати SSH і мають доступ тільки до домашньої теки.',
     'Browse, copy, edit, view, and retrieve all of your web domain files using fully featured File Manager.' => 'Перегляд, копіювання, редагування, переглядання та використання всіх файлів веб-доменів за допомогою повнофункціонального Файлового менеджеру.',
     'This is a commercial module, you would need to purchace license key to enable it.' => 'Це коммерційний модуль, ви повинні придбати ліцензіний ключ для увімкнення.',
-
     'Minutes' => 'Щохвилини',
     'Hourly' => 'Щогодини',
     'Run Command' => 'Виконати команду',
@@ -732,9 +705,7 @@ $LANG['ua'] = array(
     'every two minutes' => 'кожні дві хвилини',
     'every' => 'кожні',
     'Generate' => 'Генерувати',
-
     'awstats' => 'awstats',
-
     'Hestia SSL' => 'Hestia SSL',
     'SUBJECT' => "ОБ'ЄКТ",
     'ALIASES' => 'АЛІАСИ',
@@ -743,15 +714,16 @@ $LANG['ua'] = array(
     'SIGNATURE' => 'ПІДПИС',
     'PUB_KEY' => 'ПУБЛІЧНИЙ КЛЮЧ',
     'ISSUER' => 'ВИДАВЕЦЬ',
-
     'Use server hostname' => "Використовувати серверне ім'я хоста",
     'Use domain hostname' => "Використовувати доменне ім'я хоста",
     'Use STARTTLS' => 'Використовувати STARTTLS',
     'Use SSL / TLS' => 'Використовувати SSL / TLS',
     'No encryption' => 'Без шифрування',
     'Do not use encryption' => 'Не використовувати шифрування',
-
     'maximum characters length, including prefix' => 'максимальна %s кількість символів, включаючи префікс',
-
-    'Email Credentials' => 'Email Credentials',
-);
+    'Email Credentials' => 'Надіслати доступи на Email',
+	'2 Factor Authentication' => 'Двоетапна аутентифікація',
+    'Enable 2FA' => 'Увімкнути двоетапну аутентіфікацію',
+    'Please scan the code below in your 2FA application:' => 'Щоб закінчити налаштування 2FA, скануйте QR-Code нижче <br /> за допомогою додатку на Вашому пристрої (наприклад, <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Google Authenticator</a>):',
+    '2FA Reset Code:' => 'Код відновлення доступу до акаунту:',
+	'Force SSL/HTTPS' => 'Примусовий редирект HTTP-на-HTTPS',