Setup and configuration of Docker-Mailserver

Wed 05 Jun 2024

docker-mailserver is a great all in one mailserver container built on postfix, dovecot and some other open source tools. It makes getting those tools assembled into a cohesive mailserver take much less time than it might normally, and this is great for spinning up a mailserver without spending hours or days on the configuration - however, while getting it set up i noticed some pitfalls that I and other people seemed likely to fall into again, so here I am, documenting the installation process in a guide format.

Prerequisites

  • Publicly accessible server running some form of linux with docker, and preferably one which you can set the "reverse dns" of it's IP address. Check with your hosting provider.
  • A domain name
  • About 30 minutes of your time

Step 1 - Downloading Requisite Files

After ensuring all those things are present, it's time to begin. Start by going into an empty directory where you will store your mailserver's docker compose file (if you already have a composefile for other things, feel free to add to that instead)

The basic compose template is linked here. It's a lightly modified version of the one found in the excellent documentation for docker-mailserver. All that's different are the host volume mount paths (changed to absolute paths in /var and added the one necessary for TLS).

You'll want to download that, along with the environment file linked here into the directory you are using for your mailserver's compose file.

Step 2 - DNS

This step is pretty simple, log into your nameserver configuration (unless you changed something, this is probably on the website of the company you registered your domain with), and add the following records (make sure to replace yourdomain.com with your domain name):

Record Type Name/Location Value Priority (if applicable) TTL
MX yourdomain.com mail.yourdomain.com 10 5 Minutes
A mail.yourdomain.com [YOUR SERVER'S IP] NA NA
TXT yourdomain.com v=spf1 mx -all NA NA
TXT _dmarc v=DMARC1; p=quarantine; sp=quarantine; fo=0; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; rua=mailto:dmarc.report@[yourdomain.com]; ruf=mailto:dmarc.report@[yourdomain.com] NA NA

Then log in to your server provider's control panel and find where you configure the reverse DNS name, you want to set it to "mail.yourdomain.com"

We'll need to set some more DNS things later, but for now this is enough to get it up.

Step 3 - Initial Configuration

Back at your terminal, edit the "compose.yaml" file. The only thing you should need to change is the "hostname" value, change it to "mail.yourdomain.com" (changing yourdomain.com to your actual domain name). Don't worry, your email won't be displayed as coming from mail.yourdomain.com, just yourdomain.com. Save and close that file.

Next up, edit the "mailserver.env" file. There are only a few things that need setting in here, I'd recommend setting "ENABLE_SPAMASSASSIN" to 1, this will enable the open source SpamAssassin spam filter, providing you with a junk mail folder instead of letting everything through to the Inbox. If you have enough free ram on your server (atleast more than 2GB free after the running OS), you might want to enable ClamAV by setting "ENABLE_CLAMAV" to 1, to screen attachments for malware. It's not perfect, no tool is, but you may want to enable it.

The last thing that needs changing in "mailserver.env" is the TLS configuration. This allows for your connections to your mailserver to be encrypted, so that, for example, people can't read your emails if you view them on Public Wi-Fi.

To do this, set "SSL_TYPE" to "letsencrypt".

Step 4 - Generating the Certificates

First, if you have any applications listening on port 80, temporarily shut them down. During certificate generation, the letsencrypt tool needs to be able to listen on port 80, to pass the ACME HTTP-01 challenge.

At your terminal, still in the folder with the other mailserver files, run this command (replacing yourdomain.com at the end with your actual domain name):

docker run --rm -it -v "/var/dms/le:/etc/letsencrypt/" -v "${PWD}/docker-data/certbot/logs/:/var/log/letsencrypt/" -p 80:80 certbot/certbot certonly --standalone -d mail.yourdomain.com

While running this command, you will be prompted to enter an email address (enter a valid one, it's important that you get these notifications), and you will need to agree to the terms and conditions of LetsEncrypt.

You will also be asked if you wish to subscribe to the Electronic Frontier Foundation's newsletter, select Yes or No depending on your preference.

This command get letsencrypt certificates required for TLS encryption to take place. These certificates do expire after 3 months, so you may with to automate this in some manner, with something like a cronjob.

Step 5 - Starting Up

Now it's time to start up the mailserver, and see if it's working. At your terminal, still in the folder with the other mailserver files, run the following command to bring the container up:

docker compose up -d

You may be excited to connect, but not so fast, you still need to create your user account! All administrative actions with docker-mailserver are taken by executing the "setup" command inside the container, and the general format goes something like this:

docker exec -ti mailserver setup [arguments]

So to add a new user to the mailserver, do something like this:

docker exec -ti mailserver setup email add [address@yourdomain.com]

(ensure that yourdomain.com is your domain name, and without the mail subdomain infront)

You will need to restart your server after doing this. You can do this by running these two commands:

docker compose down
docker compose up -d

Step 6 - Connecting

Warning: Mail clients on the PlayStation Vita and Windows 98, NT4 and 2000 are known to have issues connecting to Docker Mailserver, this may not be a supported configuration.

Now you can connect. Open your mail client (I recommend Betterbird), and add the server with the following configuration:

  • IMAP Server: mail.yourdomain.com

  • IMAP Password: the password you set while creating your user

  • IMAP Username: address@yourdomain.com

  • IMAP Port: 993

  • IMAP Authentication: Normal Password

  • Connection Security: TLS/SSL

  • SMTP Server: mail.yourdomain.com

  • SMTP Password: the password you set while creating your user

  • SMTP Username: address@yourdomain.com

  • SMTP Port: 465

  • SMTP Authentication: Normal Password

  • Connection Security: TLS/SSL

You should then see your inbox appear, and you are now able to receive mail. But not so fast, there are still some steps you need to follow before you can send mail.

Step 7 - DomainKeys Identified Mail (DKIM)

DKIM is a method of spam prevention used by all major email providers, even your docker-mailserver instance is by default configured to verify DKIM on incoming email, to prevent some forms of spam. It's a method of using cryptographic signatures to verify that an email coming from one domain is actually coming from that domain. If you want emails from your server to be accepted by major email providers, you will need to set this up.

Luckily, it's not very difficult. You will first need to generate your DKIM keys, using the following command:

docker exec -ti mailserver setup config dkim

Then, you must add your DKIM "public key" to your domain's DNS records, so that other servers may use it to verify incoming email from your domain. Now, this is a bit annoying, but just stick with it, this is the last step now.

First, you need to get the contents of the file located at "/var/dms/config/opendkim/keys/[yourdomain.com]/mail.txt" (not mail.private) It should look something like this:

mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQMMqhb1S52Rg7VFS3EC6JQIMxNDdiBmOKZvY5fiVtD3Z+yd9ZV+V8e4IARVoMXWcJWSR6xkloitzfrRtJRwOYvmrcgugOalkmM0V4Gy/2aXeamuiBuUc4esDQEI3egmtAsHcVY1XCoYfs+9VqoHEq3vdr3UQ8zP/l+FP5UfcaJFCK/ZllqcO2P1GjIDVSHLdPpRHbMP/tU1a9mNZ"
"5QMZBJ/JuJK/s+2bp8gpxKn8rh1akSQjlynlV9NI+7J3CC7CUf3bGvoXIrb37C/lpJehS39KNtcGdaRufKauSfqx/7SxA0zyZC+r13f7ASbMaQFzm+/RRusTqozY/p/MsWx8QIDAQAB"
) ;

The next bit is a bit tricky, i've written a handy tool to do it automatically, but if you want to, you can do it yourself.

The automatic way Put the contents of your mail.txt file into the input box, click run, then copy the contents of the output box. That's it.

Input:


Output:

Doing it manually You need to take all the text between the brackets, and combine the contents, removing the quotes and the blank space between the quotes, but leaving any blank space inside the quotes. That example would now look like this:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQMMqhb1S52Rg7VFS3EC6JQIMxNDdiBmOKZvY5fiVtD3Z+yd9ZV+V8e4IARVoMXWcJWSR6xkloitzfrRtJRwOYvmrcgugOalkmM0V4Gy/2aXeamuiBuUc4esDQEI3egmtAsHcVY1XCoYfs+9VqoHEq3vdr3UQ8zP/l+FP5UfcaJFCK/ZllqcO2P1GjIDVSHLdPpRHbMP/tU1a9mNZ5QMZBJ/JuJK/s+2bp8gpxKn8rh1akSQjlynlV9NI+7J3CC7CUf3bGvoXIrb37C/lpJehS39KNtcGdaRufKauSfqx/7SxA0zyZC+r13f7ASbMaQFzm+/RRusTqozY/p/MsWx8QIDAQAB

Take that combined string and add a new TXT record to your domain, the name being "mail._domainkey" and the contents being that combined string. You have now configured DKIM signing on your outgoing mail.

The End!

You should now have a complete and functioning mailserver, with IMAP access and DKIM signing of outgoing mail.

Acknowledgements:

Most of this guide is adapted from the great docker-mailserver documentation, augmented and rearranged to hopefully prevent people from falling into the same issues that I did. For further configuration or to read the original, it can be found here

Thanks to Juli for beta testing the first version of this guide julimiro.eu

Tags:

silly cute flower in the corner of the page