#!/bin/bash
#=================================================================================#
#        MagenX e-commerce stack for Magento 2                                    #
#        Copyright (C) 2013-present admin@magenx.com                              #
#        All rights reserved.                                                     #
#=================================================================================#
SELF=$(basename $0)
MAGENX_VERSION=$(curl -s https://api.github.com/repos/magenx/Magento-2-server-installation/tags 2>&1 | head -3 | grep -oP '(?<=")\d.*(?=")')
MAGENX_BASE="https://magenx.sh"
###################################################################################
###                              REPOSITORY AND PACKAGES                        ###
###################################################################################

# Github installation repository raw url
MAGENX_INSTALL_GITHUB_REPO="https://raw.githubusercontent.com/magenx/Magento-2-server-installation/master"

# Magento
VERSION_LIST=$(curl -s https://api.github.com/repos/magento/magento2/tags 2>&1 | grep -oP '(?<=name": ").*(?=")' | sort -r)
PROJECT="composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition"

COMPOSER_NAME="8c681734f22763b50ea0c29dff9e7af2" 
COMPOSER_PASSWORD="02dfee497e669b5db1fe1c8d481d6974" 

## Version lock
COMPOSER_VERSION="2.7"
RABBITMQ_VERSION="1:4.1.4-1"
ERLANG_VERSION="1:27.*"
MARIADB_VERSION="11.4"
PHP_VERSION="8.4"
OPENSEARCH_VERSION="2.x"
VARNISH_VERSION="77"
REDIS_VERSION="8"
NODE_VERSION="20"
NVM_VERSION="0.40.3"

# Repositories
MARIADB_REPO_CONFIG="https://r.mariadb.com/downloads/mariadb_repo_setup"

# Nginx configuration
NGINX_VERSION=$(curl -s http://nginx.org/en/download.html | grep -oP '(?<=gz">nginx-).*?(?=</a>)' | head -1)
MAGENX_NGINX_GITHUB="https://github.com/magenx/Magento-nginx-config"

# Debug Tools
MYSQL_TUNER="https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl"

# Malware detector
MALDET="https://www.rfxn.com/downloads/maldetect-current.tar.gz"

# WebStack Packages .deb
WEB_STACK_CHECK="mysql* rabbitmq* elasticsearch opensearch percona-server* maria* php* nginx* varnish* certbot* redis* webmin"

EXTRA_PACKAGES="curl jq gnupg2 auditd apt-transport-https apt-show-versions ca-certificates lsb-release make autoconf snapd automake libtool uuid-runtime \
perl openssl unzip screen nfs-common inotify-tools iptables smartmontools vim wget sudo apache2-utils python3-setuptools \
logrotate git netcat-openbsd patch ipset postfix strace rsyslog moreutils lsof sysstat acl attr iotop expect imagemagick snmp ssl-cert-check ufw gettext-base"

PERL_MODULES="liblwp-protocol-https-perl libdbi-perl libconfig-inifiles-perl libdbd-mysql-perl libterm-readkey-perl"

PHP_PACKAGES=(cli fpm common mysql zip lz4 gd mbstring curl xml bcmath intl ldap soap oauth apcu)
###################################################################################
###                                    COLORS                                   ###
###################################################################################
RED="\e[31;40m"
GREEN="\e[32;40m"
YELLOW="\e[33;40m"
WHITE="\e[37;40m"
BLUE="\e[0;34m"
### Background
DGREYBG="  \e[100m"
BLUEBG="  \e[1;44m"
REDBG="  \e[41m"
### Styles
BOLD="\e[1m"
### Reset
RESET="\e[0m"
###################################################################################
###                            ECHO MESSAGES DESIGN                             ###
###################################################################################
WHITETXT () {
        MESSAGE=${@:-"${RESET}Error: No message passed"}
        echo -e "  ${WHITE}${MESSAGE}${RESET}"
}
BLUETXT () {
        MESSAGE=${@:-"${RESET}Error: No message passed"}
        echo -e "  ${BLUE}${MESSAGE}${RESET}"
}
REDTXT () {
        MESSAGE=${@:-"${RESET}Error: No message passed"}
        echo -e "  ${RED}${MESSAGE}${RESET}"
}
GREENTXT () {
        MESSAGE=${@:-"${RESET}Error: No message passed"}
        echo -e "  ${GREEN}${MESSAGE}${RESET}"
}
YELLOWTXT () {
        MESSAGE=${@:-"${RESET}Error: No message passed"}
        echo -e "  ${YELLOW}${MESSAGE}${RESET}"
}
BLUEBG () {
        MESSAGE=${@:-"${RESET}Error: No message passed"}
        echo -e "${BLUEBG}${MESSAGE}${RESET}"
}
_pause () {
   read -p "  $*"
}
_echo () {
  echo -en "  $@"
}
_space() {
    local count=${1:-1}
    printf '%0.s\n' $(seq 1 $count)
}

PACKAGES_INSTALLED () {
GREENTXT "Installed: "
apt -qq list --installed $@ 2>/dev/null | awk '{print "   " $0}'
}
###################################################################################
###                            ARROW KEYS UP/DOWN MENU                          ###
###################################################################################
updown_menu () {
i=1;for items in $(echo $1); do item[$i]="${items}"; let i=$i+1; done
i=1
echo -e "\n  Use up/down arrow keys then press [ Enter ] to select $2"
while [ 0 ]; do
  if [ "$i" -eq 0 ]; then i=1; fi
  if [ ! "${item[$i]}" ]; then let i=i-1; fi
  echo -en "\r                                 " 
  echo -en "\r${item[$i]}"
  read -sn 1 selector
  case "${selector}" in
    "B") let i=i+1;;
    "A") let i=i-1;;
    "") _space 1; read -sn 1 -p "  [?] To confirm [ "$(echo -e $BOLD${item[$i]}$RESET)" ] press "$(echo -e $BOLD$GREEN"y"$RESET)" or "$(echo -e $BOLD$RED"n"$RESET)" for new selection" confirm
      if [[ "${confirm}" =~ ^[Yy]$  ]]; then
        printf -v "$2" '%s' "${item[$i]}"
        break
      else
        _space 1
        echo -e "\n  Use up/down arrow keys then press [ Enter ] to select $2"
      fi
      ;;
  esac
done }
###################################################################################
###           CHECK IF ROOT AND CREATE DATABASE TO SAVE ALL SETTINGS            ###
###################################################################################
_space 2
# root?
if [[ ${EUID} -ne 0 ]]; then
  _space 1
  REDTXT "[!] This script must be run as root user!"
  YELLOWTXT "[!] Login as root and run this script again."
  exit 1
else
  GREENTXT "PASS: ROOT!"
fi

# Config path
MAGENX_CONFIG_PATH="/opt/magenx/config"
if [ ! -d "${MAGENX_CONFIG_PATH}" ]; then
  mkdir -p ${MAGENX_CONFIG_PATH}
fi

# SQLite check, create database path and command
if ! which sqlite3 >/dev/null; then
  _space 1
  YELLOWTXT "[!] SQLite is not installed on this system!"
  YELLOWTXT "[!] Installing..."
  _space 2
  apt update
  apt -y install sqlite3
fi

SQLITE3_DB="magenx.db"
SQLITE3_DB_PATH="${MAGENX_CONFIG_PATH}/${SQLITE3_DB}"
SQLITE3="sqlite3 ${SQLITE3_DB_PATH}"
if [ ! -f "${SQLITE3_DB_PATH}" ]; then
  ${SQLITE3} "" ""

# Create base tables to save configuration
${SQLITE3} "CREATE TABLE IF NOT EXISTS system(
   machine_id             text,
   distro_name            text,
   distro_version         text,
   web_stack              text,
   timezone               text,
   system_test            text,
   ssh_port               text,
   terms                  text,
   system_update          text,
   php_version            text,
   nginx_version          text,
   mariadb_version        text,
   webmin_password        text,
   mysql_root_password    text,
   opensearch_admin_password text
   );"
   
${SQLITE3} "CREATE TABLE IF NOT EXISTS magento(
   redis_password            text,
   rabbitmq_password         text,
   indexer_password          text,
   version_installed         text,
   domain                    text,
   brand                     text,
   php_user                  text,
   root_path                 text,
   database_host             text,
   database_name             text,
   database_user             text,
   database_password         text,
   admin_login               text,
   admin_password            text,
   admin_email               text,
   locale                    text,
   admin_path                text,
   crypt_key                 text,
   tfa_key                   text,
   private_ssh_key           text,
   public_ssh_key            text,
   github_actions_private_ssh_key    text,
   github_actions_public_ssh_key     text
   );"
   
${SQLITE3} "CREATE TABLE IF NOT EXISTS menu(
   lemp        text,
   magento     text,
   database    text,
   install     text,
   config      text,
   webmin      text
   );"
   
${SQLITE3} "INSERT INTO menu (lemp, magento, database, install, config, webmin)
 VALUES('-', '-', '-', '-', '-', '-');"
fi
###################################################################################
###                              CHECK IF WE CAN RUN IT                         ###
###################################################################################
## Ubuntu Debian
## Distro detectction
distro_error() {
  _space 1
  REDTXT "[!] ${OS_NAME} ${OS_VERSION} detected"
  _space 1
  echo " Unfortunately, your operating system distribution and version are not supported by this script"
  echo " Supported: Ubuntu 22|24; Debian 12|13"
  echo " Please email admin@magenx.com and let us know if you run into any issues"
  _space 1
  exit 1
}

# Check if distribution name and version are already in the database
DISTRO_INFO=($(${SQLITE3} -list -separator '  ' "SELECT distro_name, distro_version FROM system;"))
if [ -n "${DISTRO_INFO[0]}" ]; then
  DISTRO_NAME="${DISTRO_INFO[0]}"
  DISTRO_VERSION="${DISTRO_INFO[1]}"
  GREENTXT "PASS: [ ${DISTRO_NAME} ${DISTRO_VERSION} ]"
else
  ## Detect distribution name and version
  if [ -f "/etc/os-release" ]; then
    . /etc/os-release
    DISTRO_NAME="${NAME}"
    DISTRO_VERSION="${VERSION_ID}"

    ## Check if distribution is supported
    if [ "${DISTRO_NAME%% *}" == "Ubuntu" ] && [[ "${DISTRO_VERSION}" =~ ^(22.04|24.04) ]]; then
      DISTRO_NAME="Ubuntu"
    elif [ "${DISTRO_NAME%% *}" == "Debian" ] && [[ "${DISTRO_VERSION}" =~ ^(12|13) ]]; then
      DISTRO_NAME="Debian"
    else
      distro_error
    fi

    # Confirm distribution detection with user input
    _space 1
    _echo "${YELLOW}[?]${REDBG}${BOLD}[ ${DISTRO_NAME} ${DISTRO_VERSION} ]${RESET} ${YELLOW}detected correctly ? [y/n][n]: ${RESET}"
    read distro_detect
    if [ "${distro_detect}" = "y" ]; then
      _space 1
      GREENTXT "PASS: [ ${DISTRO_NAME} ${DISTRO_VERSION} ]"
      # Get machine id
      MACHINE_ID="$(cat /etc/machine-id)"
      ${SQLITE3} "INSERT INTO system (machine_id, distro_name, distro_version) VALUES ('${MACHINE_ID}', '${DISTRO_NAME}', '${DISTRO_VERSION}');"
    else
      distro_error
    fi
  else
    distro_error
  fi
fi

## network is up?
host1=${MAGENX_BASE}
host2=github.com

RESULT=$(((ping -w3 -c2 ${host1} || ping -w3 -c2 ${host2}) > /dev/null 2>&1) && echo "up" || (echo "down" && exit 1))
if [[ ${RESULT} == up ]]; then
  GREENTXT "PASS: NETWORK IS UP. GREAT, LETS START!"
  else
  _space 1
  REDTXT "[!] Network is down ?"
  YELLOWTXT "[!] Please check your network settings."
  _space 2
  exit 1
fi

## install packages to run CPU and HDD test
dpkg-query -l curl time bc bzip2 tar >/dev/null || { echo; echo; apt update -o Acquire::ForceIPv4=true; apt -y install curl time bc bzip2 tar; }

