Title Picture from www.freepik.com
Source: https://www.linuxbabe.com/mail-server/setup-basic-postfix-mail-sever-ubuntu
For saving money and taking the full control of the service, I decided to setup my own postfix email server on a Ubuntu virtual server. And this article recorded the process.
1. Prerequisites
There are a set of tasks that should be finished before we even get to Postfix.
1.1. Setup DNS
The DNS records should look like this:
HOSTNAME TTL TYPE PRIO VALUE
# Where to find the server
mail.[DOMAIN_NAME] 57600 A [IP-ADDRESS]
# If the request is related to email, then forward to mail sub-domain
[DOMAIN_NAME] 57600 MX 10 mail.[DOMAIN_NAME]
# Optional, only used for setting up MUA (mail user agent)
autoconfig.[DOMAIN_NAME] 57600 CNAME mail.[DOMAIN_NAME]
# Optional, only used for setting up MUA
autodiscover.[DOMAIN_NAME] 57600 CNAME mail.[DOMAIN_NAME]
The core of the DNS records is the A and the MX records. The A record defines the mail sub-domain pointing to the actual mail server, and the MX record redirects the mail request from the main domain to the sub-domain, so that we could use the domain name like user@[DOMAIN_NAME] instead of user@mail.[DOMAIN_NAME].
If there is an IPv6 address, we should also set up the AAAA record for the mail sub-domain.
1.2. Setup the Reverse DNS
After DNS records have been updated, go to the hosting server provider, and set the reverse DNS from the IP-Adress back to the domain name (mail.[DOMAIN_NAME]).
1.3. Firewall Setup
Enable the port 25 and 465.
This has to be done for both inbound and also outbound, otherwise either sending or recieving mails won’t work. Note that the outbound rules sometimes are disabled by hosting service providers, so we have to create a service ticket for them to enable the 2 ports for us.
1.4. Change the Hostname
Since the Postfix reads the hostname of the server to identify itself while communicating with other MTA (message transfer agent), it is important to change the hostname to match the hostname in the DNS record:
Use following command to see what the current hostname is:
hostname -f
If it is not the one configured in the DNS record, change it using the following command:
hostnamectl set-hostname mail.[DOMAIN_NAME]
2. Installation
Finally all the preparation work is done, we can install the Postfix now.
2.1. Basic Installation
Update the package manager and the installed packages first:
apt upgrade
apt update
reboot
And then install the postfix package:
apt install postfix
Then a dialog will be displayed asking us how we want to configure Postfix. In my case, I should set it to Internal Site, this is useful for most of the cases.
In the next step, I should enter my “System mail name”. Here I should make it [DOMAIN_NAME] instead of mail.[DOMAIN_NAME], because if I set it to the latter, I won’t be able to send/receive Emails from [DOMAIN_NAME] domain.
To verify the mail service, use following command:
postconf mail_version
If everything works fine, the version number will be printed to the standard output.
We could also check who is now listening to port 25:
ss -lnpt | grep master
The output should look like this:
LISTEN 0 100 0.0.0.0:25 0.0.0.0:* users:(("master",pid=2633,fd=13))
LISTEN 0 100 [::]:25 [::]:* users:(("master",pid=2633,fd=14))
If we compare the PID with the result from ps, we should find that it is the Postfix process.
2.2. Send/Receive Test Emails
To send Email, I can use the mail command in the mailutils package in Ubuntu:
apt install mailutils
Then write a short mail:
mail -a FROM:[USER]@[DOMAIN_NAME] user@example.com
Cc:
Subject: Test
This Email is sent from a newly setup mail server.
To send the Email, press Ctrl + D, and after a few seconds, the mail should be found in the mailbox.
To receive Email, use mail command:
mail
It will start an interactive CLI environment. Use ? and Enter for a short command instructions. Some useful commands are:
1: Read the first mailh: List the head of the mailsd 1: Delete first mailq: Quit program
3. Setup TLS Encryption and IMAP
There are still 2 problems after all the setup:
- All the Emails are transmitted in Internet in clear text.
- We can’t use any mail client to connect to the server.
So this paragraph will provide solutions for these two problems.
3.1. Enable More Ports in Firewall
To setup TLS and IMAP, I have to enable more ports:
80and443– to sign the TLS signature using certbot587– for encrypted SMTP465– for encrypted SMTP (deprecated)143– for non-encrypted IMAP993– for encrypted IMAP
3.2. Install Nginx and Certbot and Request for SSL Certificate
apt install nginx
snap install --classic cerbot
As an alternative to install certbot from snap, we could also use:
pip install certbot certbot-nginx
Provide an Nginx site config like this and put it into /etc/nginx/sites-enabled, name it like mail.[DOMAIN_NAME]:
server {
listen 80;
listen [::]:80;
server_name mail.[DOMAIN_NAME];
root /usr/share/nginx/html/;
location ~/.well-known/acme-challenge {
allow all;
}
}
Request a new certificate using certbot:
certbot certonly --nginx -d mail.[DOMAIN_NAME]
In this case, certbot won’t change the settings in the nginx, it just tries to get a new certificate.
After the interactive script, the certificate files will be saved:
- Certificate file:
/etc/letsencrypt/live/mail.[DOMAIN_NAME]/fullchain.pem - Key file:
/etc/letsencrypt/live/mail.[DOMAIN_NAME]/privkey.pem
3.3. Setup SMTP
Edit the /etc/postfix/master.cf file, and add following two blocks into the file:
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
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
Edit the /etc/postfix/main.cf file, modify the # TLS parameters section:
# TLS parameters
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.[DOMAIN_NAME]/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.[DOMAIN_NAME]/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
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
And then restart Postfix service:
systemctl restart postfix
After that, if I check the port which is listened by master, I can see there are not only port 25, but also 465 and 587 opened:
ss -lnpt | grep master
The result should be like:
LISTEN 0 100 0.0.0.0:25 0.0.0.0:* users:(("master",pid=12881,fd=13))
LISTEN 0 100 0.0.0.0:465 0.0.0.0:* users:(("master",pid=12881,fd=22))
LISTEN 0 100 0.0.0.0:587 0.0.0.0:* users:(("master",pid=12881,fd=18))
LISTEN 0 100 [::]:25 [::]:* users:(("master",pid=12881,fd=14))
LISTEN 0 100 [::]:465 [::]:* users:(("master",pid=12881,fd=23))
LISTEN 0 100 [::]:587 [::]:* users:(("master",pid=12881,fd=19))
3.4. Install and Setup Dovecot to Enable IMAP
To install Dovecot, simply run:
apt install dovecot-core dovecot-imapd dovecot-lmtpd
After that, edit Dovecot configruation file /etc/dovecot/dovecot.conf to enable IMAP. Add one line:
# Enable installed protocols
protocols = imap lmtp # Add this line
!include_try /usr/share/dovecot/protocols.d/*.protocol
Edit /etc/dovecot/conf.d/10-mail.conf to config it using the Maildir instead of mbox directory structure:
mail_location = maildir:~/Maildir # Modify this line
mail_privileged_group = mail # This line should be already there, just check it
After that we want to add the user dovecot to the mail group:
adduser dovecot mail
Open the /etc/dovecot/conf.d/10-master.conf file and edit the service lmtp and service auth section:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
# Create inet listener only if you can't use the above UNIX socket
#inet_listener lmtp {
# Avoid making LMTP visible for the entire internet
#address =
#port =
#}
}
service auth {
# auth_socket_path points to this userdb socket by default. It's typically
# used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
# full permissions to this socket are able to get a list of all usernames and
# get the results of everyone's userdb lookups.
#
# The default 0666 mode allows anyone to connect to the socket, but the
# userdb lookups will succeed only if the userdb returns an "uid" field that
# matches the caller process's UID. Also if caller's uid or gid matches the
# socket's uid or gid the lookup succeeds. Anything else causes a failure.
#
# To give the caller full permissions to lookup all users, set the mode to
# something else than 0666 and Dovecot lets the kernel enforce the
# permissions (e.g. 0777 allows everyone full permissions).
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
# Postfix smtp-auth
#unix_listener /var/spool/postfix/private/auth {
# mode = 0666
#}
# Auth process is run as this user.
#user = $default_internal_user
}
Edit /etc/postfix/main.cf file, and add following 2 lines at the bottom of the file:
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtputf8_enable = no
Edit /etc/dovecot/conf.d/10-auth.conf file, edit multiple places:
disable_plaintext_auth = yes # Uncomment this line
auth_username_format = %n # Uncomment and modify this line
auth_mechanisms = plain login # Modify this line
Edit /etc/dovecot/conf.d/10-ssl.conf, edit multiple places:
ssl = required # Modify this line
ssl_cert = </etc/letsencrypt/live/mail.[DOMAIN_NAME]/fullchain.pem
# Modify this line
ssl_key = </etc/letsencrypt/live/mail.[DOMAIN_NAME]/privkey.pem
# Modify this line
ssl_prefer_server_ciphers = yes # Uncomment and modify this line
ssl_min_protocol = TLSv1.2 # Uncomment and modify this line
Edit /etc/ssl/openssl.cnf file, and comment one line to disable FIPS:
#providers = provider_sect # Comment this line
Edit /etc/dovecot/conf.d/15-mailboxes.conf file, and edit it. This tells dovecot to create default folders automatically. Besides, it will also avoid to create 2 different folders for the \Sent usage (previously there are “Sent” and “Sent Messages”):
mailbox Drafts {
auto = create
special_use = \Drafts
}
mailbox Junk {
auto = create
special_use = \Junk
}
mailbox Trash {
auto = create
special_use = \Trash
}
mailbox Sent {
auto = create
special_use = \Sent
}
And finally restart everything that I have configured:
systemctl restart postfix dovecot
And check whether dovecot is up and running:
ss -lnpt | grep dovecot
The result should be like:
LISTEN 0 100 0.0.0.0:143 0.0.0.0:* users:(("dovecot",pid=18756,fd=36))
LISTEN 0 100 0.0.0.0:993 0.0.0.0:* users:(("dovecot",pid=18756,fd=38))
LISTEN 0 100 [::]:143 [::]:* users:(("dovecot",pid=18756,fd=37))
LISTEN 0 100 [::]:993 [::]:* users:(("dovecot",pid=18756,fd=39))
4. Use MUA (Mail User Agent) to Connect to the Server
4.1. Create User for Mail
Postfix will use the system users as Email users. So create a user like this:
useradd -d /home/[UNIX_USERNAME] -s /bin/false [UNIX_USERNAME]
mkdir /home/[UNIX_USERNAME]
chown [UNIX_USERNAME]:[UNIX_USERGRP] /home/[UNIX_USERNAME]
passwd [UNIX_USERNAME]
4.2. Setup MUA
Using following data to setup the Mail Client:
Name: [MAIL_NAME]
EMail Address: [UNIX_USERNAME]@[DOMAIN_NAME]
# IMAP Mail Server
Host: mail.[DOMAIN_NAME]
Port: 143
User Name: [UNIX_USERNAME]
Security: STARTTLS
Authentication Method: Normal password
# SMTP Server
Host: mail.[DOMAIN_NAME]
Port: 587
User Name: [UNIX_USERNAME]
Security: STARTTLS
Authentication Method: Normal password
5. Setup SPF
SPF or DKIM is a way to verify the ownership of the mail server, so that some famous mail service provider can ensure that our mail server is not a spammer. Since SPF is easier than DKIM, I have only setup SPF.
To do this, simply add a DNS record:
HOSTNAME TTL TYPE PRIO VALUE
[DOMAIN_NAME] A v=spf1 mx ~all
And it is done.


