mirror of
https://git.myvelabs.com/lab/myvemail.git
synced 2025-12-17 21:26:14 +00:00
1114 lines
No EOL
40 KiB
Bash
1114 lines
No EOL
40 KiB
Bash
#!/usr/bin/env bash
|
|
set -a
|
|
|
|
# Script is meant for Debian
|
|
hostnamectl | grep -q 'Debian' || exit 1
|
|
|
|
# Insert SSH keys here
|
|
sshkeys=''
|
|
|
|
# Backup mailservers
|
|
backup_mailserver=''
|
|
|
|
# Exit function
|
|
function die
|
|
{
|
|
read -n 1 -s -p $'\n\e[1;33mError encountered, exiting...\e[0m\n'
|
|
exit 1
|
|
}
|
|
|
|
# Grab options
|
|
while [ ${1} != "" ]
|
|
do
|
|
case ${1} in
|
|
-u | --user )
|
|
if [ ${2} != "" ]
|
|
then
|
|
username=${2}
|
|
shift
|
|
fi
|
|
;;
|
|
-p | --port )
|
|
if [ ${2} != "" ]
|
|
then
|
|
ssh_port=${2}
|
|
shift
|
|
fi
|
|
;;
|
|
-d | --domain )
|
|
if [ ${2} != "" ]
|
|
then
|
|
domain=${2}
|
|
shift
|
|
fi
|
|
;;
|
|
-? | -h | --help )
|
|
cat <<HELP
|
|
Parameters:
|
|
-u, --user Unix username
|
|
-p, --port SSH port
|
|
-d, --domain Domain name (eg, mail.web.com)
|
|
-?, -h, --help this help
|
|
HELP
|
|
exit 0
|
|
;;
|
|
* )
|
|
echo "Unknown parameter ${1}" 1>&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
clear
|
|
|
|
# Assign random alternate SSH port
|
|
if [ -z ${ssh_port} ]
|
|
then
|
|
ssh_port=$(shuf -i 10027-65000 -n 1)
|
|
fi
|
|
|
|
# Random username
|
|
if [ -z ${username} ]
|
|
then
|
|
username=$(cat /dev/urandom | tr -d -c 'a-z' | fold -w 8 | head -n 1)
|
|
fi
|
|
|
|
# Domain
|
|
if [ -z ${domain} ]
|
|
then
|
|
echo -e '\e[1;34mType in your full mail domain name (eg. mael.elgoog.com)\e[0m'
|
|
until [ "${domain}" ]
|
|
do
|
|
read -r -p 'Domain name: ' domain
|
|
[ "${domain}" ] || echo -e '\n\e[1;31mDomain name cannot be empty, try again\e[0m'
|
|
done
|
|
echo
|
|
fi
|
|
|
|
# Superuser password
|
|
echo -e '\e[1;34mCreate a root superuser password\e[0m'
|
|
until [ "${rootpass}" = "${rootpass2}" -a "${rootpass}" ]
|
|
do
|
|
read -s -r -p 'Superuser password: ' rootpass
|
|
read -s -r -p $'\nVerify superuser password: ' rootpass2
|
|
if [ -z "${rootpass}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPassword field cannot be empty, try again\e[0m'
|
|
elif [ "${rootpass}" != "${rootpass2}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPasswords did not match, try again\e[0m'
|
|
fi
|
|
done
|
|
printf '%s\n' "${rootpass}" "${rootpass}" | passwd &>/dev/null
|
|
echo -e '\n\n\e[1;32mRoot superuser password has been saved\e[0m\n'
|
|
unset rootpass rootpass2
|
|
|
|
# User password
|
|
echo -e '\e[1;34mSet a password for '"${username}"'\e[0m'
|
|
until [ "${userpass}" = "${userpass2}" -a "${userpass}" ]
|
|
do
|
|
read -s -r -p 'User password: ' userpass
|
|
read -s -r -p $'\nVerify user password: ' userpass2
|
|
if [ -z "${userpass}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPassword field cannot be empty, try again\e[0m'
|
|
elif [ "${userpass}" != "${userpass2}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPasswords did not match, try again\e[0m'
|
|
fi
|
|
done
|
|
printf '%s\n' "${userpass}" "${userpass}" "" "" "" "" "" | adduser ${username} &>/dev/null
|
|
echo -e '\n\n\e[1;32mPassword for '${username}'@'${domain}' -p' ${ssh_port}' has been saved\e[0m\n'
|
|
unset userpass userpass2
|
|
|
|
echo -e '\e[1;34mUpgrading system...\e[0m'
|
|
apt remove -y nano exim* &>/dev/null
|
|
apt update -y || die
|
|
apt upgrade -y || die
|
|
apt dist-upgrade -y || die
|
|
|
|
debconf-set-selections <<< "postfix postfix/mailname string $(echo ${domain} | awk -F . '{print $2}').$(echo ${domain} | awk -F . '{print $3}')"
|
|
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
|
|
apt install -y sudo ufw vim fail2ban wget telnet dnsutils rsyslog zram-tools \
|
|
composer git acl dbconfig-no-thanks \
|
|
nginx certbot python3-certbot-nginx \
|
|
mariadb-server mariadb-client postfix-mysql dovecot-mysql \
|
|
php php-fpm php-imap php-mbstring php-mysql php-json php-curl php-zip php-xml php-bz2 php-intl php-gmp php-net-ldap3 php-imagick php-common php-gd php-sqlite3 php-cli \
|
|
postfix postfix-pcre \
|
|
dovecot-core dovecot-imapd dovecot-lmtpd \
|
|
postfix-policyd-spf-python opendkim opendkim-tools \
|
|
opendmarc || die 'Apt failed'
|
|
|
|
# cron rsyslog
|
|
sed -i 's/#cron/cron/' /etc/rsyslog.conf
|
|
|
|
# ufw firewall
|
|
ufw allow ${ssh_port}/tcp >/dev/null
|
|
yes | ufw enable >/dev/null
|
|
systemctl -q enable --now ufw fail2ban
|
|
|
|
# fail2ban
|
|
tee /etc/fail2ban/jail.d/sshd.conf >/dev/null <<'SSHD'
|
|
[sshd]
|
|
enabled = true
|
|
filter = sshd
|
|
backend = systemd
|
|
maxretry = 5
|
|
findtime = 1d
|
|
bantime = 4w
|
|
ignoreip = 127.0.0.1/8
|
|
SSHD
|
|
install /dev/stdin /usr/local/bin/fail2ban-jails <<'ALL-JAILS'
|
|
#!/bin/bash
|
|
JAILS=$(sudo fail2ban-client status | grep "Jail list" | sed -E 's/^[^:]+:[ \t]+//' | sed 's/,//g')
|
|
for JAIL in $JAILS
|
|
do
|
|
sudo fail2ban-client status $JAIL
|
|
done
|
|
ALL-JAILS
|
|
|
|
# zram swap
|
|
echo -e "ALGO=zstd\nPERCENT=60" >>/etc/default/zramswap
|
|
|
|
# Shut up fstrim
|
|
rm -f /etc/cron.weekly/fstrim &>/dev/null
|
|
|
|
# Hostname and unix users
|
|
hostnamectl set-hostname ${domain}
|
|
sed -i '/127.0.0.1/ s/$/ '${domain}'/' /etc/hosts
|
|
adduser ${username} sudo &>/dev/null
|
|
|
|
# SSH settings
|
|
echo "Port ${ssh_port}
|
|
PermitRootLogin no
|
|
PasswordAuthentication no
|
|
Protocol 2" >/etc/ssh/sshd_config.d/zz-ssh.conf
|
|
|
|
# Disable history saving
|
|
cat >>~/.bashrc <<EOF
|
|
|
|
if [ -f ~/.bash_history ]
|
|
then
|
|
rm -f ~/.bash_history
|
|
fi
|
|
|
|
unset HISTFILE
|
|
history -c
|
|
EOF
|
|
|
|
if hostname | grep -q "${domain}" && grep -q "${domain}" /etc/hosts
|
|
then
|
|
install /dev/stdin /usr/local/bin/mail-server <<MAILSERVER
|
|
#!/usr/bin/env bash
|
|
|
|
# Backup mailservers
|
|
backup_mailserver=(${backup_mailserver})
|
|
MAILSERVER
|
|
|
|
tee -a /usr/local/bin/mail-server >/dev/null <<'MAILSERVER'
|
|
|
|
# UFW
|
|
sudo ufw allow 25/tcp &>/dev/null
|
|
sudo ufw allow 80,443/tcp >/dev/null
|
|
sudo ufw allow 587/tcp >/dev/null
|
|
sudo ufw allow 143,993/tcp >/dev/null
|
|
|
|
# Check port 25
|
|
echo
|
|
if ! grep -q 'Connected to' <<< $(printf 'quit' | telnet -4 gmail-smtp-in.l.google.com 25)
|
|
then
|
|
echo -e '\n\e[1;31mPort 25 needs to be open for mail server installation to continue, exiting...\e[0m\n'
|
|
exit
|
|
fi
|
|
|
|
# Exit function
|
|
function die
|
|
{
|
|
read -n 1 -s -p $'\n\e[1;33mError encountered, exiting...\e[0m\n'
|
|
exit 1
|
|
}
|
|
|
|
# Static variables
|
|
ip_addr=$(wget -q4O- ipv4.icanhazip.com)
|
|
subdomain=$(hostname | awk -F . '{print $1}')
|
|
domain="$(hostname | awk -F . '{print $2}').$(hostname | awk -F . '{print $3}')"
|
|
eff_email='eff@'${domain}
|
|
roundcubedbpass=$(cat /dev/urandom | tr -d -c 'a-zA-Z0-9' | fold -w 128 | head -n 1)
|
|
postfixadmindbpass=$(cat /dev/urandom | tr -d -c 'a-zA-Z0-9' | fold -w 128 | head -n 1)
|
|
roundcubepass_strength_drive=$(cat /dev/urandom | tr -d -c 'a-z' | fold -w 8 | head -n 1)
|
|
|
|
# Exit if static variable is null
|
|
if [ -z ${ip_addr} ] || [ -z ${subdomain} ] || [ -z ${domain} ] || [ -z ${eff_email} ]
|
|
then
|
|
die 'A static variable is nonexistent'
|
|
fi
|
|
|
|
clear
|
|
|
|
# Activate sudo
|
|
if sudo -v
|
|
then
|
|
until [[ ${proceed} = [yY] ]]
|
|
do
|
|
unset proceed
|
|
echo -e '\e[1;34mHit "y" to proceed with installation\e[0m'
|
|
read -n 1 -s -p $'\e[3m# If transferring mail servers to another provider, backup mail through Thunderbird or other IMAP clients before pressing any key to proceed\e[0m\n' proceed
|
|
echo
|
|
done
|
|
else
|
|
echo -e '\e[1;31mActivate sudo before running script\e[0m\n'
|
|
exit
|
|
fi
|
|
|
|
# Dovecot
|
|
cd ~
|
|
sudo mkdir -p /usr/share/dovecot /usr/share/webapps
|
|
sudo touch /usr/share/dovecot/dh.pem
|
|
|
|
# Mail username
|
|
echo -e '\e[1;34mType in your email username\e[0m'
|
|
until [ ${mailuser} ]
|
|
do
|
|
read -r -p 'Username: ' mailuser
|
|
[ ${mailuser} ] || echo -e '\n\e[1;31mUsername cannot be empty, try again\e[0m'
|
|
done
|
|
echo -e '\n\e[1;32mMail user '${mailuser}'@'${domain}' has been saved\e[0m'
|
|
|
|
# Postfixadmin password
|
|
echo -e '\n\e[1;34mCreate a postfixadmin setup password\e[0m'
|
|
until [ "${postfixadminpass}" = "${postfixadminpass2}" -a "${postfixadminpass}" ]
|
|
do
|
|
read -s -r -p 'Postfixadmin password: ' postfixadminpass
|
|
read -s -r -p $'\nVerify Postfixadmin password: ' postfixadminpass2
|
|
if [ -z "${postfixadminpass}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPassword field cannot be empty, try again\e[0m'
|
|
elif [ "${postfixadminpass}" != "${postfixadminpass2}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPasswords did not match, try again\e[0m'
|
|
fi
|
|
done
|
|
echo -e '\n\n\e[1;32mPostfixadmin password has been saved\e[0m'
|
|
|
|
# Mail account password
|
|
echo -e '\n\e[1;34mCreate a password for your mail account\e[0m'
|
|
until [ "${mailpass}" = "${mailpass2}" -a "${mailpass}" ]
|
|
do
|
|
read -s -r -p 'Mail password: ' mailpass
|
|
read -s -r -p $'\nVerify mail password: ' mailpass2
|
|
if [ -z "${mailpass}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPassword field cannot be empty, try again\e[0m'
|
|
elif [ "${mailpass}" != "${mailpass2}" ]
|
|
then
|
|
echo -e '\n\n\e[1;31mPasswords did not match, try again\e[0m'
|
|
fi
|
|
done
|
|
echo -e '\n\n\e[1;32mMail password has been saved\e[0m\n'
|
|
|
|
# fail2ban
|
|
sudo tee /etc/fail2ban/jail.d/postfix.local >/dev/null <<'POSTFIX-FLOOD-ATTACK'
|
|
[postfix-flood-attack]
|
|
enabled = true
|
|
bantime = 12h
|
|
filter = postfix-flood-attack
|
|
action = iptables-multiport[name=postfix, port="http,https,smtp,submission,pop3,pop3s,imap,imaps,sieve", protocol=tcp]
|
|
logpath = /var/log/mail.log
|
|
|
|
[postfix]
|
|
enabled = true
|
|
maxretry = 3
|
|
bantime = 12h
|
|
filter = postfix
|
|
logpath = /var/log/mail.log
|
|
POSTFIX-FLOOD-ATTACK
|
|
|
|
sudo tee /etc/fail2ban/filter.d/postfix-flood-attack.conf >/dev/null <<'POSTFIX-FLOOD-ATTACK'
|
|
[Definition]
|
|
failregex = lost connection after AUTH from (.*)\[<HOST>\]
|
|
ignoreregex =
|
|
POSTFIX-FLOOD-ATTACK
|
|
sudo systemctl -q restart fail2ban.service
|
|
|
|
# One last update before installing packages
|
|
echo -e '\e[1;34mInstalling required packages\e[5m...\e[0m'
|
|
sudo apt update -y &&
|
|
sudo apt upgrade -y
|
|
|
|
# PHP
|
|
sudo sed -i -e 's/^upload_max_filesize =.*/upload_max_filesize = 0/g' -e 's/^post_max_size =.*/post_max_size = 0/g' -e 's/^memory_limit =.*/memory_limit = 4096M/g' $(find /etc/php -name 'php.ini' | grep fpm)
|
|
|
|
# Download Postfixadmin and Roundcube
|
|
sudo mkdir -p /usr/share/webapps/{roundcube,postfixadmin}
|
|
wget -q4 https://github.com/postfixadmin/postfixadmin/archive/refs/tags/$(wget -q4O- https://api.github.com/repos/postfixadmin/postfixadmin/releases/latest | grep tag_name | awk '{print $2}' | tr -d '"|,').tar.gz -O postfixadmin.tar.gz || die
|
|
wget -q4 $(wget -q4O- https://api.github.com/repos/roundcube/roundcubemail/releases/latest | grep 'complete.tar.gz"$' | awk '{print $2}' | tr -d '"|,') -O roundcubemail.tar.gz || die
|
|
sudo tar zxf roundcubemail.tar.gz -C /usr/share/webapps/roundcube --strip-components 1
|
|
sudo tar zxf postfixadmin.tar.gz -C /usr/share/webapps/postfixadmin --strip-components 1
|
|
rm *.tar.gz
|
|
|
|
# Postfixadmin
|
|
echo -e '\n\e[1;34mInstalling Postfixadmin\e[0m'
|
|
cd /usr/share/webapps/postfixadmin
|
|
# Postfixadmin composer
|
|
wget -q4O- https://raw.githubusercontent.com/postfixadmin/postfixadmin/master/install.sh | sudo COMPOSER_ALLOW_SUPERUSER=1 bash -
|
|
sudo setfacl -R -m u:www-data:rwx templates_c/
|
|
|
|
# Roundcube
|
|
echo -e '\e[1;34mInstalling Roundcube\e[0m'
|
|
# Roundcube composer
|
|
cd /usr/share/webapps/roundcube
|
|
sudo COMPOSER_ALLOW_SUPERUSER=1 composer -n update --no-dev
|
|
sudo COMPOSER_ALLOW_SUPERUSER=1 composer -n install --no-dev
|
|
sudo chown www-data:www-data temp/ logs/ -R
|
|
|
|
# Postwhite
|
|
cd /usr/local/bin
|
|
sudo git clone --quiet https://github.com/spf-tools/spf-tools.git
|
|
sudo git clone --quiet https://github.com/stevejenkins/postwhite.git
|
|
sudo cp /usr/local/bin/postwhite/postwhite.conf /etc
|
|
cd
|
|
|
|
# Install MariaDB
|
|
echo -e '\n\e[1;34mInstalling MariaDB\e[0m'
|
|
printf '%s\n' "" "n" "y" "${postfixadminpass}" "${postfixadminpass}" "" "" "" "" | sudo mysql_secure_installation &>/dev/null
|
|
|
|
# Roundcube database
|
|
sudo mysql -u root <<ROUNDCUBE
|
|
CREATE DATABASE roundcubemail CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
GRANT ALL PRIVILEGES ON roundcubemail.* TO 'roundcube'@'localhost' IDENTIFIED BY '${roundcubedbpass}';
|
|
flush privileges;
|
|
ROUNDCUBE
|
|
sudo mysql roundcubemail </usr/share/webapps/roundcube/SQL/mysql.initial.sql
|
|
|
|
# Postfixadmin database
|
|
sudo mysql -u root <<POSTFIXADMIN
|
|
CREATE DATABASE postfixadmin;
|
|
GRANT ALL PRIVILEGES ON postfixadmin.* to 'postfixadmin'@'localhost' IDENTIFIED BY '${postfixadmindbpass}';
|
|
flush privileges;
|
|
POSTFIXADMIN
|
|
|
|
sudo systemctl -q restart mariadb
|
|
|
|
# Roundcube config setup
|
|
echo -e '\n\e[1;34mConfiguring Roundcube webmail\e[0m'
|
|
echo "<?php
|
|
\$config['db_dsnw'] = 'mysql://roundcube:${roundcubedbpass}@localhost/roundcubemail';
|
|
|
|
\$config['imap_host'] = 'ssl://${subdomain}.${domain}';
|
|
\$config['default_port'] = 993;
|
|
|
|
\$config['smtp_host'] = 'tls://${subdomain}.${domain}';
|
|
\$config['product_name'] = '${subdomain}.${domain}';
|
|
|
|
\$config['create_default_folders'] = true;
|
|
\$config['support_url'] = '';
|
|
|
|
\$config['des_key'] = '$(cat /dev/urandom | tr -d -c 'a-zA-Z0-9' | fold -w 24 | head -n 1)';
|
|
|
|
\$config['plugins'] = [$(printf "'%s', " $(ls /usr/share/webapps/roundcube/plugins | grep -v 'enigma\|database_attachments\|managesieve') | sed "s/\(.*\), /\1/")];" | sudo tee /usr/share/webapps/roundcube/config/config.inc.php >/dev/null
|
|
|
|
# Roundcube password plugin
|
|
sudo cp /usr/share/webapps/roundcube/plugins/password/config.inc.php.dist /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
|
|
sudo sed -i "/^\$config\['password_db_dsn'\]/ s|=.*|= 'mysql://postfixadmin:${postfixadmindbpass}@localhost/postfixadmin';|" /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
sudo sed -i "/^\$config\['password_query'\]/ s/=.*/= 'UPDATE mailbox SET password=%P,modified=NOW() WHERE username=%u';/" /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
sudo sed -i "/^\$config\['password_strength_driver'\]/ s/=.*/= '${roundcubepass_strength_drive}';\\
|
|
\$config['password_"${roundcubepass_strength_drive}"_min_score'] = 5;/" /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
sudo sed -i "/^\$config\['password_algorithm'\]/ s/=.*/= 'dovecot';/" /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
sudo sed -i "/^\$config\['password_dovecotpw'\]/ s|=.*|= '/usr/bin/doveadm pw -r 5';|" /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
sudo sed -i "/^\$config\['password_dovecotpw_method'\]/ s/=.*/= 'ARGON2I';/" /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
sudo sed -i "/^\$config\['password_dovecotpw_with_method'\]/ s/=.*/= true;/" /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
|
|
sudo rm /usr/share/webapps/roundcube/installer/ -r
|
|
sudo chown www-data:www-data /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
sudo chmod 600 /usr/share/webapps/roundcube/plugins/password/config.inc.php
|
|
|
|
# Postfixadmin config setup
|
|
# https://git.banananet.work/banananetwork/postfixadmin/raw/commit/864065cd37ef34b6dab915206eea4bd2ac4ebaed/config.inc.php
|
|
echo -e '\e[1;34mCreating mail users\e[0m'
|
|
echo -e '<?php
|
|
$CONF['\''configured'\''] = true;
|
|
$CONF['\''database_type'\''] = '\''mysqli'\'';
|
|
$CONF['\''database_host'\''] = '\''localhost'\'';
|
|
$CONF['\''database_port'\''] = '\''3306'\'';
|
|
$CONF['\''database_user'\''] = '\''postfixadmin'\'';
|
|
$CONF['\''database_password'\''] = '\'${postfixadmindbpass}\'';
|
|
$CONF['\''database_name'\''] = '\''postfixadmin'\'';
|
|
$CONF['\''encrypt'\''] = '\''dovecot:ARGON2I'\'';
|
|
$CONF['\''dovecotpw'\''] = "/usr/bin/doveadm pw -r 5";
|
|
if(@file_exists('\''/usr/bin/doveadm'\'')) { // @ to silence openbase_dir stuff; see https://github.com/postfixadmin/postfixadmin/issues/171
|
|
$CONF['\''dovecotpw'\''] = "/usr/bin/doveadm pw -r 5"; # debian
|
|
}
|
|
|
|
$CONF['\''default_aliases'\''] = array (
|
|
'\''root'\'' => '\''postmaster@'${domain}''\'',
|
|
'\''eff'\'' => '\''postmaster@'${domain}''\'',
|
|
'\''dmarc'\'' => '\''postmaster@'${domain}''\'',
|
|
);
|
|
|
|
$CONF['\''password_validation'\''] = array(
|
|
# # '\''/regular expression/'\'' => '\''$PALANG key (optional: + parameter)'\'',
|
|
# '\''/.{5}/'\'' => '\''password_too_short 5'\'', # minimum length 5 characters
|
|
# '\''/([a-zA-Z].*){3}/'\'' => '\''password_no_characters 3'\'', # must contain at least 3 characters
|
|
# '\''/([0-9].*){2}/'\'' => '\''password_no_digits 2'\'', # must contain at least 2 digits
|
|
);
|
|
|
|
$CONF['\''fetchmail'\''] = '\''NO'\'';
|
|
$CONF['\''show_footer_text'\''] = '\''NO'\'';
|
|
|
|
$CONF['\''quota'\''] = '\''YES'\'';
|
|
$CONF['\''domain_quota'\''] = '\''YES'\'';
|
|
$CONF['\''quota_multiplier'\''] = '\''1024000'\'';
|
|
$CONF['\''used_quotas'\''] = '\''YES'\'';
|
|
$CONF['\''new_quota_table'\''] = '\''YES'\'';
|
|
|
|
$CONF['\''aliases'\''] = '\''0'\'';
|
|
$CONF['\''mailboxes'\''] = '\''0'\'';
|
|
$CONF['\''maxquota'\''] = '\''0'\'';
|
|
$CONF['\''domain_quota_default'\''] = '\''0'\'';
|
|
$CONF['\''password_expiration'\''] = '\''NO'\'';
|
|
|
|
# Postfixadmin hash
|
|
$CONF['\''setup_password'\''] = '\'$(sudo php -r "echo password_hash('${postfixadminpass}', PASSWORD_DEFAULT);")\'';' | sudo tee /usr/share/webapps/postfixadmin/config.local.php >/dev/null
|
|
|
|
# Update Postfixadmin databases
|
|
# https://git.banananet.work/banananetwork/postfixadmin/raw/commit/864065cd37ef34b6dab915206eea4bd2ac4ebaed/config.inc.php
|
|
sudo -u www-data php /usr/share/webapps/postfixadmin/public/upgrade.php
|
|
|
|
# Create Postfixadmin domain
|
|
sudo bash /usr/share/webapps/postfixadmin/scripts/postfixadmin-cli domain add "${domain}" --aliases 0 --mailboxes 0 --maxquota 0 --quota 0 --active --default-aliases -q
|
|
|
|
# Create Postfixadmin admin
|
|
sudo bash /usr/share/webapps/postfixadmin/scripts/postfixadmin-cli admin add "postmaster@${domain}" --superadmin --active --domains "${domain}" --password "${postfixadminpass}" --password2 "${postfixadminpass}" -q
|
|
|
|
# Create Postfixadmin mail users
|
|
sudo bash /usr/share/webapps/postfixadmin/scripts/postfixadmin-cli mailbox add "postmaster@${domain}" --active --password "${postfixadminpass}" --password2 "${postfixadminpass}" -q
|
|
sudo bash /usr/share/webapps/postfixadmin/scripts/postfixadmin-cli mailbox add "${mailuser}@${domain}" --active --password "${mailpass}" --password2 "${mailpass}" -q
|
|
|
|
# Create Postfixadmin mail catch-all alias
|
|
sudo bash /usr/share/webapps/postfixadmin/scripts/postfixadmin-cli alias add "*@${domain}" --goto "${mailuser}@${domain}" --active -q
|
|
|
|
unset mailuser postfixadminpass postfixadminpass2 mailpass mailpass2 roundcubedbpass roundcubepass_strength_drive
|
|
echo
|
|
|
|
# Autorestart services
|
|
sudo mkdir -p /etc/systemd/system/{dovecot,postfix}.service.d
|
|
sudo tee /etc/systemd/system/dovecot.service.d/restart.conf >/dev/null <<'RESTART'
|
|
[Service]
|
|
Restart=always
|
|
RestartSec=5s
|
|
RESTART
|
|
sudo tee /etc/systemd/system/postfix.service.d/restart.conf >/dev/null <<'RESTART'
|
|
[Service]
|
|
Restart=on-failure
|
|
RestartSec=5s
|
|
RESTART
|
|
sudo systemctl -q daemon-reload
|
|
|
|
# Postfix
|
|
# sudo postconf myhostname alias_maps alias_database myorigin mydestination relayhost mynetworks mailbox_size_limit recipient_delimiter inet_interfaces inet_protocols
|
|
# cat /etc/mailname
|
|
echo -e '\e[1;34mConfiguring Postfix\e[0m'
|
|
echo ${domain} | sudo tee /etc/mailname >/dev/null
|
|
sudo postconf -e "myhostname = ${subdomain}.${domain}"
|
|
sudo postconf -e 'relay_domains = $mydestination'
|
|
sudo postconf -e 'smtp_tls_security_level = may'
|
|
sudo postconf -e 'smtp_tls_loglevel = 1'
|
|
sudo postconf -e 'smtpd_tls_security_level = may'
|
|
sudo postconf -e 'smtpd_tls_loglevel = 1'
|
|
sudo postconf -e 'mailbox_size_limit = 0'
|
|
sudo postconf -e 'message_size_limit = 0'
|
|
sudo postconf -e "authorized_submit_users = root,www-data,${USER}"
|
|
|
|
sudo postconf -e 'smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache'
|
|
sudo postconf -e 'smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache'
|
|
|
|
sudo postconf -e 'smtp_tls_note_starttls_offer = yes'
|
|
sudo postconf -e 'smtpd_tls_received_header = yes'
|
|
|
|
sudo postconf -e 'inet_interfaces = all'
|
|
# sudo postconf -e ' inet_interfaces = 127.0.0.1'
|
|
sudo postconf -e 'inet_protocols = ipv4'
|
|
sudo postconf -e 'smtp_address_preference = ipv4'
|
|
sudo postconf -e "mydomain = ${domain}"
|
|
sudo postconf -e 'myorigin = $mydomain'
|
|
sudo postconf -e 'mydestination = $myhostname, localhost.$mydomain, localhost'
|
|
|
|
if [ ${backup_mailserver} ]
|
|
then
|
|
sudo postconf -e "$(sudo postconf mynetworks)$(printf ' %s/32' ${backup_mailserver[@]})"
|
|
sudo postconf -e "smtp_fallback_relay =$(printf ' [%s]:25' ${backup_mailserver[@]})"
|
|
fi
|
|
|
|
# main.cf
|
|
echo -e '\n# Enforce TLSv1.3 or TLSv1.2
|
|
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
|
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
|
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
|
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
|
|
|
|
# Virtual mailboxes
|
|
mailbox_transport = lmtp:unix:private/dovecot-lmtp
|
|
smtputf8_enable = no
|
|
|
|
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
|
|
virtual_mailbox_maps =
|
|
proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf,
|
|
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
|
|
virtual_alias_maps =
|
|
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf,
|
|
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf,
|
|
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
|
|
|
|
virtual_transport = lmtp:unix:private/dovecot-lmtp
|
|
|
|
virtual_mailbox_base = /var/vmail
|
|
virtual_minimum_uid = 600
|
|
virtual_uid_maps = static:600
|
|
virtual_gid_maps = static:600
|
|
virtual_mailbox_limit = 0
|
|
|
|
smtp_header_checks = pcre:/etc/postfix/smtp_header_checks
|
|
|
|
# SPF and DKIM checks
|
|
policyd-spf_time_limit = 3600
|
|
smtpd_recipient_restrictions =
|
|
permit_mynetworks,
|
|
permit_sasl_authenticated,
|
|
reject_unauth_destination,
|
|
check_policy_service unix:private/policyd-spf,
|
|
check_client_access hash:/etc/postfix/rbl_override,
|
|
reject_rhsbl_helo dbl.spamhaus.org,
|
|
reject_rhsbl_reverse_client dbl.spamhaus.org,
|
|
reject_rhsbl_sender dbl.spamhaus.org
|
|
|
|
# Milter configuration
|
|
milter_default_action = accept
|
|
milter_protocol = 6
|
|
smtpd_milters = local:opendkim/opendkim.sock
|
|
non_smtpd_milters = $smtpd_milters
|
|
|
|
# Blocking spam
|
|
smtpd_sender_restrictions =
|
|
permit_mynetworks
|
|
permit_sasl_authenticated
|
|
reject_unknown_sender_domain
|
|
reject_unknown_reverse_client_hostname
|
|
reject_unknown_client_hostname
|
|
smtpd_helo_required = yes
|
|
smtpd_helo_restrictions =
|
|
permit_mynetworks
|
|
permit_sasl_authenticated
|
|
check_helo_access hash:/etc/postfix/helo_access
|
|
reject_invalid_helo_hostname
|
|
reject_non_fqdn_helo_hostname
|
|
reject_unknown_helo_hostname
|
|
|
|
# Postscreen spambots
|
|
postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr cidr:/etc/postfix/postscreen_spf_whitelist.cidr
|
|
postscreen_blacklist_action = drop
|
|
|
|
postscreen_greet_action = enforce
|
|
|
|
postscreen_dnsbl_threshold = 3
|
|
postscreen_dnsbl_action = enforce
|
|
postscreen_dnsbl_sites =
|
|
zen.spamhaus.org*3
|
|
bl.spameatingmonkey.net*2
|
|
bl.spamcop.net
|
|
dnsbl.sorbs.net
|
|
|
|
postscreen_dnsbl_whitelist_threshold = -2
|
|
|
|
header_checks = pcre:/etc/postfix/header_checks
|
|
body_checks = pcre:/etc/postfix/body_checks' | sudo tee -a /etc/postfix/main.cf >/dev/null
|
|
|
|
# master.cf
|
|
sudo sed -i 's/smtp .*smtpd/# &/' /etc/postfix/master.cf
|
|
sudo sed -i '/#smtp\|#smtpd\|#dnsblog\|#tlsproxy/ s/^#//' /etc/postfix/master.cf
|
|
|
|
echo -e '\n# Enable submission
|
|
submission inet n - y - - smtpd
|
|
-o syslog_name=postfix/submission
|
|
-o smtpd_tls_security_level=encrypt
|
|
-o smtpd_tls_wrappermode=no
|
|
-o smtpd_sasl_auth_enable=yes
|
|
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
|
|
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
|
|
-o smtpd_sasl_type=dovecot
|
|
-o smtpd_sasl_path=private/auth
|
|
|
|
# SPF Policy
|
|
policyd-spf unix - n n - 0 spawn
|
|
user=policyd-spf argv=/usr/bin/policyd-spf' | sudo tee -a /etc/postfix/master.cf >/dev/null
|
|
|
|
# Deleting Email Headers For Outgoing Emails
|
|
echo -e '/^X-Spam-Status:/ IGNORE
|
|
/^X-Spam-Checker-Version:/ IGNORE
|
|
/^Received:.*/ IGNORE
|
|
/^User-Agent:.*/ IGNORE' | sudo tee /etc/postfix/smtp_header_checks >/dev/null
|
|
|
|
# Header checks
|
|
echo "/free mortgage quote/ DISCARD
|
|
/repair your credit/ DISCARD
|
|
/lose weight/ DISCARD
|
|
/To:.*(gmail.com|yahoo.com|outlook|hotmail.com).*${mailuser}@${domain}/ DISCARD
|
|
/To:.*${mailuser}@${domain}.*(gmail.com|yahoo.com|outlook|hotmail.com)/ DISCARD
|
|
/Cc:.*(gmail.com|yahoo.com|outlook|hotmail.com).*${mailuser}@${domain}/ DISCARD
|
|
/Cc:.*${mailuser}@${domain}.*(gmail.com|yahoo.com|outlook|hotmail.com)/ DISCARD
|
|
/To:.*<>/ DISCARD
|
|
/From:.*<>/ DISCARD" | sudo tee -a /etc/postfix/header_checks >/dev/null
|
|
|
|
# Body checks
|
|
echo "/free mortgage quote/ DISCARD
|
|
/repair your credit/ DISCARD
|
|
/lose weight/ DISCARD" | sudo tee -a /etc/postfix/body_checks >/dev/null
|
|
|
|
echo -e "# Permit my own IP addresses
|
|
${ip_addr}/32\tpermit" | sudo tee /etc/postfix/postscreen_access.cidr >/dev/null
|
|
|
|
# Blocking Email Spam with Postfix
|
|
echo -e "${domain} OK" | sudo tee /etc/postfix/{helo_access,rbl_override} >/dev/null
|
|
|
|
# Virtual mailboxes
|
|
sudo mkdir -p /etc/postfix/sql
|
|
|
|
sudo tee /etc/postfix/sql/mysql_virtual_domains_maps.cf >/dev/null <<EOF
|
|
user = postfixadmin
|
|
password = ${postfixadmindbpass}
|
|
hosts = localhost
|
|
dbname = postfixadmin
|
|
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
|
|
#query = SELECT domain FROM domain WHERE domain='%s'
|
|
#optional query to use when relaying for backup MX
|
|
#query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
|
|
#expansion_limit = 100
|
|
EOF
|
|
|
|
sudo tee /etc/postfix/sql/mysql_virtual_mailbox_maps.cf >/dev/null <<EOF
|
|
user = postfixadmin
|
|
password = ${postfixadmindbpass}
|
|
hosts = localhost
|
|
dbname = postfixadmin
|
|
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
|
|
#expansion_limit = 100
|
|
EOF
|
|
|
|
sudo tee /etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf >/dev/null <<EOF
|
|
user = postfixadmin
|
|
password = ${postfixadmindbpass}
|
|
hosts = localhost
|
|
dbname = postfixadmin
|
|
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
|
|
EOF
|
|
|
|
sudo tee /etc/postfix/sql/mysql_virtual_alias_maps.cf >/dev/null <<EOF
|
|
user = postfixadmin
|
|
password = ${postfixadmindbpass}
|
|
hosts = localhost
|
|
dbname = postfixadmin
|
|
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
|
|
#expansion_limit = 100
|
|
EOF
|
|
|
|
sudo tee /etc/postfix/sql/mysql_virtual_alias_domain_maps.cf >/dev/null <<EOF
|
|
user = postfixadmin
|
|
password = ${postfixadmindbpass}
|
|
hosts = localhost
|
|
dbname = postfixadmin
|
|
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
|
|
EOF
|
|
|
|
sudo tee /etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf >/dev/null <<eof
|
|
# handles catch-all settings of target-domain
|
|
user = postfixadmin
|
|
password = ${postfixadmindbpass}
|
|
hosts = localhost
|
|
dbname = postfixadmin
|
|
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
|
|
eof
|
|
|
|
sudo chmod 0640 /etc/postfix/sql/*
|
|
sudo setfacl -R -m u:postfix:rx /etc/postfix/sql/
|
|
|
|
sudo adduser vmail --system --group --uid 600 --disabled-login --no-create-home >/dev/null
|
|
sudo mkdir -p /var/vmail
|
|
sudo chown vmail:vmail /var/vmail/ -R
|
|
|
|
sudo sed -i 's/#!include auth-sql.conf.ext/!include auth-sql.conf.ext/' /etc/dovecot/conf.d/10-auth.conf
|
|
sudo sed -i 's/!include auth-system.conf.ext/#&/' /etc/dovecot/conf.d/10-auth.conf
|
|
echo -e '\nauth_debug = yes
|
|
auth_debug_passwords = yes' | sudo tee -a /etc/dovecot/conf.d/10-auth.conf >/dev/null
|
|
|
|
sudo tee -a /etc/dovecot/dovecot-sql.conf.ext >/dev/null <<eof
|
|
|
|
# Virtual mailboxes
|
|
driver = mysql
|
|
connect = host=localhost dbname=postfixadmin user=postfixadmin password=${postfixadmindbpass}
|
|
default_pass_scheme = ARGON2I
|
|
password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'
|
|
user_query = SELECT maildir, 600 AS uid, 600 AS gid FROM mailbox WHERE username = '%u' AND active='1'
|
|
iterate_query = SELECT username AS user FROM mailbox
|
|
eof
|
|
|
|
unset postfixadmindbpass
|
|
|
|
sudo postmap /etc/postfix/helo_access /etc/postfix/rbl_override /etc/postfix/smtp_header_checks /etc/postfix/header_checks /etc/postfix/body_checks /etc/postfix/postscreen_access.cidr
|
|
|
|
# Run postwhite installer
|
|
echo -e '\e[1;34mInstalling Postwhite\e[0m'
|
|
sudo /usr/local/bin/postwhite/postwhite
|
|
|
|
# Dovecot
|
|
echo -e '\n\e[1;34mConfiguring Dovecot\e[0m'
|
|
echo -e '\nprotocols = imap lmtp' | sudo tee -a /etc/dovecot/dovecot.conf >/dev/null
|
|
|
|
sudo sed -i 's|^mail_location =.*|mail_location = maildir:~/Maildir\
|
|
'"$(if ! grep -q '^mail_home = /var/vmail/%d/%n/' /etc/dovecot/conf.d/10-mail.conf
|
|
then
|
|
echo 'mail_home = /var/vmail/%d/%n/'
|
|
fi)"'|g' /etc/dovecot/conf.d/10-mail.conf
|
|
|
|
sudo sed -i 's|unix_listener lmtp {|unix_listener /var/spool/postfix/private/dovecot-lmtp {\
|
|
mode = 0600\
|
|
user = postfix\
|
|
group = postfix|' /etc/dovecot/conf.d/10-master.conf
|
|
sudo sed -i 's|unix_listener auth-userdb {|unix_listener /var/spool/postfix/private/auth {\
|
|
mode = 0660\
|
|
user = postfix\
|
|
group = postfix|' /etc/dovecot/conf.d/10-master.conf
|
|
sudo sed -i '/#disable_plaintext_auth/ s/^#//' /etc/dovecot/conf.d/10-auth.conf
|
|
sudo sed -i 's/#auth_username_format = %Lu/auth_username_format = %u/' /etc/dovecot/conf.d/10-auth.conf
|
|
|
|
sudo sed -i 's/#auth_default_realm.*/auth_default_realm = '${domain}'/' /etc/dovecot/conf.d/10-auth.conf
|
|
|
|
sudo sed -i 's/auth_mechanisms = plain/& login/' /etc/dovecot/conf.d/10-auth.conf
|
|
sudo sed -i 's/ssl = yes/ssl = required/' /etc/dovecot/conf.d/10-ssl.conf
|
|
sudo sed -i 's/#ssl_prefer_server_ciphers = no/ssl_prefer_server_ciphers = yes/' /etc/dovecot/conf.d/10-ssl.conf
|
|
sudo sed -i 's/#ssl_min_protocol =.*/ssl_min_protocol = TLSv1.2/' /etc/dovecot/conf.d/10-ssl.conf
|
|
echo -e '\nservice stats {
|
|
unix_listener stats-reader {
|
|
user = www-data
|
|
group = www-data
|
|
mode = 0660
|
|
}
|
|
|
|
unix_listener stats-writer {
|
|
user = www-data
|
|
group = www-data
|
|
mode = 0660
|
|
}
|
|
}' | sudo tee -a /etc/dovecot/conf.d/10-master.conf >/dev/null
|
|
sudo gpasswd -a www-data dovecot >/dev/null
|
|
|
|
# Mailboxes
|
|
sudo sed -i 's/namespace inbox {/&\
|
|
# Archive folder\
|
|
mailbox Archive {\
|
|
special_use = \\Archive\
|
|
}/' /etc/dovecot/conf.d/15-mailboxes.conf
|
|
sudo sed -i '/Sent Messages/! s/^ mailbox.*{/&\
|
|
auto = subscribe/' /etc/dovecot/conf.d/15-mailboxes.conf
|
|
sudo adduser dovecot mail >/dev/null
|
|
|
|
sudo systemctl restart dovecot postfix
|
|
|
|
# SPF and DKIM
|
|
echo -e '\e[1;34mConfiguring SPF and DKIM policies\e[0m'
|
|
sudo gpasswd -a postfix opendkim >/dev/null
|
|
|
|
grep -q '^Canonicalization.*relaxed/simple$' /etc/opendkim.conf || sudo sed -i 's|.*Canonicalization.*|Canonicalization relaxed/simple|' /etc/opendkim.conf
|
|
sudo sed -i '/^#Mode.*sv\|^#SubDomains.*no/ s/^#//' /etc/opendkim.conf
|
|
echo -e '\n# Map domains in "from" addresses to keys used to sign messages
|
|
KeyTable refile:/etc/opendkim/KeyTable
|
|
SigningTable refile:/etc/opendkim/SigningTable
|
|
|
|
# Hosts to ignore when verifying signatures
|
|
ExternalIgnoreList /etc/opendkim/trusted.hosts
|
|
|
|
# A set of internal hosts whose mail should be signed
|
|
InternalHosts /etc/opendkim/trusted.hosts' | sudo tee -a /etc/opendkim.conf >/dev/null
|
|
|
|
sudo mkdir -p /etc/opendkim/keys
|
|
sudo chown -R opendkim:opendkim /etc/opendkim
|
|
sudo chmod go-rw /etc/opendkim/keys
|
|
|
|
echo "*@${domain} default._domainkey.${domain}" | sudo tee -a /etc/opendkim/SigningTable >/dev/null
|
|
echo "default._domainkey.${domain} ${domain}:default:/etc/opendkim/keys/${domain}/default.private" | sudo tee -a /etc/opendkim/KeyTable >/dev/null
|
|
echo "127.0.0.1
|
|
localhost
|
|
|
|
*.${domain}" | sudo tee -a /etc/opendkim/trusted.hosts >/dev/null
|
|
|
|
sudo mkdir -p /etc/opendkim/keys/${domain}
|
|
sudo opendkim-genkey -b 2048 -d ${domain} -D /etc/opendkim/keys/${domain} -s default
|
|
sudo chown opendkim:opendkim /etc/opendkim/keys/${domain}/default.private
|
|
sudo chmod 600 /etc/opendkim/keys/${domain}/default.private
|
|
|
|
sudo mkdir -p /var/spool/postfix/opendkim
|
|
sudo chown opendkim:postfix /var/spool/postfix/opendkim
|
|
sudo sed -i '/^#Socket.*local:\/var\/spool\/postfix\/opendkim\/opendkim.sock/ s/^#//' /etc/opendkim.conf || sudo sed -i 's\^Socket.*local:/run/opendkim/opendkim.sock\Socket local:/var/spool/postfix/opendkim/opendkim.sock\' /etc/opendkim.conf
|
|
sudo sed -i 's\^SOCKET=local:$RUNDIR/opendkim.sock\SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"\' /etc/default/opendkim
|
|
|
|
# DMARC
|
|
echo -e '\e[1;34mConfiguring DMARC\e[0m'
|
|
sudo sed -i 's/# AuthservID name/AuthservID OpenDMARC/' /etc/opendmarc.conf
|
|
sudo sed -i 's/# TrustedAuthservIDs HOSTNAME/TrustedAuthservIDs '${subdomain}'.'${domain}'/' /etc/opendmarc.conf
|
|
sudo sed -i 's/# RejectFailures false/RejectFailures true\
|
|
IgnoreAuthenticatedClients true\
|
|
RequiredHeaders true\
|
|
SPFSelfValidate true/' /etc/opendmarc.conf
|
|
sudo sed -i 's|Socket local:/run/opendmarc/opendmarc.sock|Socket local:/var/spool/postfix/opendmarc/opendmarc.sock|' /etc/opendmarc.conf
|
|
sudo mkdir -p /var/spool/postfix/opendmarc
|
|
sudo chown opendmarc:opendmarc /var/spool/postfix/opendmarc -R
|
|
sudo chmod 750 /var/spool/postfix/opendmarc/ -R
|
|
sudo adduser postfix opendmarc >/dev/null
|
|
echo -e '\nIgnoreHosts /etc/opendmarc/ignore.hosts' | sudo tee -a /etc/opendmarc.conf >/dev/null
|
|
sudo mkdir -p /etc/opendmarc
|
|
echo '127.0.0.1' | sudo tee -a /etc/opendmarc/ignore.hosts >/dev/null
|
|
|
|
# OpenDKIM and OpenDMARC headers
|
|
echo -e '\nSoftwareHeader yes' | sudo tee -a /etc/{opendkim,opendmarc}.conf >/dev/null
|
|
|
|
sudo systemctl -q restart opendkim postfix opendmarc
|
|
|
|
# Roundcube/Nginx
|
|
echo -e '\e[1;34mConfiguring Nginx\e[0m'
|
|
sudo tee $(find /etc/php/ -type d -name "pool.d")/zz-php-handler.conf >/dev/null <<EOF
|
|
listen = /run/php/php-fpm.sock
|
|
EOF
|
|
|
|
sudo tee /etc/nginx/proxy_params >/dev/null <<'PROXY'
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
PROXY
|
|
|
|
echo -e '
|
|
upstream php-handler {
|
|
server unix:/run/php/php-fpm.sock;
|
|
}
|
|
|
|
server {
|
|
server_name '${subdomain}'.'${domain}';
|
|
|
|
index index.php index.html;
|
|
|
|
error_log /var/log/nginx/roundcube_error.log;
|
|
access_log /var/log/nginx/roundcube_access.log;
|
|
|
|
root /usr/share/webapps/roundcube;
|
|
|
|
# Postfixadmin
|
|
location ^~ /admin/ {
|
|
proxy_pass http://127.0.0.1:12000/;
|
|
include proxy_params;
|
|
}
|
|
|
|
# Roundcube
|
|
location ~ \.php$ {
|
|
try_files $uri =404;
|
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
fastcgi_pass php-handler;
|
|
fastcgi_index index.php;
|
|
include fastcgi_params;
|
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|
}
|
|
}
|
|
|
|
server {
|
|
listen 12000;
|
|
root /usr/share/webapps/postfixadmin/public/;
|
|
index index.php index.html;
|
|
client_max_body_size 0;
|
|
|
|
error_log /var/log/nginx/postfixadmin_error.log;
|
|
access_log /var/log/nginx/postfixadmin_access.log;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.php;
|
|
}
|
|
|
|
location ~ ^/(.+\.php)$ {
|
|
try_files $uri =404;
|
|
fastcgi_pass php-handler;
|
|
fastcgi_index index.php;
|
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
include /etc/nginx/fastcgi_params;
|
|
}
|
|
}' | sudo tee /etc/nginx/sites-available/mail.conf >/dev/null
|
|
sudo ln -s /etc/nginx/sites-available/mail.conf /etc/nginx/sites-enabled/
|
|
sudo rm /etc/nginx/sites-available/default
|
|
|
|
# Certbot
|
|
sudo systemctl -q disable --now apache2.service
|
|
sudo systemctl -q reload nginx.service
|
|
sudo /etc/init.d/php*-fpm reload
|
|
|
|
until sudo certbot --nginx --agree-tos --redirect --hsts --no-eff-email --staple-ocsp -m ${eff_email} -d ${subdomain}.${domain}
|
|
do
|
|
sleep 10
|
|
done
|
|
sudo setfacl -R -m u:www-data:rx /etc/letsencrypt/live/ /etc/letsencrypt/archive/
|
|
|
|
# Postfix
|
|
sudo postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/${subdomain}.${domain}/privkey.pem"
|
|
sudo postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/${subdomain}.${domain}/fullchain.pem"
|
|
|
|
# Dovecot
|
|
# sudo sed -i 's|ssl_cert = </etc/dovecot/private/dovecot.pem|# &|' /etc/dovecot/conf.d/10-ssl.conf
|
|
# sudo sed -i 's|ssl_key = </etc/dovecot/private/dovecot.key|# &|' /etc/dovecot/conf.d/10-ssl.conf
|
|
echo 'ssl_cert = </etc/letsencrypt/live/'${subdomain}'.'${domain}'/fullchain.pem
|
|
ssl_key = </etc/letsencrypt/live/'${subdomain}'.'${domain}'/privkey.pem' | sudo tee /etc/dovecot/ssl-keys.conf >/dev/null
|
|
sudo chmod 600 /etc/dovecot/ssl-keys.conf
|
|
echo -e '!include_try ssl-keys.conf' | sudo tee -a /etc/dovecot/dovecot.conf >/dev/null
|
|
|
|
# Home directory mods
|
|
echo -e "
|
|
if [ -f ~/.bash_history ]
|
|
then
|
|
rm -f ~/.bash_history
|
|
fi
|
|
|
|
unset HISTFILE
|
|
history -c
|
|
|
|
# Mail logs
|
|
function mail-watch
|
|
{
|
|
sudo tail -f /var/log/mail.log
|
|
}
|
|
|
|
function mail-log
|
|
{
|
|
sudo cat /var/log/mail.log
|
|
}
|
|
|
|
function mail-troubleshoot
|
|
{
|
|
systemctl status postfix.service dovecot.service opendkim.service opendmarc.service nginx.service mariadb.service
|
|
/etc/init.d/php*-fpm status
|
|
}
|
|
|
|
function mail-reboot
|
|
{
|
|
sudo systemctl -q restart postfix.service dovecot.service opendkim.service opendmarc.service nginx.service mariadb.service
|
|
sudo /etc/init.d/php*-fpm restart
|
|
}
|
|
|
|
function mail-check
|
|
{
|
|
if systemctl list-units --state failed | grep -q 'postfix\|dovecot\|opendkim\|opendmarc\|nginx\|mariadb\|php.*-fpm'
|
|
then
|
|
echo -e '\nErrors found...\n'
|
|
systemctl list-units --state failed
|
|
else
|
|
echo -e '\nAll good!\n'
|
|
fi
|
|
}
|
|
|
|
function mail-test
|
|
{
|
|
sudo systemctl stop postfix dovecot
|
|
read -n 1 -s -p $'\nPress any key to continue...\n'
|
|
sudo systemctl start postfix dovecot &&
|
|
mail-watch
|
|
}
|
|
|
|
# SSH pubkey access
|
|
function ssh-on
|
|
{
|
|
sudo sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config.d/10-personal-sshd.conf
|
|
sudo systemctl -q restart sshd
|
|
}
|
|
|
|
function ssh-off
|
|
{
|
|
sudo sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config.d/10-personal-sshd.conf
|
|
sudo systemctl -q restart sshd
|
|
}" >> ~/.bashrc
|
|
|
|
# Cron tasks
|
|
echo '#!/bin/sh
|
|
certbot renew --quiet && systemctl -q reload postfix dovecot nginx
|
|
/usr/local/bin/postwhite/postwhite &>/dev/null # Update Postscreen Whitelists' | sudo install /dev/stdin /etc/cron.daily/mailserver
|
|
echo '#!/bin/sh
|
|
/usr/local/bin/postwhite/scrape_yahoo &>/dev/null # Update Yahoo! IPs for Postscreen Whitelists' | sudo install /dev/stdin /etc/cron.weekly/mailserver
|
|
sudo ln -s /usr/share/webapps/roundcube/bin/cleandb.sh /etc/cron.daily/roundcube-cleandb
|
|
|
|
# In your DNS manager, create a TXT record, enter default._domainkey in the name field
|
|
echo -e '\n\e[1;34mUpdate DKIM TXT on DNS registrar and press any key to continue\e[5m...\e[0m'
|
|
echo -e '\e[3m# Use default._domainkey in the host field'
|
|
echo -e '# Visit https://www.dmarcanalyzer.com/dkim/dkim-checker/ to check manually\e[0m'
|
|
sudo cat /etc/opendkim/keys/${domain}/default.txt | sed 's/.*( //' | sed 's/ ).*//' | sed 's/"//g' | sed 's/^[ \t]*//g' | sed ':a;N;$!ba;s/\n//g'
|
|
|
|
echo -e '\n\e[1;34mRestarting system services...\e[0m\n'
|
|
sudo systemctl -q restart postfix.service dovecot.service opendkim.service opendmarc.service nginx.service mariadb.service fail2ban.service
|
|
sudo /etc/init.d/php*-fpm restart
|
|
|
|
# # Check DKIM key
|
|
# while :
|
|
# do
|
|
# if sudo opendkim-testkey -d ${domain} -s default
|
|
# then
|
|
# echo -e '\n\e[1;32mDKIM key has been verified!\e[0m'
|
|
# break
|
|
# fi
|
|
# sleep 5
|
|
# done &
|
|
# disown
|
|
|
|
sudo apt autoremove -y &>/dev/null
|
|
|
|
install /dev/stdin ~/dhparam >/dev/null <<'dhparam'
|
|
#!/bin/sh
|
|
echo
|
|
|
|
# Create certificates
|
|
echo -e '\e[1;34mGenerating DH parameters with openssl\e[0m'
|
|
echo -e '\e[3m# a notification will pop up once completed\e[0m'
|
|
|
|
sudo openssl dhparam -out /usr/share/dovecot/dh.pem 4096 &&
|
|
echo -e '\n\n\e[1;32mOpenssl certificates have successfully been generated!\e[0m'
|
|
|
|
rm ${0}
|
|
dhparam
|
|
|
|
echo -e '\n\e[1m\t## Run "~/dhparam" upon logging in\n\e[0m'
|
|
|
|
echo -e "\e[1;32mInstaller has completed, login at https://${subdomain}.${domain} to access your new email."
|
|
echo -e "Reboot is recommended...\e[0m\n"
|
|
sudo rm ${0}
|
|
history -c
|
|
MAILSERVER
|
|
|
|
su ${username} <<"CHANGEUSER"
|
|
# SSH
|
|
yes | ssh-keygen -t ed25519 -q -f ~/.ssh/id_ed25519 -P ""
|
|
echo "${sshkeys}" >~/.ssh/authorized_keys
|
|
CHANGEUSER
|
|
echo -e '\n\e[1m\t## Run "mail-server" immediately\n\e[0m'
|
|
su ${username}
|
|
|
|
clear
|
|
echo -e "###
|
|
### Login ssh as new user
|
|
###
|
|
while :
|
|
do
|
|
clear
|
|
if ping -q -c 1 -W 3 ${domain} >/dev/null
|
|
then
|
|
sleep 1
|
|
ssh ${username}@${domain} -p ${ssh_port}
|
|
break
|
|
fi
|
|
sleep 1
|
|
done\n"
|
|
|
|
. ~/.bashrc
|
|
reboot
|
|
fi |