Skip to content

Instantly share code, notes, and snippets.

@howyay
Last active April 3, 2024 07:11
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save howyay/57982e6ba9eedd3a5662c518f1b985c7 to your computer and use it in GitHub Desktop.
Save howyay/57982e6ba9eedd3a5662c518f1b985c7 to your computer and use it in GitHub Desktop.
A guide to set up a Postfix + Dovecot IMAP server with complete spf, dkim and dmarc support.

An ultimate guide to Postfix + Dovecot IMAP server with complete SPF, DKIM and DMARC support and additional instructions for a multi-domain setup

In this guide, domain.com will be your root domain and mail.domain.com will be the hostname of your mail server

0x01 Adding DNS records

Add following DNS record to your domain

mail  IN  A   your_mail_server_ip
@     IN  MX  mail.domain.com

Additional record like SPF, DKIM, and DMARC will look similar to these

@               IN  TXT "v=spf1 mx a -all"
//SPF, no additional settings required
default._domainkey IN  TXT "v=DKIM1; h=sha256; k=rsa; p=*"
//DKIM, additional settings with opendkim is required
_dmarc          IN  TXT "v=DMARC1;p=quarantine;rua=mailto:your@email.com"
//DMARC, no additional settings required

Now we've finished setting up SPF and DMARC, we will move onto actual setup of a postfix+dovecot imap server with complete DKIM support

0x02 Set hostname

Use your favorite editor to append your hostname to /etc/hostname

/etc/hostname

mail.domain.com

0x03 Verify DNS resolution

apt-get update
apt-get upgrade

Install dnsutils

apt-get install dnsutils

Verify dns resolution

dig mx domain.com +short
dig a mail.domain.com +short

Check if the output of the second command above matches your current mail server's ip

0x04 Get SSL certificate

For additional instructions for a multi-domain mail server, check out the Appendix

apt-get update
apt-get upgrade

Install certbot

apt-get install certbot

Acquire the certificate file only

certbot --agree-tos --standalone -d mail.domain.com certonly

Fill in the information accordingly, select the standalone option when authenticating with the CA,

Put mail.domain.com when it asks you for your domain,

Finally, the certificate(cert.pem) and the private key(privkey.pem) will be saved to /etc/letsencrypt/live/mail.domain.com/

Copy the certificate file and private key to somewhere easy to access

