Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Simple and full-featured mail server using Docker

License

NotificationsYou must be signed in to change notification settings

mailserver2/mailserver

 
 

Repository files navigation

Fork

This is a fork that provides the bare minimum of maintenance for the excellenthardware/mailserver.Thank you very much.

Chat & questions

Build

Build Status

Docker image

mailserver2/mailserver is a simple and full-featured mail server build as a set of multiple docker images, including:

  • Postfix: a full-set SMTP email server
  • Dovecot: secure IMAP and POP3 email server
  • Rspamd: anti-spam filter with SPF, DKIM, DMARC, ARC, rate limiting and greylisting capabilities
  • Clamav: antivirus with automatic updates and third-party signature databases
  • Zeyple: automatic GPG encryption of all your emails
  • Sieve: email filtering (vacation auto-responder, auto-forward, etc...)
  • Fetchmail: fetch emails from external IMAP/POP3 server into local mailbox
  • Rainloop: web based email client
  • Postfixadmin: web-based administration interface
  • Unbound: recursive caching DNS resolver with DNSSEC support
  • NSD: authoritative DNS server with DNSSEC support
  • Træfik: modern HTTP reverse proxy
  • SSL:Let's Encrypt with auto-renewal (SAN and wildcard certificates), custom and self-signed certificates support
  • *OpenLDAP: [BETA] LDAP support available (only in1.1-latest for now)
  • Supporting multiple virtual domains over MySQL/PostgreSQL backend
  • Integration tests with Travis CI
  • Automated builds on DockerHub

Summary

System Requirements

Please check, if your system meets the following minimum requirements:

With MariaDB/PostgreSQL and Redis on the same host

TypeWithout ClamAVWith ClamAV
CPU1 GHz1 GHz
RAM1.5 GiB2 GiB

With MariaDB/PostgreSQL and Redis hosted on another server

TypeWithout ClamAVWith ClamAV
CPU1 GHz1 GHz
RAM512 MiB1 GiB

NOTE: If you are having problems with clamd using too much memory on startup, setCLAMD_MEMORY_FIX totrue.Seethe ClamAV documentation for details.

Back to table of contents 🔼

Prerequisites

Cleaning

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 MTAExim4:

# 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.

Ports

If you have a firewall, unblock the following ports, according to your needs:

ServiceSoftwareProtocolPort
SMTPPostfixTCP25
HTTPNginxTCP80
POP3DovecotTCP110
IMAPDovecotTCP143
HTTPSNginxTCP443
SMTPSPostfixTCP465
SubmissionPostfixTCP587
IMAPSDovecotTCP993
POP3SDovecotTCP995
ManageSieveDovecotTCP4190

DNS setup

I recommend you to usehardware/nsd-dnssec as an authoritative name server with DNSSEC capabilities. NSD is an authoritative only, high performance, simple and open source name server.

DNS records and reverse PTR

A correct DNS setup is required, this step is very important.

HOSTNAMECLASSTYPEPRIORITYVALUE
mailINA/AAAAany1.2.3.4
spamINCNAMEanymail.domain.tld.
webmailINCNAMEanymail.domain.tld.
postfixadminINCNAMEanymail.domain.tld.
@INMX10mail.domain.tld.
@INTXTany"v=spf1 a mx ip4:SERVER_IPV4 ~all"
{{selector}}._domainkeyINTXTany"v=DKIM1; k=rsa; p=YOUR DKIM Public Key"
_dmarcINTXTany"v=DMARC1; p=reject; rua=mailto:postmaster@domain.tld; ruf=mailto:admin@domain.tld; fo=0; adkim=s; aspf=s; pct=100; rf=afrf; sp=reject"

Notes:

  • Make sure that thePTR record of your IP matches the FQDN (default: mail.domain.tld) of your mailserver host. This record is usually set in your web hosting interface.
  • {{selector}} defaults tomail unless changed viaDKIM_SELECTOR
  • DKIM, SPF and DMARC records are recommended to build a good reputation score.
  • The DKIM public key will be available on host after the container startup:
/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 a1024-bit key is generated, you can increase this size by setting theDKIM_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:

Testing

You can audit your mailserver with the following assessment services:

Back to table of contents 🔼

Installation

1 - Prepare your environment

💡 The reverse proxy used in this setup isTraefik, but you can use the solution of your choice (Nginx, Apache, Haproxy, Caddy, H2O, etc pp).

⚠️ This docker image may not work with some hardened Linux distribution using security-enhancing kernel patches like GrSecurity, please use asupported 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 filesmkdir -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 \&& curl https://raw.githubusercontent.com/mailserver2/mailserver/master/file.sample.toml -o traefik/file.toml \&& touch traefik/acme/acme.json \&& chmod 600 docker-compose.yml .env traefik/traefik.toml traefik/file.toml traefik/acme/acme.json

Edit the.env andtraefik.toml, adapt to your needs, then start all services:

docker-compose up -d

2 - Postfixadmin installation

PostfixAdmin is a web based interface used to manage mailboxes, virtual domains and aliases.

3 - Rainloop installation (optional)

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.

4 - Done, congratulation ! 🎉

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:

ServiceURI
Traefik dashboardhttps://mail.domain.tld/
Rspamd dashboardhttps://spam.domain.tld/
Administrationhttps://postfixadmin.domain.tld/
Webmailhttps://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 usehtpasswd to generate those ones. Users can be specified directly in thetraefik.toml file. Rspamd dashboard use the password defined in yourdocker-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 process2017-08-26T11:06:59.059077+00:00 mail root: s6-supervise : spawning freshclam process2017-08-26T11:06:59.395214+00:00 mail root: s6-supervise : spawning rspamd process2017-08-26T11:07:01.615597+00:00 mail root: s6-supervise : spawning unbound process2017-08-26T11:07:01.870856+00:00 mail root: s6-supervise : spawning postfix process2017-08-26T11:07:03.303536+00:00 mail root: s6-supervise : spawning dovecot process...

Back to table of contents 🔼

Rancher Catalog

rancher-logo

https://github.com/hardware/mailserver-rancher

This catalog provides a basic template to easily deploy an email server based onhardware/mailserver very quickly. To use it, just add this repository to your Rancher system as a catalog inAdmin > Settings page and followthe readme. This catalog has been initiated by@MichelDiz.

rancher-ui

Back to table of contents 🔼

Ansible Playbooks

logo

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 🔼

Environment variables

VariableDescriptionTypeDefault value
VMAILUIDvmail user idoptional1024
VMAILGIDvmail group idoptional1024
VMAIL_SUBDIRIndividual mailbox' subdirectoryoptionalmail
DKIM_KEY_LENGTHSize of your DKIM RSA key pairoptional1024
DKIM_SELECTORYour DKIM selectoroptionalmail
DEBUG_MODEEnable Postfix, Dovecot, Rspamd and Unbound verbose loggingoptionalfalse
PASSWORD_SCHEMEPasswords encryption schemeoptionalSHA512-CRYPT
DBDRIVERDatabase type: mysql, pgsql, ldapoptionalmysql
DBHOSTDatabase instance ip/hostnameoptionalmariadb
DBPORTDatabase instance portoptional3306 / 389 (sql/ldap)
DBUSERDatabase usernameoptionalpostfix
DBNAMEDatabase nameoptionalpostfix
DBPASSDatabase password or location of a file containing itrequired*1)null
REDIS_HOSTRedis instance ip/hostnameoptionalredis
REDIS_PORTRedis instance portoptional6379
REDIS_PASSRedis database password or location of a file containing itoptionalnull
REDIS_NUMBRedis database numberoptional0
RSPAMD_PASSWORDRspamd WebUI and controller password or location of a file containing itrequirednull
ADD_DOMAINSAdd additional domains to the mailserver separated by commas (needed for dkim keys etc.)optionalnull
RELAY_NETWORKSAdditional IPs or networks the mailserver relays without authenticationoptionalnull
WHITELIST_SPAM_ADDRESSESList of whitelisted email addresses separated by commasoptionalnull
DISABLE_RSPAMD_MODULEList of disabled modules separated by commasoptionalnull
DISABLE_CLAMAVDisable virus scanningoptionalfalse
CLAMD_MEMORY_FIXWill addConcurrentDatabaseReload no in clamd.confoptionalfalse
DISABLE_SIEVEDisable ManageSieve protocoloptionalfalse
DISABLE_SIGNINGDisable DKIM/ARC signingoptionalfalse
DISABLE_GREYLISTINGDisable greylisting policyoptionalfalse
DISABLE_RATELIMITINGDisable rate limiting policyoptionaltrue
DISABLE_DNS_RESOLVERDisable the local DNS resolveroptionalfalse
DISABLE_SSL_WATCHDisable watching ofacme.json and the Let's Encrypt directoryoptionalfalse
DISABLE_VHOSTS_OWNERSHIP_SETDisable set permission onvhosts folderoptionalfalse
ENABLE_POP3Enable POP3 protocoloptionalfalse
ENABLE_FETCHMAILEnable fetchmail forwardingoptionalfalse
ENABLE_ENCRYPTIONEnable automatic GPG encryptionoptionalfalse
FETCHMAIL_INTERVALFetchmail polling intervaloptional10
RECIPIENT_DELIMITERRFC 5233 subaddress extension separator (single character only)optional+

*1)DBPASS is NOT required when using LDAP authentication

  • UseDEBUG_MODE to enable the debug mode. Switch totrue to enable verbose logging forpostfix,dovecot,rspamd andUnbound. To debug components separately, use this syntax:DEBUG_MODE=postfix,rspamd.
  • VMAIL_SUBDIR is the mail location subdirectory name/var/mail/vhosts/%domain/%user/$subdir. For more information, read this:https://wiki.dovecot.org/VirtualUsers/Home
  • PASSWORD_SCHEME for compatible schemes, read this:https://wiki.dovecot.org/Authentication/PasswordSchemes
  • Currently, only a singleRECIPIENT_DELIMITER is supported. Support for multiple delimiters will arrive with Dovecot v2.3.
  • FETCHMAIL_INTERVAL must be a number between1 and59 minutes.
  • UseDISABLE_DNS_RESOLVER if you have some DNS troubles and DNSSEC lookup issues with the local DNS resolver.
  • UseDISABLE_RSPAMD_MODULE to disable any module listed here:https://rspamd.com/doc/modules/
  • OPENDKIM_KEY_LENGTH has been renamed toDKIM_KEY_LENGTH, but falls back toOPENDKIM_KEY_LENGTH for backwards compatability

When using LDAP authentication the following additional variables become available. AllDBUSER,DBNAME andDBPASS variables will not be used in this case:

VariableDescriptionTypeDefault value
LDAP_TLS_ENABLEDEnable TLS on LDAPoptionalfalse
LDAP_TLS_CA_FILEThe TLS CA Filerequired ifLDAP_TLS_ENABLED
LDAP_TLS_FORCEForce TLS connectionsrequired ifLDAP_TLS_ENABLEDfalse
LDAP_BINDBind to LDAP Serveroptionaltrue
LDAP_BIND_DNThe DN to bind torequired ifLDAP_BIND
LDAP_BIND_PWLDAP password or location of a file containing itrequired ifLDAP_BIND
LDAP_DEFAULT_SEARCH_BASEThe base DN for all lookupsrequired
LDAP_DEFAULT_SEARCH_SCOPEThe default scope for all lookups (sub, base or one)optionalsub
LDAP_DOMAIN_SEARCH_BASEThe search base for domain lookupsoptional${LDAP_DEFAULT_SEARCH_BASE}
LDAP_DOMAIN_SEARCH_SCOPEThe search scope for domain lookupsoptional${LDAP_DEFAULT_SEARCH_SCOPE}
LDAP_DOMAIN_FILTERThe search filter for domain lookupsrequired
LDAP_DOMAIN_ATTRIBUTEThe attributes for domain lookuprequired
LDAP_DOMAIN_FORMATThe format for domain lookupsoptional
LDAP_MAILBOX_SEARCH_BASEThe search base for mailbox lookupsoptional${LDAP_DEFAULT_SEARCH_BASE}
LDAP_MAILBOX_SEARCH_SCOPEThe search scope for mailbox lookupsoptional${LDAP_DEFAULT_SEARCH_SCOPE}
LDAP_MAILBOX_FILTERThe search filter for mailbox lookupsrequired
LDAP_MAILBOX_ATTRIBUTEThe attributes for mailbox lookuprequired
LDAP_MAILBOX_FORMATThe format for domain mailboxoptional
LDAP_ALIAS_SEARCH_BASEThe search base for domain lookupsoptional${LDAP_DEFAULT_SEARCH_BASE}
LDAP_ALIAS_SEARCH_SCOPEThe search scope for domain lookupsoptional${LDAP_DEFAULT_SEARCH_SCOPE}
LDAP_ALIAS_FILTERThe search filter for domain lookupsrequired
LDAP_ALIAS_ATTRIBUTEThe attributes for domain lookuprequired
LDAP_ALIAS_FORMATThe format for domain lookupsoptional
LDAP_FORWARD_SEARCH_BASEThe search base for forward lookupsoptional${LDAP_DEFAULT_SEARCH_BASE}
LDAP_FORWARD_SEARCH_SCOPEThe search scope for forward lookupsoptional${LDAP_DEFAULT_SEARCH_SCOPE}
LDAP_FORWARD_FILTERThe search filter for forward lookupsoptional
LDAP_FORWARD_ATTRIBUTEThe attributes for forward lookupoptional
LDAP_FORWARD_FORMATThe format for forward lookupsoptional
LDAP_GROUP_SEARCH_BASEThe search base for group lookupsoptional${LDAP_DEFAULT_SEARCH_BASE}
LDAP_GROUP_SEARCH_SCOPEThe search scope for group lookupsoptional${LDAP_DEFAULT_SEARCH_SCOPE}
LDAP_GROUP_FILTERThe search filter for group lookupsoptional
LDAP_GROUP_ATTRIBUTEThe attributes for group lookupoptional
LDAP_GROUP_FORMATThe format for group lookupsoptional
LDAP_GROUP_RESULT_ATTRIBUTEThe leaf result attribute groupoptional
LDAP_GROUP_RESULT_MEMBERThe special result attribute of the groupoptional
LDAP_SENDER_SEARCH_BASEThe search base for sender lookupsoptional${LDAP_DEFAULT_SEARCH_BASE}
LDAP_SENDER_SEARCH_SCOPEThe search scope for sender lookupsoptional${LDAP_DEFAULT_SEARCH_SCOPE}
LDAP_SENDER_FILTERThe search filter for sender lookupsrequired
LDAP_SENDER_ATTRIBUTEThe attributes for sender lookuprequired
LDAP_SENDER_FORMATThe format for sender lookupsrequired
LDAP_DOVECOT_USER_ATTRSDovecot user attribute mappingrequired
LDAP_DOVECOT_USER_FILTERDovecot user search filterrequired
LDAP_DOVECOT_PASS_ATTRSDovecot user password attribute mappingrequired
LDAP_DOVECOT_PASS_FILTERDovecot user password filterrequired
LDAP_DOVECOT_ITERATE_ATTRSDovecot user iterate attributesoptional
LDAP_DOVECOT_ITERATE_FILTERDovecot user iterate filtersoptional
LDAP_MASTER_USER_ENABLEDEnable LDAP master usersoptionalfalse
LDAP_MASTER_USER_SEPARATORLDAP master user separatorrequired ifLDAP_MASTER_USER_ENABLED*
LDAP_MASTER_USER_SEARCH_BASELDAP master user search baserequired ifLDAP_MASTER_USER_ENABLED${LDAP_DEFAULT_SEARCH_BASE}
LDAP_MASTER_USER_SEARCH_SCOPELDAP master user scoperequired ifLDAP_MASTER_USER_ENABLED${LDAP_DEFAULT_SEARCH_SCOPE}
LDAP_DOVECOT_MASTER_USER_ATTRSLDAP master user Dovecot attributesrequired ifLDAP_MASTER_USER_ENABLED
LDAP_DOVECOT_MASTER_USER_FILTERLDAP master user Dovecot search filterrequired ifLDAP_MASTER_USER_ENABLED