## check if you need self update
MD5_NEW=$(curl -sL ${MAGENX_BASE} > ${SELF}.new && md5sum ${SELF}.new | awk '{print $1}')
MD5=$(md5sum ${SELF} | awk '{print $1}')
 if [[ "${MD5_NEW}" == "${MD5}" ]]; then
   GREENTXT "PASS: INTEGRITY CHECK FOR '${SELF}' OK"
   rm ${SELF}.new
  elif [[ "${MD5_NEW}" != "${MD5}" ]]; then
   _space 1
   YELLOWTXT "Integrity check for '${SELF}'"
   YELLOWTXT "detected different md5 checksum"
   YELLOWTXT "remote repository file has some changes"
   _space 1
   REDTXT "IF YOU HAVE LOCAL CHANGES REMOVE INTEGRITY CHECK OR SKIP UPDATES"
   _space 1
   _echo "[?] Would you like to update the file now?  [y/n][y]: "
   read update_agree
  if [ "${update_agree}" == "y" ];then
   mv ${SELF}.new ${SELF}
   _space 1
   GREENTXT "The file has been upgraded, please run it again"
   _space 1
  exit 1
  else
   _space 1
   YELLOWTXT "New file saved to ${SELF}.new"
   _space 1
  fi
fi

# check if memory is enough
TOTALMEM=$(awk '/MemTotal/{print $2}' /proc/meminfo | xargs -I {} echo "scale=4; {}/1024^2" | bc | xargs printf "%1.0f")
if [ "${TOTALMEM}" -ge "4" ]; then
  GREENTXT "PASS: TOTAL RAM [${TOTALMEM}Gb]"
 else
  _space 1
  REDTXT "[!] Total RAM less than ${BOLD}4Gb"
  YELLOWTXT "[!] To run complete stack you need more RAM"
  _space 1
fi

## check if web stack is clean
WEB_STACK=$(${SQLITE3} "SELECT web_stack FROM system;")
if [ "${WEB_STACK}" != "magenx" ]; then
  installed_packages="$(apt -qq list --installed ${WEB_STACK_CHECK} 2> /dev/null | cut -d'/' -f1 | tr '\n' ' ')"
  if [ ! -z "$installed_packages" ]; then
    REDTXT  "[!] Some webstack packages already installed"
    YELLOWTXT "[!] You need to remove them or reinstall minimal OS version"
    _space 1
    echo -e "\t\t apt -y remove ${installed_packages}"
    _space 2
    exit 1
  else
    ## set web_stack clean
    ${SQLITE3} "UPDATE system SET web_stack = 'magenx';"
  fi
fi

## print path
GREENTXT "PATH: ${PATH}"

## configure system/magento timezone
TIMEZONE="$(${SQLITE3} "SELECT timezone FROM system;")"
if [ -z "${TIMEZONE}" ]; then
  _space 2
  YELLOWTXT "[!] Server and Magento timezone configuration:"
  _space 1
  _pause "[] Press [Enter] key to proceed"
  _space 1
  dpkg-reconfigure tzdata
  TIMEZONE=$(timedatectl | awk '/Time zone:/ {print $3}')
  ${SQLITE3} "UPDATE system SET timezone = '${TIMEZONE}';"
fi
GREENTXT "TIMEZONE: ${TIMEZONE}"

_space 2
SYSTEM_TEST=$(${SQLITE3} "SELECT system_test FROM system;")
if [ -z "${SYSTEM_TEST}" ]; then
 _space 1
 BLUEBG "~    QUICK SYSTEM TEST    ~"
 WHITETXT "-------------------------------------------------------------------------------------"
 _space 1
  # run I/O and CPU tests
  TEST_FILE="TEST_FILE__$$"
  TAR_FILE="TAR_FILE"
  _echo "${YELLOW}[?] I/O PERFORMANCE${RESET}:"
  IO=$( ( dd if=/dev/zero of=${TEST_FILE} bs=64k count=16k conv=fdatasync && rm -f ${TEST_FILE} ) 2>&1 | awk -F, '{IO=$NF} END { print IO}' )
  _echo ${IO}
  _space 1
  _echo "${YELLOW}[?] CPU PERFORMANCE${RESET}:"
  dd if=/dev/urandom of=${TAR_FILE} bs=1024 count=25000 >>/dev/null 2>&1
  CPU_TIME=$( (/usr/bin/time -f "%es" tar cfj ${TAR_FILE}.bz2 ${TAR_FILE}) 2>&1 )
  rm -f ${TAR_FILE}*
  _echo ${CPU_TIME}
 _space 3
 # set system_test tested
 ${SQLITE3} "UPDATE system SET system_test = 'I/O:${IO} CPU:${CPU_TIME}';"
 _space 1
 _pause "[] Press [Enter] key to proceed"
 _space 1
fi

_space 1
## ssh service/socket test
if systemctl is-enabled ssh.socket >/dev/null 2>&1; then
  YELLOWTXT "SSH socket is enabled, disabling it"
  systemctl disable ssh.socket
  systemctl enable ssh.service
  systemctl restart ssh.service
  GREENTXT "SSH service enabled"
else
  GREENTXT "SSH socket is already disabled"
fi

## ssh port test
SSH_PORT=$(${SQLITE3} "SELECT ssh_port FROM system;")
if [ -z "${SSH_PORT}" ]; then
_space 1
OVERRIDE_DIR="/etc/ssh/sshd_config.d"
_space 1
YELLOWTXT "SSH config optimization:"
tee ${OVERRIDE_DIR}/10-magenx-security.conf << 'EOF'
LoginGraceTime 30
MaxAuthTries 6
X11Forwarding no
PrintLastLog yes
TCPKeepAlive yes
ClientAliveInterval 600
ClientAliveCountMax 3
UseDNS no
PrintMotd no
#Subsystem sftp /usr/lib/openssh/sftp-server -l INFO
EOF

_space 2
CURRENT_PORT=$(sshd -T | grep '^port ' | awk '{print $2}')
if [ "${CURRENT_PORT}" = "22" ]; then
  SSH_PORT=$(shuf -i 9537-9554 -n 1)
tee ${OVERRIDE_DIR}/20-magenx-custom-port.conf << EOF
Port ${SSH_PORT}
EOF
  YELLOWTXT "Changed SSH port from 22 to ${SSH_PORT}"
fi

chmod 600 ${OVERRIDE_DIR}/*magenx*.conf

systemctl restart sshd.service
  _space 1
  GREENTXT "SSH configurations were updated - OK"
  _space 1
  GREENTXT "[!] SSH Port: ${SSH_PORT}"
  _space 1
  systemctl restart sshd.service
  ss -tlp | grep sshd
  _space 2
REDTXT "[!] IMPORTANT: Now open new SSH session with the new port!"
REDTXT "[!] IMPORTANT: Do not close your current session!"
_space 1
_echo "[?] Have you logged in another session? [y/n][n]: "
read ssh_test
if [ "${ssh_test}" == "y" ]; then
  _space 1
   GREENTXT "[!] SSH Port: ${SSH_PORT}"
   _space 1
   ${SQLITE3} "UPDATE system SET ssh_port = '${SSH_PORT}';"
   _space 2
   _pause "[] Press [Enter] key to proceed"
  else
   _space 1
   rm ${OVERRIDE_DIR}/*magenx*.conf
   REDTXT "Restoring sshd_config file back to defaults ${GREEN} [ok]"
   systemctl restart sshd.service
   _space 1
   GREENTXT "SSH configuration has been restored - OK"
   ss -tlp | grep sshd
  fi
fi

# Enter domain name and ssh user per environment
DOMAIN=($(${SQLITE3} "SELECT domain FROM magento;"))
if [ "${DOMAIN}" = "" ]; then
 _space 3
 read -e -p "$(echo -e ${YELLOW}"  [?] Store domain name: "${RESET})" -i "domain.com" DOMAIN
 read -e -p "$(echo -e ${YELLOW}"  [?] Files brand/SSH user: "${RESET})" -i "${DOMAIN//[-.]/}" BRAND
 
 ${SQLITE3} "INSERT INTO magento (domain, brand, php_user, root_path) VALUES ( '${DOMAIN}', '${BRAND}', 'php-${BRAND}', '/home/${BRAND}' );"
 else
   GREENTXT "DOMAIN: ${DOMAIN}"
fi
 _space 2
###################################################################################
###                                  AGREEMENT                                  ###
###################################################################################
_space 1
TERMS=$(${SQLITE3} "SELECT terms FROM system;")
if [ "${TERMS}" != "agreed" ]; then
_space 1
  YELLOWTXT "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
  _space 1
  YELLOWTXT "BY INSTALLING THIS SOFTWARE AND BY USING ANY AND ALL SOFTWARE"
  YELLOWTXT "YOU ACKNOWLEDGE AND AGREE:"
  _space 1
  YELLOWTXT "THIS SOFTWARE AND ALL SOFTWARE PROVIDED IS PROVIDED AS IS"
  YELLOWTXT "UNSUPPORTED AND WE ARE NOT RESPONSIBLE FOR ANY DAMAGE"
  _space 1
  YELLOWTXT "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
  _space 2
    _echo "[?] Do you agree to these terms ?  [y/n][y]: "
    read terms_agree
    if [ "${terms_agree}" == "y" ]; then
      # set terms agreed
      ${SQLITE3} "UPDATE system SET terms = 'agreed';"
    else
      REDTXT "Going out."
      _space 1
      exit 1
  fi
fi
###################################################################################
###                                  MAIN MENU                                  ###
###################################################################################
showMenu () {
MENU_CHECK=($(${SQLITE3} -list -separator '  ' "SELECT lemp, magento, database, install, config, webmin FROM menu;"))
printf "\033c"
    _space 2
        echo -e "${DGREYBG}${BOLD}  MAGENTO SERVER CONFIGURATION v.${MAGENX_VERSION}  ${RESET}"
        BLUETXT ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
        _space 1
        WHITETXT "[${MENU_CHECK[0]}] Install repository and LEMP packages :  ${YELLOW}\tlemp"
        WHITETXT "[${MENU_CHECK[1]}] Download Magento latest version      :  ${YELLOW}\tmagento"
        WHITETXT "[${MENU_CHECK[2]}] Setup Magento database               :  ${YELLOW}\tdatabase"
        WHITETXT "[${MENU_CHECK[3]}] Install Magento no sample data       :  ${YELLOW}\tinstall"
        WHITETXT "[${MENU_CHECK[4]}] Post-Installation config             :  ${YELLOW}\tconfig"
        _space 1
        BLUETXT ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
        _space 1
        WHITETXT "[${MENU_CHECK[6]}] Install Webmin control panel         :  ${YELLOW}\twebmin"
        _space 1
        BLUETXT ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
        _space 1
        WHITETXT "[-] To quit and exit                     :  ${RED}\texit"
      _space 2
}
while [ 1 ]
do
  showMenu
  read CHOICE
  case "${CHOICE}" in
  "lemp")
_space 2
###################################################################################
###                                  SYSTEM UPGRADE                             ###
###################################################################################
## Get distro_name to make sure its set
DISTRO_NAME=$(${SQLITE3} "SELECT distro_name FROM system;")

## check if system update still required
SYSTEM_UPDATE=$(${SQLITE3} "SELECT system_update FROM system;")
if [ -z "${SYSTEM_UPDATE}" ]; then
  ## install all extra packages
  _space 1
BLUEBG "[~]    SYSTEM UPDATE AND PACKAGES INSTALLATION   [~]"
WHITETXT "-------------------------------------------------------------------------------------"
  _space 1
  debconf-set-selections <<< "postfix postfix/mailname string localhost"
  debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Local only'"
  apt update && apt upgrade -y
  DEBIAN_FRONTEND=noninteractive apt -y install ${EXTRA_PACKAGES} ${PERL_MODULES}
  _space 1
 if [ "$?" != 0 ]; then
  _space 1
  REDTXT "[!] Installation error."
  REDTXT "[!] Please correct errors and run it again."
  exit 1
  _space 1
 fi
  # Set system_update to full release version
  [ "${DISTRO_NAME}" == "Debian" ] && FULL_VERSION="$(cat /etc/debian_version )" || FULL_VERSION="$(lsb_release -d | awk '/(22|24)\.04.+/{print $3}')"
  ${SQLITE3} "UPDATE system SET system_update = 'installed @ ${FULL_VERSION}';"
  _space 1
fi
  _space 2
BLUEBG "[~]    LEMP WEB STACK INSTALLATION    [~]"
WHITETXT "-------------------------------------------------------------------------------------"
  _space 2
  _echo "${YELLOW}[?] Install MariaDB ${MARIADB_VERSION} database ? [y/n][n]:${RESET} "
  read mariadb_install
if [ "${mariadb_install}" == "y" ]; then
  _space 1
  read -e -p "$(echo -e ${YELLOW}"  [?] Enter required MARIADB version: "${RESET})" -i "${MARIADB_VERSION}" MARIADB_VERSION
  # Set mariadb-server-version
  ${SQLITE3} "UPDATE system SET mariadb_version = '${MARIADB_VERSION}';"
  curl -LsS "${MARIADB_REPO_CONFIG}" | bash -s -- --mariadb-server-version="mariadb-${MARIADB_VERSION}" --skip-maxscale --skip-verify --skip-eol-check
  _space 1
 if [ "$?" = 0 ] # if repository installed then install package
   then
    _space 1
    GREENTXT "MariaDB repository installed  -  OK"
    _space 1
    YELLOWTXT "MariaDB ${MARIADB_VERSION} database installation:"
    _space 1
    apt update
    systemctl stop mariadb
    apt install -y mariadb-server
  if [ "$?" = 0 ] # if package installed then configure
    then
     _space 1
     GREENTXT "MariaDB installed  -  OK"
     _space 1
     systemctl enable mariadb
     _space 1
     PACKAGES_INSTALLED mariadb*
     echo "127.0.0.1 mariadb" >> /etc/hosts
     echo "127.0.0.1 mariadb" >> /etc/cloud/templates/hosts.debian.tmpl
     _space 1
     WHITETXT "Downloading my.cnf file from MagenX Github repository"
     curl -sSo /etc/my.cnf https://raw.githubusercontent.com/magenx/magento-mysql/master/my.cnf/my.cnf
     _space 1
     WHITETXT "[?] Calculating [innodb_buffer_pool_size]:"
     INNODB_BUFFER_POOL_SIZE=$(echo "0.5*$(awk '/MemTotal/ { print $2 / (1024*1024)}' /proc/meminfo | cut -d'.' -f1)" | bc | xargs printf "%1.0f")
     if [ "${INNODB_BUFFER_POOL_SIZE}" == "0" ]; then IBPS=1; fi
     sed -i "s/innodb_buffer_pool_size = 4G/innodb_buffer_pool_size = ${INNODB_BUFFER_POOL_SIZE}G/" /etc/my.cnf
     _space 1
     WHITETXT "innodb_buffer_pool_size = ${INNODB_BUFFER_POOL_SIZE}G"
     WHITETXT "innodb_buffer_pool_instances = ${INNODB_BUFFER_POOL_SIZE}"
     _space 1
    else
     _space 1
     REDTXT "MariaDB installation error"
    exit # if package is not installed then exit
  fi
    else
     _space 1
     REDTXT "MariaDB repository installation error"
    exit # if repository is not installed then exit
   fi
    else
     _space 1
     YELLOWTXT "MariaDB installation was skipped by user input. Proceeding to next step."
fi
  _space 1
WHITETXT "============================================================================="
  _space 1
  _echo "${YELLOW}[?] Install Nginx ${NGINX_VERSION} ? [y/n][n]:${RESET} "
  read nginx_install
if [ "${nginx_install}" == "y" ]; then
  _space 1
  read -e -p "$(echo -e ${YELLOW}"  [?] Enter required NGINX version: "${RESET})" -i "${NGINX_VERSION}" NGINX_VERSION
  # Set nginx version
  ${SQLITE3} "UPDATE system SET nginx_version = '${NGINX_VERSION}';"
  echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/mainline/${DISTRO_NAME,,} `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list
  curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
  echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | tee /etc/apt/preferences.d/99nginx
   if [ "$?" = 0 ]; then # if repository installed then install package
    _space 1
    GREENTXT "Nginx repository installed  -  OK"
    _space 1
    YELLOWTXT "Nginx ${NGINX_VERSION} installation:"
    _space 1
    apt update
    apt -y install nginx
    if [ "$?" = 0 ]; then
     _space 1
     GREENTXT "Nginx ${NGINX_VERSION} installed  -  OK"
     echo "127.0.0.1 nginx" >> /etc/hosts
     echo "127.0.0.1 nginx" >> /etc/cloud/templates/hosts.debian.tmpl 
     _space 1
     systemctl enable nginx >/dev/null 2>&1
     PACKAGES_INSTALLED nginx*
    else
     _space 1
     REDTXT "Nginx ${NGINX_VERSION} installation error"
    exit # if package is not installed then exit
  fi
    else
     _space 1
     REDTXT "Nginx repository installation error"
    exit
    fi
   else
    _space 1
    YELLOWTXT "Nginx installation was skipped by user input. Proceeding to next step."
fi
echo
WHITETXT "============================================================================="
_space 1
_echo "${YELLOW}[?] Install PHP ? [y/n][n]:${RESET} "
read php_install
if [ "${php_install}" == "y" ]; then
  _space 1
  read -e -p "$(echo -e ${YELLOW}"  [?] Enter required PHP version: "${RESET})" -i "${PHP_VERSION}" PHP_VERSION
  # Set php_version
  ${SQLITE3} "UPDATE system SET php_version = '${PHP_VERSION}';"
  _space 1
 if [ "${DISTRO_NAME}" == "Debian" ]; then
  curl -o /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
  echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
 else
  add-apt-repository ppa:ondrej/php -y
 fi
 if [ "$?" = 0 ]; then
   _space 1
   GREENTXT "PHP repository installed  -  OK"
   _space 2
   YELLOWTXT "PHP ${PHP_VERSION} installation:"
   _space 1
   apt update
   apt -y install php${PHP_VERSION} ${PHP_PACKAGES[@]/#/php${PHP_VERSION}-} php-pear
  if [ "$?" = 0 ]; then
    _space 1
    GREENTXT "PHP ${PHP_VERSION} installed  -  OK"
    _space 1
    PACKAGES_INSTALLED php${PHP_VERSION}*
    _space 1
    # composer download
    _space 1
    YELLOWTXT "Composer ${COMPOSER_VERSION} installation:"
    _space 1
    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    php composer-setup.php --${COMPOSER_VERSION} --install-dir=/usr/bin --filename=composer
    php -r "unlink('composer-setup.php');"
   else
    _space 1
    REDTXT "PHP installation error"
   exit 1 # if package is not installed then exit
   fi
    else
     _space 1
     REDTXT "PHP repository installation error"
    exit 1 # if repository is not installed then exit
  fi
   else
    _space 1
    YELLOWTXT "PHP installation was skipped by user input. Proceeding to next step."
fi
_space 2
WHITETXT "============================================================================="
_space 1
_echo "${YELLOW}[?] Install Redis ${REDIS_VERSION} ? [y/n][n]:${RESET} "
read redis_install
if [ "${redis_install}" == "y" ]; then
  curl -fL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
  echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/redis.list
 if [ "$?" = 0 ]; then # 
     _space 1
     GREENTXT "Redis repository installed - OK"
     _space 1
     YELLOWTXT "Redis installation:"
     _space 1
     apt update
     apt -y install redis
     _space 1
     if [ "$?" = 0 ]; then
      _space 1
      GREENTXT "Redis installed  -  OK"
      _space 1
      PACKAGES_INSTALLED redis-server*
      _space 2
      YELLOWTXT "Redis configuration per environment:"
      _space 1

systemctl stop redis-server
systemctl disable redis-server

# Create Redis config
cat > /etc/systemd/system/redis@.service <<END
[Unit]
Description=Advanced key-value store at %i
After=network.target

[Service]
Type=notify
User=redis
Group=redis

# Security options
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
ReadOnlyPaths=/

# Resource limits
LimitNOFILE=65535

# Directories to create and permissions
RuntimeDirectory=redis
RuntimeDirectoryMode=2755
UMask=007

# Directories and files that Redis can read and write
ReadWritePaths=-/var/lib/redis
ReadWritePaths=-/var/log/redis
ReadWritePaths=-/run/redis

# Command-line options
PIDFile=/run/redis/%i.pid
ExecStartPre=/usr/bin/test -f /etc/redis/%i.conf
ExecStart=/usr/bin/redis-server /etc/redis/%i.conf --daemonize yes --supervised systemd

# Timeouts
Restart=on-failure
TimeoutStartSec=5s
TimeoutStopSec=5s

[Install]
WantedBy=multi-user.target

END

mkdir -p /var/lib/redis
chmod 750 /var/lib/redis
chown redis /var/lib/redis
mkdir -p /etc/redis/
rm /etc/redis/redis.conf

PORT=6379
# Loop through services to create redis config
REDIS_PASSWORD="$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9@%&?' | fold -w 32 | head -n 1)"
${SQLITE3} "UPDATE magento SET redis_password = '${REDIS_PASSWORD}';"
for SERVICE in session cache
do
if [ "${SERVICE}" = "session" ]; then
# Perfect options for sessions
CONFIG_OPTIONS="
save 900 1
save 300 10
save 60 10000

appendonly yes
appendfsync everysec
"
else
# Default options for cache
CONFIG_OPTIONS="save \"\""
fi

cat > /etc/redis/${SERVICE}.conf<<END

bind 127.0.0.1
port ${PORT}

daemonize yes
supervised auto
protected-mode yes
timeout 0

requirepass ${REDIS_PASSWORD}

dir /var/lib/redis
logfile /var/log/redis/${SERVICE}.log
pidfile /run/redis/${SERVICE}.pid

${CONFIG_OPTIONS}

maxmemory 1024mb
maxmemory-policy allkeys-lru

lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
lazyfree-lazy-user-del yes

rename-command SLAVEOF ""
rename-command CONFIG ""
rename-command PUBLISH ""
rename-command SAVE ""
rename-command SHUTDOWN ""
rename-command DEBUG ""
rename-command BGSAVE ""
rename-command BGREWRITEAOF ""
END

((PORT++))

chown redis /etc/redis/${SERVICE}.conf
chmod 640 /etc/redis/${SERVICE}.conf

echo "127.0.0.1 ${SERVICE}" >> /etc/hosts
echo "127.0.0.1 ${SERVICE}" >> /etc/cloud/templates/hosts.debian.tmpl 

systemctl daemon-reload
systemctl enable redis@${SERVICE}
systemctl restart redis@${SERVICE}
done
   else
    _space 1
    REDTXT "Redis installation error"
   exit 1 # if package is not installed then exit
   fi
 else
  _space 1
  REDTXT "Redis repository installation error"
 exit 1
 fi
  else
   _space 1
   YELLOWTXT "Redis installation was skipped by user input. Proceeding to next step."
fi
_space 1
WHITETXT "============================================================================="
_space 2
_echo "${YELLOW}[?] Install RabbitMQ ${RABBITMQ_VERSION} ? [y/n][n]:${RESET} "
read rabbitmq_install
if [ "${rabbitmq_install}" == "y" ];then
  curl -1sLf "https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA" | gpg --dearmor | tee /usr/share/keyrings/com.rabbitmq.team.gpg > /dev/null
    _space 1
  tee /etc/apt/sources.list.d/rabbitmq.list <<END
## Modern Erlang/OTP releases
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/${DISTRO_NAME,,}/$(lsb_release -cs) $(lsb_release -cs) main
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-erlang/${DISTRO_NAME,,}/$(lsb_release -cs) $(lsb_release -cs) main
## Provides modern RabbitMQ releases
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-server/${DISTRO_NAME,,}/$(lsb_release -cs) $(lsb_release -cs) main
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-server/${DISTRO_NAME,,}/$(lsb_release -cs) $(lsb_release -cs) main
END
  _space 1
  tee /etc/apt/preferences.d/rabbitmq <<END
Package: rabbitmq-server
Pin: version ${RABBITMQ_VERSION}
Pin-Priority: 999
END
  _space 1
  tee /etc/apt/preferences.d/erlang <<END
Package: erlang*
Pin: version ${ERLANG_VERSION}
Pin-Priority: 999
END

  if [ "$?" = 0 ]; then
    _space 1
    GREENTXT "RabbitMQ repository installed - OK"
    _space 1
    YELLOWTXT "RabbitMQ ${RABBITMQ_VERSION} installation:"
    _space 1
    apt update
    apt -y install rabbitmq-server --fix-missing
    if [ "$?" = 0 ]; then
     _space 1
     GREENTXT "RabbitMQ ${RABBITMQ_VERSION} installed  -  OK"
     _space 1
     PACKAGES_INSTALLED rabbitmq* erlang*
     echo "127.0.0.1 rabbitmq" >> /etc/hosts
     echo "127.0.0.1 rabbitmq" >> /etc/cloud/templates/hosts.debian.tmpl
     _space 2
     YELLOWTXT "RabbitMQ ${RABBITMQ_VERSION} configuration per environment:"
     _space 1
     systemctl stop rabbitmq-server
     systemctl stop epmd*
     epmd -kill

cat > /etc/rabbitmq/rabbitmq.conf <<END
# AMQP listener - localhost only
listeners.tcp.default = 127.0.0.1:5672
# Management UI - localhost only  
management.tcp.ip = 127.0.0.1
management.tcp.port = 15672
END

cat > /etc/rabbitmq/rabbitmq-env.conf <<END
NODENAME=rabbit@localhost
NODE_IP_ADDRESS=127.0.0.1
ERL_EPMD_ADDRESS=127.0.0.1
PID_FILE=/var/lib/rabbitmq/mnesia/rabbitmq_pid
END

cat > /etc/rabbitmq/advanced.config <<'END'
[{kernel, [
    % Bind Erlang distribution to localhost only
    {inet_dist_use_interface, {127,0,0,1}},
    % Fix Erlang distribution port range
    {inet_dist_listen_min, 25672},
    {inet_dist_listen_max, 25672}
  ]}
].
END

cat >> /etc/sysctl.conf <<END
net.ipv6.conf.lo.disable_ipv6 = 0
END

sysctl -q -p

cat > /etc/systemd/system/epmd.service <<END
[Unit]
Description=Erlang Port Mapper Daemon
After=network.target
Requires=epmd.socket

[Service]
ExecStart=/usr/bin/epmd -address 127.0.0.1 -daemon
Type=simple
StandardOutput=journal
StandardError=journal
User=epmd
Group=epmd

[Install]
Also=epmd.socket
WantedBy=multi-user.target
END

cat > /etc/systemd/system/epmd.socket <<END
[Unit]
Description=Erlang Port Mapper Daemon Activation Socket

[Socket]
ListenStream=4369
BindIPv6Only=both
Accept=no

[Install]
WantedBy=sockets.target
END

systemctl daemon-reload
systemctl start rabbitmq-server
rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbitmq_pid
sleep 5

# delete guest user
rabbitmqctl delete_user guest

# generate rabbitmq password
  RABBITMQ_PASSWORD="$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 15 | head -n 1)"
  ${SQLITE3} "UPDATE magento SET rabbitmq_password = '${RABBITMQ_PASSWORD}';"
  BRAND=$(${SQLITE3} "SELECT brand FROM magento;")
  rabbitmqctl add_user ${BRAND} ${RABBITMQ_PASSWORD}
  rabbitmqctl add_vhost /${BRAND}
  rabbitmqctl set_permissions -p /${BRAND} ${BRAND} ".*" ".*" ".*"
   else
    _space 1
    REDTXT "RabbitMQ ${RABBITMQ_VERSION} installation error"
   exit 1 # if package is not installed then exit
   fi
  else
   _space 1
   REDTXT "RabbitMQ repository installation error"
   exit 1
  fi
  else
   _space 1
   YELLOWTXT "RabbitMQ ${RABBITMQ_VERSION} installation was skipped by user input. Proceeding to next step."
fi
_space 1
WHITETXT "============================================================================="
_space 2
_echo "${YELLOW}[?] Install Varnish Cache ? [y/n][n]:${RESET} "
read varnish_install
if [ "${varnish_install}" == "y" ];then 
  curl -s https://packagecloud.io/install/repositories/varnishcache/varnish${VARNISH_VERSION}/script.deb.sh | bash
  if [ "$?" = 0 ]; then
    _space 1
    GREENTXT "Varnish Cache repository installed - OK"
    echo
    YELLOWTXT "Varnish Cache installation:"
    _space 1
    apt update
    apt -y install varnish
   if [ "$?" = 0 ]; then
     _space 1
     GREENTXT "Varnish Cache installed  -  OK"
     _space 1
     curl -sSo /etc/systemd/system/varnish.service ${MAGENX_INSTALL_GITHUB_REPO}/varnish.service
     curl -sSo /etc/varnish/varnish.params ${MAGENX_INSTALL_GITHUB_REPO}/varnish.params
     uuidgen > /etc/varnish/secret
     systemctl daemon-reload
     PACKAGES_INSTALLED varnish*
	 sed -i "s/VARNISH_LISTEN_ADDRESS=127.0.0.1/VARNISH_LISTEN_ADDRESS=PRIVATE_IP/" /etc/varnish/varnish.params
     echo "PRIVATE_IP varnish" >> /etc/hosts
     echo "PRIVATE_IP varnish" >> /etc/cloud/templates/hosts.debian.tmpl
    else
    _space 1
    REDTXT "Varnish Cache installation error"
   exit 1
   fi
  else
   _space 1
   REDTXT "Varnish Cache repository installation error"
   exit 1
  fi
  else
   _space 1
   YELLOWTXT "Varnish installation was skipped by user input. Proceeding to next step."
fi
echo
WHITETXT "============================================================================="
echo
_echo "${YELLOW}[?] Install OpenSearch ${OPENSEARCH_VERSION} ? [y/n][n]:${RESET} "
read opensearch_install
if [ "${opensearch_install}" == "y" ];then
   curl -o- https://artifacts.opensearch.org/publickeys/opensearch.pgp | gpg --dearmor --batch --yes -o /usr/share/keyrings/opensearch-keyring
   echo "deb [signed-by=/usr/share/keyrings/opensearch-keyring] https://artifacts.opensearch.org/releases/bundle/opensearch/${OPENSEARCH_VERSION}/apt stable main" > /etc/apt/sources.list.d/opensearch-${OPENSEARCH_VERSION}.list
  if [ "$?" = 0 ]; then
    _space 1
    GREENTXT "OpenSearch ${OPENSEARCH_VERSION} repository installed - OK"
    _space 1
    YELLOWTXT "OpenSearch ${OPENSEARCH_VERSION} installation:"
    _space 1
    YELLOWTXT "Re-generating random password for admin user"
    if [[ -z "$(${SQLITE3} "SELECT opensearch_admin_password FROM system;")" ]]; then
      OPENSEARCH_ADMIN_PASSWORD="$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9-#?$&' | fold -w 20 | head -n 1)"
      ${SQLITE3} "UPDATE system SET opensearch_admin_password = '${OPENSEARCH_ADMIN_PASSWORD}';"
    fi
    
    apt update
    OPENSEARCH_ADMIN_PASSWORD="$(${SQLITE3} "SELECT opensearch_admin_password FROM system;")"
    env OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_ADMIN_PASSWORD} apt -y install opensearch
    
    YELLOWTXT "OpenSearch pre-configuration:"
    _space 1
    ## opensearch settings
    BRAND=$(${SQLITE3} "SELECT brand FROM magento LIMIT 1;")
    if ! grep -q "${BRAND}" /etc/opensearch/opensearch.yml >/dev/null 2>&1 ; then
    cp /etc/opensearch/opensearch.yml /etc/opensearch/opensearch.yml_default
cat > /etc/opensearch/opensearch.yml <<END
#--------------------------------------------------------------------#
#----------------------- MAGENX CONFIGURATION -----------------------#
# -------------------------------------------------------------------#
# original config saved: /etc/opensearch/opensearch.yml_default

cluster.name: ${BRAND}
node.name: ${BRAND}-node1
node.attr.rack: r1
node.max_local_storage_nodes: 1

discovery.type: single-node
cluster.routing.allocation.enable: all

path.data: /var/lib/opensearch
path.logs: /var/log/opensearch

network.host: 127.0.0.1
http.port: 9200

# WARNING: revise all the lines below before you go into production
plugins.security.ssl.transport.pemcert_filepath: esnode.pem
plugins.security.ssl.transport.pemkey_filepath: esnode-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: root-ca.pem

plugins.security.ssl.transport.enforce_hostname_verification: false
plugins.security.ssl.http.enabled: false
plugins.security.allow_unsafe_democertificates: true
plugins.security.allow_default_init_securityindex: true

plugins.security.audit.type: internal_opensearch
plugins.security.enable_snapshot_restore_privilege: true
plugins.security.check_snapshot_restore_write_privileges: true
plugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]
plugins.security.system_indices.enabled: true
plugins.security.system_indices.indices: [".plugins-ml-config", ".plugins-ml-connector", ".plugins-ml-model-group", ".plugins-ml-model", ".plugins-ml-task", ".plugins-ml-conversation-meta", ".plugins-ml-conversation-interactions", ".opendistro-alerting-config", ".opendistro-alerting-alert*", ".opendistro-anomaly-results*", ".opendistro-anomaly-detector*", ".opendistro-anomaly-checkpoints", ".opendistro-anomaly-detection-state", ".opendistro-reports-*", ".opensearch-notifications-*", ".opensearch-notebooks", ".opensearch-observability", ".ql-datasources", ".opendistro-asynchronous-search-response*", ".replication-metadata-store", ".opensearch-knn-models", ".geospatial-ip2geo-data*"]

END

## OpenSearch jvm options
HEAP_SIZE=$(echo "0.30*$(awk '/MemTotal/ { print $2 / (1024*1024)}' /proc/meminfo | cut -d'.' -f1)" | bc | xargs printf "%1.0f")
if [ "${HEAP_SIZE}" == "0" ]; then HEAP_SIZE=1; fi

cat <<END > /etc/opensearch/jvm.options.d/${parameter["BRAND"]}.options
-Xms${HEAP_SIZE}g
-Xmx${HEAP_SIZE}g
END

fi
    
   if [ "$?" = 0 ]; then
    _space 1
    GREENTXT "OpenSearch ${OPENSEARCH_VERSION} installed  -  OK"
    _space 1

chown -R :opensearch /etc/opensearch/*
systemctl daemon-reload
systemctl enable opensearch.service
systemctl restart opensearch.service

    if [ "$?" != 0 ]; then
      _space 1
      REDTXT "[!] OpenSearch startup error"
      REDTXT "[!] Please correct error above and try again"
      _space 1
      exit 1
    fi

  ## generate opensearch password
  INDEXER_PASSWORD="$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)"
  ${SQLITE3} "UPDATE magento SET indexer_password = '${INDEXER_PASSWORD}';"
  BRAND=$(${SQLITE3} "SELECT brand FROM magento;")
  _space 1
  YELLOWTXT "Waiting for OpenSearch initialization ..."
  timeout 10 sh -c 'until nc -z $0 $1; do sleep 1; done' 127.0.0.1 9200
  curl -XGET -u admin:${OPENSEARCH_ADMIN_PASSWORD} "http://127.0.0.1:9200/_cluster/health?wait_for_status=green&timeout=60s"
  sleep 5
  
  ## Create role
  curl -u admin:${OPENSEARCH_ADMIN_PASSWORD} -XPUT "http://127.0.0.1:9200/_plugins/_security/api/roles/${BRAND}" \
  -H "Content-Type: application/json" \
  -d "$(cat <<EOF
{
    "cluster_permissions": [
      "cluster_composite_ops_monitor",
      "cluster:monitor/main",
      "cluster:monitor/state",
      "cluster:monitor/health"
    ],
    "index_permissions": [
      {
        "index_patterns": ["${BRAND}*"],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": ["*"]
      },
      {
        "index_patterns": ["*"],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices:admin/aliases/get",
		      "indices:data/read/search",
		      "indices:admin/get"
        ]
      }
    ],
    "tenant_permissions": []
}
EOF
)"

_space 1

  ## Create user
  curl -u admin:${OPENSEARCH_ADMIN_PASSWORD} -XPUT "http://127.0.0.1:9200/_plugins/_security/api/internalusers/${BRAND}" \
  -H "Content-Type: application/json" \
  -d "$(cat <<EOF
{
    "password": "${INDEXER_PASSWORD}",
    "opendistro_security_roles": ["${BRAND}", "own_index"]
}
EOF
)"
_space 1
YELLOWTXT "Created OpenSearch user: ${BRAND} and role: ${BRAND}"
_space 1
YELLOWTXT "Installing OpenSearch plugins:"
/usr/share/opensearch/bin/opensearch-plugin install --batch \
  analysis-icu \
  analysis-phonetic
  _space 2
  PACKAGES_INSTALLED opensearch
  echo "127.0.0.1 opensearch" >> /etc/hosts
  echo "127.0.0.1 opensearch" >> /etc/cloud/templates/hosts.debian.tmpl
  else
  _space 1
    REDTXT "OpenSearch ${OPENSEARCH_VERSION} installation error"
   exit 1
   fi
 else
_space 1
REDTXT "OpenSearch ${OPENSEARCH_VERSION} repository installation error"
exit 1
fi
else
_space 1
YELLOWTXT "OpenSearch ${OPENSEARCH_VERSION} installation was skipped by user input. Proceeding to next step."
fi
_space 2
${SQLITE3} "UPDATE menu SET lemp = 'x';"
## keep versions for critical services to avoid issues
apt-mark hold opensearch erlang rabbitmq-server
echo "127.0.0.1 phpmyadmin" >> /etc/hosts
echo "127.0.0.1 imgproxy" >> /etc/hosts
_space 2
GREENTXT "~    REPOSITORIES AND PACKAGES INSTALLATION IS COMPLETED    ~"
WHITETXT "-------------------------------------------------------------------------------------"
_space 2
_pause '[] Press [Enter] key to show the menu'
printf "\033c"
;;
###################################################################################
###                                  MAGENTO DOWNLOAD                           ###
###################################################################################
"magento")
printf "\033c"
_space 1
BLUEBG "[~]  MAGENTO 2 CONFIGURATION  [~]"
WHITETXT "-------------------------------------------------------------------------------------"
_space 1
 ## configure
 DOMAIN="$(${SQLITE3} "SELECT domain FROM magento;")"
 BRAND="$(${SQLITE3} "SELECT brand FROM magento;")"
 PHP_USER="$(${SQLITE3} "SELECT php_user FROM magento;")"
 ROOT_PATH="$(${SQLITE3} "SELECT root_path FROM magento;")"
 
 ## create magento/ssh user
 useradd -d ${ROOT_PATH} -s /bin/bash ${BRAND}
 INSTALLATION_RELEASE="$(date +'%Y%m%d%H%M')"
 mkdir -p ${ROOT_PATH}/{releases/${INSTALLATION_RELEASE},shared}
 echo "007" > ${ROOT_PATH}/shared/magento_umask
 
 ## create magento php user
 useradd -M -s /sbin/nologin -d ${ROOT_PATH} ${PHP_USER}
 usermod -g ${PHP_USER} ${BRAND}

 ## magento root folder permissions
 chmod 711 ${ROOT_PATH}
 chown -R ${BRAND}:${PHP_USER} ${ROOT_PATH}/{shared,releases}
 chmod 2770 ${ROOT_PATH}/{shared,releases}
 su ${BRAND} -s /bin/bash -c "mkdir -p ${ROOT_PATH}/shared/{var/tmp,pub}"

 ## ACL php read only for releases
 setfacl -R -m m:r-X,u:${BRAND}:rwX,g:${PHP_USER}:r-X,o::-,d:u:${BRAND}:rwX,d:g:${PHP_USER}:r-X,d:o::- ${ROOT_PATH}/releases
 
 ## ACL write permissions for shared
 setfacl -R -m u:${BRAND}:rwX,g:${PHP_USER}:rwX,o::-,d:u:${BRAND}:rwX,d:g:${PHP_USER}:rwX,d:o::- ${ROOT_PATH}/shared
 
 ## ACL nginx reads everything
 setfacl -R -m u:nginx:r-X,d:u:nginx:r-X ${ROOT_PATH}/{shared,releases}
 
 _space 1
 _echo "[?] Download Magento 2 ? [y/n][n]: "
 read download_magento
 if [ "${download_magento}" == "y" ];then
   _space 2
   cd ${ROOT_PATH}/releases/${INSTALLATION_RELEASE}
   YELLOWTXT "[?] Select Magento full version: "
   updown_menu "${VERSION_LIST}" VERSION_INSTALLED
   _space 2
   echo "   [!] Magento [ ${VERSION_INSTALLED} ]"
   echo "   [!] Downloading to [ ${ROOT_PATH}/releases/${INSTALLATION_RELEASE} ]"
   _space 2
   _pause '[] Press [Enter] key to start downloading'
   _space 1
   mkdir -p ${ROOT_PATH}/.config
   chmod 2700 ${ROOT_PATH}/.config
   chown -R ${BRAND}:${BRAND} ${ROOT_PATH}/.config
   su ${BRAND} -s /bin/bash -c "composer -n -q config -g http-basic.repo.magento.com ${COMPOSER_NAME} ${COMPOSER_PASSWORD}"
   su ${BRAND} -s /bin/bash -c "${PROJECT}=${VERSION_INSTALLED} . --no-install"

   ## composer replace bloatware
   curl -sO ${MAGENX_INSTALL_GITHUB_REPO}/composer_replace
   sed -i '/"conflict":/ {
   r composer_replace
   N
   }' composer.json

   rm composer_replace

   ### install magento from here ###
   su ${BRAND} -s /bin/bash -c "composer install"
   
    if [ "$?" != 0 ]; then
      _space 1
      REDTXT "[!] Magento composer installation error"
      REDTXT "[!] Please correct error above and try again"
      _space 1
      exit 1
    fi
   
   ## make magento great again
   su ${BRAND} -s /bin/bash -c "cp -rf ${ROOT_PATH}/releases/${INSTALLATION_RELEASE}/var/* ${ROOT_PATH}/shared/var/"
   su ${BRAND} -s /bin/bash -c "rm -rf ${ROOT_PATH}/releases/${INSTALLATION_RELEASE}/var"
   su ${BRAND} -s /bin/bash -c "mv -f ${ROOT_PATH}/releases/${INSTALLATION_RELEASE}/pub/media ${ROOT_PATH}/shared/pub/"
   
   ## create symlink to shared and release
   su ${BRAND} -s /bin/bash -c "ln -sfn ${ROOT_PATH}/shared/var ${ROOT_PATH}/releases/${INSTALLATION_RELEASE}/var"
   su ${BRAND} -s /bin/bash -c "ln -sfn ${ROOT_PATH}/shared/pub/media ${ROOT_PATH}/releases/${INSTALLATION_RELEASE}/pub/media"
   su ${BRAND} -s /bin/bash -c "ln -sfn ${ROOT_PATH}/shared/magento_umask ${ROOT_PATH}/releases/${INSTALLATION_RELEASE}/magento_umask"
   ln -sfn ${ROOT_PATH}/releases/${INSTALLATION_RELEASE} ${ROOT_PATH}/current
 fi

   ## save all the variables
   ${SQLITE3} "UPDATE menu SET magento = 'x';"
   ${SQLITE3} "UPDATE magento SET version_installed = '${VERSION_INSTALLED}';" 

_space 3
GREENTXT "[~]    MAGENTO ${VERSION_INSTALLED} DOWNLOADED AND READY FOR SETUP    [~]"
WHITETXT "--------------------------------------------------------------------"
_space 2
_pause '[] Press [Enter] key to show menu'
printf "\033c"
;;
###################################################################################
###                                  DATABASE SETUP                             ###
###################################################################################
"database")
printf "\033c"
_space 1
BLUEBG "[~]    CREATE MYSQL USER AND DATABASE    [~]"
WHITETXT "-------------------------------------------------------------------------------------"
if [ ! -f /root/.my.cnf ]; then
MYSQL_ROOT_PASSWORD="$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9@%^&?=+_[]{}()<>-' | fold -w 15 | head -n 1)${RANDOM}"
systemctl restart mariadb
mariadb-admin status --wait=2 &>/dev/null || { REDTXT "\n [!] MYSQL SERVER DOWN \n"; exit 1; }
mariadb --connect-expired-password  <<EOMYSQL
ALTER USER 'root'@'localhost' IDENTIFIED BY "${MYSQL_ROOT_PASSWORD}";
DELETE FROM mysql.user WHERE User='';
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
exit
EOMYSQL

cat > /root/.my.cnf <<END
[client]
user=root
password="${MYSQL_ROOT_PASSWORD}"
END
cat > /root/.mytop <<END
user=root
pass=${MYSQL_ROOT_PASSWORD}
db=mysql
END
cat > /root/.my.cnf <<END
[client]
user=root
password="${MYSQL_ROOT_PASSWORD}"
END

## set mysql root password
${SQLITE3} "UPDATE system SET mysql_root_password = '${MYSQL_ROOT_PASSWORD}';"
fi

chmod 600 /root/.my.cnf /root/.mytop

## configure database
 _space 1
 BRAND=$(${SQLITE3} "SELECT brand FROM magento;")
 YELLOWTXT "[-] Settings for database:"
 read -e -p "$(echo -e ${YELLOW}"  [?] Host name: "${RESET})" -i "mariadb"  DATABASE_HOST
 read -e -p "$(echo -e ${YELLOW}"  [?] Database name: "${RESET})" -i "${BRAND}"  DATABASE_NAME
 read -e -p "$(echo -e ${YELLOW}"  [?] User name: "${RESET})" -i "${BRAND}"  DATABASE_USER
 read -e -p "$(echo -e ${YELLOW}"  [?] Password: "${RESET})" -i "$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9%^&+_{}()<>-' | fold -w 15 | head -n 1)${RANDOM}"  DATABASE_PASSWORD
 _space 1
for USER_HOST in ${DATABASE_HOST} localhost 127.0.0.1
  do
mariadb <<EOMYSQL
 CREATE USER '${DATABASE_USER}'@'${USER_HOST}' IDENTIFIED BY '${DATABASE_PASSWORD}';
 CREATE DATABASE IF NOT EXISTS ${DATABASE_NAME};
 GRANT ALL PRIVILEGES ON ${DATABASE_NAME}.* TO '${DATABASE_USER}'@'${USER_HOST}' WITH GRANT OPTION;
 exit
EOMYSQL
done

 ## save database variables
 ${SQLITE3} "UPDATE menu SET database = 'x';"
 ${SQLITE3} "UPDATE magento SET
  database_host = '${DATABASE_HOST}',
  database_name = '${DATABASE_NAME}',
  database_user = '${DATABASE_USER}',
  database_password = '${DATABASE_PASSWORD}';"

_space 3
_pause '[] Press [Enter] key to show menu'
printf "\033c"
;;
###################################################################################
###                                  MAGENTO SETUP                              ###
###################################################################################
"install")
printf "\033c"
_space 1
BLUEBG   "[~]    MAGENTO CONFIGURATION TO SETUP   [~]"
WHITETXT "-------------------------------------------------------------------------------------"
_space 2
REDIS_PORTS="$(awk '/port /{print $2}' /etc/redis/[case]*.conf)"
for PORT_SELECTED in ${REDIS_PORTS} 9200 5672 3306; do nc -4zvw3 localhost ${PORT_SELECTED}; if [ "$?" != 0 ]; then REDTXT "  [!] SERVICE ${PORT_SELECTED} OFFLINE"; exit 1; fi;  done

  ## Create an associative array
  declare -A GET_
  ## Get the data for the Magento mode from the magento table | sqlite .mode line key=value
  QUERY=$(${SQLITE3} -line "SELECT * FROM magento;")
  ## Loop through the lines of the query output and add the key=value pairs to the associative array
  while IFS='=' read -r KEY VALUE; do
    ## Extract the key and value from the line separated by ' = '
    KEY=$(echo "${KEY}" | tr -d '[:space:]')
    VALUE=$(echo "${VALUE}" | tr -d '[:space:]')
    ## Skip adding key=value pair if value is empty
    if [[ -n "${VALUE}" ]]; then
      ## Add the key=value pair to the associative array
      GET_["${KEY}"]="${VALUE}"
    fi
  done <<< "${QUERY}"
## Use associative array here
if [ -f "${GET_[root_path]}/current/bin/magento" ]; then
 _space 1
 YELLOWTXT "[-] Configuration for Magento ${GET_[version_installed]}"
 _space 1
 TIMEZONE=$(${SQLITE3} "SELECT timezone FROM system;")
 cd ${GET_[root_path]}/current/
 chown -R ${GET_[brand]}:${GET_[php_user]} *
 chmod u+x bin/magento
 YELLOWTXT "[-] Administrator settings and store base url:"
 read -e -p "$(echo -e ${YELLOW}"  [?] First name: "${RESET})" -i "Magento"  ADMIN_FIRSTNAME
 read -e -p "$(echo -e ${YELLOW}"  [?] Last name: "${RESET})" -i "Administrator"  ADMIN_LASTNAME
 read -e -p "$(echo -e ${YELLOW}"  [?] Email: "${RESET})" -i "admin@${GET_[domain]}"  ADMIN_EMAIL
 read -e -p "$(echo -e ${YELLOW}"  [?] Login name: "${RESET})" -i "admin"  ADMIN_LOGIN
 read -e -p "$(echo -e ${YELLOW}"  [?] Password: "${RESET})" -i "$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9%&?=' | fold -w 10 | head -n 1)${RANDOM}"  ADMIN_PASSWORD
 _space 1
 YELLOWTXT "[-] Language and currency settings:"
 updown_menu "$(bin/magento info:language:list | sed "s/[|+-]//g" | awk 'NR > 3 {print $NF}' | sort )" LOCALE
 _space 1
 updown_menu "$(bin/magento info:currency:list | sed "s/[|+-]//g" | awk 'NR > 3 {print $NF}' | sort )" CURRENCY
 _space 2
 YELLOWTXT "[-] Magento ${GET_[version_installed]} ready to be installed"
 _space 1
 _pause '[!] Press [Enter] key to run setup:install'
 _space 1
 su ${GET_[brand]} -s /bin/bash -c "bin/magento setup:install --base-url=https://${GET_[domain]}/ \
 --db-host=${GET_[database_host]} \
 --db-name=${GET_[database_name]} \
 --db-user=${GET_[database_user]} \
 --db-password='${GET_[database_password]}' \
 --admin-firstname=${ADMIN_FIRSTNAME} \
 --admin-lastname=${ADMIN_LASTNAME} \
 --admin-email=${ADMIN_EMAIL} \
 --admin-user=${ADMIN_LOGIN} \
 --admin-password='${ADMIN_PASSWORD}' \
 --language=${LOCALE} \
 --currency=${CURRENCY} \
 --timezone=${TIMEZONE} \
 --cleanup-database \
 --use-rewrites=1 \
 --session-save=redis \
 --session-save-redis-host=session \
 --session-save-redis-port=6379 \
 --session-save-redis-log-level=3 \
 --session-save-redis-db=0 \
 --session-save-redis-password='${GET_[redis_password]}' \
 --session-save-redis-compression-lib=lz4 \
 --cache-backend=redis \
 --cache-backend-redis-server=cache \
 --cache-backend-redis-port=6380 \
 --cache-backend-redis-db=0 \
 --cache-backend-redis-password='${GET_[redis_password]}' \
 --cache-backend-redis-compress-data=1 \
 --cache-backend-redis-compression-lib=l4z \
 --amqp-host=rabbitmq \
 --amqp-port=5672 \
 --amqp-user=${GET_[brand]} \
 --amqp-password='${GET_[rabbitmq_password]}' \
 --amqp-virtualhost='/${GET_[brand]}' \
 --consumers-wait-for-messages=0 \
 --search-engine=opensearch \
 --opensearch-host=opensearch \
 --opensearch-port=9200 \
 --opensearch-index-prefix=${GET_[brand]} \
 --opensearch-enable-auth=1 \
 --opensearch-username=${GET_[brand]} \
 --opensearch-password='${GET_[indexer_password]}'"

 if [ "$?" != 0 ]; then
   _space 1
   REDTXT "[!] Magento setup:install error"
   REDTXT "[!] Please correct error above and try again"
   _space 1
   exit 1
 fi

_space 1
YELLOWTXT "[-] Reset permissions:"
find ${GET_[root_path]}/{releases,shared} -type d ! -perm 2770 -exec chmod 2770 {} \;
find ${GET_[root_path]}/{releases,shared} -type f ! -perm 660 -exec chmod 660 {} \;
chmod +x bin/magento
 
 ## Save config variables
 ${SQLITE3} "UPDATE magento SET
  admin_login = '${ADMIN_LOGIN}',
  admin_password = '${ADMIN_PASSWORD}',
  admin_email = '${ADMIN_EMAIL}',
  locale = '${LOCALE}',
  admin_path = '$(bin/magento info:adminuri | xargs | cut -d"/" -f2)',
  crypt_key = '$(grep -Po "(?<='key' => ')\w*(?=')" ${GET_[root_path]}/current/app/etc/env.php)';"
  
  ${SQLITE3} "UPDATE menu SET install = 'x';"
fi

_space 3
    WHITETXT "============================================================================="
    _space 1
    GREENTXT "Magento ${GET_[version_installed]} installed"
    _space 1
    WHITETXT "============================================================================="
_space 1

_pause '[] Press [Enter] key to show menu'
printf "\033c"
;;
###################################################################################
###                                FINAL CONFIGURATION                          ###
###################################################################################
"config")
printf "\033c"
_space 1
BLUEBG "[~]    POST-INSTALLATION CONFIGURATION    [~]"
WHITETXT "-------------------------------------------------------------------------------------"
_space 1
## network is up?
host1=google.com
host2=github.com

RESULT=$(((ping -w3 -c2 ${host1} || ping -w3 -c2 ${host2}) > /dev/null 2>&1) && echo "up" || (echo "down" && exit 1))
if [[ ${RESULT} == up ]]; then
  GREENTXT "PASS: NETWORK IS UP. GREAT, LETS START!"
  else
  _space 1
  REDTXT "[!] NETWORK IS DOWN"
  YELLOWTXT "[!] PLEASE CHECK YOUR NETWORK SETTINGS"
  _space 2
  exit 1
fi

##
## Configuration
## Create an associative array
  declare -A GET_
  ## Get the data for the Magento mode from the magento table | sqlite .mode line key=value
  QUERY=$(${SQLITE3} -line "SELECT * FROM magento;")
  ## Loop through the lines of the query output and add the key=value pairs to the associative array
  while IFS='=' read -r KEY VALUE; do
    ## Extract the key and value from the line separated by ' = '
    KEY=$(echo "${KEY}" | tr -d '[:space:]')
    VALUE=$(echo "${VALUE}" | tr -d '[:space:]')
    ## Skip adding key=value pair if value is empty
    if [[ -n "${VALUE}" ]]; then
      ## Add the key=value pair to the associative array
      GET_["${KEY}"]="${VALUE}"
    fi
  done <<< "${QUERY}"

SSH_PORT="$(${SQLITE3} "SELECT ssh_port FROM system;")"
PHP_VERSION="$(${SQLITE3} "SELECT php_version FROM system;")"
TIMEZONE="$(${SQLITE3} "SELECT timezone FROM system;")"

_space 1
YELLOWTXT "[-] Server hostname settings"
hostnamectl set-hostname "${GET_[domain]}" --static
hostname

_space 1
YELLOWTXT "[-] Create motd banner"
curl -o /etc/motd "${MAGENX_INSTALL_GITHUB_REPO}/motd"
sed -i "s/MAGENX_VERSION/${MAGENX_VERSION}/" /etc/motd

_space 1
YELLOWTXT "[-] Sysctl parameters"
tee /etc/sysctl.conf <<END
fs.file-max = 1000000
fs.inotify.max_user_watches = 1000000
vm.swappiness = 10
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
kernel.msgmnb = 65535
kernel.msgmax = 65535
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 8388608 8388608 8388608
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 65535 8388608
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_challenge_ack_limit = 1073741823
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 15
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_max_tw_buckets = 400000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_sack = 1
net.ipv4.route.flush = 1
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 8388608
net.core.wmem_default = 8388608
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 65535
END

sysctl -q -p

_space 1
YELLOWTXT "[-] Downloading mysqltuner and mytop"
curl -o /usr/local/bin/mysqltuner ${MYSQL_TUNER}
ln -s /usr/bin/mytop /usr/local/bin/mytop

for dir in cli fpm
do
_space 1
YELLOWTXT "[-] PHP global system settings overrides ${dir} ini"
tee /etc/php/${PHP_VERSION}/$dir/conf.d/zz-magenx-overrides.ini <<END
opcache.enable_cli = 1
opcache.memory_consumption = 512
opcache.interned_strings_buffer = 4
opcache.max_accelerated_files = 60000
opcache.max_wasted_percentage = 5
opcache.use_cwd = 1
opcache.validate_timestamps = 0
;opcache.revalidate_freq = 2
;opcache.validate_permission= 1
opcache.validate_root= 1
opcache.file_update_protection = 2
opcache.revalidate_path = 0
opcache.save_comments = 1
opcache.load_comments = 1
opcache.fast_shutdown = 1
opcache.enable_file_override = 0
opcache.optimization_level = 0xffffffff
opcache.inherited_hack = 1
opcache.blacklist_filename=/etc/opcache-default.blacklist
opcache.max_file_size = 0
opcache.consistency_checks = 0
opcache.force_restart_timeout = 60
opcache.error_log = "/var/log/php-fpm/opcache.log"
opcache.log_verbosity_level = 1
opcache.preferred_memory_model = ""
opcache.protect_memory = 0
;opcache.mmap_base = ""

max_execution_time = 7200
max_input_time = 7200
memory_limit = 2048M
post_max_size = 64M
upload_max_filesize = 64M
expose_php = Off
realpath_cache_size = 4096k
realpath_cache_ttl = 86400
short_open_tag = On
max_input_vars = 50000
session.gc_maxlifetime = 28800
mysql.allow_persistent = On
mysqli.allow_persistent = On
date.timezone = "${TIMEZONE}"
END
done

_space 1
YELLOWTXT "[-] Downloading: /usr/local/bin/n98-magerun2"
curl -o /usr/local/bin/n98-magerun2 https://files.magerun.net/n98-magerun2.phar

_space 1
YELLOWTXT "[-] Creating cache cleaner script: /usr/local/bin/cacheflush"
tee /usr/local/bin/cacheflush <<END
#!/bin/bash
sudo -u \${SUDO_USER} n98-magerun2 --root-dir=/home/\${SUDO_USER}/current cache:flush
/usr/bin/systemctl restart php${PHP_VERSION}-fpm.service
nginx -t && /usr/bin/systemctl restart nginx.service || echo "[!] Error: check nginx config"
END

_space 1
YELLOWTXT "[-] Certbot installation with snapd"
snap install --classic certbot

_space 1
YELLOWTXT "[-] Generating default selfsigned ssl cert for nginx"
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout /etc/ssl/private/default_server.key -out /etc/ssl/certs/default_server.crt \
-subj "/CN=default_server" -days 3650 -subj "/C=US/ST=Oregon/L=Portland/O=default_server/OU=Org/CN=default_server"

_space 1
YELLOWTXT "[-] Downloading nginx configuration files"
mkdir -p /tmp/nginx
cd /tmp/nginx
git init
git config core.sparseCheckout true
echo "magento2/*" >> .git/info/sparse-checkout
git remote add origin https://github.com/magenx/Magento-nginx-config
git pull origin master

mv magento2/sites-available/magento2.conf  magento2/sites-available/${GET_[domain]}.conf


_space 1
YELLOWTXT "[-] Nginx configuration"

export DOMAIN="${GET_[domain]}"
export ROOT_PATH="${GET_[root_path]}/current/"
export ADMIN_PATH="${GET_[admin_path]}"
export PHP_FPM="unix:/var/run/php/${GET_[brand]}.sock"
export PROFILER="$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 12 | head -n 1)"
export PHPMYADMIN_PATH="mysql_$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)"
export RABBITMQ_PATH="rabbitmq_$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)"


find /tmp/nginx/magento2 -type f -exec sh -c '
  dest_path="/etc/nginx/$(echo "{}" | sed "s|/tmp/nginx/magento2||")";
  mkdir -p "$(dirname "$dest_path")";
  envsubst '\''${DOMAIN} ${ROOT_PATH} ${ADMIN_PATH} ${PHP_FPM} ${PROFILER} ${PHPMYADMIN_PATH} ${RABBITMQ_PATH} ${RESOLVER}'\'' < "{}" > "$dest_path";
' \;
  
ln -s /etc/nginx/sites-available/${GET_[domain]}.conf /etc/nginx/sites-enabled/${GET_[domain]}.conf
ln -s /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/default.conf

rm -rf /tmp/nginx/magento2

_space 1
YELLOWTXT "[-] Varnish Cache configuration file"
systemctl enable varnish.service
curl -o /etc/varnish/devicedetect.vcl https://raw.githubusercontent.com/varnishcache/varnish-devicedetect/master/devicedetect.vcl
curl -o /etc/varnish/devicedetect-include.vcl ${MAGENX_INSTALL_GITHUB_REPO}/devicedetect-include.vcl
curl -o /etc/varnish/default.vcl ${MAGENX_INSTALL_GITHUB_REPO}/default.vcl
sed -i "s/PROFILER/${PROFILER}/g" /etc/varnish/default.vcl

_space 1
YELLOWTXT "[-] Realtime malware monitor with email alerts"
cd /usr/local/src
curl -Lo maldetect-current.tar.gz ${MALDET}
tar -zxf maldetect-current.tar.gz
cd maldetect-*/
./install.sh

sed -i 's/email_alert="0"/email_alert="1"/' /usr/local/maldetect/conf.maldet
sed -i 's/quarantine_hits="0"/quarantine_hits="1"/' /usr/local/maldetect/conf.maldet
sed -i '/default_monitor_mode="users"/d' /usr/local/maldetect/conf.maldet
sed -i 's,# default_monitor_mode="/usr/local/maldetect/monitor_paths",default_monitor_mode="/usr/local/maldetect/monitor_paths",' /usr/local/maldetect/conf.maldet
sed -i 's/inotify_base_watches="16384"/inotify_base_watches="35384"/' /usr/local/maldetect/conf.maldet

maldet --monitor /usr/local/maldetect/monitor_paths

_space 1
YELLOWTXT "[-] GoAccess real-time web log analyzer"
curl -o- https://deb.goaccess.io/gnugpg.key | gpg --dearmor | tee /usr/share/keyrings/goaccess.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg arch=$(dpkg --print-architecture)] https://deb.goaccess.io/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/goaccess.list
apt update
apt -y install goaccess

  _space 1
## Use associative array here
_echo "${YELLOW}[?]${REDBG}${BOLD}[ Configuration ]${RESET} ${YELLOW}${RESET}"
_space 2

YELLOWTXT "[-] Php-fpm pool configuration"
tee /etc/php/${PHP_VERSION}/fpm/pool.d/${GET_[brand]}.conf <<END
[${GET_[brand]}]

