Some Computer Hints

Ubuntu Mail Configuration

Mail server configuration is one of the most difficult aspects of Linux server configuration. I generally use Postfix and Dovecot on my Ubuntu VPS’s. I have prepared the following rough checklist which I used during my latest (Ubuntu 22.04) mail server configuration.

The following assumes that:

  • You have created your Ubuntu VPS Server and you have command line root access (via sudo -i) to your server.
  • All DNS configuration for your domain(s) is completed and you have control of your DNS server(s).
  • You have opened inbound ports 25/tcp (smtp), 587/tcp (submission), and 995/tcp (pop3s).
  • Your VPS provider supports outbound 25/tcp (smtp) connections (most providers do not).
  • Your domain name is something like, your server hostname is something like, and your MX record for your domain is something like

Installation and Initial Configurations


# apt install postfix
# dpkg-reconfigure postfix
# /etc/init.d/postfix restart
# cat >/etc/postfix/sasl/smtpd.conf
pwcheck_method: saslauthd
mech_list: plain login


# cat >/etc/profile.d/
export MAIL=$HOME/Maildir

Use the instructions at to create virtual mailboxes for separate domains and non-Linux accounts; to create a virtual mailbox owner; and to set up Postfix to use virtual mailboxes.

Install Dovecot:

# apt install dovecot-core dovecot-imapd dovecot-pop3d
# apt autoremove

Configure /etc/dovecot/local.conf file (as explained in “Configure Dovecot / file /etc/dovecot/dovecot.conf / Ubuntu 12.04”) and change ssl = yes in the file.

Add /usr/local/sbin/adddovecotuser and /usr/local/sbin/deldovecotuser scripts.

Add Dovecot (POP3, IMAP) users, like:

# adddovecotuser

Check configurations once more with the below:



SSL & Auth


Configure Postfix for SMTP-AUTH using SASL (Dovecot SASL):

# postconf -e 'smtpd_sasl_auth_enable = yes'
# postconf -e 'smtpd_sasl_security_options = noanonymous'
# postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination'
# postconf -e 'smtpd_sasl_type = dovecot'
# postconf -e 'smtpd_sasl_path = private/auth'
# postconf -e 'smtpd_sasl_local_domain ='
# postconf -e 'broken_sasl_auth_clients = yes'


If your secure server is to be used in a production environment, you probably need a CA-signed certificate. It is not recommended to use a self-signed certificate. Obtain a digital certificate for TLS from Let’s Encrypt. Assuming the CA (letsencrypt) certificate resides in the /etc/letsencrypt/live/ directory, run the following:

# postconf -e 'smtpd_tls_key_file = /etc/letsencrypt/live/'
# postconf -e 'smtpd_tls_cert_file = /etc/letsencrypt/live/'

Configure Postfix to provide TLS encryption for both incoming and outgoing mail:

# postconf -e 'smtp_tls_security_level = may'
# postconf -e 'smtpd_tls_security_level = may'
# postconf -e 'smtp_tls_note_starttls_offer = yes'
# postconf -e 'smtpd_tls_loglevel = 1'
# postconf -e 'smtpd_tls_received_header = yes'
# postconf -e 'myhostname ='
# postconf -e 'smtp_helo_name ='

SMTP Authentication

Postfix supports two SASL implementations Cyrus SASL and Dovecot SASL.

Check the files /etc/dovecot/conf.d/10-master.conf and /etc/dovecot/conf.d/10-auth.conf as described in (Configuring SASL):

File /etc/dovecot/conf.d/10-master.conf:

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix

File /etc/dovecot/conf.d/10-auth.conf:

auth_mechanisms = plain login

and uncomment the following line:

disable_plaintext_auth = yes

Change also the following files:


mail_location = maildir:~/Maildir


pop3_uidl_format = %08Xu%08Xv

Dovecot SSL Configuration

After a letsencrypt certificate is obtained and assuming that the certificate files are in /etc/letsencrypt/live/ directory:

# cd /etc/dovecot/private
# mv dovecot.key dovecot.key.old
# mv dovecot.pem dovecot.pem.old
# ln -s /etc/letsencrypt/live/   dovecot.key
# ln -s /etc/letsencrypt/live/ dovecot.pem

Note: The configuration file for Dovecot SSL is: /etc/dovecot/conf.d/10-ssl.conf. As an alternative, you can change the ssl_cert and ssl_key entries in that file.

Configure for Mail Submission (port 587)

Edit /etc/postfix/ like this:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_tls_auth_only=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

and run:

# /etc/init.d/postfix restart

Other Configurations


# postconf -e ' smtpd_banner = ESMTP'

Check your IP address’ abuse status (replace myipaddress with your real external IP address in the link below):


Extra configurations for spam control


Put _SPF and _DMARC records in your DNS



Add the following TXT DNS records to your mail sending ( zone configuration file:

	IN TXT	"v=spf1 ~all"
mail	IN TXT	"v=spf1 ~all"
_dmarc	IN TXT	"v=DMARC1; p=none; rua=mailto:your_email_address; ruf=mailto:your_email_address; sp=reject; ri=86400"
_spf	IN TXT	"v=spf1 ip4:ip_addr1 ip6:ip_addr2 ip4:ip_addr3 ~all"

Here, ip_addrX is the IP address(es) of your email server(s).

Check SPF records at

Tell Postfix to check for SPF records for incoming emails



# apt install postfix-policyd-spf-python

Add the following lines at the end of /etc/postfix/

policyd-spf  unix  -       n       n       -       0       spawn
    user=policyd-spf argv=/usr/bin/policyd-spf

Merge the following lines into /etc/postfix/

policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =
   check_policy_service unix:private/policyd-spf

The first line specifies the Postfix policy agent timeout setting. The following lines will impose restriction on incoming emails by checking SPF records.

# systemctl restart postfix

Setting up DKIM



# apt install opendkim opendkim-tools

Add postfix user to opendkim group:

# gpasswd -a postfix opendkim

Uncomment the following lines in /etc/opendkim.conf: (Replace simple with relaxed/simple.)

Canonicalization   relaxed/simple
Mode               sv
SubDomains         no

Add the following below “SubDomains no”:

AutoRestart		yes
AutoRestartRate		10/1M
Background		yes
DNSTimeout		5
SignatureAlgorithm 	rsa-sha256

Add the following to the end of the file:

#OpenDKIM user
# Remember to add user postfix to group opendkim
UserID		opendkim

# Map domains in From addresses to keys used to sign messages
KeyTable		/etc/opendkim/key.table
SigningTable		refile:/etc/opendkim/signing.table

# Hosts to ignore when verifying signatures
ExternalIgnoreList	/etc/opendkim/trusted.hosts
InternalHosts		/etc/opendkim/trusted.hosts

Create signing table, key table and trusted hosts file:

# mkdir /etc/opendkim
# mkdir /etc/opendkim/keys
# chown -R opendkim:opendkim /etc/opendkim
# chmod go-rw /etc/opendkim/keys
# echo '* default._domainkey.mydomain' \
# echo 'default._domainkey.mydomain' \
 '' \
# echo '
*' >/etc/opendkim/trusted.hosts

Generate private/public key pair:

# mkdir /etc/opendkim/keys/
# opendkim-genkey -b 2048 -d \
 -D /etc/opendkim/keys/ -s default -v
# chown opendkim:opendkim /etc/opendkim/keys/

Get contents of public key:

# cat /etc/opendkim/keys/

Insert it into your DNS records (for example, update /etc/bind/ if you are using BIND) and check:

# opendkim-testkey -d -s default -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key ''
opendkim-testkey: key not secure
opendkim-testkey: key OK

Connect Postfix to OpenDKIM:

# mkdir /var/spool/postfix/opendkim
# chown opendkim:postfix /var/spool/postfix/opendkim

Edit the socket configuration file /etc/opendkim.conf and replace “Socket local:/var/run/opendkim/opendkim.sock” with:

Socket			local:/var/spool/postfix/opendkim/opendkim.sock

Add the following to the end of /etc/postfix/

# Milter configuration
# OpenDKIM
milter_default_action = accept
milter_protocol = 2
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = local:/opendkim/opendkim.sock


# systemctl restart opendkim ; systemctl restart postfix

To check DKIM send a test email to A report like this should be returned from

Summary of Results
SPF check:           pass
"iprev" check:       pass
DKIM check:          pass
SpamAssassin check:  ham

Whitelist Hosts/IP Addresses

To whitelist some servers from spam lists:

# cat >/etc/postfix/rbl_override
## Don't forget: postmap /etc/postfix/rbl_override
my_ip OK OK

add a:

	check_client_access hash:/etc/postfix/rbl_override,

line to smtpd_recipient_restrictions = entry in /etc/postfix/ file and run:

# postmap /etc/postfix/rbl_override
# /etc/init.d/postfix restart

Mail Operations

# postmap /etc/postfix/vmaps; \
  postmap /etc/postfix/valiases; \
  systemctl restart postfix

Sample contents of configuration files

# cat /etc/postfix/vhosts
# cat /etc/postfix/vmaps

To define mail address aliases:

# cat /etc/postfix/valiases

Mail Queue Management

# mailq
# qshape deferred	# show deferred mails
# mailq -q		# attempt to deliver all queued mail!
# postsuper -d ALL	# delete all (or specific) queued mails from mailq
# postcat -q queue_id	# show contents of mail queued with queue_id




Final contents of /etc/postfix/

The order of lines may be different:

smtpd_banner = ESMTP
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 3.6
smtpd_tls_cert_file = /etc/letsencrypt/live/
smtpd_tls_key_file = /etc/letsencrypt/live/
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_relay_restrictions = permit_mynetworks,permit_sasl_authenticated,defer_unauth_destination
myhostname =
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = localhost.localdomain, localhost
relayhost =
mynetworks = [::ffff:]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination,
	check_client_access hash:/etc/postfix/rbl_override,
	check_policy_service unix:private/policyd-spf
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
home_mailbox = Maildir/
virtual_mailbox_domains = /etc/postfix/vhosts
virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = hash:/etc/postfix/vmaps
virtual_minimum_uid = 1000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_alias_maps = hash:/etc/postfix/valiases
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_local_domain =
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
smtpd_sasl_auth_enable = yes
smtp_helo_name =
disable_vrfy_command = yes
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_data_restrictions = reject_unauth_pipelining
anvil_rate_time_unit = 600
anvil_status_update_time = 3600
policyd-spf_time_limit = 3600
milter_default_action = accept
milter_protocol = 2
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = local:/opendkim/opendkim.sock

Checking Once More Everything

Step by step check:


Test your sending email configuration using: