#!/bin/bash
 
# Ensure the log directory exists
mkdir -p /tmp/migration_logs/

# Get the filename of current script and strip .sh from the end
SCRIPT_FILE_NAME=$(basename "$0" .sh)

# Create the log and error filenames
LOG_FILE_NAME="/tmp/migration_logs/$SCRIPT_FILE_NAME.log"
ERR_FILE_NAME="/tmp/migration_logs/$SCRIPT_FILE_NAME.err"

# Print info about logging
echo "STDOUT redirected to $LOG_FILE_NAME"
echo "STDERR redirected to $ERR_FILE_NAME"

# update installed components
echo "Install OS Updates"

# Debian / Ubuntu
if command -v apt-get &>/dev/null; then
  export DEBIAN_FRONTEND=noninteractive
  apt update >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME" && apt upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
# Modern CenotOS, AlmaLinux etc 
elif command -v dnf &>/dev/null; then
  dnf update -y >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME" && dnf install -y ca-certificates bind-utils grep net-tools nmap pwgen traceroute vim-common vim whois >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"  
else
  echo "Package manager not detected. Please install imapsync manually."
  exit 1
fi

# update plesk
echo "Install Plesk Updates"
plesk installer --select-release-latest --upgrade-installed-components >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

sleep 30

# Install php_handler
echo "Install PHP Handler"
available_php=()
available_php=$(plesk installer --select-release-current --show-components 2>&1 | grep 'php' | grep '\[install\]')

sleep 30

# Display the list of available PHP handlers before asking the user
echo "Available PHP handlers:"
  for ITEM in "${available_php[@]}"; do
          echo "$ITEM"
  done

  # Ask the user about outdated PHP handlers
  read -r -p "Install outdated PHP handlers (y/N)? " install_outdated

  # Default to 'n' if the user just presses Enter
  install_outdated="${install_outdated:-n}"

  # Filter outdated handlers if the user chooses 'n' or presses Enter
  if [[ "$install_outdated" == "n" || "$install_outdated" == "N" ]]; then
          available_php=($(echo "$available_php" | grep -v "outdated" | awk '{print $1}')) # Filter component name and exclude outdated handlers
          echo "Only Up2Date PHP handlers will be installed"
          for ITEM in "${available_php[@]}"; do
                  echo "Installing $ITEM - This might take a while"
                  plesk installer --select-release-current --install-component $ITEM >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
                  sleep 30
          done
  elif [[ "$install_outdated" == "y" || "$install_outdated" == "Y" ]]; then
          available_php=($(echo "$available_php" | awk '{print $1}')) # Filter component name
          echo "All, even outdated PHP handlers will be installed"
          for ITEM in "${available_php[@]}"; do
                  echo "Installing $ITEM - This might take a while"
                  plesk installer --select-release-current --install-component $ITEM >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
                  sleep 30
          done
  else
          echo "Invalid input. Defaulting to no outdated PHP handlers."
  fi
 
# Remove unwanted extensions
echo "Remove unwandet Plesk extensions"
for EXTENSION in revisium-antivirus advisor social-login domain-connect ; 
  do /usr/local/psa/bin/extension --uninstall ${EXTENSION} >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"; 
done
 
# disable Plesk Server Backup
echo "Disable Plesk Backups"
plesk db "UPDATE BackupsScheduled SET active = 'false' where obj_type = 'server'"
 
# Install typical extensions
echo "Install typical extensions"
for EXTENSION in dnssec traffic-monitor symantec sectigo ; 
  do /usr/local/psa/bin/extension --install ${EXTENSION} >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"; 
done
 
# Install typical components
echo "Install typical components - This might take a while"
for COMPONENT in postfix dovecot proftpd webalizer awstats modsecurity mod_fcgid mod_perl mod_python webservers nginx psa-firewall wp-toolkit xovi sslit letsencrypt composer monitoring site-import roundcube fail2ban pmm mysqlgroup sitebuilder git spamassassin ; 
  do plesk installer --select-release-current --install-component ${COMPONENT} >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"; 
done
 
# Enable typical apache modules
echo "Enable typical apache modules - This might take a while"
for MODULE in auth_digest authz_groupfile cache cgi dav dav_fs dav_lock expires ; 
  do plesk bin optimization_settings -e ${MODULE} >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME";
done
 
# Remove social-media-links
echo "Remove social-media-links in Plesk"

if ! grep -q '[facebook]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[facebook]
		; Hide Like link
		showLikeLink = off
	EOF
fi
 
if ! grep -q '[rating]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[rating]
		; Hide feedback dialog with question to rate product
		enabled = off
	EOF
fi

if ! grep -q '[extensions]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[extensions]
		blacklist = "kernelcare-plesk"
		autoBackup = off
	EOF
fi

if ! grep -q '[twitter]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[twitter]
		showFollowLink = off
	EOF
fi

if ! grep -q '[promos]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[promos]
		enabled = off
		extensions.featured = off
		extensions.installed = off
		extensions.catalog = off
	EOF
fi

if ! grep -q '[userActivityTracking]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[userActivityTracking]
		enabled = off
	EOF
fi

if ! grep -q '[rating]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[rating]
		; Hide feedback dialog with question to rate product
		enabled = off
	EOF
fi

# Configure timezone Europe/Berlin
echo "Configure timezone Europe/Berlin"
timedatectl set-timezone Europe/Berlin >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
 
# Configure locales
echo "Configure locales"
localectl set-locale LANG=de_DE.UTF-8 >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
/usr/local/psa/bin/server_pref --set-default -locale de-DE >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Set the interface language to english
echo "Setting Plesk interface language"
plesk bin admin -u -locale en-US
plesk bin locales --enable en-US
plesk bin locales --set-default en-US
plesk bin server_pref --set-default -locale en-US

# Remove unwanted locales
echo "Remove unwanted locales"
for LANGUAGES in ar ca-ES cs-CZ da-DK el-GR es-ES fi-FI fr-FR he-IL hu-HU id-ID it-IT ja-JP ko-KR ms-MY nb-NO nl-NL pl-PL pt-BR pt-PT ro-RO ru-RU sv-SE th-TH tl-PH tr-TR uk-UA vi-VN zh-CN zh-TW ; do
  plesk bin locales --disable ${LANGUAGES}
done

# Enable MySQL upgrade in Plesk GUI
echo "Enable MySQL upgrade in Plesk GUI"
if ! grep -q '[databaseManagement]' /usr/local/psa/admin/conf/panel.ini; then
	cat >> /usr/local/psa/admin/conf/panel.ini <<-EOF
		[databaseManagement]
		features.canBeUpgraded = 1
	EOF
fi
 
# Configure IPs in Plesk as shared
echo "Configure IPs in Plesk as shared"
plesk bin ipmanage -u $(ip a | grep -w 'inet' | grep 'global' | cut -d" " -f6) -type shared >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME" && \
plesk bin ipmanage -u $(ip a | grep -w 'inet6' | grep 'global' | cut -d" " -f6) -type shared >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
 
# Limit DNS recursions to localhost
echo "Limit DNS recursions to localhost"
plesk bin server_dns -u -recursion localhost >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
 
# Modify DNS Template
echo "Modify DNS Template"
HOST=$(hostname -f)
 
/usr/local/psa/bin/server_dns --set "NS,,pdns02.domaincontrol.com;NS,,$HOST;A,,<ip>;AAAA,,<ipv6>;A,webmail,<ip>;AAAA,webmail,<ipv6>;MX,,mail.<domain>.,10;A,mail,<ip>;AAAA,mail,<ipv6>;CNAME,www,<domain>.;CNAME,ftp,<domain>.;TXT,,v=spf1 +a +mx include:secureserver.net -all;A,ipv4,<ip>;AAAA,ipv6,<ipv6>;" >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
 