;;
;; Pool user
user = php-\$pool
group = php-\$pool

listen = /var/run/php/\$pool.sock
listen.owner = nginx
listen.group = php-\$pool
listen.mode = 0660

;;
;; Pool size and settings
pm = ondemand
pm.max_children = 100
pm.max_requests = 1000

;;
;; [php ini] settings
php_admin_flag[expose_php] = Off
php_admin_flag[short_open_tag] = On
php_admin_flag[display_errors] = Off
php_admin_flag[log_errors] = On
php_admin_flag[mysql.allow_persistent] = On
php_admin_flag[mysqli.allow_persistent] = On
php_admin_value[default_charset] = "UTF-8"
php_admin_value[memory_limit] = 1024M
php_admin_value[max_execution_time] = 7200
php_admin_value[max_input_time] = 7200
php_admin_value[max_input_vars] = 50000
php_admin_value[post_max_size] = 64M
php_admin_value[upload_max_filesize] = 64M
php_admin_value[realpath_cache_size] = 4096k
php_admin_value[realpath_cache_ttl] = 86400
php_admin_value[session.gc_maxlifetime] = 28800
php_admin_value[error_log] = "/home/\$pool/current/var/log/php-fpm-error.log"
php_admin_value[date.timezone] = "${TIMEZONE}"
php_admin_value[upload_tmp_dir] = "/home/\$pool/current/var/tmp"
php_admin_value[sys_temp_dir] = "/home/\$pool/current/var/tmp"

