docs(refactor): Convert more content to use admonitions + improvements

This commit is contained in:
wernerfred 2021-03-02 17:39:06 +01:00 committed by polarathene
parent 463bc967d2
commit 711b4c9d83
18 changed files with 884 additions and 792 deletions

View File

@ -6,38 +6,39 @@ title: 'Advanced | LDAP Authentication'
Getting started with ldap and this mailserver we need to take 3 parts in account: Getting started with ldap and this mailserver we need to take 3 parts in account:
* POSTFIX - `postfix`
* DOVECOT - `dovecot`
* SASLAUTHD (this can also be handled by dovecot above) - `saslauthd` (this can also be handled by dovecot)
## Variables to Control Provisioning by the Container ## Variables to Control Provisioning by the Container
__POSTFIX__: Have a look at the [`ENVIRONMENT.md`][github-file-env] for information on the default values.
* `LDAP_QUERY_FILTER_USER` !!! example "postfix"
* `LDAP_QUERY_FILTER_GROUP`
* `LDAP_QUERY_FILTER_ALIAS`
* `LDAP_QUERY_FILTER_DOMAIN`
__SASLAUTHD__: - `LDAP_QUERY_FILTER_USER`
- `LDAP_QUERY_FILTER_GROUP`
- `LDAP_QUERY_FILTER_ALIAS`
- `LDAP_QUERY_FILTER_DOMAIN`
* `SASLAUTHD_LDAP_FILTER` !!! example "saslauthd"
__DOVECOT__: - `SASLAUTHD_LDAP_FILTER`
* `DOVECOT_USER_FILTER` !!! example "dovecot"
* `DOVECOT_PASS_FILTER`
!!! note - `DOVECOT_USER_FILTER`
This page will provide several use cases like recipes to show, how this project can be used with it's LDAP Features. - `DOVECOT_PASS_FILTER`
## LDAP Setup - Kopano / Zarafa ## LDAP Setup - Kopano / Zarafa
```yaml ???+ example "Example Code"
---
version: '2'
services: ```yaml
---
version: '2'
services:
mail: mail:
image: mailserver/docker-mailserver:latest image: mailserver/docker-mailserver:latest
hostname: mail hostname: mail
@ -100,12 +101,12 @@ services:
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN
volumes: volumes:
maildata: maildata:
driver: local driver: local
mailstate: mailstate:
driver: local driver: local
``` ```
If your directory has not the postfix-book schema installed, then you must change the internal attribute handling for dovecot. For this you have to change the `pass_attr` and the `user_attr` mapping, as shown in the example below: If your directory has not the postfix-book schema installed, then you must change the internal attribute handling for dovecot. For this you have to change the `pass_attr` and the `user_attr` mapping, as shown in the example below:
@ -122,3 +123,5 @@ The following example illustrates this for a directory that has the qmail-schema
- DOVECOT_PASS_FILTER=(&(objectClass=qmailUser)(uid=%u)(accountStatus=active)) - DOVECOT_PASS_FILTER=(&(objectClass=qmailUser)(uid=%u)(accountStatus=active))
- DOVECOT_USER_FILTER=(&(objectClass=qmailUser)(uid=%u)(accountStatus=active)) - DOVECOT_USER_FILTER=(&(objectClass=qmailUser)(uid=%u)(accountStatus=active))
``` ```
[github-file-env]: https://github.com/docker-mailserver/docker-mailserver/blob/master/ENVIRONMENT.md

View File

