mailtrain/setup/functions
2020-04-29 15:08:54 +02:00

574 lines
15 KiB
Text

# This is not a standalone script. It provides common functions to server-*.sh scripts
case "$hostType" in
centos7)
hostTypeLabel="CentOS 7"
redisService=redis
apacheConf="/etc/httpd/conf.d/mailtrain.conf"
apacheLogsPath="logs"
if hash firewall-cmd 2>/dev/null; then
firewallCmdExists=yes
fi
;;
centos8)
hostTypeLabel="CentOS 8"
redisService=redis
apacheConf="/etc/httpd/conf.d/mailtrain.conf"
apacheLogsPath="logs"
if hash firewall-cmd 2>/dev/null; then
firewallCmdExists=true
fi
;;
ubuntu1804)
hostTypeLabel="Ubuntu 18.04 LTS"
redisService=redis-server
apacheConf="/etc/apache2/conf-available/mailtrain.conf"
apacheLogsPath="/var/log/apache2"
if hash ufw 2>/dev/null; then
firewallCmdExists=yes
fi
;;
debian10)
hostTypeLabel="Debian 10"
redisService=redis-server
apacheConf="/etc/apache2/conf-available/mailtrain.conf"
apacheLogsPath="/var/log/apache2"
if hash ufw 2>/dev/null; then
firewallCmdExists=yes
fi
;;
esac
function performInstallLocal {
local paramCount="$1"
if [ $paramCount -ne 0 ]; then
echo "Error: incorrect number of parameters."
cat <<EOF
Basic usage: install-${hostType}-local.sh
Installs Mailtrain 2 on ${hostTypeLabel}. This performs installation for local use on HTTP ports 3000, 3003, 3004. If you want
to make these ports available from outside, setup an HTTPS proxy yourself or use install-${hostType}-https.sh instead.
Example: install-${hostType}-local.sh
EOF
exit 1
fi
installPrerequisities
installMailtrain http://localhost:3000 http://localhost:3003 http://localhost:3004 0.0.0.0 false
installService
echo
echo "Success!"
}
function performInstallHttps {
local paramCount="$1"
hostTrusted="$2"
hostSandbox="$3"
hostPublic="$4"
email="$5"
if [ $paramCount -ne 4 ]; then
echo "Error: incorrect number of parameters."
cat <<EOF
Basic usage: install-${hostType}-https.sh <trusted host> <sandbox host> <public host> <email>
Installs Mailtrain 2 on ${hostTypeLabel}. This performs installation for external use. It installs Mailtrain, sets up
a reverse HTTPS proxy using Apache HTTPD, sets up firewall rules, and obtains a certificate from Letsencrypt.
You have to allocate three endpoints for Mailtrain - trusted (admin UI), sandbox (editors for templates), public (subscription forms and archive).
These endpoints have to differ in hostname. It's fine to host them all from one IP address. The email parameters is needed by certbot.
Note, that this will automatically accept the Let's Encrypt's Terms of Service.
Thus, by running this script below, you agree with the Let's Encrypt's Terms of Service (https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf).
Example: install-${hostType}-https.sh mailtrain.example.com sbox.mailtrain.example.com lists.example.com admin@example.com
EOF
exit 1
fi
installPrerequisities
installHttpd 443 443 443
createCertificates "${hostTrusted}" "${hostSandbox}" "${hostPublic}" "${email}"
installHttpsProxy "${hostTrusted}" 443 "${hostSandbox}" 443 "${hostPublic}" 443 "/etc/letsencrypt/live/${hostPublic}/cert.pem" "/etc/letsencrypt/live/${hostPublic}/privkey.pem" "/etc/letsencrypt/live/${hostPublic}/chain.pem"
installMailtrain "https://${hostTrusted}" "https://${hostSandbox}" "https://${hostPublic}" 127.0.0.1 true
installService
echo
echo "Success!"
}
function installPrerequisities {
# Run as root!
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
case "$hostType" in
centos7)
yum -y install epel-release
curl --silent --location https://rpm.nodesource.com/setup_10.x | bash -
cat > /etc/yum.repos.d/mongodb-org.repo <<EOT
[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
EOT
yum -y install mariadb-server nodejs ImageMagick redis pwgen gcc-c++ make mongodb-org bzip2
;;
centos8)
dnf -y install epel-release
cat > /etc/yum.repos.d/mongodb-org.repo <<EOT
[mongodb-org-4.2]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/4.2/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc
EOT
dnf -y module install nodejs/development
dnf -y module install mariadb/server
dnf -y module install redis
dnf -y install ImageMagick pwgen gcc-c++ make mongodb-org bzip2
;;
ubuntu1804)
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list
apt-get update
apt-get install -y mariadb-server nodejs imagemagick redis pwgen g++ make mongodb-org bzip2
;;
debian10)
apt-get install -y gnupg
wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | apt-key add -
echo "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list
apt-get update
apt-get install -y mariadb-server nodejs imagemagick redis pwgen g++ make mongodb-org bzip2 npm
;;
esac
systemctl start mariadb
systemctl enable mariadb
systemctl start ${redisService}
systemctl enable ${redisService}
systemctl start mongod
systemctl enable mongod
}
function installMailtrain {
local urlBaseTrusted="$1"
local urlBaseSandbox="$2"
local urlBasePublic="$3"
local wwwHost="$4"
local wwwProxy="$5"
mysqlPassword=`pwgen 12 -1`
mysqlRoPassword=`pwgen 12 -1`
# Setup MySQL user for Mailtrain
mysql -u root -e "CREATE USER 'mailtrain'@'localhost' IDENTIFIED BY '$mysqlPassword';"
mysql -u root -e "GRANT ALL PRIVILEGES ON mailtrain.* TO 'mailtrain'@'localhost';"
mysql -u root -e "CREATE USER 'mailtrain_ro'@'localhost' IDENTIFIED BY '$mysqlRoPassword';"
mysql -u root -e "GRANT SELECT ON mailtrain.* TO 'mailtrain_ro'@'localhost';"
mysql -u mailtrain --password="$mysqlPassword" -e "CREATE database mailtrain;"
# Add new user for the mailtrain daemon to run as
useradd mailtrain || true
# Setup installation configuration
cat > server/config/production.yaml <<EOT
user: mailtrain
group: mailtrain
roUser: nobody
roGroup: nobody
www:
host: $wwwHost
proxy: $wwwProxy
secret: "`pwgen -1`"
trustedUrlBase: $urlBaseTrusted
sandboxUrlBase: $urlBaseSandbox
publicUrlBase: $urlBasePublic
mysql:
password: "$mysqlPassword"
redis:
enabled: true
log:
level: info
builtinZoneMTA:
log:
level: warn
queue:
processes: 5
EOT
cat >> server/services/workers/reports/config/production.yaml <<EOT
log:
level: warn
mysql:
user: mailtrain_ro
password: "$mysqlRoPassword"
EOT
reinstallAllModules
(cd client && npm run build)
chown -R mailtrain:mailtrain .
chmod o-rwx server/config
}
function doForAllModules {
# Install required node packages
for idx in client shared server zone-mta mvis/client mvis/server mvis/test-embed mvis/ivis-core/client mvis/ivis-core/server mvis/ivis-core/shared mvis/ivis-core/embedding; do
if [ -d $idx ]; then
($1 $idx)
fi
done
}
function reinstallModules {
local idx=$1
echo Reinstalling modules in $idx
cd $idx && rm -rf node_modules && npm install
}
function reinstallAllModules {
doForAllModules reinstallModules
}
function installHttpd {
local portTrusted="$1"
local portSandbox="$2"
local portPublic="$3"
case "$hostType" in
centos7)
yum -y install httpd mod_ssl
systemctl start httpd
systemctl enable httpd
setsebool -P httpd_can_network_connect 1
if [ -n "$firewallCmdExists" ]; then
# Enable SSL ports on the firewall
for port in "80/tcp" "${portTrusted}/tcp" "${portSandbox}/tcp" "${portPublic}/tcp"; do
firewall-cmd --add-port=$port --permanent
done
# Activate the firefall settings
firewall-cmd --reload
fi
;;
centos8)
dnf -y install httpd mod_ssl
systemctl start httpd
systemctl enable httpd
setsebool -P httpd_can_network_connect 1
if [ -n "$firewallCmdExists" ]; then
# Enable SSL ports on the firewall
for port in "80/tcp" "${portTrusted}/tcp" "${portSandbox}/tcp" "${portPublic}/tcp"; do
firewall-cmd --add-port=$port --permanent
done
# Activate the firefall settings
firewall-cmd --reload
fi
;;
ubuntu1804|debian10)
apt-get install -y apache2
if [ -n "$firewallCmdExists" ]; then
# Enable SSL ports on the firewall
for port in "80/tcp" "${portTrusted}/tcp" "${portSandbox}/tcp" "${portPublic}/tcp"; do
ufw allow $port
done
fi
;;
esac
}
function installHttpsProxy {
local hostTrusted="$1"
local portTrusted="$2"
local hostSandbox="$3"
local portSandbox="$4"
local hostPublic="$5"
local portPublic="$6"
local certificateFile="$7"
local certificateKey="$8"
local caChainFile="$9"
> $apacheConf
cat >> $apacheConf <<EOT
<VirtualHost *:80>
ServerName ${hostTrusted}
ServerSignature Off
RewriteEngine On
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
ErrorLog ${apacheLogsPath}/${hostTrusted}_redirect_error.log
LogLevel warn
</VirtualHost>
<VirtualHost *:80>
ServerName ${hostSandbox}
ServerSignature Off
RewriteEngine On
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
ErrorLog ${apacheLogsPath}/${hostSandbox}_redirect_error.log
LogLevel warn
</VirtualHost>
<VirtualHost *:80>
ServerName ${hostPublic}
ServerSignature Off
RewriteEngine On
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
ErrorLog ${apacheLogsPath}/${hostPublic}_redirect_error.log
LogLevel warn
</VirtualHost>
<VirtualHost *:${portTrusted}>
ServerName ${hostTrusted}:${portTrusted}
ErrorLog ${apacheLogsPath}/${hostTrusted}_ssl_error.log
TransferLog ${apacheLogsPath}/${hostTrusted}_ssl_access.log
LogLevel warn
SSLEngine on
SSLCertificateFile ${certificateFile}
SSLCertificateKeyFile ${certificateKey}
SSLCertificateChainFile ${caChainFile}
ProxyPreserveHost On
ProxyPass "/" "http://127.0.0.1:3000/"
ProxyPassReverse "/" "http://127.0.0.1:3000/"
</VirtualHost>
<VirtualHost *:${portSandbox}>
ServerName ${hostSandbox}:${portSandbox}
ErrorLog ${apacheLogsPath}/${hostSandbox}_ssl_error.log
TransferLog ${apacheLogsPath}/${hostSandbox}_ssl_access.log
LogLevel warn
SSLEngine on
SSLCertificateFile ${certificateFile}
SSLCertificateKeyFile ${certificateKey}
SSLCertificateChainFile ${caChainFile}
ProxyPreserveHost On
ProxyPass "/" "http://127.0.0.1:3003/"
ProxyPassReverse "/" "http://127.0.0.1:3003/"
</VirtualHost>
<VirtualHost *:${portPublic}>
ServerName ${hostPublic}:${portPublic}
ErrorLog ${apacheLogsPath}/${hostPublic}_ssl_error.log
TransferLog ${apacheLogsPath}/${hostPublic}_ssl_access.log
LogLevel warn
SSLEngine on
SSLCertificateFile ${certificateFile}
SSLCertificateKeyFile ${certificateKey}
SSLCertificateChainFile ${caChainFile}
ProxyPreserveHost On
ProxyPass "/" "http://127.0.0.1:3004/"
ProxyPassReverse "/" "http://127.0.0.1:3004/"
</VirtualHost>
EOT
case "$hostType" in
centos7|centos8)
systemctl restart httpd
;;
ubuntu1804|debian10)
a2enmod ssl
a2enmod rewrite
a2enmod proxy
a2enmod proxy_http
a2enconf mailtrain
systemctl restart apache2
;;
esac
}
function createCertificates {
# This assumes that HTTPD is already running
local hostTrusted="$1"
local hostSandbox="$2"
local hostPublic="$3"
local email="$4"
case "$hostType" in
centos7)
yum install -y certbot python2-certbot-apache
;;
centos8)
dnf install -y certbot
;;
ubuntu1804|debian10)
apt-get install -y certbot python3-certbot-apache
;;
esac
certbot certonly --agree-tos --email "${email}" --webroot --webroot-path /var/www/html -n -d "${hostPublic}" -d "${hostTrusted}" -d "${hostSandbox}"
# Install cron
echo "0 3 * * * /usr/bin/certbot certonly --apache -n -d \"${hostPublic}\" -d \"${hostTrusted}\" -d \"${hostSandbox}\"" > crontab
crontab crontab
rm -rf crontab
}
function installService {
cat > /etc/systemd/system/mailtrain.service <<EOT
[Unit]
Description=Mailtrain server
After=syslog.target network.target mariadb.service ${redisService}.service mongod.service
[Service]
Environment="NODE_ENV=production"
WorkingDirectory=/opt/mailtrain/server
ExecStart=/usr/bin/node index.js
Type=simple
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOT
systemctl daemon-reload
}
function deleteModules {
local idx=$1
echo Deleting modules in $idx
cd $idx && rm -rf node_modules
}
function deleteAllModules {
doForAllModules deleteModules
}
function setupTest {
mysqlPassword=`pwgen 12 -1`
# Setup MySQL user for Mailtrain
mysql -u root -e "CREATE USER 'mailtrain_test'@'localhost' IDENTIFIED BY '$mysqlPassword';"
mysql -u root -e "GRANT ALL PRIVILEGES ON mailtrain_test.* TO 'mailtrain_test'@'localhost';"
mysql -u mailtrain_test --password="$mysqlPassword" -e "CREATE database mailtrain_test;"
# Setup installation configuration
cat > server/config/test.yaml <<EOT
mysql:
user: mailtrain_test
password: "$mysqlPassword"
database: mailtrain_test
redis:
enabled: true
log:
level: info
builtinZoneMTA:
log:
level: warn
queue:
processes: 5
testServer:
enabled: true
EOT
cat >> server/services/workers/reports/config/test.yaml <<EOT
log:
level: warn
mysql:
user: mailtrain_test
password: "$mysqlPassword"
database: mailtrain_test
EOT
}