;;
;; [opcache] settings
php_admin_flag[opcache.enable] = On
php_admin_flag[opcache.use_cwd] = On
php_admin_flag[opcache.validate_root] = On
php_admin_flag[opcache.revalidate_path] = Off
php_admin_flag[opcache.validate_timestamps] = Off
php_admin_flag[opcache.save_comments] = On
php_admin_flag[opcache.load_comments] = On
php_admin_flag[opcache.fast_shutdown] = On
php_admin_flag[opcache.enable_file_override] = Off
php_admin_flag[opcache.inherited_hack] = On
php_admin_flag[opcache.consistency_checks] = Off
php_admin_flag[opcache.protect_memory] = Off
php_admin_value[opcache.memory_consumption] = 512
php_admin_value[opcache.interned_strings_buffer] = 4
php_admin_value[opcache.max_accelerated_files] = 60000
php_admin_value[opcache.max_wasted_percentage] = 5
php_admin_value[opcache.file_update_protection] = 2
php_admin_value[opcache.optimization_level] = 0xffffffff
php_admin_value[opcache.blacklist_filename] = "/home/\$pool/opcache.blacklist"
php_admin_value[opcache.max_file_size] = 0
php_admin_value[opcache.force_restart_timeout] = 60
php_admin_value[opcache.error_log] = "/home/\$pool/current/var/log/opcache.log"
php_admin_value[opcache.log_verbosity_level] = 1
php_admin_value[opcache.preferred_memory_model] = ""
php_admin_value[opcache.jit_buffer_size] = 536870912
php_admin_value[opcache.jit] = 1235
END


tee /etc/php/${PHP_VERSION}/fpm/pool.d/www.conf <<END
[www]
user = www-data
group = www-data
listen = /var/run/php/php${PHP_VERSION}-fpm.sock
listen.owner = nginx
listen.group = www-data
pm = ondemand
pm.max_children = 5
END

systemctl daemon-reload

_space 1
YELLOWTXT "[-] Add user ${GET_[brand]} to sudo to execute cacheflush"
tee -a /etc/sudoers <<END
${GET_[brand]} ALL=(ALL) NOPASSWD: /usr/local/bin/cacheflush
END

_space 1
YELLOWTXT "[-] Logrotate script for Magento logs"
tee /etc/logrotate.d/${GET_[brand]} <<END
${GET_[root_path]}/current/var/log/*.log
{
su ${GET_[brand]} ${GET_[php_user]}
create 660 ${GET_[brand]} ${GET_[php_user]}
weekly
rotate 2
notifempty
missingok
compress
}
END

_space 1
YELLOWTXT "[-] Audit configuration for Magento folders and files"
sed -i "s/you@domain.com/${GET_[admin_email]}/" /usr/local/maldetect/conf.maldet
tee -a /usr/local/maldetect/monitor_paths <<END
${GET_[root_path]}/current/
END
tee -a /etc/audit/rules.d/audit.rules <<END
## audit magento files for ${GET_[brand]}
-a never,exit -F dir=${GET_[root_path]}/current/var/ -k exclude
-w ${GET_[root_path]}/current/ -p wa -k ${GET_[brand]}
END
service auditd reload
service auditd restart
auditctl -l

_space 1
YELLOWTXT "[-] Fail2ban installation and configuration"
cd /usr/local/src
git clone https://github.com/fail2ban/fail2ban.git
cd fail2ban

_space 1
python3 setup.py install

_space 1
tee /etc/fail2ban/filter.d/nginx-local-403.conf <<'END'
[Definition]
failregex = ^<HOST> -.*(GET|POST|HEAD).*"\s(444|403|401)\s
ignoreregex =
datepattern = \[%%d/%%b/%%Y:%%H:%%M:%%S
END

_space 1
tee /etc/fail2ban/filter.d/nginx-local-429.conf <<'END'
[Definition]
failregex = ^<HOST> -.*"(GET|POST|HEAD).*" 429
ignoreregex =
datepattern = \[%%d/%%b/%%Y:%%H:%%M:%%S
END

_space 1
tee /etc/fail2ban/action.d/nginx-local-deny.conf <<'END'
[Definition]
actionstart =
actionstop =
actioncheck =
actionban   = echo "<ip>  1; ## $(date '+%%Y-%%m-%%d %%H:%%M:%%S') <name>" >> <nginx_local_deny> && nginx -s reload
actionunban = sed -i "/.*<ip>  1;.*/d" <nginx_local_deny> && nginx -s reload
END

_space 1
tee /etc/fail2ban/jail.d/nginx-local.conf <<'END'
[nginx-local-403]
enabled  = true
port     = http,https
filter   = nginx-local-403
logpath  = /var/log/nginx/access.log
backend  = auto
maxretry = 5
findtime = 600
bantime  = -1
ignoreip =
action   = %(action_)s
           nginx-local-deny[nginx_local_deny=/etc/nginx/ipset/deny.conf]

[nginx-local-429]
enabled  = true
port     = http,https
filter   = nginx-local-429
logpath  = /var/log/nginx/access.log
backend  = auto
maxretry = 5
findtime = 60
bantime  = 600
ignoreip =
action   = %(action_)s
           nginx-local-deny[nginx_local_deny=/etc/nginx/ipset/deny.conf]
END

_space 1
tee /etc/systemd/system/fail2ban.service <<'END'
[Unit]
Description=Fail2Ban Service
Documentation=man:fail2ban(1)
After=network.target iptables.service firewalld.service ip6tables.service ipset.service nftables.service
PartOf=iptables.service firewalld.service ip6tables.service ipset.service nftables.service

[Service]
Type=simple
Environment="PYTHONNOUSERSITE=1"
ExecStartPre=/bin/mkdir -p /run/fail2ban
ExecStart=/usr/local/bin/fail2ban-server -xf start
# Use this line for systemd journal logging instead of file logs:
# ExecStart=/usr/local/bin/fail2ban-server -xf --logtarget=sysout start
ExecStop=/usr/local/bin/fail2ban-client stop
ExecReload=/usr/local/bin/fail2ban-client reload
PIDFile=/run/fail2ban/fail2ban.pid
Restart=on-failure
RestartPreventExitStatus=0 255

[Install]
WantedBy=multi-user.target
END

_space 1
if [ -f "${GET_[root_path]}/current/bin/magento" ]; then
 _echo "${YELLOW}[?] Apply config optimization and settings ? [y/n][n]:${RESET} "
read apply_config
if [ "${apply_config}" == "y" ]; then
 _space 1
 YELLOWTXT "[-] Enable Varnish Cache and add cache hosts to Magento env.php"
 cd ${GET_[root_path]}/current/
 chmod u+x bin/magento
 su ${GET_[brand]} -s /bin/bash -c "${GET_[root_path]}/current/bin/magento config:set --scope=default --scope-code=0 system/full_page_cache/caching_application 2"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento setup:config:set --http-cache-hosts=varnish:80"

 chown -R ${GET_[brand]}:${GET_[php_user]} ${GET_[root_path]}/current/
 
 _space 1
 YELLOWTXT "[-] Clean Magento cache add some optimization config"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set trans_email/ident_general/email ${GET_[admin_email]}"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set web/url/catalog_media_url_format image_optimization_parameters"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set dev/css/minify_files 1"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set dev/js/minify_files 1"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set dev/js/move_script_to_bottom 1"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set web/secure/enable_hsts 1"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set web/secure/enable_upgrade_insecure 1"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set dev/caching/cache_user_defined_attributes 1"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento setup:upgrade"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento deploy:mode:set -s production"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento setup:di:compile"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento setup:static-content:deploy -j auto"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento cache:flush"
 
 _space 1
 YELLOWTXT "[-] Configure Google 2FA code for ${GET_[admin_login]}"
 _space 1
 GOOGLE_TFA_CODE="$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9!@#$%^&' | fold -w 15 | head -n 1 | base32)"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set twofactorauth/general/force_providers google"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento config:set twofactorauth/google/otp_window 29"
 su ${GET_[brand]} -s /bin/bash -c "bin/magento security:tfa:google:set-secret ${GET_[admin_login]} ${GOOGLE_TFA_CODE}"
 echo "  Google Authenticator mobile app configuration:"
 echo "  - select: Enter a setup key"
 echo "  - type in: Account name"
 echo "  - Paste passkey: ${GOOGLE_TFA_CODE}"
 echo "  - Choose Time based"
 _space 1
 ${SQLITE3} "UPDATE magento SET tfa_key = '${GOOGLE_TFA_CODE}';"
 _space 1
 fi
 sed -i "s/VERSION_INSTALLED/${GET_[version_installed]}/" /etc/motd
