From cf8e5552124eac9222143d4789195f54ad7cbf1e Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Sat, 8 Apr 2023 11:54:16 +0200 Subject: [PATCH] docs: miscellaneous improvements (#3219) Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- .github/workflows/scripts/docs/build-docs.sh | 2 +- README.md | 2 +- docs/content/config/advanced/auth-ldap.md | 4 +- .../config/advanced/full-text-search.md | 8 +- docs/content/config/advanced/kubernetes.md | 2 +- .../override-defaults/user-patches.md | 4 +- docs/content/config/debugging.md | 48 ++++ docs/content/config/environment.md | 6 +- docs/content/config/security/mail_crypt.md | 8 +- docs/content/config/security/ssl.md | 32 ++- .../security/understanding-the-ports.md | 111 ++++++++-- docs/content/config/setup.sh.md | 8 +- .../config/troubleshooting/debugging.md | 65 ------ .../config/user-management/accounts.md | 2 +- .../examples/tutorials/basic-installation.md | 127 +++++------ .../examples/tutorials/docker-build.md | 3 +- .../tutorials/mailserver-behind-proxy.md | 2 +- .../examples/use-cases/imap-folders.md | 12 +- docs/content/faq.md | 20 +- docs/content/index.md | 14 +- docs/content/introduction.md | 142 ++++++------ docs/content/usage.md | 207 ++++++++++++------ docs/mkdocs.yml | 5 +- 23 files changed, 470 insertions(+), 364 deletions(-) create mode 100644 docs/content/config/debugging.md delete mode 100644 docs/content/config/troubleshooting/debugging.md diff --git a/.github/workflows/scripts/docs/build-docs.sh b/.github/workflows/scripts/docs/build-docs.sh index cf059709..dd9ef3a5 100755 --- a/.github/workflows/scripts/docs/build-docs.sh +++ b/.github/workflows/scripts/docs/build-docs.sh @@ -10,7 +10,7 @@ docker run \ --user "$(id -u):$(id -g)" \ --volume "${PWD}:/docs" \ --name "build-docs" \ - squidfunk/mkdocs-material:8.3.9 build --strict + squidfunk/mkdocs-material:9.1.5 build --strict # Remove unnecessary build artifacts: https://github.com/squidfunk/mkdocs-material/issues/2519 # site/ is the build output folder. diff --git a/README.md b/README.md index b549a593..1115249f 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ If you have issues, please search through [the documentation][documentation::web ## :package: Included Services -- [Postfix](http://www.postfix.org) with SMTP or LDAP authentication and support for [extension delimiters](http://www.postfix.org/postconf.5.html#recipient_delimiter) (_mail to `you+extension@example.com` delivered to `you@example.com`_) +- [Postfix](http://www.postfix.org) with SMTP or LDAP authentication and support for [extension delimiters](https://docker-mailserver.github.io/docker-mailserver/latest/config/user-management/aliases/#address-tags-extension-delimiters-an-alternative-to-aliases) - [Dovecot](https://www.dovecot.org) with SASL, IMAP, POP3, LDAP, [basic Sieve support](https://docker-mailserver.github.io/docker-mailserver/latest/config/advanced/mail-sieve) and [quotas](https://docker-mailserver.github.io/docker-mailserver/latest/config/user-management/accounts#notes) - [Rspamd](https://rspamd.com/) - [Amavis](https://www.amavis.org/) diff --git a/docs/content/config/advanced/auth-ldap.md b/docs/content/config/advanced/auth-ldap.md index 822145cf..723deb7a 100644 --- a/docs/content/config/advanced/auth-ldap.md +++ b/docs/content/config/advanced/auth-ldap.md @@ -191,7 +191,7 @@ The changes on the configurations necessary to work with Active Directory (**onl ```yaml services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver hostname: mail.example.com @@ -253,7 +253,7 @@ The changes on the configurations necessary to work with Active Directory (**onl ```yaml services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver hostname: mail.example.com diff --git a/docs/content/config/advanced/full-text-search.md b/docs/content/config/advanced/full-text-search.md index efd21d23..8c513047 100644 --- a/docs/content/config/advanced/full-text-search.md +++ b/docs/content/config/advanced/full-text-search.md @@ -61,7 +61,7 @@ While indexing is memory intensive, you can configure the plugin to limit the am version: '3.8' services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver hostname: mail domainname: example.com @@ -134,7 +134,7 @@ While indexing is memory intensive, you can configure the plugin to limit the am ```yaml services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest volumes: - ./docker-data/dms/cron/fts_xapian:/etc/cron.d/fts_xapian ``` @@ -144,7 +144,7 @@ While indexing is memory intensive, you can configure the plugin to limit the am The [dovecot-solr Plugin](https://wiki2.dovecot.org/Plugins/FTS/Solr) is used in conjunction with [Apache Solr](https://lucene.apache.org/solr/) running in a separate container. This is quite straightforward to setup using the following instructions. -Solr is a mature and fast indexing backend that runs on the JVM. The indexes are relatively compact compared to the size of your total email. +Solr is a mature and fast indexing backend that runs on the JVM. The indexes are relatively compact compared to the size of your total email. However, Solr also requires a fair bit of RAM. While Solr is [highly tuneable](https://solr.apache.org/guide/7_0/query-settings-in-solrconfig.html), it may require a bit of testing to get it right. @@ -162,7 +162,7 @@ However, Solr also requires a fair bit of RAM. While Solr is [highly tuneable](h mailserver: depends_on: - solr - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest ... volumes: ... diff --git a/docs/content/config/advanced/kubernetes.md b/docs/content/config/advanced/kubernetes.md index a84e1064..cc5f51ee 100644 --- a/docs/content/config/advanced/kubernetes.md +++ b/docs/content/config/advanced/kubernetes.md @@ -186,7 +186,7 @@ spec: hostname: mail containers: - name: mailserver - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest imagePullPolicy: IfNotPresent securityContext: diff --git a/docs/content/config/advanced/override-defaults/user-patches.md b/docs/content/config/advanced/override-defaults/user-patches.md index b1017336..ba3206e3 100644 --- a/docs/content/config/advanced/override-defaults/user-patches.md +++ b/docs/content/config/advanced/override-defaults/user-patches.md @@ -4,7 +4,7 @@ title: 'Custom User Changes & Patches | Scripting' If you'd like to change, patch or alter files or behavior of `docker-mailserver`, you can use a script. -In case you cloned this repository, you can copy the file [`user-patches.sh.dist` (_under `config/`_)][gh-file-userpatches] with `#!sh cp config/user-patches.sh.dist docker-data/dms/config/user-patches.sh` in order to create the `user-patches.sh` script. +In case you cloned this repository, you can copy the file [`user-patches.sh.dist` (_under `config/`_)][github-file-userpatches] with `#!sh cp config/user-patches.sh.dist docker-data/dms/config/user-patches.sh` in order to create the `user-patches.sh` script. If you are managing your directory structure yourself, create a `docker-data/dms/config/` directory and add the `user-patches.sh` file yourself. @@ -40,4 +40,4 @@ And you're done. The user patches script runs right before starting daemons. Tha !!! note Many "patches" can already be done with the Docker Compose-/Stack-file. Adding hostnames to `/etc/hosts` is done with the `#!yaml extra_hosts:` section, `sysctl` commands can be managed with the `#!yaml sysctls:` section, etc. -[gh-file-userpatches]: https://github.com/docker-mailserver/docker-mailserver/blob/master/config-examples/user-patches.sh +[github-file-userpatches]: https://github.com/docker-mailserver/docker-mailserver/blob/master/config-examples/user-patches.sh diff --git a/docs/content/config/debugging.md b/docs/content/config/debugging.md new file mode 100644 index 00000000..0392e8fa --- /dev/null +++ b/docs/content/config/debugging.md @@ -0,0 +1,48 @@ +--- +title: 'Debugging' +hide: + - toc +--- + +This page contains valuable information when it comes to resolving issues you encounter. + +!!! info "Contributions Welcome!" + + Please consider contributing solutions to the [FAQ][docs-faq] :heart: + +## Preliminary Information + +### Mail sent from DMS does not arrive at destination + +Some service providers block outbound traffic on port 25. Common hosting providers known to have this issue: + +- [Azure](https://docs.microsoft.com/en-us/azure/virtual-network/troubleshoot-outbound-smtp-connectivity) +- [AWS EC2](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-port-25-throttle/) +- [Vultr](https://www.vultr.com/docs/what-ports-are-blocked/) + +These links may advise how the provider can unblock the port through additional services offered, or via a support ticket request. + +## Steps for Debugging DMS + +1. **Increase log verbosity**: Very helpful for troubleshooting problems during container startup. Set the environment variable [`LOG_LEVEL`][docs-environment-log-level] to `debug` or `trace`. +2. **Use error logs as a search query**: Try finding an _existing issue_ or _search engine result_ from any errors in your container log output. Often you'll find answers or more insights. If you still need to open an issue, sharing links from your search may help us assist you. The mail server log can be acquired by running `docker log ` (_or `docker logs -f ` if you want to follow the log_). +3. **Understand the basics of mail servers**: Especially for beginners, make sure you read our [Introduction][docs-introduction] and [Usage][docs-usage] articles. +4. **Search the whole FAQ**: Our [FAQ][docs-faq] contains answers for common problems. Make sure you go through the list. +5. **Reduce the scope**: Ensure that you can run a basic setup of DMS first. Then incrementally restore parts of your original configuration until the problem is reproduced again. If you're new to DMS, it is common to find the cause is misunderstanding how to configure a minimal setup. + +### Debug a running container + +To get a shell inside the container run: `docker exec -it bash`. + +If you need more flexibility than `docker logs` offers, within the container `/var/log/mail/mail.log` and `/var/log/supervisor/` are the most useful locations to get relevant DMS logs. Use the `tail` or `cat` commands to view their contents. + +To install additional software: + +- `apt-get update` is needed to update repository metadata. +- `apt-get install ` +- For example if you need a text editor, `nano` is a good package choice for beginners. + +[docs-faq]: ../faq.md +[docs-environment-log-level]: ./environment.md#log_level +[docs-introduction]: ../introduction.md +[docs-usage]: ../usage.md diff --git a/docs/content/config/environment.md b/docs/content/config/environment.md index 582c4dad..ad5c86e9 100644 --- a/docs/content/config/environment.md +++ b/docs/content/config/environment.md @@ -4,7 +4,7 @@ title: Environment Variables !!! info - Values in **bold** are the default values. If an option doesn't work as documented here, check if you are running the latest image. The current `master` branch corresponds to the image `mailserver/docker-mailserver:edge`. + Values in **bold** are the default values. If an option doesn't work as documented here, check if you are running the latest image. The current `master` branch corresponds to the image `ghcr.io/docker-mailserver/docker-mailserver:edge`. #### General @@ -13,10 +13,6 @@ title: Environment Variables - **empty** => uses the `hostname` command to get canonical hostname for `docker-mailserver` to use. - => Specify a fully-qualified domainname to serve mail for. This is used for many of the config features so if you can't set your hostname (_eg: you're in a container platform that doesn't let you_) specify it via this environment variable. It will take priority over `docker run` options: `--hostname` and `--domainname`, or `docker-compose.yml` config equivalents: `hostname:` and `domainname:`. -##### DMS_DEBUG - -**This environment variable was removed in `v11.0.0`!** Use `LOG_LEVEL` instead. - ##### LOG_LEVEL Set the log level for DMS. This is mostly relevant for container startup scripts and change detection event feedback. diff --git a/docs/content/config/security/mail_crypt.md b/docs/content/config/security/mail_crypt.md index 7b641ea7..12f8698b 100644 --- a/docs/content/config/security/mail_crypt.md +++ b/docs/content/config/security/mail_crypt.md @@ -3,7 +3,7 @@ title: 'Security | mail_crypt (email/storage encryption)' --- !!! info - + The Mail crypt plugin is used to secure email messages stored in a Dovecot system. Messages are encrypted before written to storage and decrypted after reading. Both operations are transparent to the user. In case of unauthorized access to the storage backend, the messages will, without access to the decryption keys, be unreadable to the offending party. @@ -34,11 +34,11 @@ Official Dovecot documentation: https://doc.dovecot.org/configuration_manual/mai 3. You then need to [generate your global EC key](https://doc.dovecot.org/configuration_manual/mail_crypt_plugin/#ec-key). We named them `/certs/ecprivkey.pem` and `/certs/ecpubkey.pem` in step #1. -4. The EC key needs to be available in the container. I prefer to mount a /certs directory into the container: +4. The EC key needs to be available in the container. I prefer to mount a /certs directory into the container: ```yaml services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest volumes: . . . - ./certs/:/certs @@ -49,7 +49,7 @@ Official Dovecot documentation: https://doc.dovecot.org/configuration_manual/mai ```yaml services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest volumes: . . . - ./config/dovecot/10-custom.conf:/etc/dovecot/conf.d/10-custom.conf diff --git a/docs/content/config/security/ssl.md b/docs/content/config/security/ssl.md index 3791affe..2588b975 100644 --- a/docs/content/config/security/ssl.md +++ b/docs/content/config/security/ssl.md @@ -121,7 +121,7 @@ Certbot provisions certificates to `/etc/letsencrypt`. Add a volume to store the !!! example Add these additions to the `mailserver` service in your [`docker-compose.yml`][github-file-compose]: - + ```yaml services: mailserver: @@ -169,7 +169,7 @@ Obtain a Cloudflare API token: 3. Click "Create Token", and choose the `Edit zone DNS` template (_Certbot [requires the `ZONE:DNS:Edit` permission](https://certbot-dns-cloudflare.readthedocs.io/en/stable/#credentials)_). !!! warning "Only include the necessary Zone resource configuration" - + Be sure to configure "Zone Resources" section on this page to `Include -> Specific zone -> `. This restricts the API token to only this zone (domain) which is an important security measure. @@ -264,7 +264,7 @@ After completing the steps above, your certificate should be ready to use. ``` You can manually run this service to renew the cert within 90 days: - + ```sh docker-compose run certbot-cloudflare-renew ``` @@ -274,14 +274,14 @@ After completing the steps above, your certificate should be ready to use. ```log Saving debug log to /var/log/letsencrypt/letsencrypt.log - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Processing /etc/letsencrypt/renewal/mail.example.com.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Account registered. Simulating renewal of an existing certificate for mail.example.com Waiting 10 seconds for DNS changes to propagate - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/mail.example.com/fullchain.pem (success) @@ -640,7 +640,7 @@ This setup only comes with one caveat: The domain has to be configured on anothe version: '3.8' services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver hostname: mail domainname: example.com @@ -696,10 +696,6 @@ Add `SSL_TYPE=self-signed` to your `docker-mailserver` environment variables. Po #### Generating a self-signed certificate -!!! note - - Since `docker-mailserver` v10, support in `setup.sh` for generating a _self-signed SSL certificate_ internally was removed. - One way to generate self-signed certificates is with [Smallstep's `step` CLI](https://smallstep.com/docs/step-cli). This is exactly what [`docker-mailserver` does for creating test certificates][github-file::tls-readme]. For example with the FQDN `mail.example.test`, you can generate the required files by running: @@ -821,15 +817,13 @@ These options in conjunction mean: If you have another source for SSL/TLS certificates you can import them into the server via an external script. The external script can be found here: [external certificate import script][hanscees-renewcerts]. -!!! attention "Only compatible with `docker-mailserver` releases < `v10.2`" +This is a community contributed script, and in most cases you will have better support via our _Change Detection_ service (_automatic for `SSL_TYPE` of `manual` and `letsencrypt`_) - Unless you're using LDAP which disables the service. - The script expects `/etc/postfix/ssl/cert` and `/etc/postfix/ssl/key` files to be configured paths for both Postfix and Dovecot to use. +!!! warning "Script Compatibility" - Since the `docker-mailserver` 10.2 release, certificate files have moved to `/etc/dms/tls/`, and the file name may differ depending on provisioning method. - - This third-party script also has `fullchain.pem` and `privkey.pem` as hard-coded, thus is incompatible with other filenames. - - Additionally it has never supported handling `ALT` fallback certificates (for supporting dual/hybrid, RSA + ECDSA). + - Relies on private filepaths `/etc/dms/tls/cert` and `/etc/dms/tls/key` intended for internal use only. + - Only supports hard-coded `fullchain.key` + `privkey.pem` as your mounted file names. That may not align with your provisioning method. + - No support for `ALT` fallback certificates (_for supporting dual/hybrid, RSA + ECDSA_). The steps to follow are these: @@ -864,7 +858,7 @@ export SITE_URL="mail.example.com" export SITE_IP_URL="192.168.0.72" # can also use `mail.example.com` export SITE_SSL_PORT="993" # imap port dovecot -##works: check if certificate will expire in two weeks +##works: check if certificate will expire in two weeks #2 weeks is 1209600 seconds #3 weeks is 1814400 #12 weeks is 7257600 @@ -921,7 +915,7 @@ if [ "$certcheck_2weeks" = "Certificate will not expire" ]; then echo "Cert seems to be expiring pretty soon, within two weeks: $certcheck_2weeks" echo "we will send an alert email and log as well" logger Certwatch: cert $SITE_URL will expire in two weeks - echo "Certwatch: cert $SITE_URL will expire in two weeks" | mail -s "cert $SITE_URL expires in two weeks " $ALERT_EMAIL_ADDR + echo "Certwatch: cert $SITE_URL will expire in two weeks" | mail -s "cert $SITE_URL expires in two weeks " $ALERT_EMAIL_ADDR fi ``` diff --git a/docs/content/config/security/understanding-the-ports.md b/docs/content/config/security/understanding-the-ports.md index f7d8e364..6a3e91b9 100644 --- a/docs/content/config/security/understanding-the-ports.md +++ b/docs/content/config/security/understanding-the-ports.md @@ -4,20 +4,31 @@ title: 'Security | Understanding the Ports' ## Quick Reference -Prefer Implicit TLS ports, they're more secure and if you use a Reverse Proxy, should be less hassle (although it's probably wiser to expose these ports directly to `docker-mailserver`). +Prefer ports with Implicit [TLS][wikipedia-tls] ports, they're more secure than ports using Explicit TLS, and if you use a Reverse Proxy should be less hassle. ## Overview of Email Ports -| Protocol | Explicit TLS1 | Implicit TLS | Purpose | -|----------|--------------------------|-----------------|----------------------| -| SMTP | 25 | N/A | Transfer2 | -| ESMTP | 587 | 4653 | Submission | -| POP3 | 110 | 995 | Retrieval | -| IMAP4 | 143 | 993 | Retrieval | +| Protocol | Explicit TLS1 | Implicit TLS | Purpose | Enabled by Default | +|--------------------------|--------------------------|-----------------|----------------------|--------------------| +| [ESMTP][wikipedia-esmtp] | 25 | N/A | Transfer2 | Yes | +| ESMTP | 587 | 4653 | Submission | Yes | +| POP3 | 110 | 995 | Retrieval | No | +| IMAP4 | 143 | 993 | Retrieval | Yes | + +1. A connection _may_ be secured over TLS when both ends support `STARTTLS`. On ports 110, 143 and 587, `docker-mailserver` will reject a connection that cannot be secured. Port 25 is [required][ref-port25-mandatory] to support insecure connections. +2. Receives email, `docker-mailserver` additionally filters for spam and viruses. For submitting email to the server to be sent to third-parties, you should prefer the _submission_ ports (465, 587) - which require authentication. Unless a relay host is configured (eg: SendGrid), outgoing email will leave the server via port 25 (_thus outbound traffic must not be blocked by your provider or firewall_). +3. A _submission_ port since 2018 ([RFC 8314][rfc-8314]). + +??? warning "Beware of outdated advice on port 465" + + There is a common misconception of this port due to it's history detailed by various communities and blogs articles on the topic (_including by popular mail relay services_). + + Port 465 was [briefly assigned the role of SMTPS in 1997][wikipedia-smtps] as an secure alternative to Port 25 between MTA exchanges. Then RFC 2487 (`STARTTLS`) [while still in a draft status in late 1998 had IANA revoke the SMTPS assignment][history-465-revoked]. The [draft history was modified to exclude all mention of port 465 and SMTPS][history-465-politics]. + + In 2018 [RFC 8314][rfc-8314] was published which revives Port 465 as an Implicit TLS alternative to Port 587 for mail submission. It details very clearly that gaining adoption of 465 as the preferred port will take time. IANA reassigned [port 465 as the `submissions` service][iana-services-465]. Any unofficial usage as **SMTPS is legacy and has been for over two decades**. + + Understand that port 587 is more broadly supported due to this history and that lots of software in that time has been built or configured with that port in mind. [`STARTTLS` is known to have various CVEs discovered even in recent years][starttls-vulnerabilities], do not be misled by any advice implying it should be preferred over implicit TLS. Trust in more official sources, such as the [config Postfix has][postfix-upstream-config-mastercf] which acknowledges the `submissions` port (465). -1. A connection *may* be secured over TLS when both ends support `STARTTLS`. On ports 110, 143 and 587, `docker-mailserver` will reject a connection that cannot be secured. Port 25 is [required][ref-port25-mandatory] to support insecure connections. -2. Receives email, `docker-mailserver` additionally filters for spam and viruses. For submitting email to the server to be sent to third-parties, you should prefer the *submission* ports(465, 587) - which require authentication. Unless a relay host is configured(eg SendGrid), outgoing email will leave the server via port 25(thus outbound traffic must not be blocked by your provider or firewall). -3. A *submission* port since 2018 ([RFC 8314][rfc-8314]). Previously a secure variant of port 25. ### What Ports Should I Use? (SMTP) @@ -52,49 +63,101 @@ flowchart LR #### Inbound Traffic (On the left) -- **Port 25:** Think of this like a physical mailbox, it is open to receive email from anyone who wants to. `docker-mailserver` will actively filter email delivered on this port for spam or viruses and refuse mail from known bad sources. While you could also use this port internally to send email outbound without requiring authentication, you really should prefer the *Submission* ports(587, 465). -- **Port 465(*and 587*):** This is the equivalent of a post office box where you would send email to be delivered on your behalf(`docker-mailserver` is that metaphorical post office, aka the MTA). Unlike port 25, these two ports are known as the *Submission* ports and require a valid email account on the server with a password to be able to send email to anyone outside of the server(an MTA you do not control, eg Outlook or Gmail). Prefer port 465 which provides Implicit TLS. +Mail arriving at your server will be processed and stored in a mailbox, or sent outbound to another mail server. + +- **Port 25:** + - Think of this like a physical mailbox, anyone can deliver mail to you here. Typically most mail is delivered to you on this port. + -`docker-mailserver` will actively filter email delivered on this port for spam or viruses, and refuse mail from known bad sources. + - Connections to this port may be secure through STARTTLS, but is not mandatory as [mail is allowed to arrive via an unencrypted connection][ref-port25-mandatory]. + - It is possible for internal clients to submit mail to be sent outbound (_without requiring authentication_), but that is discouraged. Prefer the _submission_ ports. +- **Port 465 and 587:** + - This is the equivalent of a post office box where you would send email to be delivered on your behalf (_`docker-mailserver` is that metaphorical post office, aka the MTA_). + - These two ports are known as the _submission_ ports, they enable mail to be sent outbound to another MTA (eg: Outlook or Gmail) but require authentication via a [mail account][docs-accounts]. + - For inbound traffic, this is relevant when you send mail from your MUA (eg: ThunderBird). It's also used when `docker-mailserver` is configured as a mail relay, or when you have a service sending transactional mail (_eg: order confirmations, password resets, notifications_) through `docker-mailserver`. + - _**Prefer port 465**_ over port 587, as 465 provides Implicit TLS. + +!!! note + + When submitting mail (inbound) to be sent (outbound), this involves two separate connections to negotiate and secure. There may be additional intermediary connections which `docker-mailserver` is not involved in, and thus unable to ensure encrypted transit throughout delivery. #### Outbound Traffic (On the Right) -- **Port 25:** Send the email directly to the given email address MTA as possible. Like your own `docker-mailserver` port 25, this is the standard port for receiving email on, thus email will almost always arrive to the final MTA on this port. Note that, there may be additional MTAs further in the chain, but this would be the public facing one representing that email address. -- **Port 465(*and 587*):** SMTP Relays are a popular choice to hand-off delivery of email through. Services like SendGrid are useful for bulk email(marketing) or when your webhost or ISP are preventing you from using standard ports like port 25 to send out email(which can be abused by spammers). - - `docker-mailserver` can serve as a relay too, but the difference between a DIY relay and a professional service is reputation, which is referenced by MTAs you're delivering to such as Outlook, Gmail or others(perhaps another `docker-mailserver` server!), when deciding if email should be marked as junked or potentially not delivered at all. As a service like SendGrid has a reputation to maintain, relay is restricted to registered users who must authenticate(even on port 25), they do not store email, merely forward it to another MTA which could be delivered on a different port like 25. +Mail being sent from your server is either being relayed through another MTA (eg: SendGrid), or direct to an MTA responsible for an email address (eg: Gmail). + +- **Port 25:** + - As most MTA use port 25 to receive inbound mail, when no authenticated relay is involved this is the outbound port used. + - Outbound traffic on this port is often blocked by service providers (eg: VPS, ISP) to prevent abuse by spammers. If the port cannot be unblocked, you will need to relay outbound mail through a service to send on your behalf. +- **Port 465 and 587:** + - Submission ports for outbound traffic establish trust to forward mail through a third-party relay service. This requires [authenticating to an account on the relay service][docs-relays]. The relay will then deliver the mail through port 25 on your behalf. + - These are the two typical ports used, but smart hosts like SendGrid often document support for additional non-standard ports as alternatives if necessary. + - Usually you'll only use these outbound ports for relaying. It is possible to deliver directly to the relevant MTA for email address, but requires having credentials for each MTA. + +!!! tip + + `docker-mailserver` can function as a relay too, but professional relay services have a trusted reputation (_which increases success of delivery_). + + An MTA with low reputation can affect if mail is treated as junk, or even rejected. + +!!! note + + At best, you can only ensure a secure connection between the MTA you directly connect to. The receiving MTA may relay that mail to another MTA (_and so forth_), each connection may not be enforcing TLS. + ### Explicit vs Implicit TLS #### Explicit TLS (aka Opportunistic TLS) - Opt-in Encryption -Communication on these ports begin in [cleartext][ref-clear-vs-plain], indicating support for `STARTTLS`. If both client and server support `STARTTLS` the connection will be secured over TLS, otherwise the connection is unable to use encryption to secure it. By default, `docker-mailserver` is configured to reject connections that fail to establish a secure connection when authentication is required, rather than allow an insecure connection (_Port 25 will allow receiving unencrypted deliveries which doesn't require authentication_). +Communication on these ports begin in [cleartext][ref-clear-vs-plain]. Upgrading to an encrypted connection must be requested explicitly through the `STARTTLS` protocol **and** successfully negotiated. -Support for `STARTTLS` is not always implemented correctly, which can lead to leaking credentials(client sending too early) prior to a TLS connection being established. Third-parties such as some ISPs have also been known to intercept the `STARTTLS` exchange, modifying network traffic to prevent establishing a secure connection. +Sometimes a reverse-proxy is involved, but is misconfigured or lacks support for the `STARTTLS` negotiation to succeed. + +!!! note + + - By default, `docker-mailserver` is configured to reject connections that fail to establish a secure connection (_when authentication is required_), rather than allow an insecure connection. + - Port 25 does not require authentication. If `STARTTLS` is unsuccessful, mail can be received over an unencrypted connection. You can better secure this port between trusted parties with the addition of MTA-STS, [STARTTLS Policy List][starttls-policy-list], DNSSEC and DANE. + +!!! warning + + `STARTTLS` [continues to have vulnerabilities found][starttls-vulnerabilities] (Nov 2021 article), as per [RFC 8314 (Section 4.1)][rfc-8314-s41] you are encouraged to **prefer Implicit TLS where possible**. + + Support for `STARTTLS` is not always implemented correctly, which can lead to leaking credentials (like a client sending too early) prior to a TLS connection being established. Third-parties such as some ISPs have also been known to intercept the `STARTTLS` exchange, modifying network traffic to prevent establishing a secure connection. -Due to these security concerns, [RFC 8314 (Section 4.1)][rfc-8314-s41] encourages you to **prefer Implicit TLS ports where possible**. #### Implicit TLS - Enforced Encryption -Communication is always encrypted, avoiding the above mentioned issues with Explicit TLS. +Communication on these ports are always encrypted (_enforced, thus implicit_), avoiding the potential risks with `STARTTLS` (Explicit TLS). -You may know of these ports as **SMTPS, POP3S, IMAPS**, which indicate the protocol in combination with a TLS connection. However, Explicit TLS ports provide the same benefit when `STARTTLS` is successfully negotiated; Implicit TLS better communicates the improved security to all three protocols (SMTP/POP3/IMAP over Implicit TLS). +While Explicit TLS can provide the same benefit (_when `STARTTLS` is successfully negotiated_), Implicit TLS more reliably avoids concerns with connection manipulation and compatibility. -Additionally, referring to port 465 as *SMTPS* would be incorrect, as it is a submissions port requiring authentication to proceed via *ESMTP*, whereas ESMTPS has a different meaning(STARTTLS supported). Port 25 may lack Implicit TLS, but can be configured to be more secure between trusted parties via MTA-STS, STARTTLS Policy List, DNSSEC and DANE. ## Security !!! todo + This section should provide any related configuration advice, and probably expand on and link to resources about DANE, DNSSEC, MTA-STS and STARTTLS Policy list, with advice on how to configure/setup these added security layers. !!! todo + A related section or page on ciphers used may be useful, although less important for users to be concerned about. ### TLS connections for a Mail-Server, compared to web browsers -Unlike with HTTP where a web browser client communicates directly with the server providing a website, a secure TLS connection as discussed below is not the equivalent safety that HTTPS provides when the transit of email (receiving or sending) is sent through third-parties, as the secure connection is only between two machines, any additional machines (MTAs) between the MUA and the MDA depends on them establishing secure connections between one another successfully. +Unlike with HTTP where a web browser client communicates directly with the server providing a website, a secure TLS connection as discussed below does not provide the equivalent safety that HTTPS does when the transit of email (receiving or sending) is sent through third-parties, as the secure connection is only between two machines, any additional machines (MTAs) between the MUA and the MDA depends on them establishing secure connections between one another successfully. -Other machines that facilitate a connection that generally aren't taken into account can exist between a client and server, such as those where your connection passes through your ISP provider are capable of compromising a cleartext connection through interception. +Other machines that facilitate a connection that generally aren't taken into account can exist between a client and server, such as those where your connection passes through your ISP provider are capable of compromising a `cleartext` connection through interception. +[docs-accounts]: ../user-management/accounts.md +[docs-relays]: ../advanced/mail-forwarding/relay-hosts.md +[iana-services-465]: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=465 +[starttls-policy-list]: https://github.com/EFForg/starttls-everywhere#email-security-database-starttls-policy-list +[starttls-vulnerabilities]: https://blog.apnic.net/2021/11/18/vulnerabilities-show-why-starttls-should-be-avoided-if-possible/ [ref-clear-vs-plain]: https://www.denimgroup.com/resources/blog/2007/10/cleartext-vs-pl [ref-port25-mandatory]: https://serverfault.com/questions/623692/is-it-still-wrong-to-require-starttls-on-incoming-smtp-messages [rfc-8314]: https://tools.ietf.org/html/rfc8314 [rfc-8314-s41]: https://tools.ietf.org/html/rfc8314#section-4.1 +[history-465-revoked]: https://web.archive.org/web/20150603202057/http://www.imc.org/ietf-apps-tls/mail-archive/msg00204.html +[history-465-politics]: https://mailing.postfix.users.narkive.com/F3ACwg2F/which-port-to-use-for-ssl-tls#post21 +[postfix-upstream-config-mastercf]: https://github.com/vdukhovni/postfix/blob/62931e5b1f9f1e80d02a496c7fd0062a5aae1d25/postfix/conf/master.cf#L38-L41 +[wikipedia-smtps]: https://en.wikipedia.org/wiki/SMTPS#History +[wikipedia-esmtp]: https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#Modern_SMTP +[wikipedia-tls]: https://en.wikipedia.org/wiki/Transport_Layer_Security diff --git a/docs/content/config/setup.sh.md b/docs/content/config/setup.sh.md index 181c025d..b55b7d9d 100644 --- a/docs/content/config/setup.sh.md +++ b/docs/content/config/setup.sh.md @@ -13,12 +13,6 @@ wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/maste chmod a+x ./setup.sh ``` -!!! warning "`setup.sh` for `docker-mailserver` version `v10.1.x` and below" - - If you're using `docker-mailserver` version `v10.1.x` or below, you will need to get `setup.sh` with a specific version. Substitute `` with the [tagged release version](https://github.com/docker-mailserver/docker-mailserver/tags) that you're using: - - `wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver//setup.sh`. - ## Usage Run `./setup.sh help` and you'll get ~~all you have ever wanted~~ some usage information: @@ -40,7 +34,7 @@ DESCRIPTION Please note that the script executes most of the commands inside the container itself. If the image was not found, this script will pull the ':latest' tag of - 'mailserver/docker-mailserver'. This tag refers to the latest release, + 'docker.io/mailserver/docker-mailserver'. This tag refers to the latest release, see the tagging convention in the README under https://github.com/docker-mailserver/docker-mailserver/blob/master/README.md diff --git a/docs/content/config/troubleshooting/debugging.md b/docs/content/config/troubleshooting/debugging.md deleted file mode 100644 index 8457cd05..00000000 --- a/docs/content/config/troubleshooting/debugging.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: 'Troubleshooting | Debugging' ---- - -!!! info "Contributions Welcome!" - Please contribute your solutions to help the community :heart: - -## Enable Verbose Debugging Output - -You may find it useful to set [`LOG_LEVEL`][docs-environment-log-level] environment variable. - -## Invalid Username or Password - -1. Shell into the container: - - ```sh - docker exec -it bash - ``` - -2. Check log files in `/var/log/mail` could not find any mention of incorrect logins here neither in the dovecot logs. - -3. Check the supervisors logs in `/var/log/supervisor`. You can find the logs for startup of fetchmail, postfix and others here - they might indicate problems during startup. - -4. Make sure you set your hostname to `mail` or whatever you specified in your `docker-compose.yml` file or else your FQDN will be wrong. - -## Installation Errors - -During setup, if you get errors trying to edit files inside of the container, you likely need to install `vi`: - -```sh -sudo su -docker exec -it apt-get install -y vim -``` - -## Testing Connection - -I spent HOURS trying to debug "Connection Refused" and "Connection closed by foreign host" errors when trying to use telnet to troubleshoot my connection. I was also trying to connect from my email client (macOS mail) around the same time. Telnet had also worked earlier, so I was extremely confused as to why it suddenly stopped working. I stumbled upon `fail2ban.log` in my container. In short, when trying to get my macOS client working, I exceeded the number of failed login attempts and fail2ban put dovecot and postfix in jail! I got around it by whitelisting my ipaddresses (my ec2 instance and my local computer) - -```sh -sudo su -docker exec -it mailserver bash -cd /var/log -cat fail2ban.log | grep dovecot - -# Whitelist IP addresses: -fail2ban-client set dovecot addignoreip # Server -fail2ban-client set postfix addignoreip -fail2ban-client set dovecot addignoreip # Client -fail2ban-client set postfix addignoreip - -# This will delete the jails entirely - nuclear option -fail2ban-client stop dovecot -fail2ban-client stop postfix -``` - -## Sent email is never received - -Some hosting provides have a stealth block on port 25. Make sure to check with your hosting provider that traffic on port 25 is allowed - -Common hosting providers known to have this issue: - -- [Azure](https://docs.microsoft.com/en-us/azure/virtual-network/troubleshoot-outbound-smtp-connectivity) -- [AWS EC2](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-port-25-throttle/) - -[docs-environment-log-level]: ../environment.md#log_level diff --git a/docs/content/config/user-management/accounts.md b/docs/content/config/user-management/accounts.md index 56bb0224..cc447627 100644 --- a/docs/content/config/user-management/accounts.md +++ b/docs/content/config/user-management/accounts.md @@ -19,7 +19,7 @@ In the example above, we've added 2 mail accounts for 2 different domains. Conse docker run --rm \ -e MAIL_USER=user1@example.com \ -e MAIL_PASS=mypassword \ - -it mailserver/docker-mailserver:latest \ + -it ghcr.io/docker-mailserver/docker-mailserver:latest \ /bin/sh -c 'echo "$MAIL_USER|$(doveadm pw -s SHA512-CRYPT -u $MAIL_USER -p $MAIL_PASS)"' >> docker-data/dms/config/postfix-accounts.cf ``` diff --git a/docs/content/examples/tutorials/basic-installation.md b/docs/content/examples/tutorials/basic-installation.md index 150d9331..bdb7cfb3 100644 --- a/docs/content/examples/tutorials/basic-installation.md +++ b/docs/content/examples/tutorials/basic-installation.md @@ -9,12 +9,13 @@ This example provides you only with a basic example of what a minimal setup coul ``` YAML services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver # Provide the FQDN of your mail server here (Your DNS MX record should point to this value) hostname: mail.example.com ports: - "25:25" + - "465:465" - "587:587" - "993:993" volumes: @@ -24,11 +25,9 @@ services: - ./docker-data/dms/config/:/tmp/docker-mailserver/ - /etc/localtime:/etc/localtime:ro environment: - - ENABLE_SPAMASSASSIN=1 - - SPAMASSASSIN_SPAM_TO_INBOX=1 + - ENABLE_RSPAMD=1 - ENABLE_CLAMAV=1 - ENABLE_FAIL2BAN=1 - - ENABLE_POSTGREY=1 cap_add: - NET_ADMIN # For Fail2Ban to work restart: always @@ -41,12 +40,13 @@ services: ``` YAML services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver # Provide the FQDN of your mail server here (Your DNS MX record should point to this value) hostname: mail.example.com ports: - "25:25" + - "465:465" - "587:587" - "993:993" volumes: @@ -56,11 +56,6 @@ services: - ./docker-data/dms/config/:/tmp/docker-mailserver/ - /etc/localtime:/etc/localtime:ro environment: - - ENABLE_SPAMASSASSIN=1 - - SPAMASSASSIN_SPAM_TO_INBOX=1 - - ENABLE_CLAMAV=1 - - ENABLE_FAIL2BAN=1 - - ENABLE_POSTGREY=1 - ACCOUNT_PROVISIONER=LDAP - LDAP_SERVER_HOST=ldap # your ldap container/IP/ServerName - LDAP_SEARCH_BASE=ou=people,dc=localhost,dc=localdomain @@ -80,30 +75,28 @@ services: - SASLAUTHD_LDAP_SEARCH_BASE=ou=people,dc=localhost,dc=localdomain - SASLAUTHD_LDAP_FILTER=(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%U)) - POSTMASTER_ADDRESS=postmaster@localhost.localdomain - cap_add: - - NET_ADMIN # For Fail2Ban to work restart: always ``` -## A Detailed Example +## Using DMS as a local mail relay for containers -!!! note +!!! info - This is a community contributed guide. Please let us know via a Github Issue if you're having any difficulty following the guide so that we can update it. + This was originally a community contributed guide. Please let us know via a Github Issue if you're having any difficulty following the guide so that we can update it. -This guide is focused on only using [SMTP ports (not POP3 and IMAP)][docs-ports] with the intent to send received mail to another MTA service such as _Gmail_. It is not intended to have a MUA client (_eg: Thunderbird_) to retrieve mail directly from `docker-mailserver` via POP3/IMAP. +This guide is focused on only using [SMTP ports (not POP3 and IMAP)][docs-ports] with the intent to relay mail received from another service to an external email address (eg: `user@gmail.com`). It is not intended for mailbox storage of real users. -In this setup `docker-mailserver` is not intended to receive email externally, so no anti-spam or anti-virus software is needed, making the service lighter to run. +In this setup `docker-mailserver` is not intended to receive email from the outside world, so no anti-spam or anti-virus software is needed, making the service lighter to run. + +!!! tip "`setup`" + + The `setup` command used below is to be [run inside the container][docs-usage]. !!! warning "Open Relays" Adding the docker network's gateway to the list of trusted hosts (_eg: using the `network` or `connected-networks` option_), can create an [**open relay**](https://en.wikipedia.org/wiki/Open_mail_relay). For instance [if IPv6 is enabled on the host machine, but not in Docker][github-issue-1405-comment]. -1. If you're running a version of `docker-mailserver` earlier than v10.2, [you'll need to get `setup.sh`][docs-setup-script]. Otherwise you can substitute `./setup.sh ` with `docker exec mailserver setup `. - -2. Pull the docker image: `docker pull docker.io/mailserver/docker-mailserver:latest`. - -3. Create the file `docker-compose.yml` with a content like this: +1. Create the file `docker-compose.yml` with a content like this: !!! example @@ -126,48 +119,56 @@ In this setup `docker-mailserver` is not intended to receive email externally, s - /etc/localtime:/etc/localtime:ro environment: - ENABLE_FAIL2BAN=1 - # Using letsencrypt for SSL/TLS certificates + # Using letsencrypt for SSL/TLS certificates: - SSL_TYPE=letsencrypt - # Allow sending emails from other docker containers + # Allow sending emails from other docker containers: # Beware creating an Open Relay: https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/#permit_docker - PERMIT_DOCKER=network # You may want to enable this: https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/#spoof_protection - # See step 8 below, which demonstrates setup with enabled/disabled SPOOF_PROTECTION: + # See step 6 below, which demonstrates setup with enabled/disabled SPOOF_PROTECTION: - SPOOF_PROTECTION=0 cap_add: - NET_ADMIN # For Fail2Ban to work restart: always ``` - - The docs have a detailed page on [Environment Variables][docs-environment] for reference. + The docs have a detailed page on [Environment Variables][docs-environment] for reference. - !!! note "Firewalled ports" + ??? tip "Firewalled ports" - You may need to open ports `25`, `587` and `465` on the firewall. For example, with the firewall `ufw`, run: + If you have a firewall running, you may need to open ports `25`, `587` and `465`. + + For example, with the firewall `ufw`, run: ```sh ufw allow 25 ufw allow 587 ufw allow 465 ``` + + **Caution:** This may [not be sound advice][github-issue-ufw]. -4. Configure your DNS service to use an MX record for the _hostname_ (eg: `mail`) you configured in the previous step and add the [SPF][docs-spf] TXT record. +2. Configure your DNS service to use an MX record for the _hostname_ (eg: `mail`) you configured in the previous step and add the [SPF][docs-spf] TXT record. - If you manually manage the DNS zone file for the domain, it would look something like this: + !!! tip "If you manually manage the DNS zone file for the domain" + + It would look something like this: + + ```txt + $ORIGIN example.com + @ IN A 10.11.12.13 + mail IN A 10.11.12.13 + + ; mail-server for example.com + @ IN MX 10 mail.example.com. + + ; Add SPF record + @ IN TXT "v=spf1 mx -all" + ``` + + Then don't forget to change the `SOA` serial number, and to restart the service. - ```txt - mail IN A 10.11.12.13 - - ; mail-server for example.com - 3600 IN MX 1 mail.example.com. - - ; Add SPF record - IN TXT "v=spf1 mx ~all" - ``` - - Then don't forget to change the serial number and to restart the service. - -5. [Generate DKIM keys][docs-dkim] for your domain via `./setup.sh config dkim`. +3. [Generate DKIM keys][docs-dkim] for your domain via `setup config dkim`. Copy the content of the file `docker-data/dms/config/opendkim/keys/example.com/mail.txt` and add it to your DNS records as a TXT like SPF was handled above. @@ -179,21 +180,21 @@ In this setup `docker-mailserver` is not intended to receive email externally, s "iqq3bD/BVlwKRp5gH6TEYEmx8EBJUuDxrJhkWRUk2VDl1fqhVBy8A9O7Ah+85nMrlOHIFsTaYo9o6+cDJ6t1i6G1gu+bZD0d3/3bqGLPBQV9LyEL1Rona5V7TJBGg099NQkTz1IwIDAQAB" ) ; ----- DKIM key mail for example.com ``` -6. Get an SSL certificate, [we have a guide for you here][docs-ssl] (_Let's Encrypt_ is a popular service to get free SSL certificates). +4. Get an SSL certificate, [we have a guide for you here][docs-ssl] (_Let's Encrypt_ is a popular service to get free SSL certificates). -7. Start `docker-mailserver` and check the terminal output for any errors: `docker-compose up`. +5. Start `docker-mailserver` and check the terminal output for any errors: `docker-compose up`. -8. Create email accounts and aliases: +6. Create email accounts and aliases: !!! example "With `SPOOF_PROTECTION=0`" ```sh - ./setup.sh email add admin@example.com passwd123 - ./setup.sh email add info@example.com passwd123 - ./setup.sh alias add admin@example.com external-account@gmail.com - ./setup.sh alias add info@example.com external-account@gmail.com - ./setup.sh email list - ./setup.sh alias list + setup email add admin@example.com passwd123 + setup email add info@example.com passwd123 + setup alias add admin@example.com external-account@gmail.com + setup alias add info@example.com external-account@gmail.com + setup email list + setup alias list ``` Aliases make sure that any email that comes to these accounts is forwarded to your third-party email address (`external-account@gmail.com`), where they are retrieved (_eg: via third-party web or mobile app_), instead of connecting directly to `docker-mailserer` with POP3 / IMAP. @@ -201,25 +202,25 @@ In this setup `docker-mailserver` is not intended to receive email externally, s !!! example "With `SPOOF_PROTECTION=1`" ```sh - ./setup.sh email add admin.gmail@example.com passwd123 - ./setup.sh email add info.gmail@example.com passwd123 - ./setup.sh alias add admin@example.com admin.gmail@example.com - ./setup.sh alias add info@example.com info.gmail@example.com - ./setup.sh alias add admin.gmail@example.com external-account@gmail.com - ./setup.sh alias add info.gmail@example.com external-account@gmail.com - ./setup.sh email list - ./setup.sh alias list + setup email add admin.gmail@example.com passwd123 + setup email add info.gmail@example.com passwd123 + setup alias add admin@example.com admin.gmail@example.com + setup alias add info@example.com info.gmail@example.com + setup alias add admin.gmail@example.com external-account@gmail.com + setup alias add info.gmail@example.com external-account@gmail.com + setup email list + setup alias list ``` This extra step is required to avoid the `553 5.7.1 Sender address rejected: not owned by user` error (_the accounts used for submitting mail to Gmail are `admin.gmail@example.com` and `info.gmail@example.com`_) -9. Send some test emails to these addresses and make other tests. Once everything is working well, stop the container with `ctrl+c` and start it again as a daemon: `docker-compose up -d`. +7. Send some test emails to these addresses and make other tests. Once everything is working well, stop the container with `ctrl+c` and start it again as a daemon: `docker-compose up -d`. [docs-ports]: ../../config/security/understanding-the-ports.md -[docs-setup-script]: ../../config/setup.sh.md [docs-environment]: ../../config/environment.md [docs-spf]: ../../config/best-practices/spf.md [docs-dkim]: ../../config/best-practices/dkim.md [docs-ssl]: ../../config/security/ssl.md#lets-encrypt-recommended - +[docs-usage]: ../../usage.md#get-up-and-running +[github-issue-ufw]: https://github.com/docker-mailserver/docker-mailserver/issues/3151 [github-issue-1405-comment]: https://github.com/docker-mailserver/docker-mailserver/issues/1405#issuecomment-590106498 diff --git a/docs/content/examples/tutorials/docker-build.md b/docs/content/examples/tutorials/docker-build.md index 62471579..fc6d5c37 100644 --- a/docs/content/examples/tutorials/docker-build.md +++ b/docs/content/examples/tutorials/docker-build.md @@ -10,7 +10,7 @@ You'll need to retrieve the git submodules prior to building your own Docker ima ```sh git submodule update --init --recursive -docker build -t mailserver/docker-mailserver . +docker build -t . ``` Or, you can clone and retrieve the submodules in one command: @@ -37,4 +37,3 @@ The `Dockerfile` takes additional, so-called build arguments. These are 2. `VCS_REVISION`: the image revision (default = unknown) When using `make` to build the image, these are filled with proper values. You can build the image without supplying these arguments just fine though. - diff --git a/docs/content/examples/tutorials/mailserver-behind-proxy.md b/docs/content/examples/tutorials/mailserver-behind-proxy.md index 78606b5b..cd5bc02d 100644 --- a/docs/content/examples/tutorials/mailserver-behind-proxy.md +++ b/docs/content/examples/tutorials/mailserver-behind-proxy.md @@ -60,7 +60,7 @@ Feel free to add your configuration if you achieved the same goal using differen version: '3.8' services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver hostname: mail domainname: example.com diff --git a/docs/content/examples/use-cases/imap-folders.md b/docs/content/examples/use-cases/imap-folders.md index 1923d6a1..1d1b2539 100644 --- a/docs/content/examples/use-cases/imap-folders.md +++ b/docs/content/examples/use-cases/imap-folders.md @@ -6,17 +6,17 @@ hide: # Mailboxes (_aka IMAP Folders_) -`INBOX` is setup as the private [`inbox` namespace][dovecot-docs-namespaces]. By default [`target/dovecot/15-mailboxes.conf`][gh-config-dovecot-mailboxes] configures the special IMAP folders `Drafts`, `Sent`, `Junk` and `Trash` to be automatically created and subscribed. They are all assigned to the private [`inbox` namespace][dovecot-docs-namespaces] (_which implicitly provides the `INBOX` folder_). +`INBOX` is setup as the private [`inbox` namespace][dovecot-docs-namespaces]. By default [`target/dovecot/15-mailboxes.conf`][github-config-dovecot-mailboxes] configures the special IMAP folders `Drafts`, `Sent`, `Junk` and `Trash` to be automatically created and subscribed. They are all assigned to the private [`inbox` namespace][dovecot-docs-namespaces] (_which implicitly provides the `INBOX` folder_). These IMAP folders are considered special because they add a [_"SPECIAL-USE"_ attribute][rfc-6154], which is a standardized way to communicate to mail clients that the folder serves a purpose like storing spam/junk mail (`\Junk`) or deleted mail (`\Trash`). This differentiates them from regular mail folders that you may use for organizing. ## Adding a mailbox folder -See [`target/dovecot/15-mailboxes.conf`][gh-config-dovecot-mailboxes] for existing mailbox folders which you can modify or uncomment to enable some other common mailboxes. For more information try the [official Dovecot documentation][dovecot-docs-mailboxes]. +See [`target/dovecot/15-mailboxes.conf`][github-config-dovecot-mailboxes] for existing mailbox folders which you can modify or uncomment to enable some other common mailboxes. For more information try the [official Dovecot documentation][dovecot-docs-mailboxes]. -The `Archive` special IMAP folder may be useful to enable. To do so, make a copy of [`target/dovecot/15-mailboxes.conf`][gh-config-dovecot-mailboxes] and uncomment the `Archive` mailbox definition. Mail clients should understand that this folder is intended for archiving mail due to the [`\Archive` _"SPECIAL-USE"_ attribute][rfc-6154]. +The `Archive` special IMAP folder may be useful to enable. To do so, make a copy of [`target/dovecot/15-mailboxes.conf`][github-config-dovecot-mailboxes] and uncomment the `Archive` mailbox definition. Mail clients should understand that this folder is intended for archiving mail due to the [`\Archive` _"SPECIAL-USE"_ attribute][rfc-6154]. -With the provided [docker-compose.yml][gh-config-dockercompose] example, a volume bind mounts the host directory `docker-data/dms/config/` to the container location `/tmp/docker-mailserver/`. Config file overrides should instead be mounted to a different location as described in [Overriding Configuration for Dovecot][docs-config-overrides-dovecot]: +With the provided [docker-compose.yml][github-config-dockercompose] example, a volume bind mounts the host directory `docker-data/dms/config/` to the container location `/tmp/docker-mailserver/`. Config file overrides should instead be mounted to a different location as described in [Overriding Configuration for Dovecot][docs-config-overrides-dovecot]: ```yaml volumes: @@ -65,8 +65,8 @@ Take care to test localized names work well as well. [docs-config-overrides-dovecot]: ../../config/advanced/override-defaults/dovecot.md#override-configuration -[gh-config-dockercompose]: https://github.com/docker-mailserver/docker-mailserver/blob/master/docker-compose.yml -[gh-config-dovecot-mailboxes]: https://github.com/docker-mailserver/docker-mailserver/blob/master/target/dovecot/15-mailboxes.conf +[github-config-dockercompose]: https://github.com/docker-mailserver/docker-mailserver/blob/master/docker-compose.yml +[github-config-dovecot-mailboxes]: https://github.com/docker-mailserver/docker-mailserver/blob/master/target/dovecot/15-mailboxes.conf [dovecot-docs-namespaces]: https://doc.dovecot.org/configuration_manual/namespace/#namespace-inbox [dovecot-docs-mailboxes]: https://doc.dovecot.org/configuration_manual/namespace/#mailbox-settings [rfc-6154]: https://datatracker.ietf.org/doc/html/rfc6154 diff --git a/docs/content/faq.md b/docs/content/faq.md index abe384b8..0734481a 100644 --- a/docs/content/faq.md +++ b/docs/content/faq.md @@ -233,6 +233,22 @@ Yes, by adding the environment variable `PERMIT_DOCKER: network`. Adding the Docker network's gateway to the list of trusted hosts, e.g. using the `network` or `connected-networks` option, can create an [**open relay**](https://en.wikipedia.org/wiki/Open_mail_relay), for instance [if IPv6 is enabled on the host machine but not in Docker][github-issue-1405-comment]. +### Connection refused or No response at all + +You see errors like "Connection Refused" and "Connection closed by foreign host", or you cannot connect at all? You may not be able to connect with your mail client (MUA)? Make sure to check Fail2Ban did not ban you (for exceeding the number of tried logins for example)! You can run + +```bash +docker exec setup fail2ban +``` + +and check whether your IP address appears. Use + +```bash +docker exec setup fail2ban unban +``` + +to unban the IP address. + ### How can I authenticate users with `SMTP_ONLY=1`? See [#1247][github-issue-1247] for an example. @@ -429,7 +445,7 @@ The following configuration works nicely: ```yaml services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest volumes: - ./docker-data/dms/cron/sa-learn:/etc/cron.d/sa-learn ``` @@ -441,7 +457,7 @@ The following configuration works nicely: services: mailserver: - image: docker.io/mailserver/docker-mailserver:latest + image: ghcr.io/docker-mailserver/docker-mailserver:latest # ... configs: - source: my_sa_crontab diff --git a/docs/content/index.md b/docs/content/index.md index b22d5fc5..10d099ce 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -10,7 +10,7 @@ title: Home This documentation provides you not only with the basic setup and configuration of DMS but also with advanced configuration, elaborate usage scenarios, detailed examples, hints and more. -[docs-tagging]: ./usage/#available-images-tags-tagging-convention +[docs-tagging]: ./usage.md#tagging-convention ## About @@ -42,16 +42,18 @@ You might also want to check out: 1. A list of [all configuration options via ENV][docs-environment] 2. A list of [all optional and automatically created configuration files and directories][docs-optionalconfig] +3. How to [debug your mail server][docs-debugging] !!! tip Definitely check out the [FAQ][docs-faq] for more information and tips! Please do not open an issue before you have checked our documentation for answers, including the [FAQ][docs-faq]! -[docs-environment]: ./config/environment/ -[docs-userpatches]: ./faq/#how-to-adjust-settings-with-the-user-patchessh-script -[docs-setupsh]: ./config/setup.sh/ -[docs-optionalconfig]: ./config/advanced/optional-config/ -[docs-faq]: ./faq/ +[docs-environment]: ./config/environment.md +[docs-userpatches]: ./faq.md#how-to-adjust-settings-with-the-user-patchessh-script +[docs-setupsh]: ./config/setup.sh.md +[docs-optionalconfig]: ./config/advanced/optional-config.md +[docs-faq]: ./faq.md +[docs-debugging]: ./config/debugging.md ### Tests diff --git a/docs/content/introduction.md b/docs/content/introduction.md index b0d2f0a5..f136b795 100644 --- a/docs/content/introduction.md +++ b/docs/content/introduction.md @@ -1,28 +1,28 @@ --- -title: An overview of Mail-Server infrastructure +title: Introduction --- -What is a mail-server, and how does it perform its duty? +# An Overview of Mail Server Infrastructure -Here's an introduction to the field that covers everything you need to know to get started with `docker-mailserver`. +This article answers the question "What is a mail server, and how does it perform its duty?" and it gives the reader an introduction to the field that covers everything you need to know to get started with `docker-mailserver`. -## Anatomy of a Mail-Server +## The Anatomy of a Mail Server -A mail-server is only a part of a [client-server relationship][wikipedia-clientserver] aimed at exchanging information in the form of [emails][wikipedia-email]. Exchanging emails requires using specific means (programs and protocols). +A mail server is only a part of a [client-server relationship][wikipedia-clientserver] aimed at exchanging information in the form of [emails][wikipedia-email]. Exchanging emails requires using specific means (programs and protocols). `docker-mailserver` provides you with the server portion, whereas the client can be anything from a terminal via text-based software (eg. [Mutt][software-mutt]) to a fully-fledged desktop application (eg. [Mozilla Thunderbird][software-thunderbird], [Microsoft Outlook][software-outlook]…), to a web interface, etc. -Unlike the client-side where usually a single program is used to perform retrieval and viewing of emails, the server-side is composed of many specialized components. The mail-server is capable of accepting, forwarding, delivering, storing and overall exchanging messages, but each one of those tasks is actually handled by a specific piece of software. All of these "agents" must be integrated with one another for the exchange to take place. +Unlike the client-side where usually a single program is used to perform retrieval and viewing of emails, the server-side is composed of many specialized components. The mail server is capable of accepting, forwarding, delivering, storing and overall exchanging messages, but each one of those tasks is actually handled by a specific piece of software. All of these "agents" must be integrated with one another for the exchange to take place. -`docker-mailserver` has made informed choices about those components and their (default) configuration. It offers a comprehensive platform to run a fully featured mail-server in no time! +`docker-mailserver` has made informed choices about those components and their (default) configuration. It offers a comprehensive platform to run a fully featured mail server in no time! ## Components The following components are required to create a [complete delivery chain][wikipedia-emailagent]: -- MUA: a [Mail User Agent][wikipedia-mua] is basically any client/program capable of sending emails to a mail-server; while also capable of fetching emails from a mail-server for presenting them to the end users. -- MTA: a [Mail Transfer Agent][wikipedia-mta] is the so-called "mail-server" as seen from the MUA's perspective. It's a piece of software dedicated to accepting submitted emails, then forwarding them-where exactly will depend on an email's final destination. If the receiving MTA is responsible for the FQDN the email is sent to, then an MTA is to forward that email to an MDA (see below). Otherwise, it is to transfer (ie. forward, relay) to another MTA, "closer" to the email's final destination. -- MDA: a [Mail Delivery Agent][wikipedia-mda] is responsible for accepting emails from an MTA and dropping them into their recipients' mailboxes, whichever the form. +- **MUA**: a [Mail User Agent][wikipedia-mua] is basically any client/program capable of sending emails to a mail server; while also capable of fetching emails from a mail server for presenting them to the end users. +- **MTA**: a [Mail Transfer Agent][wikipedia-mta] is the so-called "mail server" as seen from the MUA's perspective. It's a piece of software dedicated to accepting submitted emails, then forwarding them-where exactly will depend on an email's final destination. If the receiving MTA is responsible for the FQDN the email is sent to, then an MTA is to forward that email to an MDA (see below). Otherwise, it is to transfer (ie. forward, relay) to another MTA, "closer" to the email's final destination. +- **MDA**: a [Mail Delivery Agent][wikipedia-mda] is responsible for accepting emails from an MTA and dropping them into their recipients' mailboxes, whichever the form. Here's a schematic view of mail delivery: @@ -49,7 +49,8 @@ Fetching an email: MUA <------------------------------ ┫ MDA ╯ ┃ ┗━━━━━━━┛ ``` -!!! example +??? example "An Example" + Let's say Alice owns a Gmail account, `alice@gmail.com`; and Bob owns an account on a `docker-mailserver`'s instance, `bob@dms.io`. Make sure not to conflate these two very different scenarios: @@ -62,43 +63,41 @@ Fetching an email: MUA <------------------------------ ┫ MDA ╯ ┃ One important thing to note is that MTA and MDA programs may actually handle _multiple_ tasks (which is the case with `docker-mailserver`'s Postfix and Dovecot). -For instance, Postfix is both an SMTP server (accepting emails) and a relaying MTA (transferring, ie. sending emails to other MTA/MDA); Dovecot is both an MDA (delivering emails in mailboxes) and an IMAP server (allowing MUAs to fetch emails from the *mail-server*). On top of that, Postfix may rely on Dovecot's authentication capabilities. +For instance, Postfix is both an SMTP server (accepting emails) and a relaying MTA (transferring, ie. sending emails to other MTA/MDA); Dovecot is both an MDA (delivering emails in mailboxes) and an IMAP server (allowing MUAs to fetch emails from the _mail server_). On top of that, Postfix may rely on Dovecot's authentication capabilities. The exact relationship between all the components and their respective (sometimes shared) responsibilities is beyond the scope of this document. Please explore this wiki & the web to get more insights about `docker-mailserver`'s toolchain. ## About Security & Ports -In the previous section, different components were outlined. Each one of those is responsible for a specific task, it has a specific purpose. +### Introduction -Three main purposes exist when it comes to exchanging emails: +In the previous section, three components were outlined. Each one of those is responsible for a specific task when it comes to exchanging emails: -- _Submission_: for a MUA (client), the act of sending actual email data over the network, toward an MTA (server). -- _Transfer_ (aka. _Relay_): for an MTA, the act of sending actual email data over the network, toward another MTA (server) closer to the final destination (where an MTA will forward data to an MDA). -- _Retrieval_: for a MUA (client), the act of fetching actual email data over the network, from an MDA. +- **Submission**: for a MUA (client), the act of sending actual email data over the network, toward an MTA (server). +- **Transfer** (aka. **Relay**): for an MTA, the act of sending actual email data over the network, toward another MTA (server) closer to the final destination (where an MTA will forward data to an MDA). +- **Retrieval**: for a MUA (client), the act of fetching actual email data over the network, from an MDA. -Postfix handles Submission (and might handle Relay), whereas Dovecot handles Retrieval. They both need to be accessible by MUAs in order to act as servers, therefore they expose public endpoints on specific TCP ports (see. [_Understanding the ports_][docs-understandports] for more details). Those endpoints _may_ be secured, using an encryption scheme and TLS certificates. +Postfix handles **Submission** (_and may handle **Relay**_), whereas Dovecot handles **Retrieval**. They both need to be accessible by MUAs in order to act as servers, therefore they expose public [endpoints on specific TCP ports][docs-understandports]. Those endpoints _may_ be secured, using an encryption scheme and TLS certificates. When it comes to the specifics of email exchange, we have to look at protocols and ports enabled to support all the identified purposes. There are several valid options and they've been evolving overtime. -**Here's `docker-mailserver`'s _default_ configuration:** +### Overview -| Purpose | Protocol | TCP port / encryption | -|----------------|----------|--------------------------------| -| Transfer/Relay | SMTP | 25 (unencrypted) | -| Submission | ESMTP | 587 (encrypted using STARTTLS) | -| Retrieval | IMAP4 | 143 (encrypted using STARTTLS) + 993 (TLS) | -| Retrieval | POP3 | _Not activated_ | +The following picture gives a visualization of the interplay of all components and their [respective ports][docs-understandports]: ```txt - ┏━━━━━━━━━━ Submission ━━━━━━━━━┓┏━━━━━━━━━━━━━ Transfer/Relay ━━━━━━━━━━━┓ - ┌─────────────────────┐ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ -MUA ----- STARTTLS ---> ┤(587) MTA ╮ (25)├ <-- cleartext ---> ┊ Third-party MTA ┊ - ---- cleartext ---> ┤(25) │ | └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ - |┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄| -MUA <---- STARTTLS ---- ┤(143) MDA ╯ | - <-- enforced TLS -- ┤(993) | - └─────────────────────┘ - ┗━━━━━━━━━━ Retrieval ━━━━━━━━━━┛ + ┏━━━━━━━━━━ Submission ━━━━━━━━━━━━┓┏━━━━━━━━━━━━━ Transfer/Relay ━━━━━━━━━━━┓ + + ┌─────────────────────┐ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ +MUA ----- STARTTLS ------> ┤(587) MTA ╮ (25)├ <-- cleartext ---> ┊ Third-party MTA ┊ + ----- implicit TLS --> ┤(465) │ | └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ + ----- cleartext -----> ┤(25) │ | + |┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄| +MUA <---- STARTTLS ------- ┤(143) MDA ╯ | + <---- implicit TLS --- ┤(993) | + └─────────────────────┘ + + ┗━━━━━━━━━━ Retrieval ━━━━━━━━━━━━━┛ ``` If you're new to email infrastructure, both that table and the schema may be confusing. @@ -110,9 +109,7 @@ For a MUA to send an email to an MTA, it needs to establish a connection with th In the case of `docker-mailserver`, the MTA (SMTP server) is Postfix. The MUA (client) may vary, yet its Submission request is performed as [TCP][wikipedia-tcp] packets sent over the _public_ internet. This exchange of information may be secured in order to counter eavesdropping. -#### Two kinds of Submission - -Let's say I own an account on a `docker-mailserver` instance, `me@dms.io`. There are two very different use-cases for Submission: +Now let's say I own an account on a `docker-mailserver` instance, `me@dms.io`. There are two very different use-cases for Submission: 1. I want to send an email to someone 2. Someone wants to send you an email @@ -123,67 +120,69 @@ In the second scenario, a third-party email account owner will be first submitti My MTA will thus have to support two kinds of Submission: -- Outward Submission (self-owned email is submitted directly to the MTA, then is relayed "outside") -- Inward Submission (third-party email has been submitted & relayed, then is accepted "inside" by the MTA) +- Outbound Submission (self-owned email is submitted directly to the MTA, then is relayed "outside") +- Inbound Submission (third-party email has been submitted & relayed, then is accepted "inside" by the MTA) ```txt - ┏━━━━ Outward Submission ━━━━┓ + ┏━━━━ Outbound Submission ━━━━┓ + ┌────────────────────┐ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ Me ---------------> ┤ ├ -----------------> ┊ ┊ │ My MTA │ ┊ Third-party MTA ┊ │ ├ <----------------- ┊ ┊ └────────────────────┘ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ - ┗━━━━━━━━━━ Inward Submission ━━━━━━━━━━┛ + + ┗━━━━━━━━━━ Inbound Submission ━━━━━━━━━━┛ ``` -##### Outward Submission +#### Outbound Submission -The best practice as of 2020 when it comes to securing Outward Submission is to use _Implicit TLS connection via ESMTP on port 465_ (see [RFC 8314][rfc-8314]). Let's break it down. - -- Implicit TLS means the server _enforces_ the client into using an encrypted TCP connection, using [TLS][wikipedia-tls]. With this kind of connection, the MUA _has_ to establish a TLS-encrypted connection from the get go (TLS is implied, hence the name "Implicit"). Any client attempting to either submit email in cleartext (unencrypted, not secure), or requesting a cleartext connection to be upgraded to a TLS-encrypted one using `STARTTLS`, is to be denied. Implicit TLS is sometimes called Enforced TLS for that reason. -- [ESMTP][wikipedia-esmtp] is [SMTP][wikipedia-smtp] + extensions. It's the version of the SMTP protocol that a mail-server commonly communicates with today. For the purpose of this documentation, ESMTP and SMTP are synonymous. -- Port 465 is the reserved TCP port for Implicit TLS Submission (since 2018). There is actually a boisterous history to that ports usage, but let's keep it simple. +When it comes to securing Outbound Submission you should prefer to use _Implicit TLS connection via ESMTP on port 465_ (see [RFC 8314][rfc-8314]). Please read our article about [**Understanding the Ports**][docs-understandports] for more details! !!! warning + This Submission setup is sometimes referred to as [SMTPS][wikipedia-smtps]. Long story short: this is incorrect and should be avoided. Although a very satisfactory setup, Implicit TLS on port 465 is somewhat "cutting edge". There exists another well established mail Submission setup that must be supported as well, SMTP+STARTTLS on port 587. It uses Explicit TLS: the client starts with a cleartext connection, then the server informs a TLS-encrypted "upgraded" connection may be established, and the client _may_ eventually decide to establish it prior to the Submission. Basically it's an opportunistic, opt-in TLS upgrade of the connection between the client and the server, at the client's discretion, using a mechanism known as [STARTTLS][wikipedia-starttls] that both ends need to implement. -In many implementations, the mail-server doesn't enforce TLS encryption, for backwards compatibility. Clients are thus free to deny the TLS-upgrade proposal (or [misled by a hacker](https://security.stackexchange.com/questions/168998/what-happens-if-starttls-dropped-in-smtp) about STARTTLS not being available), and the server accepts unencrypted (cleartext) mail exchange, which poses a confidentiality threat and, to some extent, spam issues. [RFC 8314 (section 3.3)][rfc-8314-s33] recommends for a mail-server to support both Implicit and Explicit TLS for Submission, _and_ to enforce TLS-encryption on ports 587 (Explicit TLS) and 465 (Implicit TLS). That's exactly `docker-mailserver`'s default configuration: abiding by RFC 8314, it [enforces a strict (`encrypt`) STARTTLS policy](http://www.postfix.org/postconf.5.html#smtpd_tls_security_level), where a denied TLS upgrade terminates the connection thus (hopefully but at the client's discretion) preventing unencrypted (cleartext) Submission. +In many implementations, the mail server doesn't enforce TLS encryption, for backwards compatibility. Clients are thus free to deny the TLS-upgrade proposal (or [misled by a hacker](https://security.stackexchange.com/questions/168998/what-happens-if-starttls-dropped-in-smtp) about STARTTLS not being available), and the server accepts unencrypted (cleartext) mail exchange, which poses a confidentiality threat and, to some extent, spam issues. [RFC 8314 (section 3.3)][rfc-8314-s33] recommends for a mail server to support both Implicit and Explicit TLS for Submission, _and_ to enforce TLS-encryption on ports 587 (Explicit TLS) and 465 (Implicit TLS). That's exactly `docker-mailserver`'s default configuration: abiding by RFC 8314, it [enforces a strict (`encrypt`) STARTTLS policy](http://www.postfix.org/postconf.5.html#smtpd_tls_security_level), where a denied TLS upgrade terminates the connection thus (hopefully but at the client's discretion) preventing unencrypted (cleartext) Submission. -- **`docker-mailserver`'s default configuration enables and _requires_ Explicit TLS (STARTTLS) on port 587 for Outward Submission.** -- It does not enable Implicit TLS Outward Submission on port 465 by default. One may enable it through simple custom configuration, either as a replacement or (better!) supplementary mean of secure Submission. +- **`docker-mailserver`'s default configuration enables and _requires_ Explicit TLS (STARTTLS) on port 587 for Outbound Submission.** +- It does not enable Implicit TLS Outbound Submission on port 465 by default. One may enable it through simple custom configuration, either as a replacement or (better!) supplementary mean of secure Submission. - It does not support old MUAs (clients) not supporting TLS encryption on ports 587/465 (those should perform Submission on port 25, more details below). One may relax that constraint through advanced custom configuration, for backwards compatibility. -A final Outward Submission setup exists and is akin SMTP+STARTTLS on port 587, but on port 25. That port has historically been reserved specifically for unencrypted (cleartext) mail exchange though, making STARTTLS a bit wrong to use. As is expected by [RFC 5321][rfc-5321], `docker-mailserver` uses port 25 for unencrypted Submission in order to support older clients, but most importantly for unencrypted Transfer/Relay between MTAs. +A final Outbound Submission setup exists and is akin SMTP+STARTTLS on port 587, but on port 25. That port has historically been reserved specifically for unencrypted (cleartext) mail exchange though, making STARTTLS a bit wrong to use. As is expected by [RFC 5321][rfc-5321], `docker-mailserver` uses port 25 for unencrypted Submission in order to support older clients, but most importantly for unencrypted Transfer/Relay between MTAs. -- **`docker-mailserver`'s default configuration also enables unencrypted (cleartext) on port 25 for Outward Submission.** -- It does not enable Explicit TLS (STARTTLS) on port 25 by default. One may enable it through advanced custom configuration, either as a replacement (bad!) or as a supplementary mean of secure Outward Submission. -- One may also secure Outward Submission using advanced encryption scheme, such as DANE/DNSSEC and/or MTA-STS. +- **`docker-mailserver`'s default configuration also enables unencrypted (cleartext) on port 25 for Outbound Submission.** +- It does not enable Explicit TLS (STARTTLS) on port 25 by default. One may enable it through advanced custom configuration, either as a replacement (bad!) or as a supplementary mean of secure Outbound Submission. +- One may also secure Outbound Submission using advanced encryption scheme, such as DANE/DNSSEC and/or MTA-STS. -##### Inward Submission +#### Inbound Submission -Granted it's still very difficult enforcing encryption between MTAs (Transfer/Relay) without risking dropping emails (when relayed by MTAs not supporting TLS-encryption), Inward Submission is to be handled in cleartext on port 25 by default. +Granted it's still very difficult enforcing encryption between MTAs (Transfer/Relay) without risking dropping emails (when relayed by MTAs not supporting TLS-encryption), Inbound Submission is to be handled in cleartext on port 25 by default. -- **`docker-mailserver`'s default configuration enables unencrypted (cleartext) on port 25 for Inward Submission.** -- It does not enable Explicit TLS (STARTTLS) on port 25 by default. One may enable it through advanced custom configuration, either as a replacement (bad!) or as a supplementary mean of secure Inward Submission. -- One may also secure Inward Submission using advanced encryption scheme, such as DANE/DNSSEC and/or MTA-STS. +- **`docker-mailserver`'s default configuration enables unencrypted (cleartext) on port 25 for Inbound Submission.** +- It does not enable Explicit TLS (STARTTLS) on port 25 by default. One may enable it through advanced custom configuration, either as a replacement (bad!) or as a supplementary mean of secure Inbound Submission. +- One may also secure Inbound Submission using advanced encryption scheme, such as DANE/DNSSEC and/or MTA-STS. Overall, `docker-mailserver`'s default configuration for SMTP looks like this: ```txt - ┏━━━━ Outward Submission ━━━━┓ + ┏━━━━ Outbound Submission ━━━━┓ + ┌────────────────────┐ ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐ Me -- cleartext --> ┤(25) (25)├ --- cleartext ---> ┊ ┊ -Me -- STARTTLS ---> ┤(587) My MTA │ ┊ Third-party MTA ┊ +Me -- TLS ---> ┤(465) My MTA │ ┊ Third-party MTA ┊ +Me -- STARTTLS ---> ┤(587) │ ┊ ┊ │ (25)├ <---cleartext ---- ┊ ┊ └────────────────────┘ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘ - ┗━━━━━━━━━━ Inward Submission ━━━━━━━━━━┛ + + ┗━━━━━━━━━━ Inbound Submission ━━━━━━━━━━┛ ``` ### Retrieval - IMAP -A MUA willing to fetch an email from a mail-server will most likely communicate with its [IMAP][wikipedia-imap] server. As with SMTP described earlier, communication will take place in the form of data packets exchanged over a network that both the client and the server are connected to. The IMAP protocol makes the server capable of handling _Retrieval_. +A MUA willing to fetch an email from a mail server will most likely communicate with its [IMAP][wikipedia-imap] server. As with SMTP described earlier, communication will take place in the form of data packets exchanged over a network that both the client and the server are connected to. The IMAP protocol makes the server capable of handling _Retrieval_. In the case of `docker-mailserver`, the IMAP server is Dovecot. The MUA (client) may vary, yet its Retrieval request is performed as [TCP][wikipedia-tcp] packets sent over the _public_ internet. This exchange of information may be secured in order to counter eavesdropping. @@ -201,31 +200,20 @@ The best practice as of 2020 would be [POP3S][wikipedia-pop3s] on port 995, rath **`docker-mailserver`'s default configuration disables POP3 altogether.** One should expect MUAs to use TLS-encrypted IMAP for Retrieval. -## How does `docker-mailserver` help with setting everything up? +## How Does `docker-mailserver` Help With Setting Everything Up? -As a _batteries included_ Docker image, `docker-mailserver` provides you with all the required components and a default configuration, to run a decent and secure mail-server. - -One may then customize all aspects of its internal components. +As a _batteries included_ container image, `docker-mailserver` provides you with all the required components and a default configuration to run a decent and secure mail server. One may then customize all aspects of its internal components. - Simple customization is supported through [docker-compose configuration][github-file-compose] and the [env-mailserver][github-file-envmailserver] configuration file. - Advanced customization is supported through providing "monkey-patching" configuration files and/or [deriving your own image][github-file-dockerfile] from `docker-mailserver`'s upstream, for a complete control over how things run. -On the subject of security, one might consider `docker-mailserver`'s **default** configuration to _not_ be 100% secure: - -- it enables unencrypted traffic on port 25 -- it enables Explicit TLS (STARTTLS) on port 587, instead of Implicit TLS on port 465 - -We believe `docker-mailserver`'s default configuration to be a good middle ground: it goes slightly beyond "old" (1999) [RFC 2487][rfc-2487]; and with developer friendly configuration settings, it makes it pretty easy to abide by the "newest" (2018) [RFC 8314][rfc-8314]. Eventually, it is up to _you_ deciding exactly what kind of transportation/encryption to use and/or enforce, and to customize your instance accordingly (with looser or stricter security). Be also aware that protocols and ports on your server can only go so far with security; third-party MTAs might relay your emails on insecure connections, man-in-the-middle attacks might still prove effective, etc. Advanced counter-measure such as DANE, MTA-STS and/or full body encryption (eg. PGP) should be considered as well for increased confidentiality, but ideally without compromising backwards compatibility so as to not block emails. -The [README][github-file-readme] is the best starting point in configuring and running your mail-server. You may then explore this wiki to cover additional topics, including but not limited to, security. - [docs-understandports]: ./config/security/understanding-the-ports.md [github-file-compose]: https://github.com/docker-mailserver/docker-mailserver/blob/master/docker-compose.yml [github-file-envmailserver]: https://github.com/docker-mailserver/docker-mailserver/blob/master/mailserver.env [github-file-dockerfile]: https://github.com/docker-mailserver/docker-mailserver/blob/master/Dockerfile -[github-file-readme]: https://github.com/docker-mailserver/docker-mailserver/blob/master/README.md [rfc-2487]: https://tools.ietf.org/html/rfc2487 [rfc-5321]: https://tools.ietf.org/html/rfc5321 [rfc-8314]: https://tools.ietf.org/html/rfc8314 @@ -236,7 +224,6 @@ The [README][github-file-readme] is the best starting point in configuring and r [wikipedia-clientserver]: https://en.wikipedia.org/wiki/Client%E2%80%93server_model [wikipedia-email]: https://en.wikipedia.org/wiki/Email [wikipedia-emailagent]: https://en.wikipedia.org/wiki/Email_agent_(infrastructure) -[wikipedia-esmtp]: https://en.wikipedia.org/wiki/ESMTP [wikipedia-imap]: https://en.wikipedia.org/wiki/IMAP [wikipedia-imaps]: https://en.wikipedia.org/wiki/IMAPS [wikipedia-mda]: https://en.wikipedia.org/wiki/Mail_delivery_agent @@ -248,4 +235,3 @@ The [README][github-file-readme] is the best starting point in configuring and r [wikipedia-smtps]: https://en.wikipedia.org/wiki/SMTPS [wikipedia-starttls]: https://en.wikipedia.org/wiki/Opportunistic_TLS [wikipedia-tcp]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol -[wikipedia-tls]: https://en.wikipedia.org/wiki/Transport_Layer_Security diff --git a/docs/content/usage.md b/docs/content/usage.md index 8361102b..4d845eaf 100644 --- a/docs/content/usage.md +++ b/docs/content/usage.md @@ -2,14 +2,74 @@ title: Usage --- -This pages explains how to get started with DMS, basically explaining how you can use it. The procedure uses Docker Compose as a reference. In our examples, [`/docker-data/dms/config/`](../faq/#what-about-the-docker-datadmsmail-state-folder) on the host is mounted to `/tmp/docker-mailserver/` inside the container. +This pages explains how to get started with DMS. The guide uses Docker Compose as a reference. In our examples, a volume mounts the host location [`docker-data/dms/config/`][docs-dms-config-volume] to `/tmp/docker-mailserver/` inside the container. -## Available Images / Tags - Tagging Convention +[docs-dms-config-volume]: ./config/advanced/optional-config.md -[CI/CD](https://github.com/docker-mailserver/docker-mailserver/actions) will automatically build, test and push new images to container registries. Currently, the following registries are supported: +## Preliminary Steps -1. DockerHub ([`docker.io/mailserver/docker-mailserver`](https://hub.docker.com/r/mailserver/docker-mailserver)) -2. GitHub Container Registry ([`ghcr.io/docker-mailserver/docker-mailserver`](https://github.com/docker-mailserver/docker-mailserver/pkgs/container/docker-mailserver)) +Before you can get started with deploying your own mail server, there are some requirements to be met: + +1. You need to have a host that you can manage. +2. You need to own a domain, and you need to able to manage DNS for this domain. + +### Host Setup + +There are a few requirements for a suitable host system: + +1. The host should have a static IP address; otherwise you will need to dynamically update DNS (undesirable due to DNS caching) +2. The host should be able to send/receive on the [necessary ports for mail][docs-ports-overview] +3. You should be able to set a `PTR` record for your host; security-hardened mail servers might otherwise reject your mail server as the IP address of your host does not resolve correctly/at all to the DNS name of your server. + +On the host, you should have a suitable container runtime (like _Docker_ or _Podman_) installed. We assume [_Docker Compose_][docker-compose] is [installed][docker-compose-installation]. + +!!! info "Podman Support" + + If you're using podman, make sure to read the related [documentation][docs-podman]. + +[docs-podman]: ./config/advanced/podman.md +[docs-ports-overview]: ./config/security/understanding-the-ports.md#overview-of-email-ports +[docker-compose]: https://docs.docker.com/compose/ +[docker-compose-installation]: https://docs.docker.com/compose/install/ + +### Minimal DNS Setup + +The DNS setup is a big and essential part of the whole setup. There is a lot of confusion for newcomers and people starting out when setting up DNS. This section provides an example configuration and supplementary explanation. We expect you to be at least a bit familiar with DNS, what it does and what the individual record types are. + +Now let's say you just bought `example.com` and you want to be able to send and receive e-mails for the address `test@example.com`. On the most basic level, you will need to + +1. set an `MX` record for your domain `example.com` - in our example, the MX record contains `mail.example.com` +2. set an `A` record that resolves the name of your mail server - in our example, the A record contains `11.22.33.44` +3. (in a best-case scenario) set a `PTR` record that resolves the IP of your mail server - in our example, the PTR contains `mail.example.com` + +We will later dig into DKIM, DMARC & SPF, but for now, these are the records that suffice in getting you up and running. Here is a short explanation of what the records do: + +- The **MX record** tells everyone which (DNS) name is responsible for e-mails on your domain. + Because you want to keep the option of running another service on the domain name itself, you run your mail server on `mail.example.com`. + This does not imply your e-mails will look like `test@mail.example.com`, the DNS name of your mail server is decoupled of the domain it serves e-mails for. + In theory, you mail server could even serve e-mails for `test@some-other-domain.com`, if the MX record for `some-other-domain.com` points to `mail.example.com`. +- The **A record** tells everyone which IP address the DNS name `mail.example.com` resolves to. +- The **PTR record** is the counterpart of the A record, telling everyone what name the IP address `11.22.33.44` resolves to. + +If you setup everything, it should roughly look like this: + +```console +$ dig @1.1.1.1 +short MX example.com +mail.example.com +$ dig @1.1.1.1 +short A mail.example.com +11.22.33.44 +$ dig @1.1.1.1 +short -x 11.22.33.44 +mail.example.com +``` + +## Deploying the Actual Image + +### Tagging Convention + +To understand which tags you should use, read this section carefully. [Our CI][github-ci] will automatically build, test and push new images to the following container registries: + +1. DockerHub ([`docker.io/mailserver/docker-mailserver`][dockerhub-image]) +2. GitHub Container Registry ([`ghcr.io/docker-mailserver/docker-mailserver`][ghcr-image]) All workflows are using the tagging convention listed below. It is subsequently applied to all images. @@ -18,41 +78,34 @@ All workflows are using the tagging convention listed below. It is subsequently | `push` on `master` | `edge` | | `push` a tag (`v1.2.3`) | `1.2.3`, `1.2`, `1`, `latest` | -## Get the Tools +[github-ci]: https://github.com/docker-mailserver/docker-mailserver/actions +[dockerhub-image]: https://hub.docker.com/r/mailserver/docker-mailserver +[ghcr-image]: https://github.com/docker-mailserver/docker-mailserver/pkgs/container/docker-mailserver -!!! note "`setup.sh` Not Required Anymore" - - Since DMS `v10.2.0`, [`setup.sh` functionality](../faq/#how-to-adjust-settings-with-the-user-patchessh-script) is included within the container image. The external convenience script is no longer required if you prefer using `docker exec setup ` instead. +### Get All Files Issue the following commands to acquire the necessary files: ``` BASH -DMS_GITHUB_URL='https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master' +DMS_GITHUB_URL="https://github.com/docker-mailserver/docker-mailserver/blob/latest" wget "${DMS_GITHUB_URL}/docker-compose.yml" wget "${DMS_GITHUB_URL}/mailserver.env" - -# Optional -wget "${DMS_GITHUB_URL}/setup.sh" -chmod a+x ./setup.sh ``` -## Create a docker-compose Environment +### Configuration Steps -1. [Install the latest Docker Compose](https://docs.docker.com/compose/install/) -2. Edit `docker-compose.yml` to your liking - - substitute `mail.example.com` according to your FQDN - - if you want to use SELinux for the `./docker-data/dms/config/:/tmp/docker-mailserver/` mount, append `-z` or `-Z` -3. Configure the mailserver container to your liking by editing `mailserver.env` ([**Documentation**](../config/environment/)), but keep in mind this `.env` file: - - [_only_ basic `VAR=VAL`](https://docs.docker.com/compose/env-file/) is supported (**do not** quote your values) - - variable substitution is **not** supported (e.g. :no_entry_sign: `OVERRIDE_HOSTNAME=$HOSTNAME.$DOMAINNAME` :no_entry_sign:) +1. First edit `docker-compose.yml` to your liking + - Substitute `mail.example.com` according to your FQDN. + - If you want to use SELinux for the `./docker-data/dms/config/:/tmp/docker-mailserver/` mount, append `-z` or `-Z`. +2. Then configure the environment specific to the mail server by editing [`mailserver.env`][docs-environment], but keep in mind that: + - only [basic `VAR=VAL`][docker-compose-env-file] is supported + - do not quote your values + - variable substitution is not supported, e.g. `OVERRIDE_HOSTNAME=$HOSTNAME.$DOMAINNAME` does not work -!!! info "Podman Support" +[docs-environment]: ./config/environment.md +[docker-compose-env-file]: https://docs.docker.com/compose/env-file/ - If you're using podman, make sure to read the related [documentation](../config/advanced/podman/) - -## Get up and running - -### First Things First +### Get Up and Running !!! danger "Using the Correct Commands For Stopping and Starting DMS" @@ -60,13 +113,12 @@ chmod a+x ./setup.sh Using `Ctrl+C` **is not supported either**! -You are able to get a full overview of how the configuration works by either running: - -1. `./setup.sh help` which includes the options of `setup.sh`. -2. `docker run --rm docker.io/mailserver/docker-mailserver:latest setup help` which provides you with all the information on configuration provided "inside" the container itself. +For an overview of commands to manage DMS config, run: `docker exec -it setup help`. ??? info "Usage of `setup.sh` when no DMS Container Is Running" + We encourage you to directly use `setup` inside the container (like shown above). If you still want to use `setup.sh`, here's some information about it. + If no DMS container is running, any `./setup.sh` command will check online for the `:latest` image tag (the current _stable_ release), performing a `docker pull ...` if necessary followed by running the command in a temporary container: ```console @@ -78,7 +130,7 @@ You are able to get a full overview of how the configuration works by either run setup - 'docker-mailserver' Administration & Configuration script ... - $ docker run --rm docker.io/mailserver/docker-mailserver:latest setup help + $ docker run --rm ghcr.io/docker-mailserver/docker-mailserver:latest setup help SETUP(1) NAME @@ -86,50 +138,71 @@ You are able to get a full overview of how the configuration works by either run ... ``` -### Starting for the first time - -On first start, you will need to add at least one email account (unless you're using LDAP). You have two minutes to do so, otherwise DMS will shutdown and restart. You can add accounts with the following two methods: - -1. Use `setup.sh`: `./setup.sh email add ` -2. Run the command directly in the container: `docker exec -ti setup email add ` - -You can then proceed by creating the postmaster alias and by creating DKIM keys. - -``` BASH -docker-compose up -d mailserver - -# you may add some more users -# for SELinux, use -Z -./setup.sh [-Z] email add [] - -# and configure aliases, DKIM and more -./setup.sh [-Z] alias add postmaster@ -``` +On first start, you will need to add at least one email account (unless you're using LDAP). You have two minutes to do so, otherwise DMS will shutdown and restart. You can add accounts by running `docker exec -ti setup email add user@example.com`. **That's it! It really is that easy**. ## Further Miscellaneous Steps -### DNS - DKIM +### Aliases -You can (and you should) generate DKIM keys by running +You should add at least one [alias][docs-aliases], the [_postmaster alias_][docs-env-postmaster]. This is a common convention, but not strictly required. -``` BASH -./setup.sh [-Z] config dkim +[docs-aliases]: ./config/user-management/aliases.md +[docs-env-postmaster]: ./config/environment.md#postmaster_address + +```bash +docker exec -ti setup alias add postmaster@example.com user@example.com ``` -If you want to see detailed usage information, run +### DKIM Keys -``` BASH -./setup.sh config dkim help +You can (_and you should_) generate DKIM keys. For more information: + +- DKIM [with OpenDKIM][docs-dkim-opendkim] (_enabled by default_) +- DKIM [with Rspamd][docs-dkim-rspamd] (_when using `ENABLE_RSPAMD=1`_) + +When keys are generated, you can configure your DNS server by just pasting the content of `config/opendkim/keys/domain.tld/mail.txt` to [set up DKIM][dkim-signing-setup]. See the [documentation][docs-dkim-dns] for more details. + +!!! note + + In case you're using LDAP, the setup looks a bit different as you do not add user accounts directly. Postfix doesn't know your domain(s) and you need to provide it when configuring DKIM: + + ``` BASH + docker exec -ti setup config dkim domain '[,]' + ``` + +[dkim-signing-setup]: https://mxtoolbox.com/dmarc/dkim/setup/how-to-setup-dkim +[docs-dkim-dns]: ./config/best-practices/dkim.md#configuration-using-a-web-interface +[docs-dkim-opendkim]: ./config/best-practices/dkim.md#enabling-dkim-signature +[docs-dkim-rspamd]: ./config/security/rspamd.md#dkim-signing + +### Advanced DNS Setup + +You will very likely want to configure your DNS with these TXT records: [SPF, DKIM, and DMARC][cloudflare-spf-dkim-dmarc]. + +The following illustrates what a (rather strict) set of records could look like: + +```console +$ dig @1.1.1.1 +short TXT example.com +"v=spf1 mx -all" +$ dig @1.1.1.1 +short TXT dkim-rsa._domainkey.example.com +"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQ..." +$ dig @1.1.1.1 +short TXT _dmarc.example.com +"v=DMARC1; p=reject; sp=reject; pct=100; adkim=s; aspf=s; fo=1" ``` -In case you're using LDAP, the setup looks a bit different as you do not add user accounts directly. Postfix doesn't know your domain(s) and you need to provide it when configuring DKIM: - -``` BASH -./setup.sh config dkim domain '[,]' -``` - -When keys are generated, you can configure your DNS server by just pasting the content of `config/opendkim/keys/domain.tld/mail.txt` to [set up DKIM](https://mxtoolbox.com/dmarc/dkim/setup/how-to-setup-dkim). See the [documentation](./config/best-practices/dkim.md) for more details. +[cloudflare-spf-dkim-dmarc]: https://www.cloudflare.com/learning/email-security/dmarc-dkim-spf/ ### Custom User Changes & Patches -If you'd like to change, patch or alter files or behavior of `docker-mailserver`, you can use a script. See [this part of our documentation](./faq.md/#how-to-adjust-settings-with-the-user-patchessh-script) for a detailed explanation. +If you'd like to change, patch or alter files or behavior of `docker-mailserver`, you can use a script. See [this part of our documentation][docs-user-patches] for a detailed explanation. + +[docs-user-patches]: ./faq.md#how-to-adjust-settings-with-the-user-patchessh-script + +## Testing + +Here are some tools you can use to verify your configuration: + +1. [MX Toolbox](https://mxtoolbox.com/SuperTool.aspx) +2. [DMARC Analyzer](https://www.mimecast.com/products/dmarc-analyzer/spf-record-check/) +3. [mail-tester.com](https://www.mail-tester.com/) +4. [multiRBL.valli.org](https://multirbl.valli.org/) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index fb7492e8..13029f65 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -114,7 +114,6 @@ nav: - 'Usage': usage.md - 'Configuration': - 'Environment Variables': config/environment.md - - 'Your Best Friend setup.sh': config/setup.sh.md - 'User Management': - 'Accounts': config/user-management/accounts.md - 'Aliases': config/user-management/aliases.md @@ -129,9 +128,9 @@ nav: - 'Fail2Ban': config/security/fail2ban.md - 'Mail Encryption' : config/security/mail_crypt.md - 'Rspamd' : config/security/rspamd.md - - 'Troubleshooting': - - 'Debugging': config/troubleshooting/debugging.md + - 'Debugging': config/debugging.md - 'Mail Delivery with POP3': config/pop3.md + - 'Your Friend setup.sh': config/setup.sh.md - 'Advanced Configuration': - 'Optional Configuration': config/advanced/optional-config.md - 'Maintenance':