Complete Mail Server Setup Guide with Postfix and Dovecot on Ubuntu Server 22.04

Tyler Maginnis | January 21, 2024

UbuntuMail ServerPostfixDovecotEmailSMTPIMAP

Need Professional Ubuntu Server Support?

Get expert assistance with your ubuntu server support implementation and management. Tyler on Tech Louisville provides priority support for Louisville businesses.

Same-day service available for Louisville area

Complete Mail Server Setup Guide with Postfix and Dovecot on Ubuntu Server 22.04

Setting up a mail server is one of the most complex tasks in system administration. This comprehensive guide walks through deploying a secure, production-ready mail server with Postfix, Dovecot, and essential security features on Ubuntu Server 22.04.

Prerequisites

  • Ubuntu Server 22.04 LTS with static IP
  • Domain name with DNS control
  • Valid SSL certificate (or use Let's Encrypt)
  • Basic understanding of email protocols
  • Minimum 2GB RAM, 20GB storage

DNS Configuration

Required DNS Records

Before starting, configure these DNS records:

# A Records
mail.example.com    A    192.168.1.100
example.com         A    192.168.1.100

# MX Record
example.com         MX   10 mail.example.com

# SPF Record
example.com         TXT  "v=spf1 mx a ip4:192.168.1.100 -all"

# DKIM Record (will be added after configuration)
# DMARC Record
_dmarc.example.com  TXT  "v=DMARC1; p=quarantine; rua=mailto:postmaster@example.com"

# PTR Record (Reverse DNS)
100.1.168.192.in-addr.arpa    PTR    mail.example.com

Initial System Setup

Set Hostname

sudo hostnamectl set-hostname mail.example.com
sudo nano /etc/hosts
127.0.0.1 localhost
192.168.1.100 mail.example.com mail

Update System

sudo apt update && sudo apt upgrade -y
sudo apt install wget curl vim net-tools -y

Postfix Installation and Configuration

Install Postfix

sudo apt install postfix postfix-mysql -y

During installation, select: - Internet Site - System mail name: example.com

Basic Postfix Configuration

sudo nano /etc/postfix/main.cf
# Basic Configuration
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
inet_interfaces = all
inet_protocols = ipv4
mydestination = $myhostname, localhost.$mydomain, localhost

# Virtual Domain Configuration
virtual_mailbox_domains = example.com
virtual_mailbox_base = /var/mail/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 100
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_alias_maps = hash:/etc/postfix/virtual

# TLS Configuration
smtpd_tls_cert_file = /etc/ssl/certs/mail.example.com.crt
smtpd_tls_key_file = /etc/ssl/private/mail.example.com.key
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_ciphers = high
smtpd_tls_mandatory_ciphers = high
tls_preempt_cipherlist = yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

# SASL Configuration
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname

# Restrictions
smtpd_relay_restrictions = 
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination

smtpd_recipient_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    reject_non_fqdn_recipient,
    reject_unknown_recipient_domain,
    reject_rbl_client zen.spamhaus.org,
    reject_rbl_client bl.spamcop.net

smtpd_sender_restrictions =
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_non_fqdn_sender,
    reject_unknown_sender_domain

# Message Size and Connection Limits
message_size_limit = 52428800
mailbox_size_limit = 0
recipient_delimiter = +
smtp_tls_security_level = may

Configure Virtual Mailboxes

# Create mail user and directories
sudo groupadd -g 5000 vmail
sudo useradd -g vmail -u 5000 vmail -d /var/mail/vhosts -m
sudo mkdir -p /var/mail/vhosts/example.com
sudo chown -R vmail:vmail /var/mail/vhosts

# Create virtual mailbox mapping
sudo nano /etc/postfix/vmailbox
info@example.com    example.com/info/
admin@example.com   example.com/admin/
user@example.com    example.com/user/
# Create virtual alias mapping
sudo nano /etc/postfix/virtual
postmaster@example.com  admin@example.com
webmaster@example.com   admin@example.com
abuse@example.com       admin@example.com
# Generate database files
sudo postmap /etc/postfix/vmailbox
sudo postmap /etc/postfix/virtual

Configure master.cf

sudo nano /etc/postfix/master.cf

Uncomment and modify these lines:

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

smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=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

Dovecot Installation and Configuration

Install Dovecot

sudo apt install dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd -y

Configure Dovecot

sudo nano /etc/dovecot/dovecot.conf
# Protocols
protocols = imap pop3 lmtp

# Listen on all interfaces
listen = *, ::

# Base directory
base_dir = /var/run/dovecot/

Configure Mail Location

sudo nano /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:/var/mail/vhosts/%d/%n
mail_privileged_group = vmail
first_valid_uid = 5000
first_valid_gid = 5000

Configure Authentication

sudo nano /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = yes
auth_mechanisms = plain login

# Comment out system auth
#!include auth-system.conf.ext

# Enable SQL auth (if using) or passwd file
!include auth-passwdfile.conf.ext

Create Password File

sudo nano /etc/dovecot/users
# Format: user@domain:password:uid:gid::/var/mail/vhosts/domain/user::
admin@example.com:{PLAIN}password123:5000:5000::/var/mail/vhosts/example.com/admin::
user@example.com:{PLAIN}password456:5000:5000::/var/mail/vhosts/example.com/user::

For encrypted passwords:

# Generate encrypted password
doveadm pw -s SHA512-CRYPT

Configure Password File Auth

sudo nano /etc/dovecot/conf.d/auth-passwdfile.conf.ext
passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /etc/dovecot/users
}

userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/users
}

Configure Master Settings

sudo nano /etc/dovecot/conf.d/10-master.conf
service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

service auth {
  unix_listener auth-userdb {
    mode = 0666
    user = vmail
    group = vmail
  }

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

  user = dovecot
}

service auth-worker {
  user = vmail
}

Configure SSL

sudo nano /etc/dovecot/conf.d/10-ssl.conf
ssl = required
ssl_cert = </etc/ssl/certs/mail.example.com.crt
ssl_key = </etc/ssl/private/mail.example.com.key
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
ssl_prefer_server_ciphers = yes

SSL Certificate Setup

Using Let's Encrypt

# Install Certbot
sudo apt install certbot -y

# Stop services temporarily
sudo systemctl stop postfix dovecot

# Get certificate
sudo certbot certonly --standalone -d mail.example.com

# Update configuration files with Let's Encrypt paths
# Postfix: /etc/postfix/main.cf
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem

# Dovecot: /etc/dovecot/conf.d/10-ssl.conf
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem

# Restart services
sudo systemctl start postfix dovecot

Auto-renewal Script

sudo nano /etc/cron.daily/renew-certificates
#!/bin/bash
certbot renew --pre-hook "systemctl stop postfix dovecot" --post-hook "systemctl start postfix dovecot"
sudo chmod +x /etc/cron.daily/renew-certificates

Spam and Virus Protection

Install SpamAssassin

sudo apt install spamassassin spamc -y
sudo systemctl enable spamassassin

Configure SpamAssassin

sudo nano /etc/default/spamassassin
ENABLED=1
OPTIONS="--create-prefs --max-children 5 --helper-home-dir"
PIDFILE="/var/run/spamd.pid"
CRON=1

Configure Postfix for SpamAssassin

sudo nano /etc/postfix/master.cf

Add after smtp line:

  -o content_filter=spamassassin

spamassassin unix -     n       n       -       -       pipe
  user=debian-spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Install ClamAV

sudo apt install clamav clamav-daemon -y
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam clamav-daemon

Install Amavis

sudo apt install amavisd-new -y

Configure Amavis

sudo nano /etc/amavis/conf.d/15-content_filter_mode

Uncomment these lines:

@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

Configure Postfix for Amavis

sudo nano /etc/postfix/main.cf

Add:

content_filter = smtp-amavis:[127.0.0.1]:10024
sudo nano /etc/postfix/master.cf

Add:

smtp-amavis unix -    -    n    -    2    smtp
  -o smtp_data_done_timeout=1200
  -o smtp_send_xforward_command=yes
  -o disable_dns_lookups=yes
  -o max_use=20

127.0.0.1:10025 inet    n    -    n    -    -    smtpd
  -o content_filter=
  -o local_recipient_maps=
  -o relay_recipient_maps=
  -o smtpd_restriction_classes=
  -o smtpd_delay_reject=no
  -o smtpd_client_restrictions=permit_mynetworks,reject
  -o smtpd_helo_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o smtpd_data_restrictions=reject_unauth_pipelining
  -o smtpd_end_of_data_restrictions=
  -o mynetworks=127.0.0.0/8
  -o smtpd_error_sleep_time=0
  -o smtpd_soft_error_limit=1001
  -o smtpd_hard_error_limit=1000
  -o smtpd_client_connection_count_limit=0
  -o smtpd_client_connection_rate_limit=0
  -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks

DKIM Configuration

Install OpenDKIM

sudo apt install opendkim opendkim-tools -y

Configure OpenDKIM

sudo nano /etc/opendkim.conf
Syslog                  yes
UMask                   007
Domain                  example.com
KeyFile                 /etc/opendkim/keys/example.com/mail.private
Selector                mail
Socket                  inet:12301@localhost
PidFile                 /var/run/opendkim/opendkim.pid
ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts           refile:/etc/opendkim/TrustedHosts
KeyTable                refile:/etc/opendkim/KeyTable
SigningTable            refile:/etc/opendkim/SigningTable

Generate DKIM Keys

sudo mkdir -p /etc/opendkim/keys/example.com
cd /etc/opendkim/keys/example.com
sudo opendkim-genkey -s mail -d example.com
sudo chown opendkim:opendkim mail.private