Back to table of contents 🔼

Automatic GPG encryption of all your emails

How does it work ?

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.

zeyple

Enable automatic GPG encryption

Please enable this option carefully and only if you know what you are doing.

SwitchENABLE_ENCRYPTION environment variable totrue. The public keyring will be saved in/var/mail/zeyple/keys.Please don't change the default value ofRECIPIENT_DELIMITER (default = "+"). If encryption is enabled with another delimiter, Zeyple could have an unpredictable behavior.

Import your public key

⚠️ 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

Import all recipients public keys

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

Specify another GPG keyserver

docker exec -ti mailserver encryption.sh import-key YOUR_KEY_ID hkp://pgp.mit.edudocker exec -ti mailserver encryption.sh import-all-keys hkp://keys.gnupg.net

Run other GPG options

You can use all options of GPG command line except an already assigned parameter called--homedir.

dockerexec -ti mailserver encryption.sh --list-keysdockerexec -ti mailserver encryption.sh --fingerprintdockerexec -ti mailserver encryption.sh --refresh-keysdockerexec -ti mailserver encryption.sh ...

Documentation:https://www.gnupg.org/documentation/manuals/gnupg/Operational-GPG-Commands.html

Back to table of contents 🔼

Relaying from other networks

TheRELAY_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 dis-advised. IPv6 addresses must be surrounded by square brackets. You can also specify an absolute 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 addresses192.168.0.0/16 172.16.0.0/12 10.0.0.0/8

⚠️ A value like0.0.0.0/0 will turn your mailserver into an open relay!

Back to table of contents 🔼

SSL certificates

Let's Encrypt certificates generated by Traefik

To use Let's Encrypt certificates generated by Traefik, mount a new docker volume like this:

mailserver:image:mailserver2/mailservervolumes:    -/mnt/docker/traefik/acme:/etc/letsencrypt/acme...

The startup script read theacme.json* file generated by Traefik and split into pem files all appropriate certificates (CN = mail.domain.tld).

💡 *Compatible with both Traefik>=1.5.0 and1.6+ ACME json format, withSAN andwildcard 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.ymllabels:  -traefik.frontend.rule=Host:mail.${DOMAIN}

Alternatively, you can specify your domains in thetraefik.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:

⚠️ ACME wildcard certificates can only be generated thanks to aDNS-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 the Traefik 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

Custom certificates

You can use Let's Encrypt or any other certification authority. Setup yourdocker-compose.yml like this:

mailserver:image:mailserver2/mailservervolumes:    -/mnt/docker/ssl:/etc/letsencrypt...

Request your certificates in/mnt/docker/ssl/live/mail.domain.tld with anACME 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:

💡 If you only have the fullchain.pem and privkey.pem, the startup script extract automatically the cert.pem and chain.pem from fullchain.pem.

FilenameDescription
privkey.pemPrivate key for the certificate
cert.pemServer certificate only
chain.pemRoot and intermediate certificates only, excluding server certificate
fullchain.pemAll certificates, including server certificate. This is concatenation of cert.pem and chain.pem

Example withacme.sh:

acme.sh --install-cert -d example.com \--ca-file${VOLUMES_ROOT_PATH}/ssl/live/mail.domain.tld/chain.pem  \--cert-file${VOLUMES_ROOT_PATH}/ssl/live/mail.domain.tld/cert.pem  \--key-file${VOLUMES_ROOT_PATH}/ssl/live/mail.domain.tld/privkey.pem  \--fullchain-file${VOLUMES_ROOT_PATH}/ssl/live/mail.domain.tld/fullchain.pem \--reloadcmd"docker restart mailserver"

Notes:

  • Important: When renewing certificates, you must restart the mailserver container.

  • If you do not use your own trusted certificates or those generated by Traefik, a default self-signed certificate (RSA 4096 bits SHA2) is added here:/mnt/docker/mail/ssl/selfsigned/{cert.pem, privkey.pem}.

  • If you have generated a ECDSA certificate with a curve other thanprime256v1 (NIST P-256), you need to change the Postfix TLS configuration because of a change in OpenSSL >= 1.1.0. For example, if you usesecp384r1 elliptic curve with your ECDSA certificate, change thetls_eecdh_strong_curve value:

# /mnt/docker/mail/postfix/custom.conftls_eecdh_strong_curve = secp384r1

Additional informations about this issue:

Testing

# IMAP STARTTLS - 143 port (IMAP)openssl s_client -connect mail.domain.tld:143 -starttls imap -tlsextdebug# SMTP STARTTLS - 587 port (Submission)openssl s_client -connect mail.domain.tld:587 -starttls smtp -tlsextdebug# IMAP SSL/TLS - 993 port (IMAPS)openssl s_client -connect mail.domain.tld:993 -tlsextdebug

Back to table of contents 🔼

MTA-STS

MTA-STS is a new standard that makes it possible to send downgrade-resistant email over SMTP. In that sense, it is like an alternative to DANE but it does this by piggybacking on the browser Certificate Authority model, not DNSSEC.

To enable Strict Transport Security on your mailserver configure the following things:

  1. Add a TLSRPT DNS TXT record at_smtp._tls on your domain, e.g._smtp._tls.domain.tld, with something likev=TLSRPTv1; rua=mailto:postmaster@domain.tld.
  2. Add a MTA-STS DNS TXT record at_mta-sts on your domain, e.g._mta-sts.domain.tld, with something likev=STSv1; id=2018072801.
  3. Add a subdomainmta-sts to your domain (note the lack of an underscore) and serve a policy file onhttps://mta-sts.domain.tld/.well-known/mta-sts.txt.

