mailtrain/setup/functions
2018-12-25 13:03:06 +01:00

416 lines
11 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"
if hash firewall-cmd 2>/dev/null; then
firewallCmdExists=yes
fi
;;
ubuntu1804)
hostTypeLabel="Ubuntu 18.04 LTS"
redisService=redis-server
apacheConf="/etc/apache2/conf-available/mailtrain.conf"
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
}
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
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
}
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
;;
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
;;
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
# Install required node packages
for idx in client shared server zone-mta; do
(cd $idx && npm install)
done
(cd client && npm run build)
chown -R mailtrain:mailtrain .
chmod o-rwx server/config
}
function installHttpd {
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
;;
ubuntu1804)
apt-get install -y apache2
a2enmod ssl
systemctl restart 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
ufw --force enable
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 logs/${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 logs/${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 logs/${hostPublic}_redirect_error.log
LogLevel warn
</VirtualHost>
<VirtualHost *:${portTrusted}>
ServerName ${hostTrusted}:${portTrusted}
ErrorLog logs/${hostTrusted}_ssl_error.log
TransferLog logs/${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 logs/${hostSandbox}_ssl_error.log
TransferLog logs/${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 logs/${hostPublic}_ssl_error.log
TransferLog logs/${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)
systemctl restart httpd
;;
ubuntu1804)
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
;;
ubuntu1804)
apt-get install -y certbot python3-certbot-apache
;;
esac
certbot certonly --agree-tos --email "${email}" --apache -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
}