Configure DKIM Tables

sudo nano /etc/opendkim/KeyTable
mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com/mail.private
sudo nano /etc/opendkim/SigningTable
*@example.com mail._domainkey.example.com
sudo nano /etc/opendkim/TrustedHosts
127.0.0.1
localhost
192.168.1.0/24
example.com
mail.example.com

Add DKIM to Postfix

sudo nano /etc/postfix/main.cf

Add:

# DKIM
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

Publish DKIM Record

sudo cat /etc/opendkim/keys/example.com/mail.txt

Add the output to your DNS as a TXT record.

Webmail Setup (Roundcube)

Install Dependencies

sudo apt install apache2 php php-mysql php-xml php-mbstring php-intl php-zip php-gd php-curl php-imagick mariadb-server -y

Setup Database

sudo mysql_secure_installation
sudo mysql -u root -p
CREATE DATABASE roundcube;
CREATE USER 'roundcube'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON roundcube.* TO 'roundcube'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Install Roundcube

cd /tmp
wget https://github.com/roundcube/roundcubemail/releases/download/1.6.5/roundcubemail-1.6.5-complete.tar.gz
tar xzf roundcubemail-1.6.5-complete.tar.gz
sudo mv roundcubemail-1.6.5 /var/www/roundcube
sudo chown -R www-data:www-data /var/www/roundcube

Configure Apache

sudo nano /etc/apache2/sites-available/roundcube.conf
<VirtualHost *:80>
    ServerName webmail.example.com
    DocumentRoot /var/www/roundcube

    <Directory /var/www/roundcube>
        Options +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/roundcube_error.log
    CustomLog ${APACHE_LOG_DIR}/roundcube_access.log combined
</VirtualHost>
sudo a2ensite roundcube
sudo a2enmod rewrite
sudo systemctl restart apache2

Testing and Troubleshooting

Test SMTP

# Test local delivery
echo "Test email" | mail -s "Test Subject" admin@example.com

# Test SMTP with telnet
telnet localhost 25
EHLO mail.example.com
QUIT

# Test SMTP-AUTH
perl -MMIME::Base64 -e 'print encode_base64("admin\@example.com");'
perl -MMIME::Base64 -e 'print encode_base64("password");'

Test IMAP

telnet localhost 143
a LOGIN admin@example.com password
b SELECT INBOX
c LOGOUT

Check Logs

# Postfix logs
sudo tail -f /var/log/mail.log

# Dovecot logs
sudo tail -f /var/log/dovecot.log

# System logs
sudo journalctl -u postfix -f
sudo journalctl -u dovecot -f

Common Issues

Permission Problems

sudo chown -R vmail:vmail /var/mail/vhosts
sudo chmod -R 700 /var/mail/vhosts

Postfix Queue Management

# View queue
sudo postqueue -p

# Flush queue
sudo postqueue -f

# Delete all queued mail
sudo postsuper -d ALL

Security Best Practices

Fail2ban Configuration

sudo apt install fail2ban -y
sudo nano /etc/fail2ban/jail.local
[postfix]
enabled = true
port = smtp,ssmtp,submission
logpath = /var/log/mail.log

[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps,submission,ssmtp
logpath = /var/log/mail.log

Rate Limiting

sudo nano /etc/postfix/main.cf

Add:

# Rate limiting
smtpd_client_connection_rate_limit = 10
smtpd_client_message_rate_limit = 30
anvil_rate_time_unit = 60s

Regular Maintenance Script

sudo nano /usr/local/bin/mail-maintenance.sh
#!/bin/bash
# Mail server maintenance script

# Update spam rules
sa-update

# Update ClamAV
freshclam

# Check mail queue
queue_size=$(mailq | tail -1 | awk '{print $5}')
if [ "$queue_size" -gt 100 ]; then
    echo "Warning: Mail queue has $queue_size messages" | mail -s "Mail Queue Alert" admin@example.com
fi

# Check disk usage
disk_usage=$(df -h /var/mail | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$disk_usage" -gt 80 ]; then
    echo "Warning: Mail partition is $disk_usage% full" | mail -s "Disk Space Alert" admin@example.com
fi

# Restart services if needed
for service in postfix dovecot spamassassin clamav-daemon; do
    if ! systemctl is-active --quiet $service; then
        systemctl start $service
        echo "$service was down and has been restarted" | mail -s "Service Restart Alert" admin@example.com
    fi
done
sudo chmod +x /usr/local/bin/mail-maintenance.sh
sudo crontab -e
# Add: 0 * * * * /usr/local/bin/mail-maintenance.sh

Conclusion

This comprehensive guide covered setting up a production-ready mail server on Ubuntu Server 22.04. The configuration includes secure SMTP/IMAP services, spam filtering, virus scanning, and webmail access. Remember to regularly monitor logs, update spam rules, and maintain security patches to keep your mail server running smoothly and securely.