Skip to content

Ansible role for as simple as possible deploy of docker-mailserver/docker-mailserver.

License

Notifications You must be signed in to change notification settings

hmlkao/ansible-docker-mailserver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ansible Docker mailserver

Ansible role is based on top of project docker-mailserver/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. on host
mail_docker_image docker.io/mailserver/docker-mailserver (optional) Shouldn't be changed
mail_docker_tag latest (optional) Image Docker tag used to run mail server
mail_dkim_size 2048 (optional) DKIM key size (available values are 1024, 2048, 4096)
mail_amavis_config "" (optional) Configure Amavis overrides

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:
      - admin@example.com
      - abuse@example.com
    restrict: []

Quick Start

Install this Ansible role within the context of playbook

ansible-galaxy install hmlkao.docker_mailserver

Then create your playbook yaml file

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

What next?

Suppose that your server host is server1.example.com

  1. Be sure your public ports are opened

  2. Add MX record to your DNS

    example.com IN     MX      "1 server1.example.com."
  3. Add TXT record with SPF to your DNS

    example.com IN     TXT     "v=spf1 a mx ~all"
  4. 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.
  5. Add TXT record with DMARC to your DNS What happen with mails which doesn't meet SPF and DKIM validation.

    _DMARC IN     TXT     "v=DMARC1; p=quarantine; pct=100; rua=mailto:abuse+rua@example.com; ruf=mailto:abuse+ruf@example.com; fo=1"
    • ruf - Reporting URI for forensic reports

    • rua - Reporting URI of aggregate reports

    • Verify in commandline if is TXT applied

      dig mail._domainkey.example.com TXT
  6. 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 are 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:
          - admin@example.com
          - abuse@example.com
        restrict: []
      - username: no-reply
        domain: example.com
        password: bbbbb
        aliases: []
        restrict:
          - receive
  2. Create file vault-pass.txt with your Ansible Vault (NOTE: You should add this file to .gitignore to prevent leak of sensitive data!)

    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: my-mail@somewhere.com  <-- notification mail for Let's Encrypt

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
    • Email Address: user1@example.com
  4. Receiving Email
    • Server Type: IMAP
    • Server: mail.example.com
    • Username: user1@example.com
    • 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:
      • Type: Login
      • Username: user1@example.com

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.

Mail (Default MacOS client)

Version: 15.0 (3693.40.0.1.81) / 2022-02-14

  1. Choose a Mail account provider... > Other Mail Account...
  2. Fill
    • Name: < your name >
    • Email address: < the whole email address >
    • Password: < password to your mail account >
  3. When is error message shown
    • Choose "IMAP"
    • Fill address of your mail server > according to MX record
  4. Sign in

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.

Sources

Contributing

All helping hands are appreciated. Check CONTRIBUTING.md

Ansible Galaxy

  1. Local setup

    $ cat ~/.ansible.cfg
    [galaxy]
    server_list = beta
    
    [galaxy_server.beta]
    url = https://beta-galaxy.ansible.com/api/
    token = <token>
  2. (first use) Create Ansible Galaxy metadata

    • Creates folder <namespace>.<collection>
    ansible-galaxy collection init hmlkao.docker_mailserver
  3. Build collection package

    • Creates tarball with tar.gz extension
    ansible-galaxy collection build
  4. Upload Collection

    ansible-galaxy collection publish ./hmlkao-docker_mailserver-<version>.tar.gz

About

Ansible role for as simple as possible deploy of docker-mailserver/docker-mailserver.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages