My requirements
Have registered domain and a web server is already hosted for the same. Need is to add a ‘mail’ subdomain associated with a different public IP and set up a mail server. Have access to DNS management and will be configuring mail server on a VM on my server (hosted in a datacenter) to which I have root access. Updated firewall rules to forward HTTP (80), HTTPS(443), IMAP (993), SMTP (587) to be forwarded to the VM IP 10.1.x.x
Note : Replace all occurrences of example.com with the registered domain if you plan to follow the how-to given here.
DNS Configurations
Added a A record with name as mail, value as the 103.x.x.x the public IP planned to be used for mail server.
Added a MX record with name as mail, value as mail.example.com and since being the only mail server set priority to 0.
Added a TXT entry with name as @ and value as v=spf1 mx ~all for SPF purposes.
Added a TXT entry with name as mail.example.com and value as v=DMARC1; p=none
– Planned to update as needed after installation.
Requested the data center team to have PTR record for 103.x.x.x (public IP assigned to mail server) so that reverse DNS lookup succeeds.
SSL certificates from Let’s Encrypt
Installed Debian Buster (minimal install). To generate a SSL certificate signed by Let’s Encrypt we need to have a web server running online for the domain name, in our case mail.example.com.
Install apache2
#apt install -y apache2
Remove all configuration files from /etc/apache2/sites-available and add mail.example.com.conf in that folder with following contents
<VirtualHost *:80> ServerName mail.example.com DirectoryIndex index.html DocumentRoot /var/www/mail.example.com ErrorLog ${APACHE_LOG_DIR}/mail-error.log CustomLog ${APACHE_LOG_DIR}/mail-access.log combined Options FollowSymLinks <Directory "/var/www/mail.example.com"> AllowOverride All Require all granted </Directory> </VirtualHost>
Create a folder /var/www/mail.example.com. Create a simple index.html file in the folder. Change the ownership of the /var/www/mail.example.com
#chown www-data:www-data -R /var/www/mail.example.com
Add a soft link in sites-enabled folder
#cd /etc/apache2/sites-enabled #ln -fs /etc/apache2/sites-available/mail.example.com.conf mail.example.com.conf
Enable modssl and modrewrite and restart apache2
#a2enmod ssl rewrite #systemctl restart apache2
Add a few port-fowrading rule in the firewall to forward all HTTP and HTTPS requests received for public IP 103.x.x.x (allocated to mail.example.com) to the VM IP.
Restart apache and verify you can access http://mail.example.com
Install certbot
#apt-get install certbot python-certbot-apache a2enmod ssl Considering dependency setenvif for ssl: Module setenvif already enabled Considering dependency mime for ssl: Module mime already enabled Considering dependency socache_shmcb for ssl: Enabling module socache_shmcb. Enabling module ssl. See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates. To activate the new configuration, you need to run: systemctl restart apache2
Generate certificate – No updates to Vritual host configuration files (certonly)
root@vm:~# certbot certonly --apache -d example.com Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator apache, Installer apache Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): xxxx@xx.in Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must agree in order to register with the ACME server at https://acme-v02.api.letsencrypt.org/directory (A)gree/(C)ancel: A Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. (Y)es/(N)o: N Obtaining a new certificate Performing the following challenges: http-01 challenge for example.com Waiting for verification… Cleaning up challenges IMPORTANT NOTES: Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/example.com/privkey.pem Your cert will expire on 2020-04-10. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew all of your certificates, run "certbot renew" Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le root@vm:~#
Verify the SSL certificate works. Add a Virtual host section for handling https requests and test.
<VirtualHost *:443> ServerName example.com DirectoryIndex index.html DocumentRoot /var/www/example.com SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined Options FollowSymLinks <Directory /var/www/example.com> AllowOverride All Require all granted </Directory> </VirtualHost>
Restart apache.
#service apache2 restart
Certificate renewal cron jobs are added on generation of certificate.
#ls -ltr /etc/cron.d -rw-r--r-- 1 root root 775 Sep 15 2018 certbot # cat /etc/cron.d/certbot /etc/cron.d/certbot: crontab entries for the certbot package # Upstream recommends attempting renewal twice a day # Eventually, this will be an opportunity to validate certificates haven't been revoked, etc. Renewal will only occur if expiration is within 30 days. # Important Note! This cronjob will NOT be executed if you are running systemd as your init system. If you are running systemd, the cronjob.timer function takes precedence over this cronjob. For more details, see the systemd.timer manpage, or use systemctl show certbot.timer. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 0 */12 * * * root test -x /usr/bin/certbot -a ! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew