mailserver
Simple and full-featured mail server using Docker
500K+
This is a fork that provides the bare minimum of maintenance for the excellent hardware/mailserver. Thank you very much.
mailserver2/mailserver is a simple and full-featured mail server build as a set of multiple docker images, including:
1.1-latest for now)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 preferred distribution. 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" |
| {{selector}}._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:
mail unless changed via DKIM_SELECTOR/mnt/docker/mail/dkim/domain.tld/{{selector}}.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 DKIM_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 pp).
: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/mailserver2/mailserver/master/docker-compose.sample.yml -o docker-compose.yml \
&& curl https://raw.githubusercontent.com/mailserver2/mailserver/master/sample.env -o .env \
&& curl https://raw.githubusercontent.com/mailserver2/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 web mail front end with Sieve scripts support (filters and vacation message), GPG and a modern user interface.
At first launch, the container takes few minutes to generate SSL certificates (if needed), DKIM keypair generation 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:
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:

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 | |
| DKIM_KEY_LENGTH | Size of your DKIM RSA key pair | optional | 1024 |
| DKIM_SELECTOR | Your DKIM selector | optional | mail |
| 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, ldap | optional | mysql |
| DBHOST | Database instance ip/hostname | optional | mariadb |
| DBPORT | Database instance port | optional | 3306 / 389 (sql/ldap) |
| DBUSER | Database username | optional | postfix |
| DBNAME | Database name | optional | postfix |
| DBPASS | Database password or location of a file containing it | required *1) | 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 rate limiting 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 | + |
*1) DBPASS is NOT required when using LDAP authentication
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/HomeWhen using LDAP authentication the following additional variables become available. All DBUSER, DBNAME and DBPASS variables will not be used in this case:
| Variable | Description | Type | Default value |
|---|---|---|---|
| LDAP_TLS_ENABLED | Enable TLS on LDAP | optional | false |
| LDAP_TLS_CA_FILE | The TLS CA File | required if LDAP_TLS_ENABLED | |
| LDAP_TLS_FORCE | Force TLS connections | required if LDAP_TLS_ENABLED | false |
| LDAP_BIND | Bind to LDAP Server | optional | true |
| LDAP_BIND_DN | The DN to bind to | required if LDAP_BIND | |
| LDAP_BIND_PW | LDAP password or location of a file containing it | required if LDAP_BIND | |
| LDAP_DEFAULT_SEARCH_BASE | The base DN for all lookups | required | |
| LDAP_DEFAULT_SEARCH_SCOPE | The default scope for all lookups (sub, base or one) | optional | sub |
| LDAP_DOMAIN_SEARCH_BASE | The search base for domain lookups | optional | ${LDAP_DEFAULT_SEARCH_BASE} |
| LDAP_DOMAIN_SEARCH_SCOPE | The search scope for domain lookups | optional | ${LDAP_DEFAULT_SEARCH_SCOPE} |
| LDAP_DOMAIN_FILTER | The search filter for domain lookups | required | |
| LDAP_DOMAIN_ATTRIBUTE | The attributes for domain lookup | required | |
| LDAP_DOMAIN_FORMAT | The format for domain lookups | optional | |
| LDAP_MAILBOX_SEARCH_BASE | The search base for mailbox lookups | optional | ${LDAP_DEFAULT_SEARCH_BASE} |
| LDAP_MAILBOX_SEARCH_SCOPE | The search scope for mailbox lookups | optional | ${LDAP_DEFAULT_SEARCH_SCOPE} |
| LDAP_MAILBOX_FILTER | The search filter for mailbox lookups | required | |
| LDAP_MAILBOX_ATTRIBUTE | The attributes for mailbox lookup | required | |
| LDAP_MAILBOX_FORMAT | The format for domain mailbox | optional | |
| LDAP_ALIAS_SEARCH_BASE | The search base for domain lookups | optional | ${LDAP_DEFAULT_SEARCH_BASE} |
| LDAP_ALIAS_SEARCH_SCOPE | The search scope for domain lookups | optional | ${LDAP_DEFAULT_SEARCH_SCOPE} |
| LDAP_ALIAS_FILTER | The search filter for domain lookups | required | |
| LDAP_ALIAS_ATTRIBUTE | The attributes for domain lookup | required | |
| LDAP_ALIAS_FORMAT | The format for domain lookups | optional | |
| LDAP_FORWARD_SEARCH_BASE | The search base for forward lookups | optional | ${LDAP_DEFAULT_SEARCH_BASE} |
| LDAP_FORWARD_SEARCH_SCOPE | The search scope for forward lookups | optional | ${LDAP_DEFAULT_SEARCH_SCOPE} |
| LDAP_FORWARD_FILTER | The search filter for forward lookups | optional | |
| LDAP_FORWARD_ATTRIBUTE | The attributes for forward lookup | optional | |
| LDAP_FORWARD_FORMAT | The format for forward lookups | optional | |
| LDAP_GROUP_SEARCH_BASE | The search base for group lookups | optional | ${LDAP_DEFAULT_SEARCH_BASE} |
| LDAP_GROUP_SEARCH_SCOPE | The search scope for group lookups | optional | ${LDAP_DEFAULT_SEARCH_SCOPE} |
| LDAP_GROUP_FILTER | The search filter for group lookups | optional | |
| LDAP_GROUP_ATTRIBUTE | The attributes for group lookup | optional | |
| LDAP_GROUP_FORMAT | The format for group lookups | optional | |
| LDAP_SENDER_SEARCH_BASE | The search base for sender lookups | optional | ${LDAP_DEFAULT_SEARCH_BASE} |
| LDAP_SENDER_SEARCH_SCOPE | The search scope for sender lookups | optional | ${LDAP_DEFAULT_SEARCH_SCOPE} |
| LDAP_SENDER_FILTER | The search filter for sender lookups | required | |
| LDAP_SENDER_ATTRIBUTE | The attributes for sender lookup | required | |
| LDAP_SENDER_FORMAT | The format for sender lookups | required | |
| LDAP_DOVECOT_USER_ATTRS | Dovecot user attribute mapping | required | |
| LDAP_DOVECOT_USER_FILTER | Dovecot user search filter | required | |
| LDAP_DOVECOT_PASS_ATTRS | Dovecot user password attribute mapping | required | |
| LDAP_DOVECOT_PASS_FILTER | Dovecot user password filter | required | |
| LDAP_DOVECOT_ITERATE_ATTRS | Dovecot user iterate attributes | optional | |
| LDAP_DOVECOT_ITERATE_FILTER | Dovecot user iterate filters | optional | |
| LDAP_MASTER_USER_ENABLED | Enable LDAP master users | optional | false |
| LDAP_MASTER_USER_SEPARATOR | LDAP master user separator | required if LDAP_MASTER_USER_ENABLED | * |
| LDAP_MASTER_USER_SEARCH_BASE | LDAP master user search base | required if LDAP_MASTER_USER_ENABLED | ${LDAP_DEFAULT_SEARCH_BASE} |
| LDAP_MASTER_USER_SEARCH_SCOPE | LDAP master user scope | required if LDAP_MASTER_USER_ENABLED | ${LDAP_DEFAULT_SEARCH_SCOPE} |
| LDAP_DOVECOT_MASTER_USER_ATTRS | LDAP master user Dovecot attributes | required if LDAP_MASTER_USER_ENABLED | |
| LDAP_DOVECOT_MASTER_USER_FILTER | LDAP master user Dovecot search filter | required if LDAP_MASTER_USER_ENABLED |
Back 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
Content type
Image
Digest
sha256:b6a65785a…
Size
161.3 MB
Last updated
3 months ago
docker pull mailserver2/mailserver:1.1.23.1