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,106 +6,107 @@ title: 'Advanced | LDAP Authentication'
Getting started with ldap and this mailserver we need to take 3 parts in account:
* POSTFIX
* DOVECOT
* SASLAUTHD (this can also be handled by dovecot above)
- `postfix`
- `dovecot`
- `saslauthd` (this can also be handled by dovecot)
## 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`
* `LDAP_QUERY_FILTER_GROUP`
* `LDAP_QUERY_FILTER_ALIAS`
* `LDAP_QUERY_FILTER_DOMAIN`
!!! example "postfix"
__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`
* `DOVECOT_PASS_FILTER`
!!! example "dovecot"
!!! note
This page will provide several use cases like recipes to show, how this project can be used with it's LDAP Features.
- `DOVECOT_USER_FILTER`
- `DOVECOT_PASS_FILTER`
## LDAP Setup - Kopano / Zarafa
```yaml
---
version: '2'
???+ example "Example Code"
services:
mail:
image: mailserver/docker-mailserver:latest
hostname: mail
domainname: domain.com
container_name: mail
```yaml
---
version: '2'
ports:
- "25:25"
- "143:143"
- "587:587"
- "993:993"
services:
mail:
image: mailserver/docker-mailserver:latest
hostname: mail
domainname: domain.com
container_name: mail
ports:
- "25:25"
- "143:143"
- "587:587"
- "993:993"
volumes:
- maildata:/var/mail
- mailstate:/var/mail-state
- ./config/:/tmp/docker-mailserver/
environment:
# We are not using dovecot here
- SMTP_ONLY=1
- ENABLE_SPAMASSASSIN=1
- ENABLE_CLAMAV=1
- ENABLE_FAIL2BAN=1
- ENABLE_POSTGREY=1
- SASLAUTHD_PASSWD=
# >>> SASL Authentication
- ENABLE_SASLAUTHD=1
- SASLAUTHD_LDAP_SERVER=<yourLdapContainer/yourLdapServer>
- SASLAUTHD_LDAP_PROTO=
- SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=loc
- SASLAUTHD_LDAP_PASSWORD=mypassword
- SASLAUTHD_LDAP_SEARCH_BASE=dc=mydomain,dc=loc
- SASLAUTHD_LDAP_FILTER=(&(sAMAccountName=%U)(objectClass=person))
- SASLAUTHD_MECHANISMS=ldap
# <<< SASL Authentication
# >>> Postfix Ldap Integration
- ENABLE_LDAP=1
- LDAP_SERVER_HOST=<yourLdapContainer/yourLdapServer>
- LDAP_SEARCH_BASE=dc=mydomain,dc=loc
- LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=loc
- LDAP_BIND_PW=mypassword
- LDAP_QUERY_FILTER_USER=(&(objectClass=user)(mail=%s))
- LDAP_QUERY_FILTER_GROUP=(&(objectclass=group)(mail=%s))
- LDAP_QUERY_FILTER_ALIAS=(&(objectClass=user)(otherMailbox=%s))
- LDAP_QUERY_FILTER_DOMAIN=(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))
# <<< Postfix Ldap Integration
# >>> Kopano Integration
- ENABLE_POSTFIX_VIRTUAL_TRANSPORT=1
- POSTFIX_DAGENT=lmtp:kopano:2003
# <<< Kopano Integration
- ONE_DIR=1
- DMS_DEBUG=0
- SSL_TYPE=letsencrypt
- PERMIT_DOCKER=host
cap_add:
- NET_ADMIN
volumes:
- maildata:/var/mail
- mailstate:/var/mail-state
- ./config/:/tmp/docker-mailserver/
environment:
# We are not using dovecot here
- SMTP_ONLY=1
- ENABLE_SPAMASSASSIN=1
- ENABLE_CLAMAV=1
- ENABLE_FAIL2BAN=1
- ENABLE_POSTGREY=1
- SASLAUTHD_PASSWD=
# >>> SASL Authentication
- ENABLE_SASLAUTHD=1
- SASLAUTHD_LDAP_SERVER=<yourLdapContainer/yourLdapServer>
- SASLAUTHD_LDAP_PROTO=
- SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=loc
- SASLAUTHD_LDAP_PASSWORD=mypassword
- SASLAUTHD_LDAP_SEARCH_BASE=dc=mydomain,dc=loc
- SASLAUTHD_LDAP_FILTER=(&(sAMAccountName=%U)(objectClass=person))
- SASLAUTHD_MECHANISMS=ldap
# <<< SASL Authentication
# >>> Postfix Ldap Integration
- ENABLE_LDAP=1
- LDAP_SERVER_HOST=<yourLdapContainer/yourLdapServer>
- LDAP_SEARCH_BASE=dc=mydomain,dc=loc
- LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=loc
- LDAP_BIND_PW=mypassword
- LDAP_QUERY_FILTER_USER=(&(objectClass=user)(mail=%s))
- LDAP_QUERY_FILTER_GROUP=(&(objectclass=group)(mail=%s))
- LDAP_QUERY_FILTER_ALIAS=(&(objectClass=user)(otherMailbox=%s))
- LDAP_QUERY_FILTER_DOMAIN=(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))
# <<< Postfix Ldap Integration
# >>> Kopano Integration
- ENABLE_POSTFIX_VIRTUAL_TRANSPORT=1
- POSTFIX_DAGENT=lmtp:kopano:2003
# <<< Kopano Integration
- ONE_DIR=1
- DMS_DEBUG=0
- SSL_TYPE=letsencrypt
- PERMIT_DOCKER=host
cap_add:
- NET_ADMIN
volumes:
maildata:
driver: local
mailstate:
driver: local
```
maildata:
driver: local
mailstate:
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:
@ -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_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,231 +6,258 @@ 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.
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.env.config
namespace: mailserver
labels:
app: mailserver
data:
OVERRIDE_HOSTNAME: example.com
ENABLE_FETCHMAIL: "0"
FETCHMAIL_POLL: "120"
ENABLE_SPAMASSASSIN: "0"
ENABLE_CLAMAV: "0"
ENABLE_FAIL2BAN: "0"
ENABLE_POSTGREY: "0"
ONE_DIR: "1"
DMS_DEBUG: "0"
??? example "ConfigMap"
---
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config
namespace: mailserver
labels:
app: mailserver
data:
postfix-accounts.cf: |
user1@example.com|{SHA512-CRYPT}$6$2YpW1nYtPBs2yLYS$z.5PGH1OEzsHHNhl3gJrc3D.YMZkvKw/vp.r5WIiwya6z7P/CQ9GDEJDr2G2V0cAfjDFeAQPUoopsuWPXLk3u1
postfix-virtual.cf: |
alias1@example.com user1@dexample.com
#dovecot.cf: |
# service stats {
# unix_listener stats-reader {
# group = docker
# mode = 0666
# }
# unix_listener stats-writer {
# group = docker
# mode = 0666
# }
# }
SigningTable: |
*@example.com mail._domainkey.example.com
KeyTable: |
mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com-mail.key
TrustedHosts: |
127.0.0.1
localhost
#user-patches.sh: |
# #!/bin/bash
#fetchmail.cf: |
---
kind: Secret
apiVersion: v1
metadata:
name: mailserver.opendkim.keys
namespace: mailserver
labels:
app: mailserver
type: Opaque
data:
example.com-mail.key: 'base64-encoded-DKIM-key'
---
kind: Service
apiVersion: v1
metadata:
name: mailserver
namespace: mailserver
labels:
app: mailserver
spec:
selector:
app: mailserver
ports:
- name: smtp
port: 25
targetPort: smtp
- name: smtp-secure
port: 465
targetPort: smtp-secure
- name: smtp-auth
port: 587
targetPort: smtp-auth
- name: imap
port: 143
targetPort: imap
- name: imap-secure
port: 993
targetPort: imap-secure
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mailserver
namespace: mailserver
spec:
replicas: 1
selector:
matchLabels:
app: mailserver
template:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.env.config
namespace: mailserver
labels:
app: mailserver
role: mail
tier: backend
spec:
#nodeSelector:
# kubernetes.io/hostname: local.k8s
#initContainers:
#- name: init-myservice
# image: busybox
# command: ["/bin/sh", "-c", "cp /tmp/user-patches.sh /tmp/files"]
# volumeMounts:
# - name: config
# subPath: user-patches.sh
# mountPath: /tmp/user-patches.sh
# readOnly: true
# - name: tmp-files
# mountPath: /tmp/files
containers:
- name: docker-mailserver
image: mailserver/docker-mailserver:latest
imagePullPolicy: Always
volumeMounts:
- name: config
subPath: postfix-accounts.cf
mountPath: /tmp/docker-mailserver/postfix-accounts.cf
readOnly: true
#- name: config
# subPath: postfix-main.cf
# mountPath: /tmp/docker-mailserver/postfix-main.cf
# readOnly: true
- name: config
subPath: postfix-virtual.cf
mountPath: /tmp/docker-mailserver/postfix-virtual.cf
readOnly: true
- name: config
subPath: fetchmail.cf
mountPath: /tmp/docker-mailserver/fetchmail.cf
readOnly: true
- name: config
subPath: dovecot.cf
mountPath: /tmp/docker-mailserver/dovecot.cf
readOnly: true
#- name: config
# subPath: user1.example.com.dovecot.sieve
# mountPath: /tmp/docker-mailserver/user1@example.com.dovecot.sieve
# readOnly: true
#- name: tmp-files
# subPath: user-patches.sh
# mountPath: /tmp/docker-mailserver/user-patches.sh
- name: config
subPath: SigningTable
mountPath: /tmp/docker-mailserver/opendkim/SigningTable
readOnly: true
- name: config
subPath: KeyTable
mountPath: /tmp/docker-mailserver/opendkim/KeyTable
readOnly: true
- name: config
subPath: TrustedHosts
mountPath: /tmp/docker-mailserver/opendkim/TrustedHosts
readOnly: true
- name: opendkim-keys
mountPath: /tmp/docker-mailserver/opendkim/keys
readOnly: true
- name: data
mountPath: /var/mail
subPath: data
- name: data
mountPath: /var/mail-state
subPath: state
- name: data
mountPath: /var/log/mail
subPath: log
ports:
- name: smtp
containerPort: 25
protocol: TCP
- name: smtp-secure
containerPort: 465
protocol: TCP
- name: smtp-auth
containerPort: 587
- name: imap
containerPort: 143
protocol: TCP
- name: imap-secure
containerPort: 993
protocol: TCP
envFrom:
- configMapRef:
name: mailserver.env.config
volumes:
- name: config
configMap:
name: mailserver.config
- name: opendkim-keys
secret:
secretName: mailserver.opendkim.keys
- name: data
persistentVolumeClaim:
claimName: mail-storage
- name: tmp-files
emptyDir: {}
```
data:
OVERRIDE_HOSTNAME: example.com
ENABLE_FETCHMAIL: "0"
FETCHMAIL_POLL: "120"
ENABLE_SPAMASSASSIN: "0"
ENABLE_CLAMAV: "0"
ENABLE_FAIL2BAN: "0"
ENABLE_POSTGREY: "0"
ONE_DIR: "1"
DMS_DEBUG: "0"
!!! note
---
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config
namespace: mailserver
labels:
app: mailserver
data:
postfix-accounts.cf: |
user1@example.com|{SHA512-CRYPT}$6$2YpW1nYtPBs2yLYS$z.5PGH1OEzsHHNhl3gJrc3D.YMZkvKw/vp.r5WIiwya6z7P/CQ9GDEJDr2G2V0cAfjDFeAQPUoopsuWPXLk3u1
postfix-virtual.cf: |
alias1@example.com user1@dexample.com
#dovecot.cf: |
# service stats {
# unix_listener stats-reader {
# group = docker
# mode = 0666
# }
# unix_listener stats-writer {
# group = docker
# mode = 0666
# }
# }
SigningTable: |
*@example.com mail._domainkey.example.com
KeyTable: |
mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com-mail.key
TrustedHosts: |
127.0.0.1
localhost
#user-patches.sh: |
# #!/bin/bash
#fetchmail.cf: |
```
??? example "Secret"
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
kind: Secret
apiVersion: v1
metadata:
name: mailserver.opendkim.keys
namespace: mailserver
labels:
app: mailserver
type: Opaque
data:
example.com-mail.key: 'base64-encoded-DKIM-key'
```
??? example "Service"
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
kind: Service
apiVersion: v1
metadata:
name: mailserver
namespace: mailserver
labels:
app: mailserver
spec:
selector:
app: mailserver
ports:
- name: smtp
port: 25
targetPort: smtp
- name: smtp-secure
port: 465
targetPort: smtp-secure
- name: smtp-auth
port: 587
targetPort: smtp-auth
- name: imap
port: 143
targetPort: imap
- name: imap-secure
port: 993
targetPort: imap-secure
```
??? example "Deployment"
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: mailserver
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mailserver
namespace: mailserver
spec:
replicas: 1
selector:
matchLabels:
app: mailserver
template:
metadata:
labels:
app: mailserver
role: mail
tier: backend
spec:
#nodeSelector:
# kubernetes.io/hostname: local.k8s
#initContainers:
#- name: init-myservice
# image: busybox
# command: ["/bin/sh", "-c", "cp /tmp/user-patches.sh /tmp/files"]
# volumeMounts:
# - name: config
# subPath: user-patches.sh
# mountPath: /tmp/user-patches.sh
# readOnly: true
# - name: tmp-files
# mountPath: /tmp/files
containers:
- name: docker-mailserver
image: mailserver/docker-mailserver:latest
imagePullPolicy: Always
volumeMounts:
- name: config
subPath: postfix-accounts.cf
mountPath: /tmp/docker-mailserver/postfix-accounts.cf
readOnly: true
#- name: config
# subPath: postfix-main.cf
# mountPath: /tmp/docker-mailserver/postfix-main.cf
# readOnly: true
- name: config
subPath: postfix-virtual.cf
mountPath: /tmp/docker-mailserver/postfix-virtual.cf
readOnly: true
- name: config
subPath: fetchmail.cf
mountPath: /tmp/docker-mailserver/fetchmail.cf
readOnly: true
- name: config
subPath: dovecot.cf
mountPath: /tmp/docker-mailserver/dovecot.cf
readOnly: true
#- name: config
# subPath: user1.example.com.dovecot.sieve
# mountPath: /tmp/docker-mailserver/user1@example.com.dovecot.sieve
# readOnly: true
#- name: tmp-files
# subPath: user-patches.sh
# mountPath: /tmp/docker-mailserver/user-patches.sh
- name: config
subPath: SigningTable
mountPath: /tmp/docker-mailserver/opendkim/SigningTable
readOnly: true
- name: config
subPath: KeyTable
mountPath: /tmp/docker-mailserver/opendkim/KeyTable
readOnly: true
- name: config
subPath: TrustedHosts
mountPath: /tmp/docker-mailserver/opendkim/TrustedHosts
readOnly: true
- name: opendkim-keys
mountPath: /tmp/docker-mailserver/opendkim/keys
readOnly: true
- name: data
mountPath: /var/mail
subPath: data
- name: data
mountPath: /var/mail-state
subPath: state
- name: data
mountPath: /var/log/mail
subPath: log
ports:
- name: smtp
containerPort: 25
protocol: TCP
- name: smtp-secure
containerPort: 465
protocol: TCP
- name: smtp-auth
containerPort: 587
- name: imap
containerPort: 143
protocol: TCP
- name: imap-secure
containerPort: 993
protocol: TCP
envFrom:
- configMapRef:
name: mailserver.env.config
volumes:
- name: config
configMap:
name: mailserver.config
- name: opendkim-keys
secret:
secretName: mailserver.opendkim.keys
- name: data
persistentVolumeClaim:
claimName: mail-storage
- name: tmp-files
emptyDir: {}
```
!!! warning
Any sensitive data (keys, etc) should be deployed via [Secrets][k8s-config-secret]. Other configuration just fits well into [ConfigMaps][k8s-config-pod].
!!! 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):
```yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config
labels:
app: mailserver
data:
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
# ...
!!! example
---
```yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config
labels:
app: mailserver
data:
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
# ...
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: mailserver
# ...
volumeMounts:
- name: config
subPath: postfix-main.cf
mountPath: /tmp/docker-mailserver/postfix-main.cf
readOnly: true
```
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: mailserver
# ...
volumeMounts:
- name: config
subPath: postfix-main.cf
mountPath: /tmp/docker-mailserver/postfix-main.cf
readOnly: true
```
### External IPs Service
The simplest way is to expose mailserver as a [Service][k8s-network-service] with [external IPs][k8s-network-external-ip].
```yaml
kind: Service
apiVersion: v1
metadata:
name: mailserver
labels:
app: mailserver
spec:
selector:
app: mailserver
ports:
- name: smtp
port: 25
targetPort: smtp
# ...
externalIPs:
- 80.11.12.10
```
!!! example
```yaml
kind: Service
apiVersion: v1
metadata:
name: mailserver
labels:
app: mailserver
spec:
selector:
app: mailserver
ports:
- name: smtp
port: 25
targetPort: smtp
# ...
externalIPs:
- 80.11.12.10
```
**Downsides**
@ -313,29 +344,31 @@ 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.
```yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: mailserver
# ...
spec:
hostNetwork: true
# ...
containers:
# ...
ports:
- name: smtp
containerPort: 25
hostPort: 25
- name: smtp-auth
containerPort: 587
hostPort: 587
- name: imap-secure
containerPort: 993
hostPort: 993
# ...
```
!!! example
```yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: mailserver
# ...
spec:
hostNetwork: true
# ...
containers:
# ...
ports:
- name: smtp
containerPort: 25
hostPort: 25
- name: smtp-auth
containerPort: 587
hostPort: 587
- name: imap-secure
containerPort: 993
hostPort: 993
# ...
```
**Downsides**
@ -363,53 +396,55 @@ 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:
```yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config
labels:
app: mailserver
data:
postfix-main.cf: |
postscreen_upstream_proxy_protocol = haproxy
postfix-master.cf: |
submission/inet/smtpd_upstream_proxy_protocol=haproxy
smtps/inet/smtpd_upstream_proxy_protocol=haproxy
dovecot.cf: |
# Assuming your ingress controller is bound to 10.0.0.0/8
haproxy_trusted_networks = 10.0.0.0/8, 127.0.0.0/8
service imap-login {
inet_listener imaps {
haproxy = yes
}
}
# ...
---
!!! example
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: mailserver
spec:
template:
```yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: mailserver.config
labels:
app: mailserver
data:
postfix-main.cf: |
postscreen_upstream_proxy_protocol = haproxy
postfix-master.cf: |
submission/inet/smtpd_upstream_proxy_protocol=haproxy
smtps/inet/smtpd_upstream_proxy_protocol=haproxy
dovecot.cf: |
# Assuming your ingress controller is bound to 10.0.0.0/8
haproxy_trusted_networks = 10.0.0.0/8, 127.0.0.0/8
service imap-login {
inet_listener imaps {
haproxy = yes
}
}
# ...
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: mailserver
spec:
containers:
- name: docker-mailserver
volumeMounts:
- name: config
subPath: postfix-main.cf
mountPath: /tmp/docker-mailserver/postfix-main.cf
readOnly: true
- name: config
subPath: postfix-master.cf
mountPath: /tmp/docker-mailserver/postfix-master.cf
readOnly: true
- name: config
subPath: dovecot.cf
mountPath: /tmp/docker-mailserver/dovecot.cf
readOnly: true
```
template:
spec:
containers:
- name: docker-mailserver
volumeMounts:
- name: config
subPath: postfix-main.cf
mountPath: /tmp/docker-mailserver/postfix-main.cf
readOnly: true
- name: config
subPath: postfix-master.cf
mountPath: /tmp/docker-mailserver/postfix-master.cf
readOnly: true
- name: config
subPath: dovecot.cf
mountPath: /tmp/docker-mailserver/dovecot.cf
readOnly: true
```
**Downsides**
@ -419,52 +454,56 @@ 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.
```yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: mailserver
labels:
app: mailserver
annotations:
kubernetes.io/tls-acme: 'true'
spec:
rules:
- host: example.com
http:
paths:
- path: /
backend:
serviceName: default-backend
servicePort: 80
tls:
- secretName: mailserver.tls
hosts:
- example.com
```
!!! example
```yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: mailserver
labels:
app: mailserver
annotations:
kubernetes.io/tls-acme: 'true'
spec:
rules:
- host: example.com
http:
paths:
- path: /
backend:
serviceName: default-backend
servicePort: 80
tls:
- secretName: mailserver.tls
hosts:
- 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:
```yaml
# ...
env:
- name: SSL_TYPE
value: 'manual'
- name: SSL_CERT_PATH
value: '/etc/ssl/mailserver/tls.crt'
- name: SSL_KEY_PATH
value: '/etc/ssl/mailserver/tls.key'
# ...
volumeMounts:
- name: tls
mountPath: /etc/ssl/mailserver
readOnly: true
# ...
volumes:
- name: tls
secret:
secretName: mailserver.tls
```
!!! example
```yaml
# ...
env:
- name: SSL_TYPE
value: 'manual'
- name: SSL_CERT_PATH
value: '/etc/ssl/mailserver/tls.crt'
- name: SSL_KEY_PATH
value: '/etc/ssl/mailserver/tls.key'
# ...
volumeMounts:
- name: tls
mountPath: /etc/ssl/mailserver
readOnly: true
# ...
volumes:
- name: tls
secret:
secretName: mailserver.tls
```
[docs-dovecot]: ./override-defaults/dovecot.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].
### Example IMAP Configuration
### IMAP Configuration
```fetchmailrc
poll 'imap.example.com' proto imap
user 'username'
pass 'secret'
is 'user1@domain.tld'
ssl
```
!!! example
### Example POP3 Configuration
```fetchmailrc
poll 'imap.example.com' proto imap
user 'username'
pass 'secret'
is 'user1@domain.tld'
ssl
```
```fetchmailrc
poll 'pop3.example.com' proto pop3
user 'username'
pass 'secret'
is 'user2@domain.tld'
ssl
```
### POP3 Configuration
!!! example
```fetchmailrc
poll 'pop3.example.com' proto pop3
user 'username'
pass 'secret'
is 'user2@domain.tld'
ssl
```
!!! 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`.

View file

@ -2,7 +2,7 @@
title: 'Mail Forwarding | AWS SES'
---
!!! note
!!! warning
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.

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:
* **RELAY_HOST** _default host to relay mail through, empty will disable this feature_
* **RELAY_PORT** _port on default relay, defaults to port 25_
* **RELAY_USER** _username for the default relay_
* **RELAY_PASSWORD** _password for the default user_
* `RELAY_HOST`: _default host to relay mail through, empty will disable this feature_
* `RELAY_PORT`: _port on default relay, defaults to port 25_
* `RELAY_USER`: _username for the default relay_
* `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.
!!! note
!!! warning
For users of the previous `AWS_SES_*` variables: please update your configuration to use these new variables, no other configuration is required.
## 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:
```sieve
require ["fileinto", "reject"];
!!! example
if address :contains ["From"] "spam@spam.com" {
fileinto "INBOX.spam";
} else {
keep;
}
```
```sieve
require ["fileinto", "reject"];
!!! note
if address :contains ["From"] "spam@spam.com" {
fileinto "INBOX.spam";
} else {
keep;
}
```
!!! warning
That folders have to exist beforehand if sieve should move them.
Another example of a sieve filter that forward mails to a different address:
```sieve
require ["copy"];
!!! example
redirect :copy "user2@otherdomain.tld";
```
```sieve
require ["copy"];
redirect :copy "user2@otherdomain.tld";
```
Just forward all incoming emails and do not save them locally:
```sieve
redirect "user2@otherdomain.tld";
```
!!! example
```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).
@ -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.
```yaml
# docker-compose.yml
ports:
- "4190:4190"
environment:
- ENABLE_MANAGESIEVE=1
```
!!! example
```yaml
# docker-compose.yml
ports:
- "4190:4190"
environment:
- 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.
@ -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.
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>`
!!! 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:

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`.
[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.

View file

@ -2,7 +2,10 @@
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

View file

@ -4,7 +4,8 @@ hide:
- 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

View file

@ -6,9 +6,11 @@ hide:
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

View file

@ -4,10 +4,11 @@ hide:
- 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 :
Add the ports 110 and 995, and add environment variable ENABLE_POP :
**We do not recommend using POP3. Use IMAP instead.**
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
mail:

View file

@ -134,98 +134,102 @@ 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.
```yaml
version: "2"
???+ example "Example Code"
```yaml
version: "2"
services:
nginx:
image: nginx
container_name: nginx
ports:
- 80:80
- 443:443
volumes:
- /mnt/data/nginx/htpasswd:/etc/nginx/htpasswd
- /mnt/data/nginx/conf.d:/etc/nginx/conf.d
- /mnt/data/nginx/vhost.d:/etc/nginx/vhost.d
- /mnt/data/nginx/html:/usr/share/nginx/html
- /mnt/data/nginx/certs:/etc/nginx/certs:ro
networks:
- proxy-tier
restart: always
nginx-gen:
image: jwilder/docker-gen
container_name: nginx-gen
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /mnt/data/nginx/templates/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
volumes_from:
- nginx
entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
restart: always
letsencrypt-nginx-proxy-companion:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: letsencrypt-companion
volumes_from:
- nginx
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /mnt/data/nginx/certs:/etc/nginx/certs:rw
environment:
- NGINX_DOCKER_GEN_CONTAINER=nginx-gen
- DEBUG=false
restart: always
services:
nginx:
image: nginx
container_name: nginx
ports:
- 80:80
- 443:443
volumes:
- /mnt/data/nginx/htpasswd:/etc/nginx/htpasswd
- /mnt/data/nginx/conf.d:/etc/nginx/conf.d
- /mnt/data/nginx/vhost.d:/etc/nginx/vhost.d
- /mnt/data/nginx/html:/usr/share/nginx/html
- /mnt/data/nginx/certs:/etc/nginx/certs:ro
networks:
- proxy-tier
restart: always
nginx-gen:
image: jwilder/docker-gen
container_name: nginx-gen
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /mnt/data/nginx/templates/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
volumes_from:
- nginx
entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
restart: always
letsencrypt-nginx-proxy-companion:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: letsencrypt-companion
volumes_from:
- nginx
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /mnt/data/nginx/certs:/etc/nginx/certs:rw
environment:
- NGINX_DOCKER_GEN_CONTAINER=nginx-gen
- DEBUG=false
restart: always
networks:
proxy-tier:
external:
name: nginx-proxy
```
proxy-tier:
external:
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):
```yaml
version: '2'
services:
mail:
image: mailserver/docker-mailserver:latest
hostname: ${HOSTNAME}
domainname: ${DOMAINNAME}
container_name: ${CONTAINER_NAME}
ports:
- "25:25"
- "143:143"
- "465:465"
- "587:587"
- "993:993"
volumes:
- ./mail:/var/mail
- ./mail-state:/var/mail-state
- ./config/:/tmp/docker-mailserver/
- /mnt/data/nginx/certs/:/etc/letsencrypt/live/:ro
cap_add:
- NET_ADMIN
- SYS_PTRACE
restart: always
???+ example "Example Code"
```yaml
version: '2'
services:
mail:
image: mailserver/docker-mailserver:latest
hostname: ${HOSTNAME}
domainname: ${DOMAINNAME}
container_name: ${CONTAINER_NAME}
ports:
- "25:25"
- "143:143"
- "465:465"
- "587:587"
- "993:993"
volumes:
- ./mail:/var/mail
- ./mail-state:/var/mail-state
- ./config/:/tmp/docker-mailserver/
- /mnt/data/nginx/certs/:/etc/letsencrypt/live/:ro
cap_add:
- NET_ADMIN
- SYS_PTRACE
restart: always
cert-companion:
image: nginx
environment:
- "VIRTUAL_HOST="
- "VIRTUAL_NETWORK=nginx-proxy"
- "LETSENCRYPT_HOST="
- "LETSENCRYPT_EMAIL="
networks:
- proxy-tier
restart: always
cert-companion:
image: nginx
environment:
- "VIRTUAL_HOST="
- "VIRTUAL_NETWORK=nginx-proxy"
- "LETSENCRYPT_HOST="
- "LETSENCRYPT_EMAIL="
networks:
- proxy-tier
restart: always
networks:
proxy-tier:
external:
name: nginx-proxy
```
proxy-tier:
external:
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)
@ -275,70 +279,72 @@ 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:
```json
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"mail.domain.com",
]
}
???+ example "Example Code"
```json
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"handle": [
"routes": [
{
"handler": "subroute",
"routes": [
"match": [
{
"handle": [
"host": [
"mail.domain.com",
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"body": "",
"handler": "static_response"
"handle": [
{
"body": "",
"handler": "static_response"
}
]
}
]
}
]
}
],
"terminal": true
},
]
}
}
},
"tls": {
"automation": {
"policies": [
{
"subjects": [
"mail.domain.com",
],
"key_type": "rsa2048",
"issuer": {
"email": "email@email.com",
"module": "acme"
}
},
{
"issuer": {
"email": "email@email.com",
"module": "acme"
],
"terminal": true
},
]
}
}
]
},
"tls": {
"automation": {
"policies": [
{
"subjects": [
"mail.domain.com",
],
"key_type": "rsa2048",
"issuer": {
"email": "email@email.com",
"module": "acme"
}
},
{
"issuer": {
"email": "email@email.com",
"module": "acme"
}
}
]
}
}
}
}
}
}
```
```
The generated certificates can be mounted:
@ -375,44 +381,46 @@ 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/):
```yaml
version: '3.8'
services:
mail:
image: mailserver/docker-mailserver:stable
hostname: mail
domainname: example.com
volumes:
- /etc/ssl/acme-v2.json:/etc/letsencrypt/acme.json:ro
environment:
SSL_TYPE: letsencrypt
# SSL_DOMAIN: "*.example.com"
traefik:
image: traefik:v2.2
restart: always
ports:
- "80:80"
- "443:443"
command:
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.websecure.address=:443
- --entrypoints.websecure.http.middlewares=hsts@docker
- --entrypoints.websecure.http.tls.certResolver=le
- --certificatesresolvers.le.acme.email=admin@example.net
- --certificatesresolvers.le.acme.storage=/acme.json
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/ssl/acme-v2.json:/acme.json
???+ example "Example Code"
whoami:
image: containous/whoami
labels:
- "traefik.http.routers.whoami.rule=Host(`mail.example.com`)"
```
```yaml
version: '3.8'
services:
mail:
image: mailserver/docker-mailserver:stable
hostname: mail
domainname: example.com
volumes:
- /etc/ssl/acme-v2.json:/etc/letsencrypt/acme.json:ro
environment:
SSL_TYPE: letsencrypt
# SSL_DOMAIN: "*.example.com"
traefik:
image: traefik:v2.2
restart: always
ports:
- "80:80"
- "443:443"
command:
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.websecure.address=:443
- --entrypoints.websecure.http.middlewares=hsts@docker
- --entrypoints.websecure.http.tls.certResolver=le
- --certificatesresolvers.le.acme.email=admin@example.net
- --certificatesresolvers.le.acme.storage=/acme.json
- --certificatesresolvers.le.acme.httpchallenge.entrypoint=web
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/ssl/acme-v2.json:/acme.json
whoami:
image: containous/whoami
labels:
- "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).
@ -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.
## 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
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.
!!! note
!!! info
You may have to restart your mailserver once the certificates change.
## Testing a Certificate is Valid
@ -509,9 +521,11 @@ docker exec mail openssl s_client \
## 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
ssl = yes

View file

@ -13,6 +13,10 @@ wget https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/maste
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
Run `./setup.sh -h` and you'll get some usage information:

View file

@ -22,39 +22,41 @@ We are going to use this docker based mailserver:
- Create the file `docker-compose.yml` with a content like this:
```yaml
version: '2'
!!! example
services:
mail:
image: mailserver/docker-mailserver:latest
hostname: mail
domainname: example.org
container_name: mail
ports:
- "25:25"
- "587:587"
- "465:465"
volumes:
- ./data/:/var/mail/
- ./state/:/var/mail-state/
- ./config/:/tmp/docker-mailserver/
- /var/ds/wsproxy/letsencrypt/:/etc/letsencrypt/
environment:
- PERMIT_DOCKER=network
- SSL_TYPE=letsencrypt
- ONE_DIR=1
- DMS_DEBUG=1
- SPOOF_PROTECTION=0
- REPORT_RECIPIENT=1
- ENABLE_SPAMASSASSIN=0
- ENABLE_CLAMAV=0
- ENABLE_FAIL2BAN=1
- ENABLE_POSTGREY=0
cap_add:
- NET_ADMIN
- SYS_PTRACE
```
```yaml
version: '2'
services:
mail:
image: mailserver/docker-mailserver:latest
hostname: mail
domainname: example.org
container_name: mail
ports:
- "25:25"
- "587:587"
- "465:465"
volumes:
- ./data/:/var/mail/
- ./state/:/var/mail-state/
- ./config/:/tmp/docker-mailserver/
- /var/ds/wsproxy/letsencrypt/:/etc/letsencrypt/
environment:
- PERMIT_DOCKER=network
- SSL_TYPE=letsencrypt
- ONE_DIR=1
- DMS_DEBUG=1
- SPOOF_PROTECTION=0
- REPORT_RECIPIENT=1
- ENABLE_SPAMASSASSIN=0
- ENABLE_CLAMAV=0
- ENABLE_FAIL2BAN=1
- ENABLE_POSTGREY=0
cap_add:
- NET_ADMIN
- SYS_PTRACE
```
For more details about the environment variables that can be used, and their meaning and possible values, check also these:

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`.
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-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?
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?
@ -147,68 +147,70 @@ If you run the server with `docker-compose`, you can leverage on docker configs
The following configuration works nicely:
Create a _system_ cron file:
??? example
```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
```
Create a _system_ cron file:
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
# 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
```
Edit the system cron file `nano cron/sa-learn`, and set an appropriate configuration:
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
services:
mail:
image: mailserver/docker-mailserver:latest
volumes:
- ./cron/sa-learn:/etc/cron.d/sa-learn
```
Then with plain `docker-compose`:
Or with [docker swarm](https://docs.docker.com/engine/swarm/configs/):
```yaml
services:
mail:
image: mailserver/docker-mailserver:latest
volumes:
- ./cron/sa-learn:/etc/cron.d/sa-learn
```
```yaml
version: "3.3"
Or with [docker swarm](https://docs.docker.com/engine/swarm/configs/):
```yaml
version: "3.3"
services:
mail:
image: mailserver/docker-mailserver:latest
# ...
configs:
- source: my_sa_crontab
target: /etc/cron.d/sa-learn
services:
mail:
image: mailserver/docker-mailserver:latest
# ...
configs:
- source: my_sa_crontab
target: /etc/cron.d/sa-learn
configs:
my_sa_crontab:
file: ./cron/sa-learn
```
my_sa_crontab:
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).
@ -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.
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.
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-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-1792]: https://github.com/docker-mailserver/docker-mailserver/pull/1792
[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`.
>
> 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.
> 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.
>
> 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.
!!! 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.
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.
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).
@ -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.
- 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.
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.