cp /etc/letsencrypt/live/mail.domain.com/*.pem /path/to/cert/

0x05 Install and configure Postfix

apt-get update
apt-get upgrade

Install postfix and mailutils

apt-get install postfix mailutils

Select Internet Site and put domain.com

0x05.1 main.cf

For additional instructions for a multi-domain mail server, check out the Appendix

Use your favorite editor to edit /etc/postfix/main.cf

vim /etc/postfix/main.cf

Confirm your following settings

myhostname = mail.domain.com
mydomain = domain.com
myorigin = $mydomain
mydestination = $myhostname, $mydomain, localhost.$mydomain, localhost

Here you may append the path of SSL certificate and private key to where you saved them earlier and add a few additional security settings

smtpd_tls_cert_file = /path/to/cert/fullchain.pem
smtpd_tls_key_file = /path/to/cert/privkey.pem
smtpd_tls_security_level = encrypt
smtp_tls_security_level = encrypt
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

Set up for Maildir style mailbox

home_mailbox = Maildir/

Use SASL auth and prepare for dovecot installation

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions = permit_mynetworks,permit_auth_destination,permit_sasl_authenticated,reject

Add the following to prepare for opendkim setup

smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = inet:127.0.0.1:8891
milter_default_action = accept

After saving the configuration, you can use the following command to verify your main settings

postconf -n

0x05.2 master.cf

Uncomment lines as follows in /etc/postfix/master.cf

submission inet n - - - - smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -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

0x06 Setup Dovecot IMAP server

apt-get update
apt-get upgrade

Install dovecot core and imap server

apt-get install dovecot-core dovecot-imapd

Backup original dovecot configuration and create a blank one using your favorite editor

mv /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
vim /etc/dovecot/dovecot.conf

Paste contents below

disable_plaintext_auth = yes
mail_privileged_group = mail
mail_location = maildir:~/Maildir
#set mailbox location to Maildir style

userdb {
      driver = passwd
}

passdb {
     args = %s
     driver = pam
}

protocols = "imap"

namespace inbox {
  inbox = yes

  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }
  mailbox Sent {
    auto = subscribe
    special_use = \Sent
  }
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Spam {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Archive {
    auto = subscribe
    special_use = \Archive
  }
}
#create and autosubscribe to some default folders

service auth {
      unix_listener /var/spool/postfix/private/auth {
      mode = 0660
      user = postfix
      group = postfix
    }
}

ssl = required
ssl_cert = </path/to/cert/fullchain.pem
ssl_key = </path/to/cert/privkey.pem
#set your certificate

0x07 Setup DKIM signature

For additional instructions for a multi-domain mail server, check out the Appendix

apt-get update
apt-get upgrade

Install opendkim and utilities

apt-get install opendkim opendkim-tools

Generate SigningTable, KeyTable and DNS records + private key

export domain=domain.com
mkdir /etc/opendkim
mkdir /etc/opendkim/keys
mkdir /etc/opendkim/keys/$domain
cd /etc/opendkim/keys/$domain
opendkim-genkey -d $domain -s default
chown -R opendkim:opendkim /etc/opendkim/keys/$domain
echo "default._domainkey.$domain $domain:default:/etc/opendkim/keys/$domain/default.private" >> /etc/opendkim/KeyTable
echo "*@$domain default._domainkey.$domain" >> /etc/opendkim/SigningTable

DNS record will be in /etc/opendkim/keys/domain.com/default.txt, private key will be default.private in the same directory

Edit /etc/opendkim.conf

Syslog                  yes
UMask                   007

Canonicalization        relaxed/simple
Mode                    sv
SubDomains              no
AutoRestart             yes
Background              yes
DNSTimeout              5
SignatureAlgorithm      rsa-sha256

SigningTable            refile:/etc/opendkim/SigningTable
KeyTable                /etc/opendkim/KeyTable

ExternalIgnoreList      /etc/opendkim/TrustedHosts
InternalHosts           /etc/opendkim/TrustedHosts

Socket                  inet:8891@localhost

PidFile                 /var/run/opendkim/opendkim.pid
OversignHeaders         From
TrustAnchorFile         /usr/share/dns/root.key
UserID                  opendkim

Append the following to the TrustedHosts

/etc/opendkim/TrustedHosts

127.0.0.1
localhost
mail.server.ip.address
domain.com

0x08 Add a user (you)

useradd -m -s /bin/bash username
passwd username

0x08.1 Set alias (redirect mails to root to your user)

Use your favorite editor to append the following to /etc/alias/

root:   username

Refresh aliases

newaliases

0x09 Restart

Restart everything

systemctl restart postfix dovecot opendkim && postfix reload

Appendix

Multi-domain

If you want to setup multiple domains, here are some additional instructions:

Acquire multi-domain SSL certificate

certbot --agree-tos --standalone -d mail.domain.com -d mail.domain2.com certonly

Add a virtual map in postfix settings

/etc/postfix/main.cf

virtual_alias_maps=hash:/etc/postfix/virtual

Append your other domain to /etc/postfix/virtual

/etc/postfix/virtual

domain2.com		anything
#domain3.com	anything
@domain2.com	@domain.com
#@domain3.com	@domain.com

Refresh map rules

postmap /etc/postfix/virtual

Add your other domain to DKIM SigningTable and KeyTable

export domain=domain2.com
#export domain=domain3.com
mkdir /etc/opendkim
mkdir /etc/opendkim/keys
mkdir /etc/opendkim/keys/$domain
cd /etc/opendkim/keys/$domain
opendkim-genkey -d $domain -s default
chown -R opendkim:opendkim /etc/opendkim/keys/$domain
echo "default._domainkey.$domain $domain:default:/etc/opendkim/keys/$domain/default.private" >> /etc/opendkim/KeyTable
echo "*@$domain default._domainkey.$domain" >> /etc/opendkim/SigningTable

Again, the DNS record will be saved in /etc/opendkim/keys/domain#.com/default.txt and private key in default.private

Append your other domain to the end of TrustedHosts for opendkim

/etc/opendkim/TrustedHosts

domain2.com
#domain3.com

And finally, you may restart your mail server

systemctl restart postfix dovecot opendkim && postfix reload
@Jannik-Schroeder
Copy link

Jannik-Schroeder commented Jun 7, 2023

Hi super instruction. The server is running so far and can send and receive mails via cli. Unfortunately I can not log in to the user using thunderbird. Maybe you have a good matching tutorial how i can fix this

@k0Iry
Copy link

k0Iry commented Jul 5, 2023

Thanks for this guide, but I met this error while trying to login on the client:

dovecot: imap-login: Error: Failed to initialize SSL server context: Can't load SSL certificate (ssl_cert setting): There is no valid PEM certificate.: user=<>, rip=xxxx.xxxx.xxxx.xxxx, lip=10.0.0.200, session=<MZXtiL3/Kx0l5O0s>

@tzukav
Copy link

tzukav commented Nov 29, 2023

THANK YOU SO MUCH. THIS IS THE MOST COMPLETE TUTORIAL I FOUND ON THE WEB. YOU ARE AMAZING!!!!!!!!!!!!!!! IT WORKS LIKE A CHARM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment