mirror of
https://github.com/docker-mailserver/docker-mailserver.git
synced 2025-08-31 15:30:50 +02:00
docs(refactor): Convert more content to use admonitions + improvements
This commit is contained in:
parent
463bc967d2
commit
711b4c9d83
18 changed files with 884 additions and 792 deletions
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
Don’t 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`.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue