Skip to main content

Deploy your own mail server using Docker-Mailserver

·4 mins
Gerald Gnaegy
Author
Gerald Gnaegy
I love solving problems and blog here about Python, Docker, IT automation and technology.
Table of Contents

Introduction
#

Setting up a secure and easy-to-administer mail server can be challenging. Docker-Mailserver simplifies this process by providing a production-ready, full-stack containerized mail server (SMTP, IMAP, Anti-spam, Anti-virus, etc.). Using only configuration files, it keeps everything simple and versioned, eliminating the need for SQL databases.

With Docker-Mailserver and this article, you can set up your mail server within an hour, even if you have no prior knowledge.

Prerequisites
#

  • Docker running on a Linux Server
  • A domain name with the ability to change DNS entries

Project structure
#

We’ll use the same project structure as in my article about Traefik + Authelia:

mkdir -p $HOME/docker-projects/docker-mailserver
cd $HOME/docker-projects/docker-mailserver

Set up Docker-Mailserver
#

Create docker-compose.yml
#

Download the docker-compose.yml file for docker-mailserver:

curl -o docker-compose.yml https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/compose.yaml

Modify the docker-compose.yml file. Adjust hostname according to your FQDN:

services:
  mailserver:
    image: ghcr.io/docker-mailserver/docker-mailserver:latest
    container_name: mailserver
    # Provide the FQDN of your mail server here (Your DNS MX record should point to this value)
    hostname: mail.example.com
    env_file: mailserver.env
    # More information about the mail-server ports:
    # https://docker-mailserver.github.io/docker-mailserver/latest/config/security/understanding-the-ports/
    ports:
      - "25:25"    # SMTP  (explicit TLS => STARTTLS, Authentication is DISABLED => use port 465/587 instead)
      - "143:143"  # IMAP4 (explicit TLS => STARTTLS)
      - "465:465"  # ESMTP (implicit TLS)
      - "587:587"  # ESMTP (explicit TLS => STARTTLS)
      - "993:993"  # IMAP4 (implicit 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/
      - /etc/localtime:/etc/localtime:ro
    restart: always
    stop_grace_period: 1m
    # Uncomment if using `ENABLE_FAIL2BAN=1`:
    # cap_add:
    #   - NET_ADMIN
    healthcheck:
      test: "ss --listening --tcp | grep -P 'LISTEN.+:smtp' || exit 1"
      timeout: 3s
      retries: 0

Create mailserver.env
#

Download the mailserver.env:

curl -o mailserver.env https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/mailserver.env

Review and adjust the file as needed. For example, to set your timezone:

TZ=Europe/Berlin

Activate Spam Protection
#

In mailserver.env, configure spam protection:

ENABLE_OPENDKIM=0
ENABLE_OPENDMARC=0
ENABLE_POLICYD_SPF=0
ENABLE_CLAMAV=1
ENABLE_RSPAMD=1
RSPAMD_LEARN=1

Set Up SSL Certificates
#

If you’re using Traefik, add this section to your docker-compose.yml:

services:
   mailserver:
   #...

    whoami:
        image: docker.io/traefik/whoami:latest
        networks:
        - docknet
        labels:
        - 'traefik.enable=true'
        - 'traefik.http.routers.mail.rule=Host(`mail.example.com`)'
        - 'traefik.http.routers.mail.entrypoints=https'
        - 'traefik.http.routers.mail.tls=true'
        - 'traefik.http.routers.mail.tls.certresolver=letsencrypt'
        - 'traefik.http.routers.mail.middlewares=authelia@docker'
        - 'traefik.http.routers.mail.service=mail-service'
        - 'traefik.http.services.mail-service.loadbalancer.server.port=80'
        expose:
        - 80
        logging:
        driver: "json-file"
        options:
            max-size: "1m"

networks:
    docknet:
        name: docknet
        external: true

Start the Server
#

Now, start your Docker-Mailserver:

docker compose up -d

Create Mail Addresses
#

Create the postmaster address:

docker exec -it mailserver setup email add postmaster@example.com very-secret-password

Create additional email addresses:

docker exec -it mailserver setup email add your.name@example.com another-s3c3t-password

Create alias addresses. All emails sent to hello@example.com will be then forwarded to your.name@example.com:

docker exec -it mailserver setup alias add hello@example.com your.name@example.com

DNS Setup
#

Basic
#

In my article Single-Sign-On using Traefik 3, Authelia 4 and Let’s Encrypt SSL, I already created some wildcard DNS records for my domain name.

In addition, we need a MX record which indicates the Fully Qualified Domain Name (FQDN) under which the mail server for a domain or subdomain can be reached. Let’s add a MX DNS record:

Type Name Content
MX @ mail.example.com

Advanced
#

DKIM
#

Run this command to generate DKIM keys:

docker exec -it mailserver setup config dkim

Then add a DNS TXT record:

Type Name Content
TXT mail._domainkey v=DKIM1; k=rsa; p=MIIxxx

DMARC
#

We don’t need to generate DMARC keys, but we have to add a TXT entry for DMARC:

Type Name Content
TXT _dmarc.example.com. v=DMARC1; p=none; sp=none; fo=0; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; rua=mailto:postmaster@example.com; ruf=mailto:postmaster@example.com

SPF
#

Add also a TXT entry for TXT:

Type Name Content
TXT example.com. v=spf1 mx ~all

Conclusion
#

You now have a fully functional mail server running with Docker-Mailserver. This guide covered the basic setup, but Docker-Mailserver offers extensive customization options to fit your specific needs. Feel free to explore further and adapt the setup to your requirements.

Thank you
#

I appreciate your feedback on this tutorial. If you have suggestions, improvements, or encounter any bugs, please don’t hesitate to reach out. I’ll strive to keep this guide updated with the latest best practices and features.