Skip to content

Latest commit

 

History

History
293 lines (262 loc) · 10.4 KB

README.md

File metadata and controls

293 lines (262 loc) · 10.4 KB

Ansible Docker mailserver

Ansible role is based on top of project tomav/docker-mailserver.

Role will create all needed prerequisites to run mail server in Docker but doesn't install the Docker itself.

All data are stored on host to prevent data loss during Docker restart.

Currently supported

  • Account management
    • Multiple accounts
    • Multiple domains
    • LDAP
  • Let's Encrypt Key renew automation
  • Host OS support
    • Debian based
    • Red Hat based
  • Managable features
    • ClamAV
    • Fail2Ban
    • OpenDKIM
    • OpenDMARC
    • Postgrey
    • Spamassasin

Test environment

  • Ubuntu 18.04 LTS

Variables

Variable name Default Description
mail_accounts [] List of mail accounts according to Mail account format
mail_domains [] List of mail domains (the first one should be your MX however certificate will be issued for all of them)
mail_cert_email "" Email used for Let's Encrypt account
mail_persist_folder /opt/mail (optional) Persistent folder for mail data, configuration, etc.

Mail account format

Each account in variable mail_accounts has these parameters:

  • username - part of email before "@", eg. user1
  • domain - part of email after "@", eg. example.com
  • password - user password in plaintext
  • aliases - list of aliases, each alias must be full email
  • restrict - list of restrictions, may be send for suppress mail sending or receive for suppress mail receiving

Example

mail_accounts:
  - username: user1
    domain: example.com
    password: aaaaa
    aliases:
      - [email protected]
      - [email protected]
    restrict: []

Quick Start

Install this Ansible role within the context of playbook

ansible-galaxy install hmlkao.docker_mailserver

Then create your playbook yaml

---
- name: Localhost installation
  hosts: localhost
  roles:
    - role: hmlkao.docker_mailserver
  vars:
    mail_accounts:
      - username: user1
        domain: example.com
        password: aaaaa
        aliases:
          - [email protected]
          - [email protected]
        restrict: []
      - username: no-reply
        domain: example.com
        password: bbbbb
        aliases: []
        restrict:
          - receive
    mail_domains:
      - server1.example.com
    mail_cert_email: [email protected]

What next?

Suppose that your server host is server1.example.com

  1. Add MX record to your DNS
    example.com IN     MX      "1 server1.example.com."
    
  2. Add TXT record with SPF to your DNS
    example.com IN     TXT     "v=spf1 a mx ~all"
    
  3. Add TXT record with DKIM to your DNS
    • You can find DKIM key in folder defined by mail_persist_folder variable in file config/opendkim/keys/<domain.tld>/mail.txt on your host (server)
      • Beware of that the record is divided by 250 characters so you have to concat it together
    • TXT record should look something like
      mail._domainkey IN     TXT     "v=DKIM1; h=sha256; k=rsa; p=MIIB...jwfx"
      
      • mail is DKIM selector, not subdomain so there have to be mail._domainkey for all, NO server1._domainkey or whatever else
      • Custom selector cannot be used.
  4. Add TXT record with DMARC to your DNS What happen with mails which doesn't meet SFP and DKIM validation.
    _DMARC IN     TXT     "v=DMARC1; p=quarantine; pct=5; rua=mailto:[email protected]; ruf=mailto:[email protected]; fo=1"
    
    • ruf - Reporting URI for forensic reports
    • rua - Reporting URI of aggregate reports
  5. Configure reverse DNS for host public IP
    • Ask your provider to configure reverse DNS
    • You should get something similar (where <1.2.3.4> is your public server IP)
      # dig -x <1.2.3.4> +short
      server1.example.com.
      

Test your configuration

There is many tools to test your mail server, eg.:

More complex example

  1. Create file host_vars/server1.example.com.yml encrypted by ansible-vault first.
    # ansible-vault edit host_vars/server1.example.com.yml
    mail_accounts:
      - username: user1
        domain: example.com
        password: aaaaa
        aliases:
          - [email protected]
          - [email protected]
        restrict: []
      - username: no-reply
        domain: example.com
        password: bbbbb
        aliases: []
        restrict:
          - receive
    
  2. Create file vault-pass.txt with your Ansible Vault (add this file to .gitignore)
    # echo 'my-secret-vault-password' > vault-pass.txt
    
  3. Set up Ansible with ansible.cfg
    # cat > ansible.cfg <<EOF
    [defaults]
    vault_password_file = vault-pass.txt
    EOF
    
  4. Variable mail_accounts is then available in the role for host server1.example.com.
    ---
    - name: More complex installation
      hosts: server1.example.com
      roles:
        - role: hmlkao.docker_mailserver
      vars:
        mail_domains:
          - server1.example.com                 <-- my MX server
          - mail.example.com                    <-- pretty name for email clients
        mail_cert_email: [email protected]  <-- notification mail for Let's Encrypt
        mail_persist_folder: /usr/local/mail    <-- path to folder on your host
    

Client configuration

Suppose your mail server is running on domain server1.example.com and we have some pretty CNAME like mail.example.com which points to our mail server and account with username user1 is created.

Evolution (Default Gnome client)

Version: 3.28.5-0ubuntu0.18.04.1

  1. Edit > Accounts
  2. Add "Mail Account"
  3. Identity
  4. Receiving Email
    • Server Type: IMAP
    • Server: mail.example.com
    • Username: [email protected]
    • Encryption method: TLS on dedicated port
      • Port should change to 993
    • Authentication: Password
  5. Sending Email
    • Server Type: SMTP
    • Server: mail.example.com
    • Port: 587
    • Check "Server requires authentication"
    • Encryption method: STARTTLS after connecting
    • Authentication:

Gmail app for Android

Version: 2020.03.01.300951155.release

  1. Add another account
  2. Other
  3. Fill your email > Manual setup
  4. What type of account is this?: Personal (IMAP)
  5. Fill your password > Next
  6. Server: mail.example.com
  7. IMAP port: 465 (SSL/TLS)
  8. Outgoing server
    • Server: mail.example.com

You would be able to receive/send mails now.

Thunderbird (Mozilla client)

TBD

Mail (Default Windows 10 client)

TBD

Under the hood

Ports

There are published only three ports

  • TCP/25 - SMTP port for receiving emails from other SMTP servers
  • TCP/587 - SMTP Submission port for sending emails from clients
  • TCP/993 - IMAP port for downloading emails to clients

Running server

Docker container named mail-server is configured to always restart even after server boot.

Persistent storage

All data (mail data, certificates, configuration) are stored on the host in folder defined in Ansible variable mail_persist_folder.

Certificates

TLS certificates are issued by Let's Encrypt issuer by certbot/certbot Docker image according to these instructions.

This role creates systemd renew service and timer which will run the service once per day. No cronjob configuration needed.

Mail accounts

They are generated directly to file postfix-accounts.cf according to these instructions.

Troubleshooting

You can see what happen in Docker logs on host

docker logs mail-server

When you found some bug in the role create an issue on GitHub please.

Contributing

All helping hands are appreciated. Check CONTRIBUTING.md

Sources