#!/bin/bash
# vim:ts=2 sts=2 sw=2 et ai
# shellcheck disable=SC2119 disable=2016
#
# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 grommunio GmbH
# SPDX-FileCopyrightText: 2023-2025 eryx12o45, crpb
# Interactive grommunio setup

if [ "$(id -u)" -ne 0 ]; then
  exec sudo "${BASH_SOURCE[0]}"
fi

CFG_FILE='/etc/grommunio-setup/grommunio-setup.conf'
PKGED_CFG_FILE='/etc/grommunio-setup/packaged.conf'
PROGNAME=`basename "$0"`

# Process command line arguments
USAGE="Usage: $PROGNAME [-ahx]"
usage () {
  echo "$USAGE"  1>&2
  exit 2
}

usage_full () {
  echo "$USAGE"  1>&2
  echo "" 1>&2
  echo "    -a    --apt-setup     Set up apt" 1>&2
  echo "    -h    --help          This help" 1>&2
  echo "    -x    --no-apt-setup  Don't set up apt" 1>&2
  echo "" 1>&2
  exit 2
}

OPTS=$(getopt -o ahx -l apt-setup,help,no-apt-setup -n "$PROGNAME" -- "$@")
if [ $? -ne 0 ]; then
  echo "${PROGNAME}: Failed to parse options." 1>&2
  exit 2
fi
# Reset the positional parameters to the parsed options
eval set -- "$OPTS"

# setable settings here
NO_APT_SETUP=0
[ -e "$CFG_FILE" ] && . "$CFG_FILE"
# override various settings for packaged setup script
[ -e "$PKGED_CFG_FILE" ] && . "$PKGED_CFG_FILE"
# Unsettable settings here
# Process the options
while true; do
  case "$1" in
    -a | --apt-setup)
      NO_APT_SETUP=0
      shift
      ;;
    -h | --help)
      usage_full
      shift
      ;;
    -x | --no-apt-setup)
      NO_APT_SETUP=1
      shift
      ;;
    --)
      shift
      break
      ;;
    *)
      echo "${PROGNAME}: Internal error!"
      exit 2
      ;;
  esac
done

if [ $# -ne 0 ]; then
	usage
fi

export DEBIAN_FRONTEND=noninteractive

DATADIR="${0%/*}"
if [ "${DATADIR}" = "$0" ]; then
  DATADIR="/usr/share/grommunio-setup"
else
  DATADIR="$(readlink -f "$0")"
  DATADIR="${DATADIR%/*}"
  DATADIR="$(readlink -f "${DATADIR}")"
fi
LOGFILE="/var/log/grommunio-setup.log"
if ! test -e "$LOGFILE"; then
  true >"$LOGFILE"
  chmod 0600 "$LOGFILE"
fi

apt-get() {
if [ "$1" = "update" ]; then
  shift
  if ! command apt-get update -y "$@" >>"${LOGFILE}" 2>&1; then
    echo "APT: Update failed."|tee -a "${LOGFILE}"
    echo "Please check the logfile: ${LOGFILE}"|tee -a "${LOGFILE}"
  fi
elif [ "$1" = "dist-upgrade" ]; then
  shift
  if ! command apt-get dist-upgrade -y >>"${LOGFILE}" 2>&1; then
    echo "APT: Dist-Upgrade failed."|tee -a "${LOGFILE}"
    echo "Please check the logfile: ${LOGFILE}"|tee -a "${LOGFILE}"
  fi
elif [ "$1" = "install" ]; then
  shift
  if ! command apt-get install -y "$@" >>"${LOGFILE}" 2>&1; then
    echo "APT: Installation encountered problems: ${*}." |tee -a "${LOGFILE}"
    echo "Please check the logfile: ${LOGFILE}" |tee -a "${LOGFILE}"
  fi
fi
}


apt-get update
apt-get install dialog

# shellcheck source=common/helpers
. "${DATADIR}/common/helpers"
# shellcheck source=./common/dialogs
. "${DATADIR}/common/dialogs"
TMPF=$(mktemp /tmp/setup.sh.XXXXXXXX)
trap 'rm -f "$TMPF"' EXIT

# Prevent Apache-Installation
cat <<END > /etc/apt/preferences.d/no-apache
Package: apache2
Pin: release *
Pin-Priority: -1

Package: apache2-bin
Pin: release *
Pin-Priority: -1

Package: libapache2-mod-php
Pin: release *
Pin-Priority: -1
END

echo "Installing dependencies. This might take a while..."

# make sure necessary packages are installed and up-to-date.
apt-get update
apt-get dist-upgrade
echo "postfix	postfix/mailname string $DOMAIN" | debconf-set-selections
echo "postfix	postfix/main_mailer_type string 'Internet Site'" | debconf-set-selections
SYSTEM_PACKAGES=(mariadb-server mariadb-client redis nginx postfix postfix-lmdb
  postfix-mysql php php-igbinary php-redis sqlite3 php php-fpm curl fetchmail
  rspamd certbot python3-certbot-nginx libsasl2-2 libsasl2-modules sasl2-bin
  jq firewalld clamav clamav-freshclam clamav-daemon ssl-cert
  libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static gpg)
apt-get install "${SYSTEM_PACKAGES[@]}"

phpdismod opcache >>"${LOGFILE}" 2>&1

writelog "Welcome dialog"
dialog_welcome

if [ -e "/etc/grommunio-common/setup_done" ]; then
  DELCONFIRM=$(dialog --no-mouse --colors --backtitle "grommunio Setup" --title "grommunio Setup already completed" --cr-wrap --inputbox \
    'grommunio Setup was already run.

You can abort or delete all data and setup everything from scratch. If so, confirm this operation by typing "removealldata" to continue.

\Z1If you continue, ALL data wil be removed!\Z1' \
    0 0 3>&1 1>&2 2>&3)
  dialog_exit $?
  if [ "${DELCONFIRM}" != "removealldata" ]; then
    writelog "Aborted deletion after detected existing installation"
    exit 0
	else
		writelog "Deleting existing installation after confirmation"
		echo "drop database grommunio;" | mysql
		# remove folders etc
		rm -Rf /var/lib/gromox/* \
			/etc/grommunio-common/ssl/* \
			/etc/grommunio-common/setup_done \
			/etc/apt/sources.list.d/grommunio.sources \
			/var/lib/grommunio-web/*

		# recreate them..
		mkdir -p /var/lib/gromox/{domain,user,queue/{cache,mess,save,timer}} \
			/var/lib/grommunio-web/{session,tmp/session,sqlite-index}

		# set permissions
		touch /var/lib/gromox/queue/token.ipc
		chown -Rf gromox:gromox /var/lib/gromox
		chmod -Rf 770 /var/lib/gromox
		chown -Rf groweb:groweb /var/lib/grommunio-web/{tmp,session}
		chown -Rf groindex:groweb /var/lib/grommunio-web/sqlite-index
		chmod -Rf 770 /var/lib/grommunio-web
	fi
fi

memory_check() {
  local HAVE
  HAVE=$(perl -lne 'print $1 if m{^MemTotal:\s*(\d+)}i' </proc/meminfo)
  # Install the threshold a little lower than what we ask, to account for
  # FW/OS (Vbox with 4194304 KB ends up with MemTotal of about 4020752 KB)
  local THRES=4000000
  local ASK=4096000
  if [ -z "${HAVE}" ] || [ "${HAVE}" -ge "${THRES}" ]; then
    return 0
  fi
  writelog "Memory check"
  memory_notice $((HAVE / 1024)) $((ASK / 1024))

}

memory_check

unset MYSQL_DB
unset MYSQL_HOST
unset MYSQL_USER
unset MYSQL_PASS
unset ADMIN_PASS
unset FQDN
unset DOMAIN
unset X500
unset SSL_BUNDLE
unset SSL_KEY

writelog "Installation / update of packages"
user_management() {
  adduser postfix sasl
}
user_management >>"${LOGFILE}" 2>&1

# shellcheck source=common/repo
PACKAGES=(gromox grommunio-admin-api grommunio-admin-web grommunio-index
  grommunio-admin-common grommunio-common grommunio-web grommunio-sync
  grommunio-dav grommunio-dbconf nginx-module-vts)
. "${DATADIR}/common/repo"
if [ $NO_APT_SETUP -eq 0 ]; then
  setup_repo
  if [ $? -ne 0 ]; then
    writelog "Exiting - trying to set up apt repos when already defined"
    apt_already_setup_notice
    clear
    exit 2
  fi
fi
writelog "Installing Grommunio-Packages"
apt-get update
# Fix nginx not starting becuase of no SSL certs - use dummy snakeoil self-signed cert
apt-get install grommunio-common grommunio-admin-common --reinstall
cat >/etc/grommunio-common/nginx/ssl_certificate.conf <<EOF
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
EOF
if [ -e /etc/grommunio-admin-common/nginx-ssl.conf ]; then
  rm -f /etc/grommunio-admin-common/nginx-ssl.conf
fi
ln -s /etc/grommunio-common/nginx/ssl_certificate.conf /etc/grommunio-admin-common/nginx-ssl.conf

# reinstall in case of "removealldata"
apt-get install "${PACKAGES[@]}" --reinstall
# tickets are useless... grommunio-{dav,sync} -upsteam.conf's
rm -fv /usr/share/grommunio-common/nginx/upstreams.d/grom*upstream.conf
apt-get install -f

# fix run directory for php-fpm
echo "d /run/php-fpm 0755 www-data gromox - -" >/etc/tmpfiles.d/run-php-fpm.conf
systemd-tmpfiles --create >>"${LOGFILE}" 2>&1
# fix folder permissions
chown -Rfv groweb:groweb /var/lib/grommunio-web/{tmp,session} >>"${LOGFILE}" 2>&1
chown -Rfv groindex:groweb /var/lib/grommunio-web/sqlite-index >>"${LOGFILE}" 2>&1

MYSQL_HOST="localhost"
MYSQL_USER="grommunio"
MYSQL_PASS="$(randpw)"
MYSQL_DB="grommunio"

set_mysql_param() {

  writelog "Dialog: mysql configuration"
  dialog --no-mouse --colors --backtitle "grommunio Setup" --title "MariaDB/MySQL database credentials" --ok-label "Submit" \
    --form "Enter the database credentials." 0 0 0 \
    "Host:    " 1 1 "${MYSQL_HOST}" 1 17 25 0 \
    "User:    " 2 1 "${MYSQL_USER}" 2 17 25 0 \
    "Password:" 3 1 "${MYSQL_PASS}" 3 17 25 0 \
    "Database:" 4 1 "${MYSQL_DB}" 4 17 25 0 2>"${TMPF}"
  dialog_exit $?

}

writelog "Dialog: mysql installation type"
MYSQL_INSTALL_TYPE=$(dialog --no-mouse --colors --backtitle "grommunio Setup" --title "grommunio Setup: Database" \
  --menu "Choose database setup type" 0 0 0 \
  "1" "Create database locally (default)" \
  "2" "Connect to existing database (advanced users)" 3>&1 1>&2 2>&3)
dialog_exit $?

writelog "Selected MySQL installation type: ${MYSQL_INSTALL_TYPE}"

RETCMD=1
if [ "${MYSQL_INSTALL_TYPE}" = "2" ]; then
  while [ ${RETCMD} -ne 0 ]; do
    set_mysql_param "Existing database"
    MYSQL_HOST=$(sed -n '1{p;q}' "${TMPF}")
    MYSQL_USER=$(sed -n '2{p;q}' "${TMPF}")
    MYSQL_PASS=$(sed -n '3{p;q}' "${TMPF}")
    MYSQL_DB=$(sed -n '4{p;q}' "${TMPF}")
    if [ -n "${MYSQL_HOST}" ] && [ -n "${MYSQL_USER}" ] && [ -z "${MYSQL_PASS}" ] && [ -n "${MYSQL_DB}" ]; then
      echo "show tables;" | mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" "${MYSQL_DB}" >/dev/null 2>&1
      writelog "mysql -h${MYSQL_HOST} -u${MYSQL_USER} ${MYSQL_DB}"
    elif [ -n "${MYSQL_HOST}" ] && [ -n "${MYSQL_USER}" ] && [ -n "${MYSQL_PASS}" ] && [ -n "${MYSQL_DB}" ]; then
      echo "show tables;" | mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" -p"${MYSQL_PASS}" "${MYSQL_DB}" >/dev/null 2>&1
      writelog "mysql -h${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_PASS} ${MYSQL_DB}"
    else
      failonme 1
    fi
    RETCMD=$?
    if [ ${RETCMD} -ne 0 ]; then
      dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "MySQL database credentials" --msgbox 'No connection could be established with the database using the provided credentials. Verify that the credentials are correct and that a connection to the database is possible from this system.' 0 0
      dialog_exit $?
    fi
  done
else
  while [ ${RETCMD} -ne 0 ]; do
    set_mysql_param "Create database"
    MYSQL_HOST=$(sed -n '1{p;q}' "${TMPF}")
    MYSQL_USER=$(sed -n '2{p;q}' "${TMPF}")
    MYSQL_PASS=$(sed -n '3{p;q}' "${TMPF}")
    MYSQL_DB=$(sed -n '4{p;q}' "${TMPF}")
    if [ -n "${MYSQL_HOST}" ] && [ -n "${MYSQL_USER}" ] && [ -n "${MYSQL_PASS}" ] && [ -n "${MYSQL_DB}" ]; then
      echo "DROP DATABASE IF EXISTS ${MYSQL_DB}; CREATE DATABASE ${MYSQL_DB}; GRANT ALL ON ${MYSQL_DB}.* TO '${MYSQL_USER}'@'${MYSQL_HOST}' IDENTIFIED BY '${MYSQL_PASS}';" | mysql >/dev/null 2>&1
    else
      failonme 1
    fi
    RETCMD=$?
    if [ ${RETCMD} -ne 0 ]; then
      dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "MySQL connection failed" --msgbox 'Could not set up the database. Make sure it is reachable and re-run the creation process.' 0 0
      dialog_exit $?
    fi
  done
fi
writelog "MySQL configuration: Host: ${MYSQL_HOST}, User: ${MYSQL_USER}, Password: ${MYSQL_PASS}, Database: ${MYSQL_DB}"

dialog_adminpass

set_fqdn() {

  writelog "Dialog: FQDN"
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Fully Qualified Domain Name (FQDN)" --cr-wrap --inputbox \
    "Tell us this system's fully qualified domain name (FQDN). This is used, for example, by Outlook clients to connect.

Example: grommunio.example.com

This name will be part of the certificates later generated. / This name will have to be present in imported certificates." 0 0 "$(hostname -f)" 3>&1 1>&2 2>&3
  dialog_exit $?

}

ORIGFQDN=$(set_fqdn)
FQDN="${ORIGFQDN,,}"

while [[ ${FQDN} =~ / ]]; do
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Fully Qualified Domain Name (FQDN)" --msgbox 'The FQDN is invalid. Enter a valid FQDN.' 0 0
  FQDN=$(set_fqdn)
  dialog_exit $?
done
writelog "Configured FQDN: ${FQDN}"

set_maildomain() {

  DFL=$(hostname -d)
  if [ -z "${DFL}" ]; then
    DFL="${FQDN}"
  fi
  writelog "Dialog: mail domain"
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Mail domain" --cr-wrap --inputbox \
    "Tell us the default mail domain this system serves up. This is used, for example, for Non-Delivery Reports and for generation of some simple TLS certificates. Specify ONLY ONE domain here.

Example: example.com" 0 0 "${DFL}" 3>&1 1>&2 2>&3
  dialog_exit $?

}

ORIGDOMAIN=$(set_maildomain)
DOMAIN=${ORIGDOMAIN,,}

while [[ ${DOMAIN} =~ / ]]; do
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Mail domain" --msgbox 'The entered mail domain is invalid. Enter a valid mail domain.' 0 0
  dialog_exit $?
  ORIGDOMAIN=$(set_maildomain)
  DOMAIN=${ORIGDOMAIN,,}
done
writelog "Configured mail domain: ${FQDN}"

RELAYHOST=$(get_relayhost)
writelog "Got relayhost: ${RELAYHOST}"

X500="i$(printf "%llx" "$(date +%s)")"

[ -e "/etc/grommunio-common/ssl" ] || mkdir -p "/etc/grommunio-common/ssl"

# Configure config.json of admin-web
cat >/etc/grommunio-admin-common/nginx.d/web-config.conf <<EOF
location /config.json {
  alias /etc/grommunio-admin-common/config.json;
}
EOF

choose_ssl_install_type() {

  writelog "Dialog: ssl installation type"
  SSL_INSTALL_TYPE=$(dialog --no-mouse --colors --backtitle "grommunio Setup" --title "grommunio Setup: TLS" \
    --menu "Choose your TLS setup type" 0 0 0 \
    "0" "Create self-signed certificate" \
    "1" "Create own CA and certificate" \
    "2" "Import an existing TLS certificate from files" \
    "3" "Automatically generate Let's Encrypt certificate" 3>&1 1>&2 2>&3)
  dialog_exit $?

}

choose_ssl_install_type
writelog "Selected TLS installation type: ${SSL_INSTALL_TYPE}"

SSL_COUNTRY="XX"
SSL_STATE="XX"
SSL_LOCALITY="X"
SSL_ORG="grommunio Appliance"
SSL_OU="IT"
SSL_EMAIL="admin@${DOMAIN}"
SSL_DAYS=30
SSL_PASS="$(randpw)"

choose_ssl_fullca() {

  writelog "Dialog: data for Full CA"
  dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Full CA)" --ok-label "Submit" \
    --form "Enter TLS related data" 0 0 0 \
    "Country:        " 1 1 "${SSL_COUNTRY}" 1 17 25 0 \
    "State:          " 2 1 "${SSL_STATE}" 2 17 25 0 \
    "Locality:       " 3 1 "${SSL_LOCALITY}" 3 17 25 0 \
    "Organization:   " 4 1 "${SSL_ORG}" 4 17 25 0 \
    "Org Unit:       " 5 1 "${SSL_OU}" 5 17 25 0 \
    "E-Mail:         " 6 1 "${SSL_EMAIL}" 6 17 25 0 \
    "Validity (days):" 7 1 "${SSL_DAYS}" 7 17 25 0 2>"${TMPF}"
  dialog_exit $?

}

choose_ssl_selfprovided() {

  writelog "Dialog: data for self-provided TLS cert"
  dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (self-provided)" --ok-label "Submit" \
    --form "Enter the paths to the TLS certificates" 0 0 0 \
    "PEM encoded certificate bundle:  " 1 1 "${SSL_BUNDLE}" 1 35 120 0 \
    "PEM encoded private key:         " 2 1 "${SSL_KEY}" 2 35 120 0 2>"${TMPF}"
  dialog_exit $?

}

set_letsencryptmail() {

  writelog "Dialog: Let's Encrypt"
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --cr-wrap --inputbox \
    "Specify an email adress that Let's Encrypt can contact for when there is an issue with the certificates

Example: ${SSL_EMAIL}" 0 0 "${SSL_EMAIL}" 3>&1 1>&2 2>&3
  dialog_exit $?

}

choose_ssl_letsencrypt() {

  writelog "Dialog: Let's Encrypt domains"
  LE_TERMS_URL=$(curl -Lsk https://acme-v02.api.letsencrypt.org/directory | grep termsOfService | sed 's#\(.*\)\(https://.*\)\",#\2#')
  if [ "${FQDN}" = "${DOMAIN}" ]; then
    dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --ok-label "Submit" \
      --checklist "Choose the Let's Encrypt certificates to request.\nBy requesting certificates from Let's Encrypt, you agree to the terms of service at ${LE_TERMS_URL}.\nThe DNS records should be set accordingly before proceeding." 0 0 0 \
      "${DOMAIN}" "recommended" on \
      "autodiscover.${DOMAIN}" "recommended" on \
      "mail.${DOMAIN}" "optional" off 2>"${TMPF}"
  else
    if [ "${FQDN}" = "mail.${DOMAIN}" ]; then
      dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --ok-label "Submit" \
        --checklist "Choose the Let's Encrypt certificates to request.\nBy requesting certificates from Let's Encrypt, you agree to the terms of service at ${LE_TERMS_URL}.\nThe DNS records should be set accordingly before proceeding." 0 0 0 \
        "${DOMAIN}" "recommended" on \
        "${FQDN}" "recommended" on \
        "autodiscover.${DOMAIN}" "recommended" off 2>"${TMPF}"
    else
      dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --ok-label "Submit" \
        --checklist "Choose the Let's Encrypt certificates to request.\nBy requesting certificates from Let's Encrypt, you agree to the terms of service at ${LE_TERMS_URL}.\nThe DNS records should be set accordingly before proceeding." 0 0 0 \
        "${DOMAIN}" "recommended" on \
        "autodiscover.${DOMAIN}" "recommended" on \
        "${FQDN}" "recommended" on \
        "mail.${DOMAIN}" "optional" off 2>"${TMPF}"
    fi
  fi
  dialog_exit $?

}

# shellcheck source=common/ssl_setup
. "${DATADIR}/common/ssl_setup"
RETCMD=1
if [ "${SSL_INSTALL_TYPE}" = "0" ]; then
  clear
  if ! selfcert; then
    dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (self-signed)" --msgbox "Certificate generation not successful. See ${LOGFILE}.\nContinue installation or press ESC to abort setup." 0 0
    dialog_exit $?
  fi
elif [ "${SSL_INSTALL_TYPE}" = "1" ]; then
  while [ -z "${SSL_COUNTRY}" ] || [ -z "${SSL_STATE}" ] || [ -z "${SSL_LOCALITY}" ] || [ -z "${SSL_ORG}" ] || [ -z "${SSL_OU}" ] || [ -z "${SSL_EMAIL}" ] || [ -z "${SSL_DAYS}" ] || [ "${RETCMD}" = "1" ]; do
    choose_ssl_fullca
    RETCMD=0
  done
  SSL_COUNTRY=$(sed -n '1{p;q}' "${TMPF}")
  SSL_STATE=$(sed -n '2{p;q}' "${TMPF}")
  SSL_LOCALITY=$(sed -n '3{p;q}' "${TMPF}")
  SSL_ORG=$(sed -n '4{p;q}' "${TMPF}")
  SSL_OU=$(sed -n '5{p;q}' "${TMPF}")
  SSL_EMAIL=$(sed -n '6{p;q}' "${TMPF}")
  SSL_DAYS=$(sed -n '7{p;q}' "${TMPF}")
  fullca
  writelog "TLS configuration: Country: ${SSL_COUNTRY} State: ${SSL_STATE} Locality: ${SSL_LOCALITY} Organization: ${SSL_ORG} Org Unit: ${SSL_OU} E-Mail: ${SSL_EMAIL} Validity (days): ${SSL_DAYS}"
elif [ "${SSL_INSTALL_TYPE}" = "2" ]; then
  choose_ssl_selfprovided
  SSL_BUNDLE=$(sed -n '1{p;q}' "${TMPF}")
  SSL_KEY=$(sed -n '2{p;q}' "${TMPF}")
  while [ ${RETCMD} -ne 0 ]; do
    owncert
    RETCMD=$?
  done
  writelog "TLS configuration: Bundle: ${SSL_BUNDLE} Key: ${SSL_KEY}"
elif [ "${SSL_INSTALL_TYPE}" = "3" ]; then
  choose_ssl_letsencrypt
  SSL_DOMAINS=$(sed 's# #,#g' "${TMPF}" | tr '[:upper:]' '[:lower:]')
  while [ -z "${SSL_DOMAINS}" ]; do
    dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's encrypt)" --msgbox "No valid domains have been chosen for the TLS certificates. Select valid domains." 0 0
    dialog_exit $?
    choose_ssl_letsencrypt
    SSL_DOMAINS=$(sed 's# #,#g' "${TMPF}" | tr '[:upper:]' '[:lower:]')
  done

  SSL_EMAIL=$(set_letsencryptmail)
  while ! [[ ${SSL_EMAIL} =~ ^.*\@.*$ ]]; do
    dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --msgbox "The provided email address is invalid. Enter a valid email address." 0 0
    SSL_EMAIL=$(set_letsencryptmail)
    dialog_exit $?
  done
  letsencrypt
  writelog "TLS configuration: Let's Encrypt ${SSL_EMAIL}"
fi

cat << EOF | jq > /tmp/config.json
{ "mailWebAddress": "https://${FQDN}/web",
  "rspamdWebAddress": "https://${FQDN}:8443/antispam" }"
EOF
progress 0

progress 10
writelog "Config redis for Grommunio"
{
  systemctl disable --now redis-server.service
  [ -d /var/lib/redis ] && su -m redis -c 'mkdir --mode=0750 -vp /var/lib/redis/default'
  env --chdir=/etc/redis ln -svf {,redis-}grommunio.conf
  systemctl enable --now redis-server@grommunio
 }  >>"${LOGFILE}" 2>&1

progress 15
writelog "Configure SSL Certificates for Grommunio"
cat >/etc/grommunio-common/nginx/ssl_certificate.conf <<EOF
ssl_certificate ${SSL_BUNDLE_T};
ssl_certificate_key ${SSL_KEY_T};
EOF
if [ -e /etc/grommunio-admin-common/nginx-ssl.conf ]; then
  rm -f /etc/grommunio-admin-common/nginx-ssl.conf
fi
ln -s /etc/grommunio-common/nginx/ssl_certificate.conf /etc/grommunio-admin-common/nginx-ssl.conf
chown -hfv gromox:gromox /etc/grommunio-common/ssl/* >>"${LOGFILE}" 2>&1

# set php version number 
PHPVER="$(apt-cache show php |awk '/^Depends:/ {sub("php","", $2);print$2}')"

writelog "Config stage: enable all services"
SERVICES=(redis-server@grommunio.service "php${PHPVER}-fpm.service" nginx.service
$(systemctl list-unit-files 'grom*' --no-legend|cut -d\  -f1 |grep -v snapshot)
  clamav-freshclam.service clamav-daemon.service rspamd.service)
# shellcheck disable=SC2068
systemctl enable ${SERVICES[@]} >>"${LOGFILE}" 2>&1

progress 20
writelog "Config stage: start db"
systemctl enable --now mariadb >>"${LOGFILE}" 2>&1

# https://community.grommunio.com/d/447-debian-11-clean-install-script/37
mkdir -p /var/spool/postfix/run/mysqld >>"${LOGFILE}" 2>&1
# shellcheck disable=SC2028
if ! grep -qF -- "/run/mysqld" /etc/fstab; then
  echo -e "/run/mysqld\t/var/spool/postfix/run/mysqld\tbind\tdefaults,bind\t0\t0" | \
  tee -a /etc/fstab >>"${LOGFILE}" 2>&1
  mount /var/spool/postfix/run/mysqld >>"${LOGFILE}" 2>&1
fi
writelog "Config stage: put php files into place"
if [ -e "/etc/php/$PHPVER/fpm/php-fpm.conf.default" ]; then
  mv "/etc/php/$PHPVER/fpm/php-fpm.conf.default" "/etc/php/$PHPVER/fpm/php-fpm.conf" >>"${LOGFILE}" 2>&1
fi
if [ ! -e "/etc/php/$PHPVER/fpm/pool.d/gromox.conf" ]; then
  cp -vf "/usr/share/gromox/fpm-gromox.conf.sample" "/etc/php/$PHPVER/fpm/pool.d/gromox.conf" >>"${LOGFILE}" 2>&1
fi
if [ -e "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-sync.conf" ] && [ ! -e "/etc/php/$PHPVER/fpm/pool.d/pool-grommunio-sync.conf" ]; then
  ln -vs "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-sync.conf" "/etc/php/$PHPVER/fpm/pool.d/" >>"${LOGFILE}" 2>&1
fi
if [ -e "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-dav.conf" ] && [ ! -e "/etc/php/$PHPVER/fpm/pool.d/pool-grommunio-dav.conf" ]; then
  ln -vs "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-dav.conf" "/etc/php/$PHPVER/fpm/pool.d/" >>"${LOGFILE}" 2>&1
fi

writelog "Remove default nginx host config"
rm -vf /etc/nginx/sites-enabled/default >>"${LOGFILE}" 2>&1

writelog "Config stage: gromox config"
setconf /etc/gromox/http.cfg listen_port 10080
setconf /etc/gromox/http.cfg http_support_ssl true
setconf /etc/gromox/http.cfg listen_ssl_port 10443
setconf /etc/gromox/http.cfg host_id "${FQDN}"

setconf /etc/gromox/smtp.cfg listen_port 24

writelog "Config stage: pam config"
progress 30
if [ -e /etc/pam.d/smtp ]; then
  cp -v /etc/pam.d/smtp /etc/pam.d/smtp.save
fi
cat >/etc/pam.d/smtp <<EOF
#%PAM-1.0
auth required pam_gromox.so
account required pam_permit.so service=smtp
EOF

writelog "Config stage: database creation"
progress 40
echo "CREATE DATABASE IF NOT EXISTS grommunio; GRANT ALL ON grommunio.* TO 'grommunio'@'localhost' IDENTIFIED BY '${MYSQL_PASS}';" | mysql
echo "# Do not delete this file unless you know what you do!" >/etc/grommunio-common/setup_done

writelog "Config stage: database configuration"
setconf /etc/gromox/mysql_adaptor.cfg mysql_username "${MYSQL_USER}"
setconf /etc/gromox/mysql_adaptor.cfg mysql_password "${MYSQL_PASS}"
setconf /etc/gromox/mysql_adaptor.cfg mysql_dbname "${MYSQL_DB}"
setconf /etc/gromox/mysql_adaptor.cfg schema_upgrade "host:${FQDN}"

# use system-timezone
TZ="$(readlink /etc/localtime)"
TZ="${TZ#/usr/share/zoneinfo/}"

writelog "Config stage: autodiscover configuration"
progress 50
cat >/etc/gromox/autodiscover.ini <<EOF
[database]
host = ${MYSQL_HOST}
username = '${MYSQL_USER}'
password = '${MYSQL_PASS}'
dbname = '${MYSQL_DB}'

[exchange]
organization = '${X500}'
hostname = ${FQDN}
mapihttp = 1

[default]
timezone = '${TZ}'

[system]

[http-proxy]
/var/lib/gromox/user = ${FQDN}
/var/lib/gromox/domain = ${FQDN}
EOF

cat >/etc/grommunio-admin-api/conf.d/database.yaml <<EOF
DB:
  host: '${MYSQL_HOST}'
  user: '${MYSQL_USER}'
  pass: '${MYSQL_PASS}'
  database: '${MYSQL_DB}'
EOF

writelog "Config stage: database initialization"
gromox-dbop -C >>"${LOGFILE}" 2>&1

writelog "Config stage: admin password set"
progress 60
grommunio-admin passwd --password "${ADMIN_PASS}" >>"${LOGFILE}" 2>&1

rspamadm pw -p "${ADMIN_PASS}" | sed -e 's#^#password = "#' -e 's#$#";#' >/etc/rspamd/local.d/worker-controller.inc

writelog "Add nginx config for rspamd"
cat >/etc/grommunio-admin-common/nginx.d/rspamd.conf <<'EOF'
location /rspamd/ {
    proxy_pass       http://localhost:11334/;
    proxy_set_header Host      $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
EOF

if ! [ -e /etc/gromox/spamrun.cfg ]; then
  cat << EOH > /etc/gromox/spamrun.cfg
# rspamd might run somewhere else and isn't configured as multi-instance
# see rspamc(1) for more options
# RSPAMC_OPTS=( -h a.b.c.d:1234 -P myverysecurepass )
RSPAMC_OPTS=()

# SPAM #
# Only scan messages which are older than n days.
# Default: SPAMRUN_DAYS=7
SPAMRUN_DAYS=7
# Delete the message after we scanned it? 
# Default: SPAMRUN_DELETE=false
SPAMRUN_DELETE=false

# HAM #
# Default: HAMRUN_FOLDER=NON-JUNK
HAMRUN_FOLDER=NON-JUNK
# Delete *copied* Mails which should be learned as HAM?
# Default: HAMRUN_DELETE=false
HAMRUN_DELETE=false
EOH
fi

writelog "Add grommunio-antispam service files"
cat >/lib/systemd/system/grommunio-spam-run.service <<'EOF'
[Unit]
Description=Spam classification, training and cleanup run

[Service]
ProtectSystem=full
ProtectHome=true
PrivateDevices=true
ProtectHostname=true
ProtectClock=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
RestrictRealtime=true
Type=oneshot
ExecStart=/usr/sbin/grommunio-spam-run
EOF

cat >/lib/systemd/system/grommunio-spam-run.timer <<'EOF'
[Unit]
Description=Daily spam classification, training and cleanup run

[Timer]
OnCalendar=daily
AccuracySec=12h
Persistent=true
RandomizedDelaySec=6000

[Install]
WantedBy=timers.target
EOF

cat >/usr/sbin/grommunio-spam-run <<'EOFSPAMRUN'
#!/bin/bash
# vim:ts=2 sts=2 sw=2 expandtab
# Auto Config if not present
if ! [ -e /etc/gromox/spamrun.cfg ]; then
  cat << EOF > /etc/gromox/spamrun.cfg
# rspamd might run somewhere else and isn't configured as multi-instance
# see rspamc(1) for more options
# RSPAMC_OPTS=( -h a.b.c.d:1234 -P myverysecurepass )
RSPAMC_OPTS=()

# Use soft-delete with gromox-mbop delmsg? 
SOFT_DELETE=true

# SPAM #
# Only scan messages which are older than n days.
# Default: SPAMRUN_DAYS=7
SPAMRUN_DAYS=7
# Delete the message after we scanned it? 
# Default: SPAMRUN_DELETE=false
SPAMRUN_DELETE=false

# HAM #
# Default: HAMRUN_FOLDER=TRAIN-HAM
HAMRUN_FOLDER=TRAIN-HAM
# Delete *copied* Mails which should be learned as HAM?
# Default: HAMRUN_DELETE=false
HAMRUN_DELETE=false
EOF
fi

RSPAMC_OPTS=()
SPAMRUN_DAYS=7
SPAMRUN_DELETE=false
if [ -r /etc/gromox/spamrun.cfg ]; then
  . /etc/gromox/spamrun.cfg
fi
if [ -z ${SPAMRUN_DAYS+x} ]; then
  SQLITE_QUERY='select message_id,mid_string from messages where parent_fid=0x17;'
else
read -r -d '' SQLITE_QUERY << EOSQL
SELECT m.message_id,m.mid_string
FROM messages m
INNER JOIN message_properties mp1
ON mp1.message_id = m.message_id
AND mp1.proptag = 235274304
AND (mp1.propval/10000000-11644473600) < unixepoch('now','-$SPAMRUN_DAYS days')
-- DON'T LOOK INTO SUBDIRECTORIES
WHERE m.parent_fid = 0x17
-- DON'T GET SOFTDELETED
AND m.is_deleted = 0
;
EOSQL

fi
# add "-d" to delete junk emails after they have been learned
if [ "$1" = "-d" ]
then
  SPAMRUN_DELETE=true
fi

MYSQL_CFG="/etc/gromox/mysql_adaptor.cfg"
if [ ! -e "${MYSQL_CFG}" ] ; then
  echo "MySQL configuration not found. ($MYSQL_CFG)"
  exit 1
fi
MYSQL_PARAMS="--skip-column-names --skip-line-numbers"
MYSQL_USERNAME=$(sed -ne 's/^mysql_username\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_USERNAME" ]; then
  MYSQL_USERNAME="root"
fi
MYSQL_PASSWORD=$(sed -ne 's/^mysql_password\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
MYSQL_DBNAME=$(sed -ne 's/^mysql_dbname\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_DBNAME" ]; then
  MYSQL_DBNAME="grommunio"
fi
if [ "${MYSQL_DBNAME:0:1}" = "-" ]; then
  echo "Cannot use that dbname: ${MYSQL_DBNAME}"
  exit 1
fi
MYSQL_HOST=$(sed -ne 's/^mysql_host\s*=\s*\(.*\)/-h\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_HOST" ]; then
  MYSQL_HOST="localhost"
fi
MYSQL_QUERY="SELECT username,maildir from users where id <> 0 and maildir <> \"\";"

CONFIG_FILE=$(mktemp)
cat <<CONFFILE >"${CONFIG_FILE}"
[client]
user=${MYSQL_USERNAME}
password='${MYSQL_PASSWORD}'
host=${MYSQL_HOST}
database=${MYSQL_DBNAME}
CONFFILE

cleanup() { rm -f "$CONFIG_FILE" ; }
trap cleanup EXIT

MYSQL_CMD="mysql --defaults-file=${CONFIG_FILE} ${MYSQL_PARAMS}"
# shellcheck disable=SC2068
if ${MYSQL_CMD}<<<"exit"&>/dev/null; then
  ${MYSQL_CMD} --execute "${MYSQL_QUERY}" | while read -r USERNAME MAILDIR; do
  sqlite3 -tabs -noheader "${MAILDIR}/exmdb/exchange.sqlite3" "$SQLITE_QUERY" |
    while read -r MESSAGEID MIDSTRING; do
      MBOP_CMD="$(command -v gromox-mbop)"
      MBOP_CMD="$MBOP_CMD -u "$USERNAME" delmsg"
      if [ $SOFT_DELETE = "true" ]; then
        MBOP_CMD="$MBOP_CMD --soft"
      fi
      echo "Learning spam for user ${USERNAME}" | systemd-cat -t grommunio-spam-run -p info
      MSGFILE="$MAILDIR/eml/$MIDSTRING"
      if [[ ! -f "$MSGFILE" ]]; then
        gromox-exm2eml -u "${USERNAME}" "${MESSAGEID}" 2>/dev/null | rspamc ${RSPAMC_OPTS[@]} learn_spam | systemd-cat -t grommunio-spam-run -p debug
      else
        rspamc ${RSPAMC_OPTS[@]} --header 'Learn-Type: bulk' learn_spam "$MSGFILE" | systemd-cat -t grommunio-spam-run -p debug
      fi
      if [ "${SPAMRUN_DELETE}" = "true" ]; then
        $MBOP_CMD -f 0x17 "${MESSAGEID}" | systemd-cat -t grommunio-spam-run -p notice
      fi
    done
  done
else
  echo "MySQL-Connection couldn't be established, please check your configuration." | systemd-cat -t grommunio-spam-run -p err
fi
EOFSPAMRUN

chmod +x /usr/sbin/grommunio-spam-run

systemctl daemon-reload >>"${LOGFILE}" 2>&1
systemctl enable --now grommunio-spam-run.timer grommunio-spam-run.service >>"${LOGFILE}" 2>&1

writelog "Add grommunio-PROham service files"
cat >/lib/systemd/system/grommunio-ham-run.service <<'EOF'
[Unit]
Description=ham classification, training and cleanup run

[Service]
ProtectSystem=full
ProtectHome=true
PrivateDevices=true
ProtectHostname=true
ProtectClock=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
RestrictRealtime=true
Type=oneshot
ExecStart=/usr/sbin/grommunio-ham-run
EOF

cat >/lib/systemd/system/grommunio-ham-run.timer <<'EOF'
[Unit]
Description=Daily ham classification, training and cleanup run

[Timer]
OnCalendar=*:5/30
AccuracySec=1m
Persistent=true
RandomizedDelaySec=60

[Install]
WantedBy=timers.target
EOF

cat >/usr/sbin/grommunio-ham-run <<'EOFHAMRUN'
#!/bin/bash
# vim:ts=2 sts=2 sw=2 expandtab
# Auto Config if not present
if ! [ -e /etc/gromox/spamrun.cfg ]; then
  cat << EOF > /etc/gromox/spamrun.cfg
# rspamd might run somewhere else and isn't configured as multi-instance
# see rspamc(1) for more options
# RSPAMC_OPTS=( -h a.b.c.d:1234 -P myverysecurepass )
RSPAMC_OPTS=()

# Use soft-delete with gromox-mbop delmsg? 
SOFT_DELETE=true

# SPAM #
# Only scan messages which are older than n days.
# Default: SPAMRUN_DAYS=7
SPAMRUN_DAYS=7
# Delete the message after we scanned it? 
# Default: SPAMRUN_DELETE=false
SPAMRUN_DELETE=false

# HAM #
# Default: HAMRUN_FOLDER=TRAIN-HAM
HAMRUN_FOLDER=TRAIN-HAM
# Delete *copied* Mails which should be learned as HAM?
# Default: HAMRUN_DELETE=false
HAMRUN_DELETE=false
EOF
fi

RSPAMC_OPTS=()
HAMRUN_FOLDER="TRAIN-HAM"
HAMRUN_DELETE=false
if [ -r /etc/gromox/spamrun.cfg ]; then
  . /etc/gromox/spamrun.cfg
fi

# exmdb query
read -r -d '' SQLITE_QUERY << EOSQL
/* GET MESSAGES IN  HAM-FOLDER */
SELECT m.message_id,
m.mid_string,
f.folder_id
FROM messages m
JOIN folders f
ON m.parent_fid = f.folder_id
JOIN folder_properties fp
ON fp.folder_id = f.folder_id
-- SELECT TRAINFOLDER
WHERE lower(fp.propval) = lower('${HAMRUN_FOLDER}')
-- DON'T LOOK INTO SUBDIRECTORIES
AND f.parent_id = 9
-- DON'T GET SOFTDELETED
AND m.is_deleted = 0
;
EOSQL

MYSQL_CFG="/etc/gromox/mysql_adaptor.cfg"
if [ ! -e "${MYSQL_CFG}" ] ; then
  echo "MySQL configuration not found. ($MYSQL_CFG)"
  exit 1
fi
MYSQL_PARAMS="--skip-column-names --skip-line-numbers"
MYSQL_USERNAME=$(sed -ne 's/^mysql_username\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_USERNAME" ]; then
  MYSQL_USERNAME="root"
fi
MYSQL_PASSWORD=$(sed -ne 's/^mysql_password\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
MYSQL_DBNAME=$(sed -ne 's/^mysql_dbname\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_DBNAME" ]; then
  MYSQL_DBNAME="grommunio"
fi
if [ "${MYSQL_DBNAME:0:1}" = "-" ]; then
  echo "Cannot use that dbname: ${MYSQL_DBNAME}"
  exit 1
fi
MYSQL_HOST=$(sed -ne 's/^mysql_host\s*=\s*\(.*\)/-h\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_HOST" ]; then
  MYSQL_HOST="localhost"
fi
MYSQL_QUERY="SELECT username,maildir from users where id <> 0 and maildir <> \"\";"

CONFIG_FILE=$(mktemp)
cat <<CONFFILE >"${CONFIG_FILE}"
[client]
user=${MYSQL_USERNAME}
password='${MYSQL_PASSWORD}'
host=${MYSQL_HOST}
database=${MYSQL_DBNAME}
CONFFILE

cleanup() { rm -f "$CONFIG_FILE" ; }
trap cleanup EXIT

MYSQL_CMD="mysql --defaults-file=${CONFIG_FILE} ${MYSQL_PARAMS}"
# shellcheck disable=SC2068
if ${MYSQL_CMD}<<<"exit"&>/dev/null; then
  ${MYSQL_CMD} --execute "${MYSQL_QUERY}" | while read -r USERNAME MAILDIR; do
  sqlite3 -noheader "${MAILDIR}/exmdb/exchange.sqlite3" "$SQLITE_QUERY" |
    while IFS='|' read -r MESSAGEID MIDSTRING FOLDERID; do
      MBOP_CMD="$(command -v gromox-mbop)"
      MBOP_CMD="$MBOP_CMD -u "$USERNAME" delmsg"
      if [ $SOFT_DELETE = "true" ]; then
        MBOP_CMD="$MBOP_CMD --soft"
      fi
      echo "Learning ham for user ${USERNAME}" | systemd-cat -t grommunio-ham-run -p info
      MSGFILE="$MAILDIR/eml/$MIDSTRING"
      if [[ ! -f "$MSGFILE" ]]; then
        gromox-exm2eml -u "${USERNAME}" "${MESSAGEID}" 2>/dev/null | rspamc ${RSPAMC_OPTS[@]} learn_ham | systemd-cat -t grommunio-ham-run -p debug
      else
        rspamc ${RSPAMC_OPTS[@]} --header 'Learn-Type: bulk' learn_ham "$MSGFILE" | systemd-cat -t grommunio-ham-run -p debug
      fi
      if [ "${HAMRUN_DELETE}" = "true" ]; then
        $MBOP_CMD -f "${FOLDERID}" "${MESSAGEID}" | systemd-cat -t grommunio-ham-run -p notice 
      else
        # At least mark it as read if we don't delete it.
        sqlite3 "${MAILDIR}/exmdb/exchange.sqlite3" "UPDATE messages SET read_state=1 WHERE message_id=$MESSAGEID;"
      fi
    done
  done
else
  echo "MySQL-Connection couldn't be established, please check your configuration." | systemd-cat -t grommunio-ham-run -p err
fi
EOFHAMRUN

chmod +x /usr/sbin/grommunio-ham-run

systemctl daemon-reload >>"${LOGFILE}" 2>&1
systemctl enable --now grommunio-ham-run.timer grommunio-ham-run.service >>"${LOGFILE}" 2>&1

writelog "Configure antivirus in antispam"
cat >/etc/rspamd/local.d/antivirus.conf <<EOF
# local.d/antivirus.conf

# multiple scanners could be checked, for each we create a configuration block with an arbitrary name
# More info: https://rspamd.com/doc/modules/antivirus.html
antivirus {
  # multiple scanners could be checked, for each we create a configuration block with an arbitrary name
  clamav {
    # If set force this action if any virus is found (default unset: no action is forced)
    # action = "reject";
    message = '${SCANNER}: virus found: "${VIRUS}"';
    # Scan mime_parts separately - otherwise the complete mail will be transferred to AV Scanner
    scan_mime_parts = true;
    # Scanning Text is suitable for some av scanner databases (e.g. Sanesecurity)
    scan_text_mime = false;
    scan_image_mime = false;
    # If max_size is set, messages > n bytes in size are not scanned
    #max_size = 20000000;
    # symbol to add (add it to metric if you want non-zero weight)
    symbol = "CLAM_VIRUS";
    # type of scanner: "clamav", "fprot", "sophos" or "savapi"
    type = "clamav";
    # For "savapi" you must also specify the following variable
    #product_id = 12345;
    # You can enable logging for clean messages
    #log_clean = true;
    # servers to query (if port is unspecified, scanner-specific default is used)
    # can be specified multiple times to pool servers
    # can be set to a path to a unix socket
    # Enable this in local.d/antivirus.conf
    servers = "127.0.0.1:3310";
    # if patterns is specified virus name will be matched against provided regexes and the related
    # symbol will be yielded if a match is found. If no match is found, default symbol is yielded.
    #patterns {
      # symbol_name = "pattern";
    #  JUST_EICAR = '^Eicar-Test-Signature$';
    #}
    #patterns_fail {
      # symbol_name = "pattern";
      #CLAM_PROTOCOL_ERROR = '^unhandled response';
    #}
    # whitelist points to a map of signature names. Hits on these signatures are ignored.
    whitelist = "/etc/rspamd/antivirus.wl";
  }
}
EOF

cat >/etc/rspamd/local.d/antivirus_group.conf <<EOF
group "antivirus" {
  symbol "CLAM_VIRUS" {
    weight = 4;
    description = "ClamAV found a Virus";
  }
}
EOF

writelog "Config stage: gromox tls configuration"
setconf /etc/gromox/http.cfg http_certificate_path "${SSL_BUNDLE_T}"
setconf /etc/gromox/http.cfg http_private_key_path "${SSL_KEY_T}"

setconf /etc/gromox/imap.cfg imap_support_starttls true
setconf /etc/gromox/imap.cfg listen_ssl_port 993
setconf /etc/gromox/imap.cfg imap_certificate_path "${SSL_BUNDLE_T}"
setconf /etc/gromox/imap.cfg imap_private_key_path "${SSL_KEY_T}"

setconf /etc/gromox/pop3.cfg pop3_support_stls true
setconf /etc/gromox/pop3.cfg listen_ssl_port 995
setconf /etc/gromox/pop3.cfg pop3_certificate_path "${SSL_BUNDLE_T}"
setconf /etc/gromox/pop3.cfg pop3_private_key_path "${SSL_KEY_T}"

# Domain and X500
writelog "Config stage: gromox domain and x500 configuration"
for SERVICE in http midb zcore imap pop3 smtp delivery; do
  setconf /etc/gromox/${SERVICE}.cfg default_domain "${DOMAIN}"
done
for CFG in midb.cfg zcore.cfg exmdb_local.cfg exmdb_provider.cfg exchange_emsmdb.cfg exchange_nsp.cfg; do
  setconf "/etc/gromox/${CFG}" x500_org_name "${X500}"
done

writelog "Config stage: postfix configuration"
progress 80

cat >/etc/postfix/grommunio-virtual-mailbox-domains.cf <<EOF
user = ${MYSQL_USER}
password = ${MYSQL_PASS}
hosts = ${MYSQL_HOST}
dbname = ${MYSQL_DB}
query = SELECT 1 FROM domains WHERE domain_status=0 AND domainname='%s'
EOF

cat >/etc/postfix/grommunio-virtual-mailbox-alias-maps.cf <<EOF
user = ${MYSQL_USER}
password = ${MYSQL_PASS}
hosts = ${MYSQL_HOST}
dbname = ${MYSQL_DB}
query = SELECT mainname FROM aliases WHERE aliasname='%s'
EOF

cat >/etc/postfix/grommunio-virtual-mailbox-maps.cf <<EOF
user = ${MYSQL_USER}
password = ${MYSQL_PASS}
hosts = ${MYSQL_HOST}
dbname = ${MYSQL_DB}
query = SELECT 1 FROM users WHERE username='%s'
EOF

postconf -e \
  myhostname="${FQDN}" \
  virtual_mailbox_domains="mysql:/etc/postfix/grommunio-virtual-mailbox-domains.cf" \
  virtual_mailbox_maps="mysql:/etc/postfix/grommunio-virtual-mailbox-maps.cf" \
  virtual_alias_maps="mysql:/etc/postfix/grommunio-virtual-mailbox-alias-maps.cf" \
  virtual_transport="smtp:[::1]:24" \
  relayhost="${RELAYHOST}" \
  inet_interfaces=all \
  smtpd_helo_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_invalid_hostname,reject_non_fqdn_hostname \
  smtpd_sender_restrictions=reject_non_fqdn_sender,permit_sasl_authenticated,permit_mynetworks \
  smtpd_recipient_restrictions=permit_sasl_authenticated,permit_mynetworks,reject_unknown_recipient_domain,reject_non_fqdn_hostname,reject_non_fqdn_sender,reject_non_fqdn_recipient,reject_unauth_destination,reject_unauth_pipelining \
  smtpd_data_restrictions=reject_unauth_pipelining \
  smtpd_tls_security_level=may \
  smtpd_tls_auth_only=no \
  smtpd_tls_cert_file="${SSL_BUNDLE_T}" \
  smtpd_tls_key_file="${SSL_KEY_T}" \
  smtpd_tls_received_header=yes \
  smtpd_tls_session_cache_timeout=3600s \
  smtpd_tls_protocols='!SSLv2,!SSLv3,!TLSv1,!TLSv1.1' \
  smtpd_tls_mandatory_protocols='!SSLv2,!SSLv3,!TLSv1,!TLSv1.1' \
  tls_random_source=dev:/dev/urandom \
  smtpd_sasl_auth_enable=yes \
  broken_sasl_auth_clients=yes \
  smtpd_sasl_security_options=noanonymous \
  smtpd_sasl_local_domain= smtpd_milters=inet:localhost:11332 \
  milter_default_action=accept \
  milter_protocol=6
postconf -M tlsmgr/unix="tlsmgr unix - - n 1000? 1 tlsmgr"
postconf -M submission/inet="submission inet n - n - - smtpd"
postconf -P submission/inet/syslog_name="postfix/submission"
postconf -P submission/inet/smtpd_tls_security_level=encrypt
postconf -P submission/inet/smtpd_sasl_auth_enable=yes
postconf -P submission/inet/smtpd_relay_restrictions=permit_sasl_authenticated,reject
postconf -P submission/inet/milter_macro_daemon_name=ORIGINATING
postconf -e 'cyrus_sasl_config_path=/etc/postfix/sasl'
postconf -e 'smtpd_sasl_local_domain=$myhostname'

writelog "Configure sasl smtpd"
mkdir -p "/etc/postfix/sasl"
cat > /etc/postfix/sasl/smtpd.conf <<EOF
pwcheck_method: saslauthd
mech_list: CRAM-MD5 DIGEST-MD5 LOGIN PLAIN
EOF

writelog "Config stage: postfix enable and restart"
systemctl enable --now postfix.service >>"${LOGFILE}" 2>&1
systemctl restart postfix.service >>"${LOGFILE}" 2>&1

writelog "Update sasauthd defaults"
if ! grep -q START=yes /etc/default/saslauthd ; then
  sed -i '0,/^$/s//START=yes/' /etc/default/saslauthd
fi
sed -i '/^OPTIONS/ s/"-c -m \//"-r -c -m \//g' /etc/default/saslauthd
if ! /lib/systemd/systemd-sysv-install is-enabled saslauthd; then
  /lib/systemd/systemd-sysv-install enable saslauthd
fi
systemctl start saslauthd  >>"${LOGFILE}" 2>&1

writelog "Fix log folder rights"
{
chmod -Rfv u=rwX,g=rwX,o=-rwx /var/log/grommunio-dav /var/log/grommunio-sync
chown -Rfv grosync:grosync /var/log/grommunio-sync
chown -Rfv grodav:grodav /var/log/grommunio-dav
chmod -Rfv u=rwX,g=rX,o=-rwx /etc/gromox
chown -Rfv grommunio:gromoxcf /etc/gromox
chown -Rfv grommunio:gromox /var/lib/grommunio-admin-api
} >>"${LOGFILE}" 2>&1

writelog "Enable fetchmail and configure"
setconf /etc/default/fetchmail START_DAEMON yes
systemctl enable --now fetchmail.service >>"${LOGFILE}" 2>&1
systemctl restart --now fetchmail.service >>"${LOGFILE}" 2>&1

# Note: SSH is enabled by Default
writelog "Config stage: open required firewall ports"
{
  firewall-cmd --add-service=https --zone=public --permanent
  firewall-cmd --add-port=25/tcp --zone=public --permanent
  firewall-cmd --add-port=80/tcp --zone=public --permanent
  firewall-cmd --add-port=110/tcp --zone=public --permanent
  firewall-cmd --add-port=143/tcp --zone=public --permanent
  firewall-cmd --add-port=587/tcp --zone=public --permanent
  firewall-cmd --add-port=993/tcp --zone=public --permanent
  firewall-cmd --add-port=8080/tcp --zone=public --permanent
  firewall-cmd --add-port=8443/tcp --zone=public --permanent
  firewall-cmd --reload
} >>"${LOGFILE}" 2>&1

writelog "Fix license import via admin-web-gui"
chown -v grommunio /etc/grommunio-admin-common/license >>"${LOGFILE}" 2>&1

progress 90
writelog "Config stage: restart all required services"
# shellcheck disable=SC2068
systemctl restart saslauthd.service ${SERVICES[@]} >>"${LOGFILE}" 2>&1

# grommunio-admin-api systemd-tmpfiles wrong user for nginx
cp -v /usr/lib/tmpfiles.d/grommunio-admin-api.conf /etc/tmpfiles.d/
sed -i 's/nginx/www-data/g' /etc/tmpfiles.d/grommunio-admin-api.conf
systemd-tmpfiles --create /etc/tmpfiles.d/grommunio-admin-api.conf >>"${LOGFILE}" 2>&1

mv /tmp/config.json /etc/grommunio-admin-common/config.json

# grommunio-admin-api logs
cat > /etc/grommunio-admin-api/conf.d/logs.yaml <<EOF
logs:
  PHP fpm:
    source: php$PHPVER-fpm.service
  Antispam:
    source: rspamd.service
EOF

# grommunio-admin-api add rspamd.service
# sadly it seems we can't remove/overwrite grommunio-antispam.service 
# like with logs.yaml
# NOW WE CAN / or rather know how!
# first we need to clear the data of options.dashboard.services: {}
# https://community.grommunio.com/d/1845-manual-installation-vs-appliance/12
cat > /etc/grommunio-admin-api/conf.d/00-clear-dashboard.yaml <<EOF
options:
  dashboard:
    services: {}
EOF

cat > /etc/grommunio-admin-api/conf.d/services.yaml <<EOF
options:
  dashboard:
    services:
      - unit: gromox-delivery-queue.service
      - unit: gromox-delivery.service
      - unit: gromox-event.service
      - unit: gromox-http.service
      - unit: gromox-imap.service
      - unit: gromox-midb.service
      - unit: gromox-pop3.service
      - unit: gromox-timer.service
      - unit: gromox-zcore.service
      - unit: nginx.service
      - unit: php$PHPVER-fpm.service
      - unit: postfix.service
      - unit: redis-server@grommunio.service
      - unit: rspamd.service
EOF

systemctl restart grommunio-admin-api.service

# apt capture non-finished packages
apt-get install -f

progress 100
writelog "Config stage: completed"
setup_done