# Allow zonetransfer
echo "ACL Configuration for pDNS"
/usr/local/psa/bin/server_dns -u -add-acl "80.237.128.0/24,208.109.132.0/24,50.63.22.0/24" >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
 
# Configure Notify
echo "Configure Notify for pDNS"
# Ubuntu/Debian
if command -v apt-get &>/dev/null; then
	if ! grep -q 'notify yes;' /var/named/run-root/etc/named-user-options.conf; then
		cat >> /var/named/run-root/etc/named-user-options.conf <<-EOF
			notify yes;
			also-notify { 97.74.112.1; 97.74.112.2; };
		EOF
	fi
# Modern CenotOS, AlmaLinux etc 
elif command -v dnf &>/dev/null; then
	if ! grep -q 'notify yes;' /var/named/chroot/etc/named-user-options.conf; then
		cat >> /var/named/chroot/etc/named-user-options.conf <<-EOF
			notify yes;
			also-notify { 97.74.112.1; 97.74.112.2; };
		EOF
	fi
else
  echo "Unable to configure notify"
fi

# Enable Reverse Proxy configuration (NGINX <=> apache2)
echo "Enable Reverse Proxy configuration (NGINX <=> apache2)"
/usr/local/psa/admin/sbin/nginxmng -e >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
 
# Enable HTTP/2
echo "Enable HTTP/2"
plesk bin http2_pref enable >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Postfix process limits
echo "Set Postfix process limit to 25"
echo "default_process_limit = 25" >> /etc/postfix/main.cf