fi

_space 1
YELLOWTXT "[-] Varnish Cache config optimization"
sed -i "s/DOMAIN_PLACEHOLDER/${GET_[domain]}/" /etc/varnish/default.vcl

_space 1
YELLOWTXT "[-] Add Magento cronjob to ${GET_[php_user]} user crontab"
BP_HASH="$(echo -n "${GET_[root_path]}/current/" | openssl dgst -sha256 | awk '{print $2}')"
crontab -l -u ${GET_[php_user]} > /tmp/${GET_[php_user]}_crontab
cat << END | tee -a /tmp/${GET_[php_user]}_crontab
#~ MAGENTO START ${BP_HASH}
* * * * * /usr/bin/php${PHP_VERSION} ${GET_[root_path]}/current/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> ${GET_[root_path]}/current/var/log/magento.cron.log
#~ MAGENTO END ${BP_HASH}
END
crontab -u ${GET_[php_user]} /tmp/${GET_[php_user]}_crontab
rm /tmp/${GET_[php_user]}_crontab

_space 1
YELLOWTXT "[-] Creating Magento environment variables to ${GET_[root_path]}/shared/.env"
tee ${GET_[root_path]}/shared/.env <<END
MODE="${GET_[mode]}"
DOMAIN="${GET_[domain]}"
ADMIN_PATH="${GET_[admin_path]}"
REDIS_PASSWORD="${GET_[redis_password]}"
RABBITMQ_PASSWORD="${GET_[rabbitmq_password]}"
CRYPT_KEY="${GET_[crypt_key]}"
GRAPHQL_ID_SALT=""
DATABASE_NAME="${GET_[database_name]}"
DATABASE_USER="${GET_[database_user]}"
DATABASE_PASSWORD="${GET_[database_password]}"
INDEXER_PASSWORD="${GET_[indexer_password]}"
INSTALLATION_DATE="$(date -u "+%a, %d %b %Y %H:%M:%S %z")"
END

cp ${GET_[root_path]}/current/app/etc/env.php /home/${GET_[brand]}/shared/env.php.installed
chown ${GET_[brand]} /home/${GET_[brand]}/shared/env.php.installed

_space 1
YELLOWTXT "[-] Creating .mytop config to /home/${GET_[brand]}/.mytop"
tee /home/${GET_[brand]}/.mytop <<END
user=${GET_[database_user]}
pass=${GET_[database_password]}
db=${GET_[database_name]}
END

cd ${GET_[root_path]}/
chown ${GET_[brand]}:${GET_[brand]} ${GET_[root_path]}/.mytop

_space 1
YELLOWTXT "[-] Generating SSH keys for Magento user and Github Actions"
mkdir .ssh
SSH_KEY="private_ssh_key"
ssh-keygen -o -a 256 -t ed25519 -f ${MAGENX_CONFIG_PATH}/${SSH_KEY} -C "ssh for ${GET_[domain]}" -N ""
PRIVATE_SSH_KEY=$(cat "${MAGENX_CONFIG_PATH}/${SSH_KEY}")
PUBLIC_SSH_KEY=$(cat "${MAGENX_CONFIG_PATH}/${SSH_KEY}.pub")
${SQLITE3} "UPDATE magento SET private_ssh_key = '${PRIVATE_SSH_KEY}', public_ssh_key = '${PUBLIC_SSH_KEY}';"
tee -a .ssh/authorized_keys <<END
${PUBLIC_SSH_KEY}
END

GITHUB_ACTIONS_SSH_KEY="github_actions_private_ssh_key"
ssh-keygen -o -a 256 -t ed25519 -f ${MAGENX_CONFIG_PATH}/${GITHUB_ACTIONS_SSH_KEY} -C "github actions for ${GET_[domain]}" -N ""
GITHUB_ACTIONS_PRIVATE_SSH_KEY=$(cat "${MAGENX_CONFIG_PATH}/${GITHUB_ACTIONS_SSH_KEY}")
GITHUB_ACTIONS_PUBLIC_SSH_KEY=$(cat "${MAGENX_CONFIG_PATH}/${GITHUB_ACTIONS_SSH_KEY}.pub")
${SQLITE3} "UPDATE magento SET github_actions_private_ssh_key = '${GITHUB_ACTIONS_PRIVATE_SSH_KEY}', github_actions_public_ssh_key = '${GITHUB_ACTIONS_PUBLIC_SSH_KEY}';"
cat ${MAGENX_CONFIG_PATH}/${GITHUB_ACTIONS_SSH_KEY}.pub >> .ssh/authorized_keys

_space 1
YELLOWTXT "[-] Creating bash_profile"
tee .bash_profile <<END
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi
# User specific environment and startup programs
PATH=\$PATH:\$HOME/bin
export PATH
END

_space 1
YELLOWTXT "[-] Creating bashrc"
tee .bashrc <<END
# .bashrc
# history timestamp
export HISTTIMEFORMAT="%d/%m/%y %T "
# got to app root folder
cd ~/current/
# change prompt color
PS1='\[\e[37m\][\[\e[m\]\[\e[32m\]\u\[\e[m\]\[\e[37m\]@\[\e[m\]\[\e[35m\]\h\[\e[m\]\[\e[37m\]:\[\e[m\]\[\e[36m\]\W\[\e[m\]\[\e[37m\]]\[\e[m\]$ '
END

touch ${GET_[root_path]}/.bash_history
chmod 600 ${GET_[root_path]}/{.bashrc,.bash_profile,.bash_history}
chown -R ${BRAND}:${BRAND} ${GET_[root_path]}/{.bashrc,.bash_profile,.bash_history,.ssh}

_space 2
YELLOWTXT "[-] Add timestamp to bash history and config alias:"
tee -a  ~/.bashrc <<END
### magenx
export HISTTIMEFORMAT="%d/%m/%y %T "
alias magenx_magento='sqlite3 -line /opt/magenx/config/magenx.db "select * from magento;"'
alias magenx_system='sqlite3 -line /opt/magenx/config/magenx.db "select * from system;"'
END

# clean config directory and set permissions
chmod +x /usr/local/bin/*
find ${MAGENX_CONFIG_PATH}/ -maxdepth 1 -type f ! -name "${SQLITE3_DB}" -delete
chmod -R 600 ${MAGENX_CONFIG_PATH}

systemctl daemon-reload
systemctl restart nginx.service
systemctl restart php*fpm.service
systemctl restart varnish.service
systemctl restart fail2ban
fail2ban-client version

_space 2
YELLOWTXT "Magento configuration parameters:"
${SQLITE3} -line "SELECT * FROM magento;"
_space 2
YELLOWTXT "For issues and support:"
WHITETXT "https://github.com/magenx/Magento-2-server-installation"
_space 2
YELLOWTXT "For Github Actions CI/CD integration:"
WHITETXT "https://www.magenx.com/magento-support-and-server-management.html"
_space 2
YELLOWTXT "Write a review:"
WHITETXT "https://trustpilot.com/review/www.magenx.com"
_space 2
echo "PS1='\[\e[37m\][\[\e[m\]\[\e[32m\]\u\[\e[m\]\[\e[37m\]@\[\e[m\]\[\e[35m\]\h\[\e[m\]\[\e[37m\]:\[\e[m\]\[\e[36m\]\W\[\e[m\]\[\e[37m\]]\[\e[m\]$ '" >> /etc/bashrc
_space 1
## simple installation stats
DOMAIN=$(${SQLITE3} "SELECT domain FROM magento LIMIT 1;")
DISTRO_NAME=$(${SQLITE3} "SELECT distro_name FROM system;")
curl --silent -X POST https://www.magenx.com/ping_back_os_${DISTRO_NAME}_domain_${DOMAIN}_geo_${TIMEZONE}_keep_30d >/dev/null 2>&1
_space 1
echo "#===================================================================================================================#"
GREENTXT "${BOLD}~~  SERVER IS READY. THANK YOU  ~~"
echo "#===================================================================================================================#"
_space 1
${SQLITE3} "UPDATE menu SET config = 'x';"
_space 1
_pause '[] Press [Enter] key to show menu'
;;
###################################################################################
###                                  WEBMIN INSTALLATION                        ###
###################################################################################
"webmin")
_space 2
_echo "[?] Install Webmin Control Panel ? [y/n][n]: "
DOMAIN=$(${SQLITE3} "SELECT domain FROM magento LIMIT 1;")
BRAND=$(${SQLITE3} "SELECT brand FROM magento LIMIT 1;")
ADMIN_EMAIL=$(${SQLITE3} "SELECT admin_email FROM magento LIMIT 1;")
read webmin_install
if [ "${webmin_install}" == "y" ];then
 _space 1
 YELLOWTXT "Webmin installation:"
 _space 1
 curl -s -O https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh
 bash setup-repos.sh
 apt update
 apt -y install webmin
if [ "$?" = 0 ]; then
 WEBMIN_PORT=$(shuf -i 17556-17728 -n 1)
 sed -i 's/theme=gray-theme/theme=authentic-theme/' /etc/webmin/config
 sed -i 's/preroot=gray-theme/preroot=authentic-theme/' /etc/webmin/miniserv.conf
 sed -i "s/port=10000/port=${WEBMIN_PORT}/" /etc/webmin/miniserv.conf
 sed -i "s/listen=10000/listen=${WEBMIN_PORT}/" /etc/webmin/miniserv.conf
 sed -i '/keyfile=\|certfile=/d' /etc/webmin/miniserv.conf
 echo "keyfile=/etc/letsencrypt/live/${DOMAIN}/privkey.pem" >> /etc/webmin/miniserv.conf
 echo "certfile=/etc/letsencrypt/live/${DOMAIN}/cert.pem" >> /etc/webmin/miniserv.conf
  
  echo "webmin_${BRAND}:\$1\$84720675\$F08uAAcIMcN8lZNg9D74p1:::::$(date +%s):::0::::" > /etc/webmin/miniserv.users
  sed -i "s/root:/webmin_${BRAND}:/" /etc/webmin/webmin.acl
  WEBMIN_PASSWORD=$(head -c 500 /dev/urandom | tr -dc 'a-zA-Z0-9@#%^?=+_[]{}()' | fold -w 15 | head -n 1)
  /usr/share/webmin/changepass.pl /etc/webmin/ webmin_${BRAND} "${WEBMIN_PASSWORD}"
  
  systemctl enable webmin
  /etc/webmin/restart

  _space 1
  GREENTXT "Webmin installed - OK"
  _space 1
  YELLOWTXT "[!] Webmin Port: ${WEBMIN_PORT}"
  YELLOWTXT "[!] User: webmin_${BRAND}"
  YELLOWTXT "[!] Password: ${WEBMIN_PASSWORD}"
  _space 1
  REDTXT "[!] PLEASE ENABLE TWO-FACTOR AUTHENTICATION!"
  
  ${SQLITE3} "UPDATE system SET webmin_password = '${WEBMIN_PASSWORD}';"
  else
   _space 1
   REDTXT "Webmin installation error"
  fi
  else
   _space 1
   YELLOWTXT "Webmin installation was skipped by user input."
fi
_space 2
_pause '[] Press [Enter] key to show menu'
_space 1
;;
"exit")
REDTXT "[!] Exit"
exit
;;

###################################################################################
###                             CATCH ALL MENU - THE END                        ###
###################################################################################

*)
printf "\033c"
;;
esac
done
