Part 2: Install Dovecot IMAP Server on Rocky Linux 9/Alma Linux 9 & Enable TLS Encryption
This is part 2 of building your own email server from scratch on Rocky Linux 9/Alma Linux 9 tutorial series. In part 1, we showed you how to set up a basic Postfix SMTP server. In this tutorial, we are going to configure our email server so that we can receive and send emails using a desktop email client like Mozilla Thunderbird or Microsoft Outlook.
- To send emails using a desktop email client, we need to enable the
submission
service in Postfix. - To receive emails using a desktop email client, we can install the Dovecot open-source IMAP server on Rocky Linux 9/Alma Linux 9.
- And to encrypt our communications, we need a TLS certificate.
Open Ports in Firewall
Run the following command to open email-related ports in the firewall.
sudo firewall-cmd --permanent --add-service={http,https,smtp-submission,smtps,imap,imaps}
If you use POP3 to fetch emails (I personally don’t), then also add the pop3
and pop3s
service.
sudo firewall-cmd --permanent --add-service={pop3,pop3s}
Reload firewalld for the change to take effect.
sudo systemctl reload firewalld
Securing Email Server Traffic with TLS Certificate
When we configure a desktop email client, enabling encryption is always a good idea. We can easily obtain a free TLS certificate from Let’s Encrypt. Issue the following commands to install Let’s Encrypt client (certbot) from the EPEL repository.
Rocky Linux 9/Alma Linux 9
sudo dnf install epel-release -y sudo dnf install certbot -y
RHEL 9
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm sudo dnf install certbot -y
If you don’t have a web server running yet, I recommend you install one (Apache or Nginx), because it’s easier to obtain and install TLS certificate with a web server than using other methods. And in a later tutorial, I will show you how to set up webmail, which requires running a web server.
Note that your Rocky Linux 9/Alma Linux 9 server might ship with Apache web server by default.
Apache
If you prefer Apache, run the following command to install it.
sudo dnf install httpd -y
Start Apache and enable auto-start at boot time.
sudo systemctl start httpd sudo systemctl enable httpd
Install the Certbot Apache plugin.
sudo dnf install python3-certbot-apache -y
Nginx
If you prefer Nginx, run the following command to install it.
sudo dnf install nginx -y
Start Nginx and enable auto-start at boot time.
sudo systemctl start nginx sudo systemctl enable nginx
Install the Certbot Nginx plugin.
sudo dnf install python3-certbot-nginx -y
Obtaining TLS Certificate with Apache Web Server
You need to have an Apache virtual host for mail.your-domain.com
before obtaining Let’s Encrypt TLS certificate. Create the virtual host file:
sudo nano /etc/httpd/conf.d/mail.your-domain.com.conf
Then paste the following text into the file.
<VirtualHost *:80>
ServerName mail.your-domain.com
DocumentRoot /var/www/html/
</VirtualHost>
Save and close the file. Reload Apache for the changes to take effect.
sudo systemctl reload httpd
Once virtual host is created and enabled, run the following command to obtain Let’s Encrypt TLS certificate.
sudo certbot certonly -a apache --agree-tos --no-eff-email --staple-ocsp --email [email protected] -d mail.your-domain.com
After a while, you should see the following lines which means the certificate is successfully obtained. You can also see the directory under which your cert is stored.
Obtaining TLS Certificate with Nginx Web Server
You need to have an Nginx virtual host for mail.your-domain.com
before obtaining Let’s Encrypt TLS certificate. Create the virtual host file:
sudo nano /etc/nginx/conf.d/mail.your-domain.com.conf
Next, paste the following text into the file.
server {
listen 80;
listen [::]:80;
server_name mail.your-domain.com;
root /usr/share/nginx/html/;
location ~ /.well-known/acme-challenge {
allow all;
}
}
Save and close the file. Reload Nginx for the changes to take effect.
sudo systemctl reload nginx
Once virtual host is created and enabled, run the following command to obtain Let’s Encrypt certificate with Nginx plugin.
sudo certbot certonly -a nginx --agree-tos --no-eff-email --staple-ocsp --email [email protected] -d mail.your-domain.com
After a while, you should see the following which means the certificate is successfully obtained. You can also see the directory under which your cert is stored.
Enabling Submission Service in Postfix
To send emails from a desktop email client, we need to enable the submission
service of Postfix so that the email client can submit emails to Postfix SMTP server. Edit the master.cf
file.
sudo nano /etc/postfix/master.cf
In submission
section, uncomment or add the following lines. Please allow at least one whitespace (tab or spacebar) before each -o
. In postfix configurations, a preceding whitespace character means that this line is continuation of the previous line. (By default the submission
section is commented out. You can copy the following lines and paste them into the file, so you don’t have to manually uncomment or add new text.)
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
The above configuration enables the submission daemon of Postfix and requires TLS encryption. So later on our desktop email client can connect to the submission daemon in TLS encryption. The submission daemon listens on TCP port 587. STARTTLS is used to encrypt communications between email client and the submission daemon.
Microsoft Outlook only supports submission over port 465. If you are going to use Microsoft outlook mail client, then you also need to enable submission service on port 465 by adding the following lines in the file.
smtps inet n - y - - smtpd -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -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
Save and close the file.
Hint: The SMTP protocol is used when an email client submits emails to an SMTP server.
Next, we need to run the following two commands to specify the location of TLS certificate and private key in Postfix configuration file. Your Let’s Encrypt certificate and private key are stored under /etc/letsencrypt/live/mail.your-domain.com/
directory.
sudo postconf "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.your-domain.com/fullchain.pem" sudo postconf "smtpd_tls_key_file = /etc/letsencrypt/live/mail.your-domain.com/privkey.pem"
If you want to log TLS connections in the mail log (/var/log/maillog
), then run the following two commands.
sudo postconf "smtpd_tls_loglevel = 1" sudo postconf "smtp_tls_loglevel = 1"
To disable insecure SSL/TLS versions, open the Postfix main configuration file.
sudo nano /etc/postfix/main.cf
Add the following lines at the bottom of the file. (In Nano text editor, you can quickly go to the bottom of a file by pressing Ctrl+W
, then Ctrl+V
.)
#Force 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
Save and close the file. Then reload Postfix for the changes to take effect.
sudo systemctl restart postfix
If you run the following command, you will see Postfix is now listening on port 587 and 465.
sudo ss -lnpt | grep master
Installing Dovecot IMAP Server
Enter the following command to install Dovecot on Rocky Linux 9/Alma Linux 9 server.
sudo dnf install dovecot -y
Check Dovecot version:
dovecot --version
Sample output:
2.3.16 (7e2e900c1a)
Start Dovecot and enable auto-start at boot time.
sudo systemctl start dovecot sudo systemctl enable dovecot
Configuring Dovecot
First, edit main config file.
sudo nano /etc/dovecot/dovecot.conf
Find the following line.
#protocols = imap pop3 lmtp submission
Change this line to the following to enable IMAP protocol and LMTP protocol.
protocols = imap lmtp
If you want to use POP3 to fetch emails, then also add the POP3 protocol.
protocols = imap pop3 lmtp
Note that you should not enable the submission
protocol in Dovecot, because we have already enabled submission
service in Postfix.
Save and close the file.
Configuring Mailbox Location
mbox
is the traditional and default format for storing emails. Each user’s emails are stored in a single file /var/mail/username
. You can run the following command to find the mail spool directory.
postconf mail_spool_directory
Sample output:
mail_spool_directory = /var/mail
However, nowadays it’s almost always you want to use the Maildir
format to store email messages. The config file for mailbox location is /etc/dovecot/conf.d/10-mail.conf
.
sudo nano /etc/dovecot/conf.d/10-mail.conf
Add the following line to use the Maildir
format. Email messages will be stored under the Maildir
directory under each user’s home directory.
mail_location = maildir:~/Maildir
We also need to add the following line in the file.
mail_privileged_group = mail
Save and close the file. Then add dovecot
to the mail
group so that Dovecot can read the INBOX.
sudo gpasswd -a dovecot mail
Using Dovecot to Deliver Email to Message Store
Although we configured Dovecot to store emails in Maildir
format, by default, Postfix uses its built-in local delivery agent (LDA) to move inbound emails to the message store (inbox, sent, trash, Junk, etc), and it will be saved in mbox
format.
We need to configure Postfix to pass incoming emails to Dovecot, via the LMTP protocol, which is a simplified version of SMTP, so incoming emails will saved in Maildir
format by Dovecot. LMTP allows for a highly scalable and reliable mail system. It also allows us to use the sieve
plugin to filter inbound messages to different folders.
Edit the Dovecot main configuration file.
sudo nano /etc/dovecot/dovecot.conf
Add lmtp
to the supported protocols.
protocols = imap lmtp
Save and close the file. Then edit the Dovecot 10-master.conf file.
sudo nano /etc/dovecot/conf.d/10-master.conf
Change the lmtp service definition to the following.
service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0600 user = postfix group = postfix } }
Save and close the file. Next, edit the Postfix main configuration file.
sudo nano /etc/postfix/main.cf
Add the following lines at the end of the file. The first line tells Postfix to deliver emails to local message store via the dovecot LMTP server. The second line disables SMTPUTF8 in Postfix, because Dovecot-LMTP doesn’t support this email extension.
mailbox_transport = lmtp:unix:private/dovecot-lmtp smtputf8_enable = no
Save and close the file.
Configuring Authentication Mechanism
Edit the authentication config file.
sudo nano /etc/dovecot/conf.d/10-auth.conf
Find the following line and uncomment it by removing the #
character at the beginning.
#disable_plaintext_auth = yes
This will disable plaintext authentication when there’s no SSL/TLS encryption. Then find the following line,
#auth_username_format = %Lu
Uncomment it and change its value to %n
.
auth_username_format = %n
By default, when Dovecot tries to find or deliver emails for a user, it uses the full email address. Since in this part, we only set up canonical mailbox users (using OS users as mailbox users), Dovecot can’t find the mailbox user in full domain format ([email protected]), so we need to set auth_username_format = %n
to drop the domain part, then Dovecot should be able to find the mailbox user. This also allows us to use the full email address ([email protected]) to log in.
Next, find the following line.
auth_mechanisms = plain
This line only enables the PLAIN authentication mechanism. LOGIN is another authentication mechanism you probably want to add to support older email clients.
auth_mechanisms = plain login
Save and close the file.
Configuring SSL/TLS Encryption
Next, edit SSL/TLS config file.
sudo nano /etc/dovecot/conf.d/10-ssl.conf
You can find the following line, which requires email clients to communicate with Dovecot with TLS encryption.
ssl = required
Then find the following two lines.
ssl_cert = </etc/pki/dovecot/certs/dovecot.pem ssl_key = </etc/pki/dovecot/private/dovecot.pem
We need to replace values with the location of your SSL/TLS cert and private key. Don’t leave out the <
character. It’s necessary.
ssl_cert = </etc/letsencrypt/live/mail.your-domain.com/fullchain.pem ssl_key = </etc/letsencrypt/live/mail.your-domain.com/privkey.pem
Next, find the following line and uncomment it. (Remove the beginning # character.)
#ssl_dh = </etc/dovecot/dh.pem
Find the following line.
#ssl_min_protocol = TLSv1.2
This specifies the minimum TLS versions used by Dovecot. TLSv1.0 and TLSv1.1 are insecure. so uncomment this line, which will force Dovecot to use TLSv1.2 or TLSv1.3.
ssl_min_protocol = TLSv1.2
Then find the following line.
#ssl_prefer_server_ciphers = no
It’s a good practice to prefer the server’s order of ciphers over client’s, so uncomment this line and change the value to yes
.
ssl_prefer_server_ciphers = yes
Save and close the file. Now we need to generate the Diffie-Hellman parameter with:
sudo openssl dhparam -out /etc/dovecot/dh.pem 4096
If your mail server has a single CPU core, then this is going to take a long time (about 10 minutes). If you can’t wait, you can generate the DH parameters on your local Linux computer, then upload the file to the /etc/dovecot/
directory on the mail server.
SASL Authentication Between Postfix and Dovecot
Edit the following file.
sudo nano /etc/dovecot/conf.d/10-master.conf
Change service auth
section to the following so that Postfix can find the Dovecot authentication server. Please be careful about the syntax. Every opening bracket should be terminated by a closing bracket.
service auth { unix_listener /var/spool/postfix/private/auth { mode = 0600 user = postfix group = postfix } }
Save and close the file.
Auto-create Sent and Trash Folder
Edit the below config file.
sudo nano /etc/dovecot/conf.d/15-mailboxes.conf
To auto-create a folder, simply add the following line in the mailbox section.
auto = create
Example:
mailbox Trash { auto = create special_use = \Trash }
Some common folders you will want to create includes: Drafts
, Junk
, Trash
and Sent
. The Sent
folder will be created under the user’s home directory when the user send the first email. The Trash
folder will be created when the user deletes an email for the first time, etc. After you save and close all above config files, restart Postfix and Dovecot.
sudo systemctl restart postfix dovecot
Dovecot will be listening on port 143 (IMAP) and 993 (IMAPS), as can be seen with:
sudo ss -lnpt | grep dovecot
If there’s a configuration error, dovecot will fail to restart, so it’s a good idea to check the status of Dovecot.
systemctl status dovecot
Configure Desktop Email Client
Fire up your desktop email client such as Mozilla Thunderbird. Go to Edit
-> Account Settings
-> Account Actions
-> Add Mail Account
to add a mail account. If Thunderbird found your mail server configuration like below, simply click Done button and you will be able to read and send emails.
If Thunderbird didn’t found your mail server configuration, then click Manual config button to enter your mail server details.
- In the incoming server section, select IMAP protocol, enter
mail.your-domain.com
as the server name, choose port 143 and STARTTLS. Choosenormal password
as the authentication method. - In the outgoing section, select SMTP protocol, enter
mail.your-domain.com
as the server name, choose port 587 and STARTTLS. Choosenormal password
as the authentication method.
Hint: You can also use port 993 with SSL/TLS encryption for IMAP, and use port 465 with SSL/TLS encryption for SMTP. You should not use port 25 as the SMTP port to submit outgoing emails.
You should now be able to connect to your own email server and also send and receive emails with your desktop email client!
We use local Unix accounts as email addresses, as we did in part 1. For example, if you have a user called user1
on your CentOS/RHEL server, then you have an email address: [email protected]
, and the password for the email address is the same password for the user1
user. To create a local Unix account, run
sudo adduser user1
Then set a password for this user.
sudo passwd user1
Note: Dovecot doesn’t allow you to login with the root
account. You need to create separate user accounts.
You can list all available mailbox users with:
sudo doveadm user '*'
It’s recommended to restart Dovecot after adding users, so Dovecot can recognize new mailbox users.
sudo systemctl restart dovecot
Troubleshooting Tips
As a rule of thumb, you should always check the mail log (/var/log/maillog
) on your mail server when an error happens. The following is a list of specific errors.
Can’t login from Mail Clients
If you can’t log into your mail server from a desktop mail client, scan your mail server to find if the ports (TCP 587, 465, 143, and 993) are open. Note that you should run the following command from another Linux computer or server. If you run it on your mail server, then the ports will always appear to be open.
sudo nmap mail.your-domain.com
And check if Dovecot is running.
systemctl status dovecot
You can also check the mail log (/var/log/maillog
), which may give you some clues. If Dovecot fails to start, the error might not be logged to the /var/log/maillog
file, you can run the following command to see what’s wrong.
sudo journalctl -eu dovecot
For example, some folks may have the following error in the journal.
doveconf: Fatal: Error in configuration file /etc/dovecot/conf.d/10-master.conf line 78: Unknown setting
Most of the time, it’s a simple syntax error, like a missing curly bracket. Open the configuration file, go to the specified line and fix the error.
Cloudflare DNS
As I said in part 1, if you use Cloudflare DNS service, you should not enable the CDN (proxy) feature when creating DNS A record and AAAA record for the hostname of your mail server. Cloudflare doesn’t support SMTP or IMAP proxy.
Relay Access Denied
If you see the “relay access denied” error when trying to send emails from a mail client, it’s most likely that you use port 25 as the SMTP port in your mail client. As I said a while ago, you should use port 587 or 465 as the SMTP port in mail clients (Mozilla Thunberbird, Microsoft Outlook, etc) to submit outgoing emails. Port 25 should be used for SMTP server to SMTP server communications.
If you see the following “relay access denied” error in the /var/log/maillog
file when trying to send emails from other mail services like Gmail to your own mail server, it’s likely that yourdomain.com
is not in the list of $mydestination
parameter.
NOQUEUE: reject: RCPT from mail-il1-f180.google.com[209.85.166.180]: 454 4.7.1 <[email protected]>: Relay access denied; from=<[email protected]> to=<[email protected]> proto=ESMTP helo=<mail-il1-f180.google.com>
You can display the current value of $mydestination
with:
postconf mydestination
Some folks might not have the main domain name in the list like so:
mydestination = $myhostname, localhost.$mydomain, localhost
Then run the following command to add the main domain name to the list.
sudo postconf -e "mydestination = yourdomain.com, \$myhostname, localhost.\$mydomain, localhost"
Reload Postfix for the changes to take effect.
sudo systemctl reload postfix
User Doesn’t Exist
If you see the following error message in the mail log (/var/log/maillog
), it’s likely that you forgot to set auth_username_format = %n
In /etc/dovecot/conf.d/10-auth.conf
file.
mail postfix/lmtp[2256]: 68E00FC1A5: to=, relay=mail.example.com[private/dovecot-lmtp], delay=509, delays=509/0.03/0.03/0.02, dsn=5.1.1, status=bounced (host mail.example.com[private/dovecot-lmtp] said: 550 5.1.1 User doesn't exist: [email protected] (in reply to RCPT TO command))
iOS Mail App
If you use the iOS Mail app to log into your mail server and encounter the following error.
You can try to fix it by enforcing SSL encryption, for both SMTP and IMAP.
Fun fact: It seems the iOS Mail app has difficulty in supporting STARTTLS on IMAP port 143, but it supports STARTTLS on the submission port 587.
If you encounter the “No password provided” error in the iOS Mail app, it’s likely that you have a typo when entering the username in the Mail account settings, or you didn’t enable SSL in the Mail account settings.
Unable to Receive Email From Gmail, Hotmail, Yahoo Mail, etc
If you can’t receive emails from Gmail, Hotmail, Yahoo Mail, etc, here are the possible causes:
- Your MX record is wrong, or not propagated to the Internet yet.
- Your mail server hostname doesn’t have DNS A record, or not propagated to the Internet yet.
- Your firewall doesn’t allow incoming connection to port 25. Maybe your mail server is behind a NAT?
- Postfix isn’t listening on the public IP address.
- Check the mail log (
/var/log/mail.log
) to find out if there are other errors in your Postfix and Dovecot configuration.
You can use the Network Tools Email Checker to test if your SMTP server is reachable from the Internet. Just enter your domain email address and click the Go
button. As you can see from the screenshot below, it successfully found my domain’s MX record and my SMTP server is reachable from the Internet.
If your SMTP servers isn’t reachable from the Internet, then you have a problem in the first 4 items. If your SMTP server is reachable from the Internet, but you still can’t receive emails, check the mail log (/var/log/mail.log
) to find out if there is any errors in your Postfix and Dovecot configuration.
Auto-Renew TLS Certificate
You can create Cron job to automatically renew TLS certificate. Simply open root user’s crontab file.
sudo crontab -e
If you use Apache web server, add the following line at the bottom of the file.
@daily certbot renew --quiet && systemctl reload postfix dovecot httpd
If you are using Nginx web server, then add the following line.
@daily certbot renew --quiet && systemctl reload postfix dovecot nginx
Reloading Postfix, Dovecot and the web server is necessary to make these programs pick up the new certificate and private key.
Dovecot Automatic Restart
If for any reason your Dovecot process is killed, you need to run the following command to restart it.
sudo systemctl restart dovecot
Instead of manually typing this command, we can make Dovecot automatically restart by editing the dovecot.service
systemd service unit. To override the default systemd service configuration, we create a separate directory.
sudo mkdir -p /etc/systemd/system/dovecot.service.d/
Then create a file under this directory.
sudo nano /etc/systemd/system/dovecot.service.d/custom.conf
Add the following lines in the file, which will make Dovecot automatically restart 5 seconds after a failure is detected.
[Service] Restart=always RestartSec=5s
Save and close the file. Then reload systemd.
sudo systemctl daemon-reload
To check if this would work, kill Dovecot with:
sudo pkill dovecot
Then check Dovecot status. You will find Dovecot automatically restarted.
systemctl status dovecot
Next Step
I hope this article helped you set up Postfix and Dovecot on Rocky Linux 9/Alma Linux 9 server. In part 3, I will show you how to create virtual mailboxes on Rocky Linux 9/Alma Linux 9 with PostfixAdmin.
Please fix this:
file: /etc/postfix/master.cf
line: submission inet n – y – – smtpd
should be: submission inet n – n – – smtpd
Because setting it chroot doesn’t work for me and I suspect the same for others.
Remember to add ‘permit_sasl_authenticated’ in smtpd_client_restrictions and smtpd_helo_restrictions to be able to connect to your server from Outlook or other client as follow :