hardware/mailserver is a simple and full-featured mail server build as a set of multiple docker images, including:
Please check, if your system meets the following minimum requirements :
| Type | Without ClamAV | With ClamAV |
|---|---|---|
| CPU | 1 GHz | 1 GHz |
| RAM | 1.5 GiB | 2 GiB |
| Type | Without ClamAV | With ClamAV |
|---|---|---|
| CPU | 1 GHz | 1 GHz |
| RAM | 512 MiB | 1 GiB |
Back to table of contents :arrow_up_small:
Please remove any web server and mail services running on your server. I recommend using a clean installation of your prefered distro. If you are using Debian, remember to remove the default MTA Exim4 :
# apt-get purge exim4*
Also make sure that no other application is interfering with mail server configuration :
# netstat -tulpn | grep -E -w '25|80|110|143|443|465|587|993|995|4190'
If this command returns any results please remove or stop the application running on that port.
If you have a firewall, unblock the following ports, according to your needs :
| Service | Software | Protocol | Port |
|---|---|---|---|
| SMTP | Postfix | TCP | 25 |
| HTTP | Nginx | TCP | 80 |
| POP3 | Dovecot | TCP | 110 |
| IMAP | Dovecot | TCP | 143 |
| HTTPS | Nginx | TCP | 443 |
| SMTPS | Postfix | TCP | 465 |
| Submission | Postfix | TCP | 587 |
| IMAPS | Dovecot | TCP | 993 |
| POP3S | Dovecot | TCP | 995 |
| ManageSieve | Dovecot | TCP | 4190 |
I recommend you to use hardware/nsd-dnssec as an authoritative name server with DNSSEC capabilities. NSD is an authoritative only, high performance, simple and open source name server.
A correct DNS setup is required, this step is very important.
| HOSTNAME | CLASS | TYPE | PRIORITY | VALUE |
|---|---|---|---|---|
| IN | A/AAAA | any | 1.2.3.4 | |
| spam | IN | CNAME | any | mail.domain.tld. |
| webmail | IN | CNAME | any | mail.domain.tld. |
| postfixadmin | IN | CNAME | any | mail.domain.tld. |
| @ | IN | MX | 10 | mail.domain.tld. |
| @ | IN | TXT | any | "v=spf1 a mx ip4:SERVER_IPV4 ~all" |
| mail._domainkey | IN | TXT | any | "v=DKIM1; k=rsa; p=YOUR DKIM Public Key" |
| _dmarc | IN | TXT | any | "v=DMARC1; p=reject; rua=mailto:[email protected]; ruf=mailto:[email protected]; fo=0; adkim=s; aspf=s; pct=100; rf=afrf; sp=reject" |
Notes:
/mnt/docker/mail/dkim/domain.tld/public.key
To regenerate your public and private keys, remove the /mnt/docker/mail/dkim/domain.tld folder. By default a 1024-bit key is generated, you can increase this size by setting the OPENDKIM_KEY_LENGTH environment variable with a higher value. Check your domain registrar support to verify that it supports a TXT record long enough for a key larger than 1024 bits.
These DNS record will raise your trust reputation score and reduce abuse of your domain name. You can find more information here :
You can audit your mailserver with the following assessment services :
Back to table of contents :arrow_up_small:
:bulb: The reverse proxy used in this setup is Traefik, but you can use the solution of your choice (Nginx, Apache, Haproxy, Caddy, H2O...etc).
:warning: This docker image may not work with some hardened Linux distribution using security-enhancing kernel patches like GrSecurity, please use a supported platform.
# Create a new docker network for Traefik (IPv4 only)
docker network create http_network
# If you want to support IPv6, please refer to [IPv6 support]
# Create the required folders and files
mkdir -p /mnt/docker/traefik/acme && cd /mnt/docker \
&& curl https://raw.githubusercontent.com/hardware/mailserver/master/docker-compose.sample.yml -o docker-compose.yml \
&& curl https://raw.githubusercontent.com/hardware/mailserver/master/sample.env -o .env \
&& curl https://raw.githubusercontent.com/hardware/mailserver/master/traefik.sample.toml -o traefik/traefik.toml \
&& touch traefik/acme/acme.json \
&& chmod 600 docker-compose.yml .env traefik/traefik.toml traefik/acme/acme.json
Edit the .env and traefik.toml, adapt to your needs, then start all services :
docker-compose up -d
PostfixAdmin is a web based interface used to manage mailboxes, virtual domains and aliases.
Rainloop is a simple, modern and fast webmail with Sieve scripts support (filters and vacation message), GPG and a modern user interface.
According to your preference, you can use Afterlogic Webmail Lite as alternative.
At first launch, the container takes few minutes to generate SSL certificates (if needed), DKIM keypair and update clamav database, all of this takes some time (1/2 minutes). This image comes with a snake-oil self-signed certificate, please use your own trusted certificates. See below for configuration.
List of webservices available:
| Service | URI |
|---|---|
| Traefik dashboard | https://mail.domain.tld/ |
| Rspamd dashboard | https://spam.domain.tld/ |
| Administration | https://postfixadmin.domain.tld/ |
| Webmail | https://webmail.domain.tld/ |
Traefik dashboard use a basic authentication (user:admin, password:12345), the password can be encoded in MD5, SHA1 and BCrypt. You can use htpasswd to generate those ones. Users can be specified directly in the traefik.toml file. Rspamd dashboard use the password defined in your docker-compose.yml.
You can check the startup logs with this command :
# docker logs -f mailserver
[INFO] Let's encrypt live directory found
[INFO] Using /etc/letsencrypt/live/mail.domain.tld folder
[INFO] Creating DKIM keys for domain domain.tld
[INFO] Database hostname found in /etc/hosts
[INFO] Fetchmail forwarding is enabled.
[INFO] Automatic GPG encryption is enabled.
[INFO] ManageSieve protocol is enabled.
[INFO] POP3 protocol is enabled.
-------------------------------------------------------------------------------------
2017-08-26T11:06:58.885562+00:00 mail root: s6-supervise : spawning clamd process
2017-08-26T11:06:59.059077+00:00 mail root: s6-supervise : spawning freshclam process
2017-08-26T11:06:59.395214+00:00 mail root: s6-supervise : spawning rspamd process
2017-08-26T11:07:01.615597+00:00 mail root: s6-supervise : spawning unbound process
2017-08-26T11:07:01.870856+00:00 mail root: s6-supervise : spawning postfix process
2017-08-26T11:07:03.303536+00:00 mail root: s6-supervise : spawning dovecot process
...
Back to table of contents :arrow_up_small:

https://github.com/hardware/mailserver-rancher
This catalog provides a basic template to easily deploy an email server based on hardware/mailserver very quickly. To use it, just add this repository to your Rancher system as a catalog in Admin > Settings page and follow the readme. This catalog has been initiated by @MichelDiz.

Back to table of contents :arrow_up_small:

If you use Ansible, I recommend you to go to see @ksylvan playbooks here : https://github.com/ksylvan/docker-mail-server
Back to table of contents :arrow_up_small:
| Variable | Description | Type | Default value |
|---|---|---|---|
| VMAILUID | vmail user id | optional | 1024 |
| VMAILGID | vmail group id | optional | 1024 |
| VMAIL_SUBDIR | Individual mailbox' subdirectory | optional | |
| OPENDKIM_KEY_LENGTH | Size of your DKIM RSA key pair | optional | 1024 |
| DEBUG_MODE | Enable Postfix, Dovecot, Rspamd and Unbound verbose logging | optional | false |
| PASSWORD_SCHEME | Passwords encryption scheme | optional | SHA512-CRYPT |
| DBDRIVER | Database type: mysql, pgsql | optional | mysql |
| DBHOST | Database instance ip/hostname | optional | mariadb |
| DBPORT | Database instance port | optional | 3306 |
| DBUSER | Database username | optional | postfix |
| DBNAME | Database name | optional | postfix |
| DBPASS | Database password or location of a file containing it | required | null |
| REDIS_HOST | Redis instance ip/hostname | optional | redis |
| REDIS_PORT | Redis instance port | optional | 6379 |
| REDIS_PASS | Redis database password or location of a file containing it | optional | null |
| REDIS_NUMB | Redis database number | optional | 0 |
| RSPAMD_PASSWORD | Rspamd WebUI and controller password or location of a file containing it | required | null |
| ADD_DOMAINS | Add additional domains to the mailserver separated by commas (needed for dkim keys etc.) | optional | null |
| RELAY_NETWORKS | Additional IPs or networks the mailserver relays without authentication | optional | null |
| WHITELIST_SPAM_ADDRESSES | List of whitelisted email addresses separated by commas | optional | null |
| DISABLE_RSPAMD_MODULE | List of disabled modules separated by commas | optional | null |
| DISABLE_CLAMAV | Disable virus scanning | optional | false |
| DISABLE_SIEVE | Disable ManageSieve protocol | optional | false |
| DISABLE_SIGNING | Disable DKIM/ARC signing | optional | false |
| DISABLE_GREYLISTING | Disable greylisting policy | optional | false |
| DISABLE_RATELIMITING | Disable ratelimiting policy | optional | true |
| DISABLE_DNS_RESOLVER | Disable the local DNS resolver | optional | false |
| DISABLE_SSL_WATCH | Disable watching of acme.json and the Let's Encrypt directory | optional | false |
| ENABLE_POP3 | Enable POP3 protocol | optional | false |
| ENABLE_FETCHMAIL | Enable fetchmail forwarding | optional | false |
| ENABLE_ENCRYPTION | Enable automatic GPG encryption | optional | false |
| FETCHMAIL_INTERVAL | Fetchmail polling interval | optional | 10 |
| RECIPIENT_DELIMITER | RFC 5233 subaddress extension separator (single character only) | optional | + |
true to enable verbose logging for postfix, dovecot, rspamd and Unbound. To debug components separately, use this syntax : DEBUG_MODE=postfix,rspamd./var/mail/vhosts/%domain/%user/$subdir. For more information, read this : https://wiki.dovecot.org/VirtualUsers/HomeBack to table of contents :arrow_up_small:
Zeyple catches email from the postfix queue, then encrypts it if a corresponding recipient's GPG public key is found. Finally, it puts it back into the queue.

