website-title-text

Docker Mailserver Setup

July 29, 2023

Here’s my massive docker compose file.

version: '2'

services:
  mailserver:
    image: mailserver/docker-mailserver:latest
    container_name: mailserver
    hostname: mail.plug-world.com
    ports:
      - "25:25"    # SMTP
      - "143:143"  # IMAP4
      - "993:993"  # IMAP4 TLS
      - "465:465"  # ESMTP
      - "587:587"  # ESMTP
      - "110:110"  # POP3
      - "995:995"  # POP3 (with TLS)
    volumes:
      - ./docker-data/dms/mail-data:/var/mail
      - ./docker-data/dms/mail-state:/var/mail-state
      - ./docker-data/dms/mail-logs:/var/log/mail
      - ./docker-data/dms/config:/tmp/docker-mailserver
      - /home/parker/Docker/Swag/config/etc:/swag-ssl:ro
      - /etc/localtime:/etc/localtime:ro
    environment:
      - ENABLE_FAIL2BAN=1
      - SSL_TYPE=manual
      - SSL_CERT_PATH=/swag-ssl/letsencrypt/live/plug-world.com/fullchain.pem
      - SSL_KEY_PATH=/swag-ssl/letsencrypt/live/plug-world.com/privkey.pem
      - PERMIT_DOCKER=connected-networks
      - ONE_DIR=1
      - ENABLE_POP3=1 # recieving mail
      - ENABLE_AMAVIS=1 # filtering for spam assassin
      - ENABLE_SPAMASSASSIN=1
      - ENABLE_POLICYD_SPF=1 # sender email verification
      - SPOOF_PROTECTION=1
      - POSTFIX_MESSAGE_SIZE_LIMIT=52428800
      - ENABLE_CLAMAV=1 # antivirus
      - ENABLE_OPENDKIM=1 # email verification
      - ENABLE_OPENDMARC=1 # also email verification
      - POSTMASTER_ADDRESS=postmaster@plug-world.com
      - MOVE_SPAM_TO_JUNK=1
    restart: unless-stopped
    stop_grace_period: 1m

I recommend reading through the environment variables before blindly copying my setup. But this configuration has worked really well for my personal needs. Currently I host two emails, a few aliases, and use them to send and receive mail.

You can install the setup script, this basically just makes it easier to add emails and all that fun stuff without having to use docker exec -ti <CONTAINER NAME> setup every time.

wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/setup.sh
chmod a+x ./setup.sh

For my encryption I’m just using the letsencrypt certificates created by my Swag container. I just mount the swag folder where my encryption keys are stored, and manually specify their paths. This setup will look different if you aren’t using swag so make sure you adapt it to your needs.

Adding email addresses

./setup.sh email add youremailaddress@yourdomain.com

DNS Setup

Configure openDKIM I recommend reading the docs on this first:

./setup.sh config dkim

Make sure to add the DKIM txt record to your DNS after you create it.

After setting up DKIM make sure you restart docker-mailserver.

Port forwarding

These are the ports I forwarded for receiving and sending mail.

Port Purpose
25 SMTP
587 ESMTP
465 SMTP TLS
993 IMAP4 TLS

Connecting to Thunderbird

When you login to your email with Thunderbird, use your email and password that you just created. It will try to probe the server for it’s settings, it’ll probably ask you to manually configure these settings.

Set the hostname to mail.yourdomain.com on both INCOMING SERVER and OUTGOING SERVER. Then set the port on the INCOMING SERVER to 993 which is used for IMAP.

Again these are the setting’s I used. Obviously this isn’t for everyone and you can configure it for POP3 instead and only use it for receiving mail. I recommend you get familiar with how email works and configure it the way you want. But this solution has worked great for me.

You should now be able to login to your email address. You can try sending and receiving mail now. Good luck!

Adding email aliases

./setup.sh alias add user+papertrail@domain.com user@domain.com

The first argument is the email alias you wish to add. And the second argument is the email you want to alias from. All your emails that go to your email alias will go to the email in the second argument.

./setup.sh alias list

You should now see your email alias listed after you created it.