# Set maximum message size that can be accepted by the mail server.
echo "Set max mail size to 50MB"
plesk bin mailserver --set-max-letter-size 50M >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Check users mail passwords agains the password dictionary to prevent users from setting simple passwords
echo "Prevent simple passwords"
plesk bin mailserver --use-vocabulary true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable the SPF spam protection on the mail server
echo "Enable inbound SPF check"
plesk bin mailserver --update-spf -spf-status true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable DMARC spam protection for incoming mail on the mail server
echo "Enable inbound DMARC check"
plesk bin mailserver --enable-dmarc >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable signing of outgoing mail on the mail server:
echo "Enable DKIM Outbound"
plesk bin mailserver --sign-outgoing-mail true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable the usage of limitations on outgoing mail from the Plesk server and set limits
echo "Set limits for outbound mail"
plesk bin mailserver --enable-outgoing-antispam >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
plesk bin mailserver --set-outgoing-messages-mbox-limit 500 >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
plesk bin mailserver --set-outgoing-messages-domain-limit 5000 >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
plesk bin mailserver --set-outgoing-messages-subscription-limit 25000 >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# make Outgoing Mail Control count outgoing email messages by recepients:
echo "Count outbound mail by recipient"
plesk bin mailserver --set-outgoing-messages-count-recipients true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable mail autodiscover on a Plesk server:
echo "Enable mail auto-discover"
plesk bin mailserver --set-mail-autodiscover true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# enable VERP-style email addresses for mailing lists
echo "Enable VERP-Style mail addresses"
plesk bin mailserver --email-subaddressing-enable true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable mailbox quota warnings:
echo "Enable mailbox quota warnings"
plesk bin mailserver --quota-warning-enable true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable the fixing of an incorrectly set sender:
echo "enable fixing malformed sender"
plesk bin mailserver --set-outgoing-messages-fix-sender true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# set the relaying mode to authorization is required mode, to specify the SMTP authorization type.
echo "Set ralaying mode to smtp-auth"
plesk bin mailserver --set-relay auth -auth-type smtp >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable SMTP on Port 587
echo "Enable SMTP on Port 587"
/usr/local/psa/bin/mailserver --set-message-submission true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Disable greylisting
echo "Disable greylisting"
plesk bin grey_listing --update-server -status off >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Configure DNS Blackhole Lists
echo "Configure DNSBL spam.abuse.net and bl.spamcop.net"
plesk bin mailserver --add-maps-zone spam.abuse.net,bl.spamcop.net >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"
plesk bin mailserver --set-maps-status true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Set the minimum score for marking mail messages as spam
echo "Set Spam min score to 3"
plesk bin spamassassin --update-server -hits 3 >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable subject lines automatic modification for spam messages and to specify the text to be inserted in the beginning of the subject line
echo "Enable SPAM subject prefix"
plesk bin spamassassin --update-server -modify-subj true -modify-subj-text "***SPAM*** Score: _SCORE_ :" >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Add a domain name to the list of prohibited domain names:
echo "Disable domains from large banks or online retailers in mail-from"
plesk bin domain_restriction --add-list -list amazon.com,amazon.de,bankofamerica.com,deutsche-bank.de,deutschebank.de,ebay.com,ebay.de,e-bay.de,email-telekom.de,email.telekom.de,facebook-mail.com,facebook.com,facebook.de,facebookmail.com,fiducia.de,gmail.com,gmail.de,gmx.com,gmx.de,gmx.net,google.com,google.de,googlemail.com,googlemail.de,hotmail.com,hotmail.de,live.com,live.de,mail.fiducia.de,mail.sparkasse.de,mail.telekom.de,mail.vodafone.de,mail.volksbank.de,mail-de.sparkasse.de,mail-de.volksbank.de,mastercard.de,o2mail.co.uk,online.vodafone.de,paypal-deutschland.de,paypal.com,paypal.de,paypal.info,rechnung.t-mobile.de,rechnung.t-online.de,rechnung.vodafone.de,t-online.de,sparkasse-koelnbonn.de,sparkasse.com,sparkasse.de,support.vodafone.de,telekom.de,visa.com,visa.de,vodafone.de,volksbank.de,web.de,yahoo.co.uk,yahoo.com,yahoo.de >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable WAF
echo "Enable WAF"
plesk bin server_pref --update-web-app-firewall -waf-rule-engine on -waf-rule-set crs >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Upgrade min_password_strength
echo "Upgrade min_password_strength for Plesk"
/usr/local/psa/bin/server_pref -u -min_password_strength medium >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Automatically install Plesk updates
echo "Enable auto-updates for Plesk"
plesk bin server_pref -u -autoupdates true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Automatically install updates for third-party components shipped by Plesk
echo "Enable auto-updates for third-party components"
plesk bin server_pref -u -autoupdates-third-party true >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Automatically install system package updates
echo "Enable auto-updates for OS"
plesk db "INSERT INTO misc(param, val) VALUES('automaticSystemPackageUpdates', 'true') ON DUPLICATE KEY UPDATE val = 'true';" >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable safe updates for system packages
echo "Enable safe updates"
plesk db "INSERT INTO misc(param, val) VALUES('systemPackageUpdatesSafeOnly', 'true') ON DUPLICATE KEY UPDATE val = 'true';" >> "$LOG_FILE_NAME" 2>> "$ERR_FILE_NAME"

# Enable PSA-Firewall
echo "Enable PSA-Firewall"
plesk bin modules/firewall/settings -e && \
sleep 5 && \
SSH_CLIENT="127.0.0.1 65535 22" plesk bin modules/firewall/settings --confirm

# Check for Nydus firewall rule
echo "Check for Nydus firewall rule and create if missing"
if ! iptables -L INPUT | grep -q "tcp dpt:2224"; then
  # Add and enable firewall rule for NYDUS, if grep returns empty result
  plesk bin modules/firewall/settings -s -name 'NYDUS' -direction input -action allow -ports '2224/tcp,2224/udp' && \
  sleep 5 && \
  plesk bin modules/firewall/settings -a && \
  sleep 5 && \
  SSH_CLIENT="127.0.0.1 65535 22" plesk bin modules/firewall/settings --confirm
fi

echo "Job done"