:heavy_exclamation_mark: Please enable this option carefully and only if you know what you are doing.
Switch ENABLE_ENCRYPTION environment variable to true. The public keyring will be saved in /var/mail/zeyple/keys.
Please don't change the default value of RECIPIENT_DELIMITER (default = "+"). If encryption is enabled with another delimiter, Zeyple could have an unpredictable behavior.
:warning: Make sure to send your public key on a gpg keyserver before to run the following command.
docker exec -ti mailserver encryption.sh import-key YOUR_KEY_ID
This command browses all /var/mail/vhosts/* domains directories and users subdirectories to find all the recipients addresses in the mailserver.
docker exec -ti mailserver encryption.sh import-all-keys
docker exec -ti mailserver encryption.sh import-key YOUR_KEY_ID hkp://pgp.mit.edu
docker exec -ti mailserver encryption.sh import-all-keys hkp://keys.gnupg.net
You can use all options of gpg command line except an already assigned parameter called --homedir.
docker exec -ti mailserver encryption.sh --list-keys
docker exec -ti mailserver encryption.sh --fingerprint
docker exec -ti mailserver encryption.sh --refresh-keys
docker exec -ti mailserver encryption.sh ...
Documentation : https://www.gnupg.org/documentation/manuals/gnupg/Operational-GPG-Commands.html
Back to table of contents :arrow_up_small:
The RELAY_NETWORKS is a space separated list of additional IP addresses and subnets (in CIDR notation) which the mailserver relays without authentication. Hostnames are possible, but generally disadvised. IPv6 addresses must be surrounded by square brackets. You can also specify an absolut path to a file with IPs and networks so you can keep it on a mounted volume. Note that the file is not monitored for changes.
You can use this variable to allow other local containers to relay via the mailserver. Typically you would set this to the IP range of the default docker bridge (172.17.0.0/16) or the default network of your compose. If you are unable to determine, you might just add all RFC 1918 addresses 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
:warning: A value like 0.0.0.0/0 will turn your mailserver into an open relay!
Back to table of contents :arrow_up_small:
To use Let's Encrypt certificates generated by Traefik, mount a new docker volume like this :
mailserver:
image: hardware/mailserver
volumes:
- /mnt/docker/traefik/acme:/etc/letsencrypt/acme
...
The startup script read the acme.json* file generated by Traefik and split into pem files all appropriate certificates (CN = mail.domain.tld).
:bulb: *Compatible with both Traefik >=1.5.0 and 1.6+ ACME json format, with SAN and wildcard certificates support.
docker logs -f mailserver
[INFO] Search for SSL certificates generated by Traefik
[INFO] acme.json found with ACME v2 format, dumping into pem files
[INFO] Let's encrypt live directory found
[INFO] Using /etc/letsencrypt/live/mail.domain.tld folder
Don't forget to add a new traefik frontend rule somewhere in your docker-compose.yml to generate a certificate for your mailserver FQDN (default : mail.domain.tld) subdomain.
# docker-compose.yml
labels:
- traefik.frontend.rule=Host:mail.${DOMAIN}
Alternatively, you can specify your domains in the traefik.toml to generate a SAN certificate :
[acme]
onHostRule = false
[[acme.domains]]
main = "domain.tld"
sans = ["mail.domain.tld", "spam.domain.tld", "postfixadmin.domain.tld", "webmail.domain.tld"]
Or a wildcard certificate :
:warning: ACME wildcard certificates can only be generated thanks to a DNS-01 challenge.
[acme]
onHostRule = false
# https://docs.traefik.io/v1.6/configuration/acme/#dnschallenge
[acme.dnsChallenge]
provider = "your_dns_provider"
delayBeforeCheck = 0
[[acme.domains]]
main = "*.domain.tld"
If the startup script does not find the appropriate SSL certificate and private key, look at Traefik's logs to see what's going on.
docker logs -f mailserver
[INFO] Search for SSL certificates generated by Traefik
[INFO] ...
[INFO] ...
[INFO] acme.json found with ACME v2 format, dumping into pem files
[ERROR] The certificate for mail.domain.tld or the private key was not found !
[INFO] Don't forget to add a new traefik frontend rule to generate a certificate for mail.domain.tld subdomain
[INFO] Look /mnt/docker/traefik/acme/dump.log and 'docker logs traefik' for more information
# traefik.toml
[acme]
acmeLogging = true
docker-compose restart traefik && docker logs -f traefik
When SSL certificates are renewed, the mail server must be restarted. You can proceed as follows :
apt-get install incronroot user in /etc/incron.allowincrontab -e :/mnt/docker/traefik/acme/acme.json IN_MODIFY docker-compose -f /path/to/yml restart mailserver
This job trigger a restart of the mail server container when traefik's acme file is updated.
You can use Let's Encrypt or any other certification authority. Setup your docker-compose.yml like this :
mailserver:
image: hardware/mailserver
volumes:
- /mnt/docker/ssl:/etc/letsencrypt
...
Request your certificates in /mnt/docker/ssl/live/mail.domain.tld with an ACME client if you use Let's Encrypt, otherwise get your SSL certificates with the method provided by your CA and put everything needed in this directory.
Required files in this folder :
:bulb: If you only have the fullchain.pem and privkey.pem, the startup script extract automatically the cert.pem and chain.pem from fullchain.pem.
| Filename | Description |
|---|---|
| privkey.pem | Private key for the certificate |
| cert.pem | Serv |
Content type
Image
Digest
Size
116.6 MB
Last updated
almost 7 years ago
docker pull xoneso/mailserver