Configuration

A detailed step-by-step setup guide walks through all of the following configuration with more and options.

Only start the mailserver after all initial configuration has been completed, and sufficient time has passed for DNS entries to update.

Important

DNS changes should be applied to all domains on which the mail server will be hosting.

Hosting multiple domains will generate different keys for each domain. Use the correct keys.

Add Initial User Accounts

Actual email accounts for users. These are accounts that will be logged into.

Warning

These passwords should be unique for the user.

Create email accounts for initial users (can use multiple domains).
docker run --rm -e MAIL_USER={EMAIL} -e MAIL_PASS={PASS} -ti tvial/docker-mailserver:latest /bin/sh -c 'echo "$MAIL_USER|$(doveadm pw -s SHA512-CRYPT -u $MAIL_USER -p $MAIL_PASS)"' >> /data/mail/server/config/postfix-accounts.cf

Note

If the docker container is already running, these can be added dynamically using the setup helper script.

Add user account to running mailserver.
./setup.sh email add {EMAIL} {PASS}

Add Aliases

Local system aliases for mail delivery.

0600 root root /data/mail/config/postfix-aliases.cf
blackhole: /dev/null

Note

blackhole alias is made to redirect specific mail to /dev/null (discard).

Add Virtual Mailboxes

Maps additional email addresses to accounts on the system. This enables a single user to have multiple email addresses, as well as catch-alls and blackhole known compromised email addresses.

0600 root root /data/mail/config/postfix-virtual.cf
# Some standard aliases.
handle@{DOMAIN} {USER}@{DOMAIN}
another_email_address@{DOMAIN} {USER}@{DOMAIN}
{USER}@{DOMAIN2} {USER}@{DOMAIN}

# Blackhole these addresses. (accept delivery and drop data).
known_spammer_email@{DOMAIN} blackhole@localhost

# Send all secondary domain emails to primary domain account.
@{DOMAIN2} {USER}@{DOMAIN}

Note

If the docker container is already running, these can be added dynamically using the setup helper script.

Add additional virtual email aliases.
./setup.sh alias add {EMAIL} {RECIPIENT}

Use Dovecot for SMTP Authentication

Set Dovecot to handle SMTP authentication for sending email. See SASL SMTP postfix options.

0600 root root /data/mail/config/postfix-main.cf
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth

Set Global Sieve Filters (Optional)

Apply global mail filtering rules before delivering mail.

See configure sieve filters. In this example, enable vacation messages (even for non-existing addresses to cover aliases) and send a message requesting the sender to update email address.

0600 root root /data/mail/config/90-sieve.conf
plugin {
  sieve = ~/.dovecot.sieve
  #sieve_default = /var/lib/dovecot/sieve/default.sieve
  sieve_dir = ~/sieve
  sieve_before = /usr/lib/dovecot/sieve-global/before.dovecot.sieve
  sieve_extensions = +notify +imapflags +vnd.dovecot.pipe +vnd.dovecot.filter
  sieve_plugins = sieve_extprograms
  #recipient_delimiter = +
  #sieve_max_script_size = 1M
  #sieve_max_actions = 32
  #sieve_max_redirects = 4
  #sieve_quota_max_scripts = 0
  #sieve_quota_max_storage = 0
  sieve_pipe_bin_dir = /usr/lib/dovecot/sieve-pipe
  sieve_filter_bin_dir = /usr/lib/dovecot/sieve-filter
  sieve_vacation_dont_check_recipient = yes
}

Note

90-sieve.conf can be copied from the server to use as a base template.

docker cp mail:/etc/dovecot/conf.d/90-sieve.conf .

Docker Compose
services:
  mail:
    volumes:
      - /data/mail/config/90-sieve.conf:/etc/dovecot/conf.d/90-sieve.conf
0644 root root /data/mail/config/before.dovecot.sieve
require "fileinto";
require "vacation";

# Automatically move flagged spam to spam folder
if header :contains "X-Spam-Flag" "YES" {
  fileinto "spam";
  stop;
}

# Allow email-update@{DOMAIN} to be delivered.
if address :is "to" "email-update@{DOMAIN}" {
  keep;
  stop;
}

# Autorespond with CM deprecation, send to special mailbox.
if address :is :domain "to" "{DOMAIN}" {
  fileinto "email-update";
  vacation
    :days 1
    :addresses "email-update@{DOMAIN}"
    :subject "[Action Required]: Your contact information is out of date."
    text:
You've recently sent an email to {DOMAIN}, which is no longer used.

Please request updated contact information by mailing:

  email-update@{DOMAIN}

and you'll receive new contact information. Please delete any current
{DOMAIN} email addresses you have, as these are now invalid.

.

;
}

Generate DKIM Config

DKIM provides a method for validating a domain name identity that is associated with an email message through cryptographic authentication.

Generate DKIM Keys for mailserver.
docker run --rm -v /data/mail/config:/tmp/docker-mailserver -ti tvial/docker-mailserver:latest generate-dkim-config

Note

Regenerate when new domains are added to the mail server.

Data is saved to /data/mail/config/opendkim/keys

Record

TXT

Name

mail._domainkey_.{DOMAIN}.

Target/Value/Data

“v=DKIM1; k=rsa; ” “p=AZER…” “aUIOPQSDF…”

TTL

5 seconds

Note

The DKIM data must be quoted for it to be properly stored. The generated data may be broken across multiple lines. Just use the content within the parentheses and separate quoted data with a single space. This allows the public key to be properly re-assembled for services that do not support large TXT record data.

Setup SPF Policy

Setup soft-failing for SPF policy enforcment.

Record

TXT

Name

mail.{DOMAIN}.

Target/Value/Data

“v=spf1 mx ~all”

TTL

300 seconds

Note

The MX for mail.{DOMAIN} must exist for this to work. see Setup Mail DNS Entries for all DNS entries required for functioning service.

Tip

Once server is verified to work, switch to enforce by changing the DNS record to: v-spf1 mx -all.

Setup DMARC Policy

Protects from phishing attacks by validating From fields. Setup DMARC for quarantine of flagged emails. The mailserver will automatically configure DMARC using the POSTMASTER_ADDRESS in the docker compose definition.

Record

TXT

Name

_dmarc.{DOMAIN}.

Target/Value/Data

“v=DMARC1; p=quarantine; rua=mailto:postmaster@{DOMAIN}”

TTL

300 seconds

Note

Use p=none to test and ensure everything is working correctly.

p=reject is the most strict but you must ensure everything is working properly; this should be the default when service is live.

All DMARC policies.

Setup SSL Certificates

The container will automtically setup all services correctly if provided the appropriate Let’s Encrypt certificates.

Note

Explicit FQDN certificates should be created for the mail server DNS name, and exist in the letsencrypt/live. See Initial Setup before proceeding.

Docker Compose
mail:
  volumes:
    - /data/letsencrypt:/etc/letsencrypt:ro

Just add the letsencrypt live directory in read-only to enable SSL connections.

Disable Unsecured Services

POP3 should not be used, and unencrypted IMAP should be disabled.

600 root root /data/mail/config/dovecot.cf
service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

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

Setup Mail DNS Entries

Setup DNS entries to allow for properly resolution of mail server. Redirect {DOMAIN} to mail.{DOMAIN} for mail inquries.

Root Domain Mail Redirect MX DNS Entry

Record

MX

Name

{DOMAIN}

Target/Value/Data

10 mail.{DOMAIN}.

TTL

300 seconds

Mail subdomain MX DNS Entry

Record

MX

Name

{DOMAIN}

Target/Value/Data

10 {IP}.

TTL

300 seconds

Mail subdomain A DNS Entry

Record

A

Name

mail.{DOMAIN}.

Target/Value/Data

10 {IP}.

TTL

300 seconds

Wildcard subdomain MX DNS Entry

Record

MX

Name

@.{DOMAIN}.

Target/Value/Data

10 mail.{DOMAIN}.

TTL

21600 seconds