Here is an example policy file:

version: STSv1mode: enforcemax_age: 10368000mx: mail.domain.tld

Test your mail domain using a MTA-STS validator likeHardenize. You can also add your domain name in theSTARTTLS Policy List maintained byEFF.

Back to table of contents 🔼

Third-party Clamav signature databases

Clamav-unofficial-sigs provides a simple way to download and update third-party signature databases provided by Sanesecurity, FOXHOLE, OITC, Scamnailer, BOFHLAND, CRDF, Porcupine, Securiteinfo, MalwarePatrol, Yara-Rules Project, etc.

Readme:https://github.com/extremeshok/clamav-unofficial-sigs

Required Ports

SoftwareProtocolPort
RsyncTCP873
CurlTCP443

Enable clamav-unofficial-sigs

Create youruser.conf file under/mnt/docker/mail/clamav-unofficial-sigs directory to configure clamav-unofficial-sigs updater. This file override the default configuration specified inos.conf andmaster.conf. Don't forget, once you have completed the configuration of this file, set the value ofuser_configuration_complete toyes otherwise the script will not be able to execute.

# /mnt/docker/mail/clamav-unofficial-sigs/user.conf# =========================# MalwarePatrol: https://www.malwarepatrol.net# MalwarePatrol 2016 (free) Clamav signatures## 1. Sign up for an account: https://www.malwarepatrol.net/signup-free.shtml# 2. You will receive an email containing your password/receipt number# 3. Login to your account at malwarePatrol# 4. In My Accountpage, choose the ClamAV list you will download. Free subscribers only get ClamAV Basic, commercial subscribers have access to ClamAV Extended. Do not use the aggressive lists.# 5. In the download URL, you will see 3 parameters: receipt, product and list, enter them in the variables below.# malwarepatrol_receipt_code="YOUR-RECEIPT-NUMBER"# malwarepatrol_product_code="8"# malwarepatrol_list="clamav_basic"# malwarepatrol_free="yes"# =========================# SecuriteInfo: https://www.SecuriteInfo.com# SecuriteInfo 2015 free Clamav signatures## Usage of SecuriteInfo 2015 free Clamav signatures: https://www.securiteinfo.com# - 1. Sign up for a free account: https://www.securiteinfo.com/clients/customers/signup# - 2. You will receive an email to activate your account and then a follow-up email with your login name# - 3. Login and navigate to your customer account: https://www.securiteinfo.com/clients/customers/account# - 4. Click on the Setup tab# - 5. You will need to get your unique identifier from one of the download links, they are individual for every user# - 5.1. The 128 character string is after the http://www.securiteinfo.com/get/signatures/# - 5.2. Example https://www.securiteinfo.com/get/signatures/your_unique_and_very_long_random_string_of_characters/securiteinfo.hdb#   Your 128 character authorization signature would be: your_unique_and_very_long_random_string_of_characters# - 6. Enter the authorization signature into the config securiteinfo_authorisation_signature: replacing YOUR-SIGNATURE-NUMBER with your authorization signature from the link# securiteinfo_authorisation_signature="YOUR-SIGNATURE-NUMBER"# We enable Yara rules as they are now working with Clamav releases > 0.100yararulesproject_enabled="yes"enable_yararules="yes"# We enable interserver sigsinterserver_enabled="yes"# After you have completed the configuration of this file, set the value to "yes"user_configuration_complete="yes"

If the startup script detects this file, clamav-unofficial-sigs is automatically enabled and third-party databases downloaded under/mnt/docker/mail/clamav after Clamav startup. Once the databases are downloaded, a SIGUSR2 signal is sent to Clamav to reload the signature databases:

docker logs -f mailserver[INFO] clamav-unofficial-sigs is enabled (user configuration found)[...]s6-supervise : clamav unofficial signature update runnings6-supervise : virus database downloaded, spawning clamd process[...]s6-supervise : clamav unofficial signature update doneclamd[xxxxxx]: Reading databases from /var/lib/clamavclamd[xxxxxx]: Database correctly reloaded (6812263 signatures)

Back to table of contents 🔼

Unbound DNS resolver

Unbound is a validating, recursive, and caching DNS resolver inside the container, you can control it with the remote server control utility.

Some examples:

# Display server statusdockerexec -ti mailserver unbound-control status# Print server statisticsdockerexec -ti mailserver unbound-control stats_noreset# Reload the server. This flushes the cache and reads the config file.dockerexec -ti mailserver unbound-control reload

Documentation:https://www.unbound.net/documentation/unbound-control.html

Back to table of contents 🔼

PostgreSQL support

PostgreSQL can be used instead of MariaDB. You have to make some changes in the originaldocker-compose.yml file to use this DBMS:

mailserver:environment:    -DBDRIVER=pgsql    -DBHOST=postgres    -DBPORT=5432depends_on:    -postgrespostfixadmin:environment:    -DBDRIVER=pgsql    -DBHOST=postgres    -DBPORT=5432depends_on:    -postgresrainloop:depends_on:    -postgres# Database# https://github.com/docker-library/postgres# https://postgresql.org/postgres:image:postgres:10.5-alpinecontainer_name:postgresrestart:${RESTART_MODE}stop_signal:SIGINT# Fast shutdown mode# Info: These variables are ignored when the volume already exists (if databases was created before).environment:    -POSTGRES_DB=postfix    -POSTGRES_USER=postfix    -POSTGRES_PASSWORD=${DATABASE_USER_PASSWORD}volumes:    -${VOLUMES_ROOT_PATH}/pgsql/db:/var/lib/postgresql/datanetworks:    -mail_network

Back to table of contents 🔼

LDAP support

This mailserver supports LDAP now as well. Please keep in mind that LDAP itself is an already complicated system and using this mailserver with LDAP will require you to already have a deeper understanding on how LDAP, postfix and Dovecot works. Due to the nature of LDAP there is no "default" setup you can or is suggested to be used. This meansa lot of configuration isrequired to set this mailserver up with your LDAP system and it will definitely not work out of the box.

To enable LDAP you have to setDBDRIVER toldap.DBHOST andDBPORT must point to the LDAP server used.DBUSER,DBNAME,DBPASS environment variables will not be used in this case.

If you want to use TLS setLDAP_TLS_ENABLED totrue and specify aLDAP_TLS_CA_FILE. If you want to require the use of TLS setLDAP_TLS_FORCE to true.

If you want to bind to the LDAP server (default) setLDAP_BIND totrue (default) and give your bind user DN (full path) asLDAP_BIND_DN and password asLDAP_BIND_PW. If a path to a existing file is given inLDAP_BIND_PW the content of the file will be used instead.

All lookups will by default useLDAP_DEFAULT_SEARCH_BASE as base andLDAP_DEFAULT_SEARCH_SCOPE as scope. But for any query a specific base and scope can be provided as well. Valid scopes are:sub for subtree meaning all nodes below the base.one for all direct child nodes of the base andone for only the base node itself.

Unlike with Postfixadmin where all tables are fixed, this mailserver is intended to work with existing LDAP structures. This requires all lookups to be specified by you.

There are 4 required and 2 optional lookups for postfix that have to be provided by you. Each consists of 5 variables. The lookups are: Domain, Mailbox, Alias and Sender (all 4 required) and Forward and Group (optional). Each has the environment variablesLDAP_XXX_SEARCH_BASE,LDAP_XXX_SEARCH_SCOPE,LDAP_XXX_FILTER,LDAP_XXX_ATTRIBUTE andLDAP_XXXN_FORMAT (optional) whereXXX* must be replaced withDOMAIN,MAILBOX,ALIAS,SENDER,FORWARD orGROUP. E.g.LDAP_DOMAIN_SEARCH_BASE orLDAP_MAILBOX_FILTER

TheLDAP_XXX_SEARCH_BASE is the search base DN. It will default toLDAP_DEFAULT_SEARCH_BASE asLDAP_XXX_SEARCH_SCOPE will default toLDAP_DEFAULT_SEARCH_SCOPE (which defaults tosub).

TheLDAP_XXX_FILTER must be a valid LDAP query filter. For a documentation of LDAP query filters you can look athttps://ldap.com/ldap-filters/. For a list of valid replacement tokens please look athttp://www.postfix.org/ldap_table.5.html in the sectionquery_filter. Some examples:

LDAP_DOMAIN_FILTER="(&(mail=*@%s)(objectClass=mailAccount))"LDAP_MAILBOX_FILTER="(&(mail=%s)(objectClass=mailAccount))"LDAP_SENDER_FILTER="(&(|(mail=%s)(mailalias=%s))(objectClass=mailAccount))"

TheLDAP_XXX_ATTRIBUTE specifies which attribute of the found LDAP objects will be used. Usually these are eithermail,uid,mailalias ormailacceptinggeneralid but may be completely different ones depending on your LDAP setup.

LDAP_XXX_FORMAT can be used to reformat the result. E.g. you can useLDAP_MAILBOX_FORMAT="/var/mail/vhosts/%d/%s/mail/" to set a fixed path for the mailbox location if the path is not stored within LDAP.

The optionalFORWARD andGROUP lookups are technically identical to theALIAS lookup and could be used interchangeably but are intended for additional alias/group/forward lookups. So you can use aliases using an alias field in your user objects. Forwards as source and destination mapping fields in forwarding objects and group address and group member emails in group objects. But you can also use them in different ways to suit your system.

Then you also have to provide the lookups for Dovecot. These will probably be similar to your postfix lookups but may and will differ in some cases. The variables necessary areLDAP_DOVECOT_USER_ATTRS,LDAP_DOVECOT_USER_FILTER,LDAP_DOVECOT_PASS_ATTRS,LDAP_DOVECOT_PASS_FILTER,LDAP_DOVECOT_ITERATE_ATTRS,LDAP_DOVECOT_ITERATE_FILTER. They correspond directly to the Dovecot variables of the same name. While the user and pass attributes and filters are required, the iterate attributes and filters are not. For more detailed information please look athttps://wiki.dovecot.org/AuthDatabase/LDAP/Userdb. Note that multiple attributes may be required per query and must be provided in a different form than for postfix! Here are some examples:

LDAP_DOVECOT_USER_ATTRS="=home=/var/mail/vhosts/%d/%n/,=mail=maildir:/var/mail/vhosts/%d/%n/mail/,mailuserquota=quota=quota_rule=*:bytes=%\$$"LDAP_DOVECOT_USER_FILTER="(&(mail=%u)(objectClass=mailAccount))"LDAP_DOVECOT_PASS_ATTRS="mail=user,userPassword=password"LDAP_DOVECOT_PASS_FILTER="(&(mail=%u)(objectClass=mailAccount))"LDAP_DOVECOT_ITERATE_ATTRS="mail=user"LDAP_DOVECOT_ITERATE_FILTER="(objectClass=mailAccount)"