@ -6,20 +6,22 @@ title: 'Advanced | Kubernetes'
There is nothing much in deploying mailserver to Kubernetes itself. The things are pretty same as in [`docker-compose.yml`][github-file-compose], but with Kubernetes syntax. There is nothing much in deploying mailserver to Kubernetes itself. The things are pretty same as in [`docker-compose.yml`][github-file-compose], but with Kubernetes syntax.
```yaml ??? example "ConfigMap"
apiVersion: v1
kind: Namespace ```yaml
metadata: apiVersion: v1
kind: Namespace
metadata:
name: mailserver name: mailserver
--- ---
kind: ConfigMap kind: ConfigMap
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: mailserver.env.config name: mailserver.env.config
namespace: mailserver namespace: mailserver
labels: labels:
app: mailserver app: mailserver
data: data:
OVERRIDE_HOSTNAME: example.com OVERRIDE_HOSTNAME: example.com
ENABLE_FETCHMAIL: "0" ENABLE_FETCHMAIL: "0"
FETCHMAIL_POLL: "120" FETCHMAIL_POLL: "120"
@ -30,15 +32,15 @@ data:
ONE_DIR: "1" ONE_DIR: "1"
DMS_DEBUG: "0" DMS_DEBUG: "0"
--- ---
kind: ConfigMap kind: ConfigMap
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: mailserver.config name: mailserver.config
namespace: mailserver namespace: mailserver
labels: labels:
app: mailserver app: mailserver
data: data:
postfix-accounts.cf: | postfix-accounts.cf: |
user1@example.com|{SHA512-CRYPT}$6$2YpW1nYtPBs2yLYS$z.5PGH1OEzsHHNhl3gJrc3D.YMZkvKw/vp.r5WIiwya6z7P/CQ9GDEJDr2G2V0cAfjDFeAQPUoopsuWPXLk3u1 user1@example.com|{SHA512-CRYPT}$6$2YpW1nYtPBs2yLYS$z.5PGH1OEzsHHNhl3gJrc3D.YMZkvKw/vp.r5WIiwya6z7P/CQ9GDEJDr2G2V0cAfjDFeAQPUoopsuWPXLk3u1
@ -71,28 +73,44 @@ data:
# #!/bin/bash # #!/bin/bash
#fetchmail.cf: | #fetchmail.cf: |
```
--- ??? example "Secret"
kind: Secret
apiVersion: v1 ```yaml
metadata: apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
kind: Secret
apiVersion: v1
metadata:
name: mailserver.opendkim.keys name: mailserver.opendkim.keys
namespace: mailserver namespace: mailserver
labels: labels:
app: mailserver app: mailserver
type: Opaque type: Opaque
data: data:
example.com-mail.key: 'base64-encoded-DKIM-key' example.com-mail.key: 'base64-encoded-DKIM-key'
```
--- ??? example "Service"
kind: Service
apiVersion: v1 ```yaml
metadata: apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
kind: Service
apiVersion: v1
metadata:
name: mailserver name: mailserver
namespace: mailserver namespace: mailserver
labels: labels:
app: mailserver app: mailserver
spec: spec:
selector: selector:
app: mailserver app: mailserver
ports: ports:
@ -111,13 +129,22 @@ spec:
- name: imap-secure - name: imap-secure
port: 993 port: 993
targetPort: imap-secure targetPort: imap-secure
--- ```
apiVersion: apps/v1
kind: Deployment ??? example "Deployment"
metadata:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mailserver name: mailserver
namespace: mailserver namespace: mailserver
spec: spec:
replicas: 1 replicas: 1
selector: selector:
matchLabels: matchLabels:
@ -228,9 +255,9 @@ spec:
claimName: mail-storage claimName: mail-storage
- name: tmp-files - name: tmp-files
emptyDir: {} emptyDir: {}
``` ```
!!! note !!! warning
Any sensitive data (keys, etc) should be deployed via [Secrets][k8s-config-secret]. Other configuration just fits well into [ConfigMaps][k8s-config-pod]. Any sensitive data (keys, etc) should be deployed via [Secrets][k8s-config-secret]. Other configuration just fits well into [ConfigMaps][k8s-config-pod].
!!! note !!! note
@ -246,54 +273,58 @@ Preserving real client IP is relatively [non-trivial in Kubernetes][k8s-service-
If you do not require SPF checks for incoming mails you may disable them in [Postfix configuration][docs-postfix] by dropping following line (which removes `check_policy_service unix:private/policyd-spf` option): If you do not require SPF checks for incoming mails you may disable them in [Postfix configuration][docs-postfix] by dropping following line (which removes `check_policy_service unix:private/policyd-spf` option):
```yaml !!! example
kind: ConfigMap
apiVersion: v1 ```yaml
metadata: kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config name: mailserver.config
labels: labels:
app: mailserver app: mailserver
data: data:
postfix-main.cf: | postfix-main.cf: |
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain, reject_rbl_client zen.spamhaus.org, reject_rbl_client bl.spamcop.net smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain, reject_rbl_client zen.spamhaus.org, reject_rbl_client bl.spamcop.net
# ... # ...
--- ---
kind: Deployment kind: Deployment
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
metadata: metadata:
name: mailserver name: mailserver
# ... # ...
volumeMounts: volumeMounts:
- name: config - name: config
subPath: postfix-main.cf subPath: postfix-main.cf
mountPath: /tmp/docker-mailserver/postfix-main.cf mountPath: /tmp/docker-mailserver/postfix-main.cf
readOnly: true readOnly: true
``` ```
### External IPs Service ### External IPs Service
The simplest way is to expose mailserver as a [Service][k8s-network-service] with [external IPs][k8s-network-external-ip]. The simplest way is to expose mailserver as a [Service][k8s-network-service] with [external IPs][k8s-network-external-ip].
```yaml !!! example
kind: Service
apiVersion: v1 ```yaml
metadata: kind: Service
apiVersion: v1
metadata:
name: mailserver name: mailserver
labels: labels:
app: mailserver app: mailserver
spec: spec:
selector: selector:
app: mailserver app: mailserver
ports: ports:
- name: smtp - name: smtp
port: 25 port: 25
targetPort: smtp targetPort: smtp
# ... # ...
externalIPs: externalIPs:
- 80.11.12.10 - 80.11.12.10
``` ```
**Downsides** **Downsides**
@ -313,17 +344,19 @@ The [Proxy Pod][k8s-proxy-service] helps to avoid necessity of specifying extern
The simplest way to preserve real client IP is to use `hostPort` and `hostNetwork: true` in the mailserver [Pod][k8s-workload-pod]. This comes in price of availability: you can talk to mailserver from outside world only via IPs of [Node][k8s-nodes] where mailserver is deployed. The simplest way to preserve real client IP is to use `hostPort` and `hostNetwork: true` in the mailserver [Pod][k8s-workload-pod]. This comes in price of availability: you can talk to mailserver from outside world only via IPs of [Node][k8s-nodes] where mailserver is deployed.
```yaml !!! example
kind: Deployment
apiVersion: extensions/v1beta1 ```yaml
metadata: kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: mailserver name: mailserver
# ... # ...
spec: spec:
hostNetwork: true hostNetwork: true
# ... # ...
containers: containers:
# ... # ...
ports: ports:
- name: smtp - name: smtp
containerPort: 25 containerPort: 25
@ -334,8 +367,8 @@ metadata:
- name: imap-secure - name: imap-secure
containerPort: 993 containerPort: 993
hostPort: 993 hostPort: 993
# ... # ...
``` ```
**Downsides** **Downsides**
@ -363,14 +396,16 @@ With [HAProxy][dockerhub-haproxy], the configuration should look similar to the
Then, configure both [Postfix][docs-postfix] and [Dovecot][docs-dovecot] to expect the PROXY protocol: Then, configure both [Postfix][docs-postfix] and [Dovecot][docs-dovecot] to expect the PROXY protocol:
```yaml !!! example
kind: ConfigMap
apiVersion: v1 ```yaml
metadata: kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config name: mailserver.config
labels: labels:
app: mailserver app: mailserver
data: data:
postfix-main.cf: | postfix-main.cf: |
postscreen_upstream_proxy_protocol = haproxy postscreen_upstream_proxy_protocol = haproxy
postfix-master.cf: | postfix-master.cf: |
@ -384,14 +419,14 @@ data:
haproxy = yes haproxy = yes
} }
} }
# ... # ...
--- ---
kind: Deployment kind: Deployment
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
metadata: metadata:
name: mailserver name: mailserver
spec: spec:
template: template:
spec: spec:
containers: containers:
@ -409,7 +444,7 @@ spec:
subPath: dovecot.cf subPath: dovecot.cf
mountPath: /tmp/docker-mailserver/dovecot.cf mountPath: /tmp/docker-mailserver/dovecot.cf
readOnly: true readOnly: true
``` ```
**Downsides** **Downsides**
@ -419,16 +454,18 @@ spec:
[Kube-Lego][kube-lego] may be used for a role of Let's Encrypt client. It works with Kubernetes [Ingress Resources][k8s-network-ingress] and automatically issues/manages certificates/keys for exposed services via Ingresses. [Kube-Lego][kube-lego] may be used for a role of Let's Encrypt client. It works with Kubernetes [Ingress Resources][k8s-network-ingress] and automatically issues/manages certificates/keys for exposed services via Ingresses.
```yaml !!! example
kind: Ingress
apiVersion: extensions/v1beta1 ```yaml
metadata: kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: mailserver name: mailserver
labels: labels:
app: mailserver app: mailserver
annotations: annotations:
kubernetes.io/tls-acme: 'true' kubernetes.io/tls-acme: 'true'
spec: spec:
rules: rules:
- host: example.com - host: example.com
http: http:
@ -441,30 +478,32 @@ spec:
- secretName: mailserver.tls - secretName: mailserver.tls
hosts: hosts:
- example.com - example.com
``` ```
Now, you can use Let's Encrypt cert and key from `mailserver.tls` [Secret][k8s-config-secret] in your [Pod][k8s-workload-pod] spec: Now, you can use Let's Encrypt cert and key from `mailserver.tls` [Secret][k8s-config-secret] in your [Pod][k8s-workload-pod] spec:
```yaml !!! example
# ...
env: ```yaml
# ...
env:
- name: SSL_TYPE - name: SSL_TYPE
value: 'manual' value: 'manual'
- name: SSL_CERT_PATH - name: SSL_CERT_PATH
value: '/etc/ssl/mailserver/tls.crt' value: '/etc/ssl/mailserver/tls.crt'
- name: SSL_KEY_PATH - name: SSL_KEY_PATH
value: '/etc/ssl/mailserver/tls.key' value: '/etc/ssl/mailserver/tls.key'
# ... # ...
volumeMounts: volumeMounts:
- name: tls - name: tls
mountPath: /etc/ssl/mailserver mountPath: /etc/ssl/mailserver
readOnly: true readOnly: true
# ... # ...
volumes: volumes:
- name: tls - name: tls
secret: secret:
secretName: mailserver.tls secretName: mailserver.tls
``` ```
[docs-dovecot]: ./override-defaults/dovecot.md [docs-dovecot]: ./override-defaults/dovecot.md
[docs-postfix]: ./override-defaults/postfix.md [docs-postfix]: ./override-defaults/postfix.md

View File

@ -26,25 +26,29 @@ Generate a file called `fetchmail.cf` and place it in the `config` folder. Your
A detailed description of the configuration options can be found in the [online version of the manual page][fetchmail-docs]. A detailed description of the configuration options can be found in the [online version of the manual page][fetchmail-docs].
### Example IMAP Configuration ### IMAP Configuration
```fetchmailrc !!! example
poll 'imap.example.com' proto imap
```fetchmailrc
poll 'imap.example.com' proto imap
user 'username' user 'username'
pass 'secret' pass 'secret'
is 'user1@domain.tld' is 'user1@domain.tld'
ssl ssl
``` ```
### Example POP3 Configuration ### POP3 Configuration
```fetchmailrc !!! example
poll 'pop3.example.com' proto pop3
```fetchmailrc
poll 'pop3.example.com' proto pop3
user 'username' user 'username'
pass 'secret' pass 'secret'
is 'user2@domain.tld' is 'user2@domain.tld'
ssl ssl
``` ```
!!! caution !!! caution
Dont forget the last line: eg: `is 'user1@domain.tld'`. After `is` you have to specify one email address from the configuration file `config/postfix-accounts.cf`. Dont forget the last line: eg: `is 'user1@domain.tld'`. After `is` you have to specify one email address from the configuration file `config/postfix-accounts.cf`.

View File

@ -2,7 +2,7 @@
title: 'Mail Forwarding | AWS SES' title: 'Mail Forwarding | AWS SES'
--- ---
!!! note !!! warning
New configuration, see [Configure Relay Hosts][docs-relay] New configuration, see [Configure Relay Hosts][docs-relay]
Instead of letting postfix deliver mail directly it is possible to configure it to deliver outgoing email via Amazon SES (Simple Email Service). (Receiving inbound email via SES is not implemented.) The configuration follows the guidelines provided by AWS in https://docs.aws.amazon.com/ses/latest/DeveloperGuide/postfix.html, specifically, the `STARTTLS` method. Instead of letting postfix deliver mail directly it is possible to configure it to deliver outgoing email via Amazon SES (Simple Email Service). (Receiving inbound email via SES is not implemented.) The configuration follows the guidelines provided by AWS in https://docs.aws.amazon.com/ses/latest/DeveloperGuide/postfix.html, specifically, the `STARTTLS` method.

View File

@ -12,14 +12,14 @@ Depending on the domain of the sender, you may want to send via a different rela
Basic configuration is done via environment variables: Basic configuration is done via environment variables:
* **RELAY_HOST** _default host to relay mail through, empty will disable this feature_ * `RELAY_HOST`: _default host to relay mail through, empty will disable this feature_
* **RELAY_PORT** _port on default relay, defaults to port 25_ * `RELAY_PORT`: _port on default relay, defaults to port 25_
* **RELAY_USER** _username for the default relay_ * `RELAY_USER`: _username for the default relay_
* **RELAY_PASSWORD** _password for the default user_ * `RELAY_PASSWORD`: _password for the default user_
Setting these environment variables will cause mail for all sender domains to be routed via the specified host, authenticating with the user/password combination. Setting these environment variables will cause mail for all sender domains to be routed via the specified host, authenticating with the user/password combination.
!!! note !!! warning
For users of the previous `AWS_SES_*` variables: please update your configuration to use these new variables, no other configuration is required. For users of the previous `AWS_SES_*` variables: please update your configuration to use these new variables, no other configuration is required.
## Advanced Configuration ## Advanced Configuration

View File

@ -19,32 +19,38 @@ It's even possible to install a user provided Sieve filter at startup during use
An example of a sieve filter that moves mails to a folder `INBOX/spam` depending on the sender address: An example of a sieve filter that moves mails to a folder `INBOX/spam` depending on the sender address:
```sieve !!! example
require ["fileinto", "reject"];
if address :contains ["From"] "spam@spam.com" { ```sieve
require ["fileinto", "reject"];
if address :contains ["From"] "spam@spam.com" {
fileinto "INBOX.spam"; fileinto "INBOX.spam";
} else { } else {
keep; keep;
} }
``` ```
!!! note !!! warning
That folders have to exist beforehand if sieve should move them. That folders have to exist beforehand if sieve should move them.
Another example of a sieve filter that forward mails to a different address: Another example of a sieve filter that forward mails to a different address:
```sieve !!! example
require ["copy"];
redirect :copy "user2@otherdomain.tld"; ```sieve
``` require ["copy"];
redirect :copy "user2@otherdomain.tld";
```
Just forward all incoming emails and do not save them locally: Just forward all incoming emails and do not save them locally:
```sieve !!! example
redirect "user2@otherdomain.tld";
``` ```sieve
redirect "user2@otherdomain.tld";
```
You can also use external programs to filter or pipe (process) messages by adding executable scripts in `config/sieve-pipe` or `config/sieve-filter`. This can be used in lieu of a local alias file, for instance to forward an email to a webservice. These programs can then be referenced by filename, by all users. Note that the process running the scripts run as a privileged user. For further information see [Dovecot's wiki](https://wiki.dovecot.org/Pigeonhole/Sieve/Plugins/Pipe). You can also use external programs to filter or pipe (process) messages by adding executable scripts in `config/sieve-pipe` or `config/sieve-filter`. This can be used in lieu of a local alias file, for instance to forward an email to a webservice. These programs can then be referenced by filename, by all users. Note that the process running the scripts run as a privileged user. For further information see [Dovecot's wiki](https://wiki.dovecot.org/Pigeonhole/Sieve/Plugins/Pipe).
@ -59,13 +65,15 @@ For more examples or a detailed description of the Sieve language have a look at
The [Manage Sieve](https://doc.dovecot.org/admin_manual/pigeonhole_managesieve_server/) extension allows users to modify their Sieve script by themselves. The authentication mechanisms are the same as for the main dovecot service. ManageSieve runs on port `4190` and needs to be enabled using the `ENABLE_MANAGESIEVE=1` environment variable. The [Manage Sieve](https://doc.dovecot.org/admin_manual/pigeonhole_managesieve_server/) extension allows users to modify their Sieve script by themselves. The authentication mechanisms are the same as for the main dovecot service. ManageSieve runs on port `4190` and needs to be enabled using the `ENABLE_MANAGESIEVE=1` environment variable.
```yaml !!! example
# docker-compose.yml
ports: ```yaml
# docker-compose.yml
ports:
- "4190:4190" - "4190:4190"
environment: environment:
- ENABLE_MANAGESIEVE=1 - ENABLE_MANAGESIEVE=1
``` ```
All user defined sieve scripts that are managed by ManageSieve are stored in the user's home folder in `/var/mail/domain.com/user1/sieve`. Just one sieve script might be active for a user and is sym-linked to `/var/mail/domain.com/user1/.dovecot.sieve` automatically. All user defined sieve scripts that are managed by ManageSieve are stored in the user's home folder in `/var/mail/domain.com/user1/sieve`. Just one sieve script might be active for a user and is sym-linked to `/var/mail/domain.com/user1/.dovecot.sieve` automatically.
@ -73,4 +81,5 @@ All user defined sieve scripts that are managed by ManageSieve are stored in the
ManageSieve makes sure to not overwrite an existing `.dovecot.sieve` file. If a user activates a new sieve script the old one is backuped and moved to the `sieve` folder. ManageSieve makes sure to not overwrite an existing `.dovecot.sieve` file. If a user activates a new sieve script the old one is backuped and moved to the `sieve` folder.
The extension is known to work with the following ManageSieve clients: The extension is known to work with the following ManageSieve clients:
* **Sieve Editor** a portable standalone application based on the former Thunderbird plugin (https://github.com/thsmi/sieve).
- **Sieve Editor** a portable standalone application based on the former Thunderbird plugin (https://github.com/thsmi/sieve).

View File

@ -48,7 +48,7 @@ To debug your dovecot configuration you can use:
- Or: `docker exec -it <your-container-name> doveconf | grep <some-keyword>` - Or: `docker exec -it <your-container-name> doveconf | grep <some-keyword>`
!!! note !!! note
[`setup.sh`][github-file-setupsh] is included in the `docker-mailserver` repository. [`setup.sh`][github-file-setupsh] is included in the `docker-mailserver` repository. Make sure to grap the one matching your image version.
The `config/dovecot.cf` is copied internally to `/etc/dovecot/local.conf`. To check this file run: The `config/dovecot.cf` is copied internally to `/etc/dovecot/local.conf`. To check this file run:

View File

@ -14,7 +14,9 @@ message_size_limit = 52428800
That specific example is now supported and can be handled by setting `POSTFIX_MESSAGE_SIZE_LIMIT`. That specific example is now supported and can be handled by setting `POSTFIX_MESSAGE_SIZE_LIMIT`.
[Postfix documentation](http://www.postfix.org/documentation.html) remains the best place to find configuration options. !!! seealso
[Postfix documentation](http://www.postfix.org/documentation.html) remains the best place to find configuration options.
Each line in the provided file will be loaded into postfix. Each line in the provided file will be loaded into postfix.

View File

@ -2,7 +2,10 @@
title: 'Best Practices | DKIM' title: 'Best Practices | DKIM'
--- ---
DKIM is a security measure targeting email spoofing. It is greatly recommended one activates it. See [the Wikipedia page](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail) for more details on DKIM. DKIM is a security measure targeting email spoofing. It is greatly recommended one activates it.
!!! seealso
See [the Wikipedia page](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail) for more details on DKIM.
## Enabling DKIM Signature ## Enabling DKIM Signature

View File

@ -4,7 +4,8 @@ hide:
- toc # Hide Table of Contents for this page - toc # Hide Table of Contents for this page
--- ---
DMARC Guide: https://github.com/internetstandards/toolbox-wiki/blob/master/DMARC-how-to.md !!! seealso
DMARC Guide: https://github.com/internetstandards/toolbox-wiki/blob/master/DMARC-how-to.md
## Enabling DMARC ## Enabling DMARC

View File

@ -6,9 +6,11 @@ hide:
From [Wikipedia](https://en.wikipedia.org/wiki/Sender_Policy_Framework): From [Wikipedia](https://en.wikipedia.org/wiki/Sender_Policy_Framework):
> Sender Policy Framework (SPF) is a simple email-validation system designed to detect email spoofing by providing a mechanism to allow receiving mail exchangers to check that incoming mail from a domain comes from a host authorized by that domain's administrators. The list of authorized sending hosts for a domain is published in the Domain Name System (DNS) records for that domain in the form of a specially formatted TXT record. Email spam and phishing often use forged "from" addresses, so publishing and checking SPF records can be considered anti-spam techniques. !!! quote
Sender Policy Framework (SPF) is a simple email-validation system designed to detect email spoofing by providing a mechanism to allow receiving mail exchangers to check that incoming mail from a domain comes from a host authorized by that domain's administrators. The list of authorized sending hosts for a domain is published in the Domain Name System (DNS) records for that domain in the form of a specially formatted TXT record. Email spam and phishing often use forged "from" addresses, so publishing and checking SPF records can be considered anti-spam techniques.
For a more technical review: https://github.com/internetstandards/toolbox-wiki/blob/master/SPF-how-to.md !!! seealso
For a more technical review: https://github.com/internetstandards/toolbox-wiki/blob/master/SPF-how-to.md
## Add a SPF Record ## Add a SPF Record

View File

@ -4,10 +4,11 @@ hide:
- toc # Hide Table of Contents for this page - toc # Hide Table of Contents for this page
--- ---
**We do not recommend using POP. Use IMAP instead.** !!! warning
If you really want to have POP3 running, add 3 lines to the docker-compose.yml : **We do not recommend using POP3. Use IMAP instead.**
Add the ports 110 and 995, and add environment variable ENABLE_POP :
If you really want to have POP3 running add the ports 110 and 995 and the environment variable `ENABLE_POP3` to your `docker-compose.yml`:
```yaml ```yaml
mail: mail:

View File

@ -134,10 +134,12 @@ Then: `/path/to/mailserver/docker-compose up -d mail`
The following `docker-compose.yml` is the basic setup you need for using `letsencrypt-nginx-proxy-companion`. It is mainly derived from its own wiki/documenation. The following `docker-compose.yml` is the basic setup you need for using `letsencrypt-nginx-proxy-companion`. It is mainly derived from its own wiki/documenation.
```yaml ???+ example "Example Code"
version: "2"
services: ```yaml
version: "2"
services:
nginx: nginx:
image: nginx image: nginx
container_name: nginx container_name: nginx
@ -178,17 +180,19 @@ services:
- DEBUG=false - DEBUG=false
restart: always restart: always
networks: networks:
proxy-tier: proxy-tier:
external: external:
name: nginx-proxy name: nginx-proxy
``` ```
The second part of the setup is the actual mail container. So, in another folder, create another `docker-compose.yml` with the following content (Removed all ENV variables for this example): The second part of the setup is the actual mail container. So, in another folder, create another `docker-compose.yml` with the following content (Removed all ENV variables for this example):
```yaml ???+ example "Example Code"
version: '2'
services: ```yaml
version: '2'
services:
mail: mail:
image: mailserver/docker-mailserver:latest image: mailserver/docker-mailserver:latest
hostname: ${HOSTNAME} hostname: ${HOSTNAME}
@ -221,11 +225,11 @@ services:
- proxy-tier - proxy-tier
restart: always restart: always
networks: networks:
proxy-tier: proxy-tier:
external: external:
name: nginx-proxy name: nginx-proxy
``` ```
The mail container needs to have the letsencrypt certificate folder mounted as a volume. No further changes are needed. The second container is a dummy-sidecar we need, because the mail-container do not expose any web-ports. Set your ENV variables as you need. (`VIRTUAL_HOST` and `LETSENCRYPT_HOST` are mandandory, see documentation) The mail container needs to have the letsencrypt certificate folder mounted as a volume. No further changes are needed. The second container is a dummy-sidecar we need, because the mail-container do not expose any web-ports. Set your ENV variables as you need. (`VIRTUAL_HOST` and `LETSENCRYPT_HOST` are mandandory, see documentation)
@ -275,8 +279,10 @@ For Caddy v2 you can specify the `key_type` in your server's global settings, wh
If you are instead using a json config for Caddy v2, you can set it in your site's TLS automation policies: If you are instead using a json config for Caddy v2, you can set it in your site's TLS automation policies:
```json ???+ example "Example Code"
{
```json
{
"apps": { "apps": {
"http": { "http": {
"servers": { "servers": {
@ -337,8 +343,8 @@ If you are instead using a json config for Caddy v2, you can set it in your site
} }
} }
} }
} }
``` ```
The generated certificates can be mounted: The generated certificates can be mounted:
@ -375,9 +381,11 @@ Traefik's V2 storage format is natively supported if the `acme.json` store is mo
This allows for support of wild card certificates: `SSL_DOMAIN=*.example.com`. Here is an example setup for [`docker-compose`](https://docs.docker.com/compose/): This allows for support of wild card certificates: `SSL_DOMAIN=*.example.com`. Here is an example setup for [`docker-compose`](https://docs.docker.com/compose/):
```yaml ???+ example "Example Code"
version: '3.8'
services: ```yaml
version: '3.8'
services:
mail: mail:
image: mailserver/docker-mailserver:stable image: mailserver/docker-mailserver:stable
hostname: mail hostname: mail
@ -412,7 +420,7 @@ services:
image: containous/whoami image: containous/whoami
labels: labels:
- "traefik.http.routers.whoami.rule=Host(`mail.example.com`)" - "traefik.http.routers.whoami.rule=Host(`mail.example.com`)"
``` ```
This setup only comes with one caveat: The domain has to be configured on another service for traefik to actually request it from lets-encrypt (`whoami` in this case). This setup only comes with one caveat: The domain has to be configured on another service for traefik to actually request it from lets-encrypt (`whoami` in this case).
@ -422,9 +430,13 @@ If you are using Traefik v1, you might want to _push_ your Traefik-managed certi
Depending of your Traefik configuration, certificates may be stored using a file or a KV Store (consul, etcd...) Either way, certificates will be renewed by Traefik, then automatically pushed to the mailserver thanks to the `cert-renewer` service. Finally, dovecot and postfix will be restarted. Depending of your Traefik configuration, certificates may be stored using a file or a KV Store (consul, etcd...) Either way, certificates will be renewed by Traefik, then automatically pushed to the mailserver thanks to the `cert-renewer` service. Finally, dovecot and postfix will be restarted.
## Self-Signed Certificates (Testing Only) ## Self-Signed Certificates
You can easily generate a self-signed SSL certificate by using the following command: !!! warning
Use self-signed certificates only for testing purposes!
You can generate a self-signed SSL certificate by using the following command:
```sh ```sh
docker run -it --rm -v "$(pwd)"/config/ssl:/tmp/docker-mailserver/ssl -h mail.my-domain.com -t mailserver/docker-mailserver generate-ssl-certificate docker run -it --rm -v "$(pwd)"/config/ssl:/tmp/docker-mailserver/ssl -h mail.my-domain.com -t mailserver/docker-mailserver generate-ssl-certificate
@ -472,7 +484,7 @@ environment:
This will mount the path where your ssl certificates reside as read-only under `/tmp/ssl`. Then all you have to do is to specify the location of your private key and the certificate. This will mount the path where your ssl certificates reside as read-only under `/tmp/ssl`. Then all you have to do is to specify the location of your private key and the certificate.
!!! note !!! info
You may have to restart your mailserver once the certificates change. You may have to restart your mailserver once the certificates change.
## Testing a Certificate is Valid ## Testing a Certificate is Valid
@ -509,9 +521,11 @@ docker exec mail openssl s_client \
## Plain-Text Access ## Plain-Text Access
Not recommended for purposes other than testing. !!! warning
Just add this to `config/dovecot.cf`: Not recommended for purposes other than testing.
Add this to `config/dovecot.cf`:
```cf ```cf
ssl = yes ssl = yes

View File

@ -13,6 +13,10 @@ wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/maste
chmod a+x ./setup.sh chmod a+x ./setup.sh
``` ```
!!! info
Make sure to get the `setup.sh` that comes with the release you're using. Look up the release and the git commit on which this release is based upon by selecting the appropriate tag on GitHub. This can done with the "Switch branches/tags" button on GitHub, choosing the right tag. This is done in order to rule out possible inconsistencies between versions.
## Usage ## Usage
Run `./setup.sh -h` and you'll get some usage information: Run `./setup.sh -h` and you'll get some usage information:

View File

@ -22,6 +22,8 @@ We are going to use this docker based mailserver:
- Create the file `docker-compose.yml` with a content like this: - Create the file `docker-compose.yml` with a content like this:
!!! example
```yaml ```yaml
version: '2' version: '2'

View File

@ -97,9 +97,13 @@ postfix reload
You see that besides `query_filter`, I had to customize as well `result_attribute` and `result_format`. You see that besides `query_filter`, I had to customize as well `result_attribute` and `result_format`.
For more details about using LDAP see: [LDAP managed mail server with Postfix and Dovecot for multiple domains](https://www.vennedey.net/resources/2-LDAP-managed-mail-server-with-Postfix-and-Dovecot-for-multiple-domains) !!! sealso
Another solution that serves as a forward-only mailserver is this: https://gitlab.com/docker-scripts/postfix For more details about using LDAP see: [LDAP managed mail server with Postfix and Dovecot for multiple domains](https://www.vennedey.net/resources/2-LDAP-managed-mail-server-with-Postfix-and-Dovecot-for-multiple-domains)
!!! seealso
Another solution that serves as a forward-only mailserver is this: https://gitlab.com/docker-scripts/postfix
[github-file-readme-patches]: https://github.com/docker-mailserver/docker-mailserver/blob/master/README.md#custom-user-changes--patches [github-file-readme-patches]: https://github.com/docker-mailserver/docker-mailserver/blob/master/README.md#custom-user-changes--patches
[github-issue-1247]: https://github.com/docker-mailserver/docker-mailserver/issues/1247 [github-issue-1247]: https://github.com/docker-mailserver/docker-mailserver/issues/1247

View File

@ -9,11 +9,11 @@ This image is based on config files that can be persisted using Docker volumes,
### Where are emails stored? ### Where are emails stored?
Mails are stored in `/var/mail/${domain}/${username}`. Mails are stored in `/var/mail/${domain}/${username}`. Since `v9.0.0` it is possible to add custom `user_attributes` for each accounts to have a different mailbox configuration (See [#1792][github-issue-1792]).
You should use a [data volume container](https://medium.com/@ramangupta/why-docker-data-containers-are-good-589b3c6c749e#.uxyrp7xpu) for `/var/mail` to persist data. !!! warning
Otherwise, your data may be lost. You should use a [data volume container](https://medium.com/@ramangupta/why-docker-data-containers-are-good-589b3c6c749e#.uxyrp7xpu) for `/var/mail` to persist data. Otherwise, your data may be lost.
### How to alter the running mailserver instance _without_ relaunching the container? ### How to alter the running mailserver instance _without_ relaunching the container?
@ -147,57 +147,59 @@ If you run the server with `docker-compose`, you can leverage on docker configs
The following configuration works nicely: The following configuration works nicely:
Create a _system_ cron file: ??? example
```sh Create a _system_ cron file:
# in the docker-compose.yml root directory
mkdir cron
touch cron/sa-learn
chown root:root cron/sa-learn
chmod 0644 cron/sa-learn
```
Edit the system cron file `nano cron/sa-learn`, and set an appropriate configuration: ```sh
# in the docker-compose.yml root directory
mkdir cron
touch cron/sa-learn
chown root:root cron/sa-learn
chmod 0644 cron/sa-learn
```
```conf Edit the system cron file `nano cron/sa-learn`, and set an appropriate configuration:
# This assumes you're having `environment: ONE_DIR=1` in the env-mailserver,
# with a consolidated config in `/var/mail-state`
#
# m h dom mon dow user command
#
# Everyday 2:00AM, learn spam from a specific user
# spam: junk directory
0 2 * * * root sa-learn --spam /var/mail/domain.com/username/.Junk --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: archive directories
15 2 * * * root sa-learn --ham /var/mail/domain.com/username/.Archive* --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: inbox subdirectories
30 2 * * * root sa-learn --ham /var/mail/domain.com/username/cur* --dbpath /var/mail-state/lib-amavis/.spamassassin
#
# Everyday 3:00AM, learn spam from all users of a domain
# spam: junk directory
0 3 * * * root sa-learn --spam /var/mail/otherdomain.com/*/.Junk --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: archive directories
15 3 * * * root sa-learn --ham /var/mail/otherdomain.com/*/.Archive* --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: inbox subdirectories
30 3 * * * root sa-learn --ham /var/mail/otherdomain.com/*/cur* --dbpath /var/mail-state/lib-amavis/.spamassassin
```
Then with plain `docker-compose`: ```conf
# This assumes you're having `environment: ONE_DIR=1` in the env-mailserver,
# with a consolidated config in `/var/mail-state`
#
# m h dom mon dow user command
#
# Everyday 2:00AM, learn spam from a specific user
# spam: junk directory
0 2 * * * root sa-learn --spam /var/mail/domain.com/username/.Junk --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: archive directories
15 2 * * * root sa-learn --ham /var/mail/domain.com/username/.Archive* --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: inbox subdirectories
30 2 * * * root sa-learn --ham /var/mail/domain.com/username/cur* --dbpath /var/mail-state/lib-amavis/.spamassassin
#
# Everyday 3:00AM, learn spam from all users of a domain
# spam: junk directory
0 3 * * * root sa-learn --spam /var/mail/otherdomain.com/*/.Junk --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: archive directories
15 3 * * * root sa-learn --ham /var/mail/otherdomain.com/*/.Archive* --dbpath /var/mail-state/lib-amavis/.spamassassin
# ham: inbox subdirectories
30 3 * * * root sa-learn --ham /var/mail/otherdomain.com/*/cur* --dbpath /var/mail-state/lib-amavis/.spamassassin
```
```yaml Then with plain `docker-compose`:
services:
```yaml
services:
mail: mail:
image: mailserver/docker-mailserver:latest image: mailserver/docker-mailserver:latest
volumes: volumes:
- ./cron/sa-learn:/etc/cron.d/sa-learn - ./cron/sa-learn:/etc/cron.d/sa-learn
``` ```
Or with [docker swarm](https://docs.docker.com/engine/swarm/configs/): Or with [docker swarm](https://docs.docker.com/engine/swarm/configs/):
```yaml ```yaml
version: "3.3" version: "3.3"
services: services:
mail: mail:
image: mailserver/docker-mailserver:latest image: mailserver/docker-mailserver:latest
# ... # ...
@ -205,10 +207,10 @@ services:
- source: my_sa_crontab - source: my_sa_crontab
target: /etc/cron.d/sa-learn target: /etc/cron.d/sa-learn
configs: configs:
my_sa_crontab: my_sa_crontab:
file: ./cron/sa-learn file: ./cron/sa-learn
``` ```
With the default settings, Spamassassin will require 200 mails trained for spam (for example with the method explained above) and 200 mails trained for ham (using the same command as above but using `--ham` and providing it with some ham mails). Until you provided these 200+200 mails, Spamassasin will not take the learned mails into account. For further reference, see the [Spamassassin Wiki](https://wiki.apache.org/spamassassin/BayesNotWorking). With the default settings, Spamassassin will require 200 mails trained for spam (for example with the method explained above) and 200 mails trained for ham (using the same command as above but using `--ham` and providing it with some ham mails). Until you provided these 200+200 mails, Spamassasin will not take the learned mails into account. For further reference, see the [Spamassassin Wiki](https://wiki.apache.org/spamassassin/BayesNotWorking).
@ -302,7 +304,7 @@ If we're blind, we won't be able to do anything.
1 core and 1GB of RAM + swap partition is recommended to run `docker-mailserver` with clamav. 1 core and 1GB of RAM + swap partition is recommended to run `docker-mailserver` with clamav.
Otherwise, it could work with 512M of RAM. Otherwise, it could work with 512M of RAM.
!!! note !!! warning
Clamav can consume a lot of memory, as it reads the entire signature database into RAM. Clamav can consume a lot of memory, as it reads the entire signature database into RAM.
Current figure is about 850M and growing. If you get errors about clamav or amavis failing to allocate memory you need more RAM or more swap and of course docker must be allowed to use swap (not always the case). If you can't use swap at all you may need 3G RAM. Current figure is about 850M and growing. If you get errors about clamav or amavis failing to allocate memory you need more RAM or more swap and of course docker must be allowed to use swap (not always the case). If you can't use swap at all you may need 3G RAM.
@ -407,4 +409,5 @@ supervisorctl update
[github-issue-1247]: https://github.com/docker-mailserver/docker-mailserver/issues/1247 [github-issue-1247]: https://github.com/docker-mailserver/docker-mailserver/issues/1247
[github-issue-1405-comment]: https://github.com/docker-mailserver/docker-mailserver/issues/1405#issuecomment-590106498 [github-issue-1405-comment]: https://github.com/docker-mailserver/docker-mailserver/issues/1405#issuecomment-590106498
[github-issue-1639]: https://github.com/docker-mailserver/docker-mailserver/issues/1639 [github-issue-1639]: https://github.com/docker-mailserver/docker-mailserver/issues/1639
[github-issue-1792]: https://github.com/docker-mailserver/docker-mailserver/pull/1792
[hanscees-userpatches]: https://github.com/hanscees/dockerscripts/blob/master/scripts/tomav-user-patches.sh [hanscees-userpatches]: https://github.com/hanscees/dockerscripts/blob/master/scripts/tomav-user-patches.sh

View File

@ -51,15 +51,16 @@ Fetching an email: MUA <------------------------------ ┫ MDA ╯ ┃
┗━━━━━━━┛ ┗━━━━━━━┛
``` ```
> 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`. !!! 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:
> A) Alice sends an email to `bob@dms.io` => the email is first submitted to MTA `smtp.gmail.com`, then relayed to MTA `smtp.dms.io` where it is then delivered into Bob's mailbox. Make sure not to conflate these two very different scenarios:
> B) Bob sends an email to `alice@gmail.com` => the email is first submitted to MTA `smtp.dms.io`, then relayed to MTA `smtp.gmail.com` and eventually delivered into Alice's mailbox. A) Alice sends an email to `bob@dms.io` => the email is first submitted to MTA `smtp.gmail.com`, then relayed to MTA `smtp.dms.io` where it is then delivered into Bob's mailbox.
> B) Bob sends an email to `alice@gmail.com` => the email is first submitted to MTA `smtp.dms.io`, then relayed to MTA `smtp.gmail.com` and eventually delivered into Alice's mailbox.
> In scenario *A* the email leaves Gmail's premises, that email's *initial* submission is _not_ handled by your `docker-mailserver` instance(MTA); it merely receives the email after it has been relayed by Gmail's MTA. In scenario *B*, the `docker-mailserver` instance(MTA) handles the submission, prior to relaying.
> In scenario *A* the email leaves Gmail's premises, that email's *initial* submission is _not_ handled by your `docker-mailserver` instance(MTA); it merely receives the email after it has been relayed by Gmail's MTA. In scenario *B*, the `docker-mailserver` instance(MTA) handles the submission, prior to relaying.
> The main takeaway is that when a third-party sends an email to a `docker-mailserver` instance(MTA) (or any MTA for that matter), it does _not_ establish a direct connection with that MTA. Email submission first goes through the sender's MTA, then some relaying between at least two MTAs is required to deliver the email. That will prove very important when it comes to security management.
The main takeaway is that when a third-party sends an email to a `docker-mailserver` instance(MTA) (or any MTA for that matter), it does _not_ establish a direct connection with that MTA. Email submission first goes through the sender's MTA, then some relaying between at least two MTAs is required to deliver the email. That will prove very important when it comes to security management.
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). 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).
@ -145,7 +146,7 @@ The best practice as of 2020 when it comes to securing Outward Submission is to
- [ESMTP][wikipedia-esmtp] is [SMTP][wikipedia-smtp] + extensions. It's the version of the SMTP protocol that most mail servers speak nowadays. For the purpose of this documentation, ESMTP and SMTP are synonymous. - [ESMTP][wikipedia-esmtp] is [SMTP][wikipedia-smtp] + extensions. It's the version of the SMTP protocol that most mail servers speak nowadays. 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. - 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.
!!! note !!! warning
This Submission setup is sometimes refered to as [SMTPS][wikipedia-smtps]. Long story short: this is incorrect and should be avoided. This Submission setup is sometimes refered 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. 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.