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.
- Account management
- Multiple accounts
- Multiple domains
- LDAP
- Let's Encrypt Key renew automation
- Standalone
- Nginx Proxy
- Host OS support
- Debian based
- Red Hat based
- Managable features
- ClamAV
- Fail2Ban
- OpenDKIM
- OpenDMARC
- Postgrey
- Spamassasin
- Ubuntu 18.04 LTS
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. |
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 plaintextaliases
- list of aliases, each alias must be full emailrestrict
- list of restrictions, may besend
for suppress mail sending orreceive
for suppress mail receiving
mail_accounts:
- username: user1
domain: example.com
password: aaaaa
aliases:
- [email protected]
- [email protected]
restrict: []
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]
Suppose that your server host is server1.example.com
- Add MX record to your DNS
example.com IN MX "1 server1.example.com."
- Add TXT record with SPF to your DNS
example.com IN TXT "v=spf1 a mx ~all"
- Add TXT record with DKIM to your DNS
- You can find DKIM key in folder defined by
mail_persist_folder
variable in fileconfig/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 bemail._domainkey
for all, NOserver1._domainkey
or whatever else- Custom selector cannot be used.
- You can find DKIM key in folder defined by
- 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 reportsrua
- Reporting URI of aggregate reports
- 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.
There is many tools to test your mail server, eg.:
- https://dkimvalidator.com
- Generate email address which you can use to verify your SPF/DKIM config
- [email protected]
- Just send mail to this mail address from your account mail and your will receive report back to your mail address
- https://mxtoolbox.com
- Test your SMTP configuration
- Especially Deliverability test is useful (test SPF and DKIM)
- Just send mail to [email protected] from your account mail and your will receive report back to your mail address
- NOTE: MXToolBox DKIM validation fails (eg. tomav/docker-mailserver, serverfault.com even if another validators works well, don't know why but it looks that Google DKIM validation fails too (just send mail to any Gmail adrress and you will get report to mail according to your DMARC configuration)
- https://www.checktls.com
- Test connection to your SMTP port
- Fill your
domain.tld
(eg.example.com
) to the field
- Test via OpenSSL
- Create file
host_vars/server1.example.com.yml
encrypted byansible-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
- Create file
vault-pass.txt
with your Ansible Vault (add this file to.gitignore
)# echo 'my-secret-vault-password' > vault-pass.txt
- Set up Ansible with ansible.cfg
# cat > ansible.cfg <<EOF [defaults] vault_password_file = vault-pass.txt EOF
- Variable
mail_accounts
is then available in the role for hostserver1.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
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.
Version: 3.28.5-0ubuntu0.18.04.1
- Edit > Accounts
- Add "Mail Account"
- Identity
- Email Address:
[email protected]
- Email Address:
- 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
- Sending Email
- Server Type: SMTP
- Server:
mail.example.com
- Port: 587
- Check "Server requires authentication"
- Encryption method: STARTTLS after connecting
- Authentication:
- Type: Login
- Username:
[email protected]
Version: 2020.03.01.300951155.release
- Add another account
- Other
- Fill your email > Manual setup
- What type of account is this?: Personal (IMAP)
- Fill your password > Next
- Server:
mail.example.com
- IMAP port: 465 (SSL/TLS)
- Outgoing server
- Server:
mail.example.com
- Server:
You would be able to receive/send mails now.
TBD
TBD
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
Docker container named mail-server
is configured to always restart even after server boot.
All data (mail data, certificates, configuration) are stored on the host in folder defined in Ansible variable mail_persist_folder
.
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.
They are generated directly to file postfix-accounts.cf
according to these instructions.
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.
All helping hands are appreciated. Check CONTRIBUTING.md
- RSA sign and verify using Openssl : Behind the scene
- Interesting article about how RSA signing (used by DKIM) works