This mailserver also supports the user of master users that are allowed to log into other users mailboxes using their own password. This can be used e.g. for shared mailboxes or external IMAP services that should be able to connect to all inboxes via IMAP while not knowing the users passwords. To enable the use of master users setLDAP_MASTER_USER_ENABLED totrue. WithLDAP_MASTER_USER_SEPARATOR the separator can be specified (default is *). So you can log in with the usernamenormaluser@yoursystem.com*masteruser@yoursystem.com ornormaluser*masteruser if you only use usernames as logins. The password then has to be the password of the master user.LDAP_MASTER_USER_SEARCH_BASE,LDAP_MASTER_USER_SEARCH_SCOPE,LDAP_DOVECOT_MASTER_USER_ATTRS andLDAP_DOVECOT_MASTER_USER_FILTER work analogous to the Dovecot user lookups. For more detailed documentation please look athttps://wiki.dovecot.org/Authentication/MasterUsers . Note that%u is the master user name in this case and%{login_user} can be used to get the user name of the user to be logged in.

LDAP_MASTER_USER_ENABLED=trueLDAP_DOVECOT_MASTER_PASS_ATTRS="mail=user,userPassword=password"LDAP_DOVECOT_MASTER_PASS_FILTER="(&(mail=%u)(st=%{login_user})(objectClass=mailAccount))"

Back to table of contents 🔼

IPv6 support

If you want to support inbound IPv6 connections, you need to create a docker network with IPv6 enabled, otherwise, you may have some issues with docker internal networking.

The procedure is quite simple:

  • Remove your oldhttp_network (if you already have created it)
docker network rm http_network
  • Choose a private ipv6 address range (/64)

  • Create a docker network with IPv6 enabled

# Replace subnet mask with your own "Combined/CID"docker network create http_network --ipv6 --subnet"fd00:0000:0000:0000::/64"
  • Append this to yourdocker-compose.yml
# IPv6NAT# https://github.com/robbertkl/docker-ipv6nat# https://hub.docker.com/r/robbertkl/ipv6nat/ipv6nat:image:robbertkl/ipv6natcontainer_name:ipv6natrestart:${RESTART_MODE}volumes:    -/var/run/docker.sock:/var/run/docker.sock:ro    -/lib/modules:/lib/modules:rodepends_on:    -mailservercap_add:    -NET_ADMIN    -SYS_MODULEnetwork_mode:"host"
  • Create a record namedmail of typeAAAA with yourpublic IPv6 address with your DNS provider.

Done! This is all the configuration needed to enable inbound IPv6 support on this mailserver.

You can read more on how and whyrobbertkl/docker-ipv6nat container mimics NAT for IPv6 on his page.

Back to table of contents 🔼

Persistent files and folders in /mnt/docker/mail Docker volume

/mnt/docker└──mail   ├──postfix   |     custom.conf   |     rbl_override   |     sender_access   |  ├──spool (Postfix queues directory)   │  │     defer   │  │     flush   │  │     hold   │  │     maildrop   │  │     ...   ├──dovecot   |     instances   |     ssl-parameters.dat   |  ├──conf.d (Custom dovecot configuration)   ├──clamav (ClamAV databases directory)   │     bytecode.cvd   │     daily.cld   │     main.cvd   ├──clamav-unofficial-sigs   │     user.conf   ├──rspamd (Rspamd databases directory)   │     rspamd.rrd   |     stats.ucl   ├──zeyple   │  ├──keys (GPG public keyring)   │  │     pubring.kbx   │  │     trustdb.gpg   │  │     ...   ├──sieve   │     default.sieve   │     custom.sieve (custom default Sieve rules for all users)   ├──dkim   │  ├──domain.tld   │  │     {{selector}}.private.key   │  │     {{selector}}.public.key   ├──ssl   │  ├──selfsigned (Auto-generated if no certificate found)   │  │     cert.pem   │  │     privkey.pem   ├──vhosts   │  ├──domain.tld   │  │  ├──user   │  │  │     .dovecot.sieve -> sieve/rainloop.user.sieve   │  │  │     .dovecot.svbin   │  │  │  ├──mail   │  │  │  │  ├──.Archive   │  │  │  │  ├──.Drafts   │  │  │  │  ├──.Sent   │  │  │  │  ├──.Spam   │  │  │  │  ├──.Trash   │  │  │  │  ├──cur   │  │  │  │  ├──new   │  │  │  │     ...   │  │  │  ├──sieve   │  │  │  │     rainloop.user.sieve (if using Rainloop webmail)

Back to table of contents 🔼

Override postfix configuration

Postfix default configuration can be overridden by providing a custom configuration file in postfix format. This can beused to also add configuration that are not in default configuration.Postfix documentation remains the best placeto find configuration options.

Each line in the provided file will be loaded into Postfix. Create a new file here/mnt/docker/mail/postfix/custom.confand add your custom options inside.

To edit services inmaster.cf configuration file, SFP prefixes are available to indicate what you want to change.

  • S| = service entry (service/type=value)
  • F| = service field (service/type/field=value)
  • P| = service parameter (service/type/parameter=value)

Example:

# /mnt/docker/mail/postfix/custom.conf# main.cf parameterssmtpd_banner = $myhostname ESMTP MyGreatMailServerinet_protocols = ipv4delay_notice_recipient = admin@domain.tlddelay_warning_time = 2h# master.cf servicesS|submission/inet=submission inet n       -       -       -       -       smtpdP|submission/inet/syslog_name=postfix/submission-customP|submission/inet/smtpd_tls_security_level=mayP|submission/inet/smtpd_tls_ciphers=mediumF|smtp/unix/chroot=n
docker logs -f mailserver[INFO] Override parameter in main.cf : smtpd_banner = $myhostname ESMTP MyGreatMailServer[INFO] Override parameter in main.cf : inet_protocols = ipv4[INFO] Override parameter in main.cf : delay_notice_recipient = admin@domain.tld[INFO] Override parameter in main.cf : delay_warning_time = 2h[INFO] Override service entry in master.cf : submission/inet=submission inet n       -       -       -       -       smtpd[INFO] Override service parameter in master.cf : submission/inet/syslog_name=postfix/submission-custom[INFO] Override service parameter in master.cf : submission/inet/smtpd_tls_security_level=may[INFO] Override service parameter in master.cf : submission/inet/smtpd_tls_ciphers=medium[INFO] Override service field in master.cf : smtp/unix/chroot=n[INFO] Custom Postfix configuration file loaded

Back to table of contents 🔼

Whitelist Hosts/IP Addresses In Postfix

If a blacklisted server tries to send mail to your server, you should find something like this in your mail log:

SMTP error from remote mail server after RCPT TO:<bla@example.com>: host mail.example.com [4.3.2.1]: 554 5.7.1 Service unavailable; Client host [1.2.3.4] blocked using dnsbl.sorbs.net; Currently Sending Spam See: http://www.sorbs.net/lookup.shtml?1.2.3.4

In this example, the mail server 1.2.3.4 is blacklisted and therefore blocked.

To whitelist that server, create the file next to yourdocker-compose.yml file asrbl_override then add a list all IP addresses or host names (one per line!) that you want to whitelist as an example:

1.2.3.4 OKiam-good.com OKiam-bad.com REJECT

Then open yourdocker-compose.yml file and find yourmailserver service section and go to thevolumes part. Uncomment therbl_override line:

...    volumes:      - ${VOLUMES_ROOT_PATH}/mail:/var/mail      - ${VOLUMES_ROOT_PATH}/traefik/acme:/etc/letsencrypt/acme      # Comment out the line below, when you want whitelist some IP Addresses or domains in Postfix (please check the documentation)      # - ${VOLUMES_ROOT_PATH}/<to_your_directory_where_the>/rbl_override:/etc/postfix/rbl_override...

Don't forget to update the<to_your_directory_where_the> section based on your environment setup. Then restart yourmailserver.

Back to table of contents 🔼

Custom configuration for Dovecot

Sometimes you might want to add additional configuration parameters or override the default ones. You can do so by placing configuration files to the persistent folder/mnt/docker/mail/dovecot/conf.d.

Example:

# /mnt/docker/mail/dovecot/conf.d/20-imap.confprotocol imap {  mail_max_userip_connections = 100}# /mnt/docker/mail/dovecot/conf.d/90-quota.confplugin {  quota_rule2 = Trash:storage=+200M  quota_exceeded_message = You have exceeded your mailbox quota.}

Back to table of contents 🔼

Postfix blacklist

To block some senders or an entire domain, create a new file namedsender_access in/mnt/docker/mail/postfix.

# /mnt/docker/mail/postfix/sender_access# Format: <address|domain> <action>domain.tld REJECTspam@domain2.tld REJECT
docker logs -f mailserverNOQUEUE: reject: 554 5.7.1 <john.doe@domain.tld>: Sender address rejected: Access denied

Back to table of contents 🔼

Email client settings

  • IMAP/SMTP username:user@domain.tld
  • Incoming IMAP server: mail.domain.tld (your FQDN)
  • Outgoing SMTP server: mail.domain.tld (your FQDN)
  • IMAP port: 993
  • SMTP port: 587
  • IMAP Encryption protocol: SSL/TLS
  • SMTP Encryption protocol: STARTTLS

Back to table of contents 🔼

Components

  • Postfix 3.1.8
  • Dovecot 2.2.27
  • Rspamd 1.9.4
  • Fetchmail 6.3.26
  • ClamAV 1.0.3
  • Clamav Unofficial Sigs 5.6.2
  • Zeyple 1.2.2
  • Unbound 1.6.0
  • s6 2.8.0.1
  • Rsyslog 8.24.0
  • ManageSieve server

Back to table of contents 🔼

Migration from Traefik 1 to 2

Migrating from traefik 1 to 2 does not change any mailserver images that are used, only the traefik image version. You do need to update traefik labels on all containers as perdocker-compose.sample.yml. When you do this, either delete your acme.json and let traefik request the new certificate, or use thetool to convert from v1 to v2.

Back to table of contents 🔼

Migration from 1.0 to 1.1

If you still use 1.0 version (bundled with Spamassassin, Amavisd...etc) which was available with thelatest tag, you can follow the migration steps here:

https://github.com/hardware/mailserver/wiki/Migrating-from-1.0-stable-to-1.1-stable

Or stay with1.0-legacy tag (not recommended).

Back to table of contents 🔼

Migration from hardware/mailserver to mailserver2/mailserver

Follow the migration steps here:

https://github.com/mailserver2/mailserver/wiki/Migration-from-hardware-mailserver

Community projects

Back to table of contents 🔼

Some useful Thunderbird extensions

Back to table of contents 🔼


[8]ページ先頭

©2009-2025 Movatter.jp