Cloud Provider Consideration
Before we continue, be mindful when choosing the cloud provider in which your email server will be launched. Not all cloud providers open the email-sending port, e.g., 25, hence blocking your email-sending capabilities. You will need to request them to open the port, and they will ask for some information before they can approve your request. Some providers I have known like these close their email-sending port:
Digital Ocean
Vultr
Linode
AWS
You can host your email server at Contabo or Kamatera or even build it on your on-premise server.
Server Consideration
Installing from a new server is highly recommended, as it will avoid any unnecessary dependency conflict.
Screen Installation
First, we will install the screen package. The package is helpful if we get disconnected during the build session, we can reconnect to the session and continue what we left off.
sudo dnf install -y screen
Now, start a screen session.
Later, when you get disconnected from the ssh session, run this command to resume the session:
To list active screen sessions, run this command:
To terminate current screen session, run:
Setup Hostname
We will set up a hostname to identify the server uniquely.
For example:
Then, verify the change by running this command:
The output should look like this:
Next, update the hosts file:
Change an entry like this:
Note that, x.x.x.x is the server’s IP address.
To this:
Reboot the server to apply the changes.
System Update and Dependencies Installation
We need to update the existing packages.
Then, install vim as our text editor. You can install your own preferred text editor, e.g. nano. And, install tar and socat as they are required by acme.sh.
Acme.sh Installation
Next, we will install acme.sh, a command-line tool for managing SSL/TLS certificates. I prefer acme.sh over certbot, as it does not depend on the OS version. For more details about acme.sh, check its GitHub repo here.
Next, install acme.sh.
Note that change my@example.com accordingly.
Create an alias for the acme.sh command so we can run acme.sh directly without specifying its full path.
source ~/.bash_aliases
Before we issue an SSL certificate, we must configure the DNS record properly. I will use mail.domain.com in this tutorial, and its A and MX records has already been configured. Refer to the DNS Record Configuration section at the end of this article to get more details.
After that, let us start issuing a staging SSL certificate. This certificate cannot be used on production servers and is used primarily to test certificate generation. Note that generating a live LetsEncrypt certificate is limited to 50 per week, for more info check this documentation. If it works, we can continue issuing a live SSL certificate.
Before we issue the SSL certificate, let us create a folder to store the generated certificates.
mkdir -p /etc/pki/tls/certs/live
To issue a staging SSL certificate, run this command:
-d “mail.domain.com”
–cert-home /etc/pki/tls/certs/staging
–standalone
–debug
–staging
Some notes:
-d: the domain name we want to issue the certificate for
–cert-home: the folder path where we want the generated certificate files to be stored.
–standalone: this assumes we do not have a web server capable of serving web files, e.g. apache or nginx
debug: display all information. Useful for tracing issues
staging: generate a staging certificate.
If things go well, you will see an output like this:
[Sun Mar 24 04:08:19 UTC 2024] Your cert key is in: /etc/pki/tls/certs/staging/mail.domain.com_ecc/mail.domain.com.key
[Sun Mar 24 04:08:19 UTC 2024] The intermediate CA cert is in: /etc/pki/tls/certs/staging/mail.domain.com_ecc/ca.cer
[Sun Mar 24 04:08:19 UTC 2024] And the full chain certs is there: /etc/pki/tls/certs/staging/mail.domain.com_ecc/fullchain.cer
[Sun Mar 24 04:08:19 UTC 2024] _on_issue_success
Now, let us issue a live certificate:
-d “mail.domain.com”
–cert-home /etc/pki/tls/certs/live
–standalone
–debug
This time we removed the –staging parameter, and changed the certificate home folder.
The output will look like this:
[Sun Mar 24 04:35:12 UTC 2024] Your cert key is in: /etc/pki/tls/certs/live/mail.mail.domain.com_ecc/mail.mail.domain.com.key
[Sun Mar 24 04:35:12 UTC 2024] The intermediate CA cert is in: /etc/pki/tls/certs/live/mail.mail.domain.com_ecc/ca.cer
[Sun Mar 24 04:35:12 UTC 2024] And the full chain certs is there: /etc/pki/tls/certs/live/mail.mail.domain.com_ecc/fullchain.cer
[Sun Mar 24 04:35:12 UTC 2024] _on_issue_success
Now, we need to change the future SSL generation configured via crontab. Run this command:
Replace the following cron:
With:
Configure Firewall
We will use firewalld to protect our email server. First, install the firewalld package.
Then, enable and start firewalld on server startup.
sudo systemctl start firewalld
Now, configure firewall rules.
sudo firewall-cmd –zone=public –permanent –add-service=https
sudo firewall-cmd –zone=public –add-service=pop3 –permanent
sudo firewall-cmd –zone=public –add-service=pop3s –permanent
sudo firewall-cmd –zone=public –add-service=smtp –permanent
sudo firewall-cmd –zone=public –add-service=smtps –permanent
sudo firewall-cmd –zone=public –add-service=imap –permanent
sudo firewall-cmd –zone=public –add-service=imaps –permanent
sudo firewall-cmd –reload
Validate the result by checking the configured firewall rules.
The output should look like this:
Exim Installation and Configuration
We will install Exim, a mail transfer agent used to deliver and receive emails.
Before configuring exim, we need to back up the existing config file.
This will copy exim.conf to exim.conf.orig.
After that, we can safely configure exim.
Adjust the existing exim configuration so they look like these:
domainlist local_domains = @ : domain.com
tls_advertise_hosts = *
tls_certificate = /etc/pki/tls/certs/live/mail.domain.com_ecc/mail.domain.com.cer
tls_privatekey = /etc/pki/tls/certs/live/mail.domain.com_ecc/mail.domain.com.key
auth_advertise_hosts = *
Next, find ROUTERS CONFIGURATION section, and then find localuser: block.
Adjust the whole block so it will look like these:
driver = redirect
check_local_user
file_transport = local_delivery
reply_transport = local_delivery_autoreply
data = /home/${local_part_data}/Maildir
Next, find the TRANSPORTS CONFIGURATION section and then find local_delivery: block.
Adjust the whole block so it will look like this:
driver = appendfile
directory = $home/Maildir
maildir_format
maildir_use_size_file
delivery_date_add
envelope_to_add
return_path_add
And add this block right after the local_delivery: block.
driver = autoreply
headers = Content-Type: text/plain; charset=utf-8nContent-Transfer-Encoding: base64
to = ${sender_address}
from = ${$local_part}@${$domain}
debug_print = “T: auto reply for $local_part@$domain”
once_file_size = 500K
log = /var/log/exim/sieve_autoreply.log
The autoreply transport will generate a new email message as an automatic reply to the incoming message. It is useful to generate an automatic email when we are on a vacation or out-of-office. We will utilize this later in Roundcube. For more details on autoreply, refer to the doc here.
Next, find AUTHENTICATION CONFIGURATION section.
Then, add these blocks at the end of the section.
driver = dovecot
public_name = LOGIN
server_socket = /var/run/dovecot/auth-client
server_set_id = $auth1
dovecot_plain:
driver = dovecot
public_name = PLAIN
server_socket = /var/run/dovecot/auth-client
server_set_id = $auth1
Save all the changes and then quit.
Start exim service, and automatically start the service on server startup.
sudo systemctl enable exim
sudo systemctl status exim
Test the local_delivery transport and ensure there is no warning or error message.
Next, change the certificate folder’s ownership so that Exim will be able to access the certificates later.
chown -R exim:exim /etc/pki/tls/certs/live
Dovecot Installation and Configuration
We will use dovecot, an open-source IMAP and POP3 server. It takes responsibility for connecting your email client (Thunderbird, etc.) to your mail box.
Run this command to install dovecot.
SSL Configuration
Configure SSL in dovecot.
Then adjust the existing config to this:
ssl_cert = </etc/pki/tls/certs/live/mail.domain.com_ecc/mail.domain.com.cer
ssl_key = </etc/pki/tls/certs/live/mail.domain.com_ecc/mail.domain.com.key
Note that, ensure the file paths are prefixed by <. Otherwise, it will trigger an error.
Plain Authentication
Allow plain authentication in dovecot.
Adjust the existing config.
auth_mechanisms = plain login
Mailbox Location
Configure mailbox location.
Adjust the existing config.
Allow Exim to Authenticate
Set up dovecot to allow Exim to use its authentication system.
Find the unix_listener auth-userdb block.
Then, fully comment the block, and add this block beneath it.
mode = 0660
user = exim
}
The final changes should look like this:
Start dovecot service, and automatically start the service on server startup.
sudo systemctl enable dovecot
sudo systemctl status dovecot
Create an Email Address
We will create an email address, say email-test@domain.com.
Set its password.
Create info user (optional).
passwd info
Note that, when sending an email to info@domain.com, you might encounter a problem, this is because info@domain.com is considered a root user. To fix the issue, remove it from the aliases list.
Then, comment this line by prefixing the line with #.
Test the email user routing, and ensure there is no error or warning message.
The output should look like this:
transport = local_delivery
And the other user.
The output should look like this:
transport = local_delivery
DNS Record Configuration
Before we can send and receive emails, ensure to have these records on your DNS Control Panel:
A record:
Change 1.2.3.4 with the IP Address of your email server.
MX record:
The MX record indicates it will point to your email server.