You've already forked Mailu
mirror of
https://github.com/Mailu/Mailu.git
synced 2025-11-25 22:12:28 +02:00
doc
This commit is contained in:
@@ -1,144 +0,0 @@
|
|||||||
version: '2'
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
# This would normally not be here, but where you define your system services
|
|
||||||
traefik:
|
|
||||||
image: traefik:alpine
|
|
||||||
command: --docker
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
volumes:
|
|
||||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
|
||||||
- "/data/traefik/acme.json:/acme.json"
|
|
||||||
- "/data/traefik/traefik.toml:/traefik.toml"
|
|
||||||
# This may be needed (plus defining mailu_default external: true) if traefik lives elsewhere
|
|
||||||
# networks:
|
|
||||||
# - mailu_default
|
|
||||||
|
|
||||||
certdumper:
|
|
||||||
restart: always
|
|
||||||
image: mailu/traefik-certdumper:$VERSION
|
|
||||||
environment:
|
|
||||||
# Make sure this is the same as the main=-domain in traefik.toml
|
|
||||||
# !!! Also don’t forget to add "TRAEFIK_DOMAIN=[...]" to your .env!
|
|
||||||
- DOMAIN=$TRAEFIK_DOMAIN
|
|
||||||
# Set TRAEFIK_VERSION to v2 in your .env if you're using Traefik v2
|
|
||||||
- TRAEFIK_VERSION=${TRAEFIK_VERSION:-v1}
|
|
||||||
volumes:
|
|
||||||
- "/data/traefik:/traefik"
|
|
||||||
- "$ROOT/certs:/output"
|
|
||||||
|
|
||||||
front:
|
|
||||||
image: mailu/nginx:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
labels: # Traefik labels for simple reverse-proxying
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.port=80"
|
|
||||||
- "traefik.frontend.rule=Host:$TRAEFIK_DOMAIN"
|
|
||||||
- "traefik.docker.network=mailu_default"
|
|
||||||
ports:
|
|
||||||
- "$BIND_ADDRESS4:110:110"
|
|
||||||
- "$BIND_ADDRESS4:143:143"
|
|
||||||
- "$BIND_ADDRESS4:993:993"
|
|
||||||
- "$BIND_ADDRESS4:995:995"
|
|
||||||
- "$BIND_ADDRESS4:25:25"
|
|
||||||
- "$BIND_ADDRESS4:465:465"
|
|
||||||
- "$BIND_ADDRESS4:587:587"
|
|
||||||
- "$BIND_ADDRESS6:110:110"
|
|
||||||
- "$BIND_ADDRESS6:143:143"
|
|
||||||
- "$BIND_ADDRESS6:993:993"
|
|
||||||
- "$BIND_ADDRESS6:995:995"
|
|
||||||
- "$BIND_ADDRESS6:25:25"
|
|
||||||
- "$BIND_ADDRESS6:465:465"
|
|
||||||
- "$BIND_ADDRESS6:587:587"
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/overrides/nginx:/overrides"
|
|
||||||
- /data/traefik/ssl/$TRAEFIK_DOMAIN.crt:/certs/cert.pem
|
|
||||||
- /data/traefik/ssl/$TRAEFIK_DOMAIN.key:/certs/key.pem
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:alpine
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/redis:/data"
|
|
||||||
|
|
||||||
imap:
|
|
||||||
image: mailu/dovecot:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/mail:/mail"
|
|
||||||
- "$ROOT/overrides:/overrides"
|
|
||||||
depends_on:
|
|
||||||
- front
|
|
||||||
|
|
||||||
smtp:
|
|
||||||
image: mailu/postfix:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/overrides:/overrides"
|
|
||||||
depends_on:
|
|
||||||
- front
|
|
||||||
|
|
||||||
antispam:
|
|
||||||
image: mailu/rspamd:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/filter:/var/lib/rspamd"
|
|
||||||
- "$ROOT/dkim:/dkim"
|
|
||||||
- "$ROOT/overrides/rspamd:/etc/rspamd/override.d"
|
|
||||||
depends_on:
|
|
||||||
- front
|
|
||||||
|
|
||||||
antivirus:
|
|
||||||
image: mailu/$ANTIVIRUS:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/filter:/data"
|
|
||||||
|
|
||||||
webdav:
|
|
||||||
image: mailu/$WEBDAV:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/dav:/data"
|
|
||||||
|
|
||||||
admin:
|
|
||||||
image: mailu/admin:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/data:/data"
|
|
||||||
- "$ROOT/dkim:/dkim"
|
|
||||||
depends_on:
|
|
||||||
- redis
|
|
||||||
|
|
||||||
webmail:
|
|
||||||
image: "mailu/$WEBMAIL:$VERSION"
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
volumes:
|
|
||||||
- "$ROOT/webmail:/data"
|
|
||||||
- "$ROOT/overrides/$WEBMAIL:/overrides:ro"
|
|
||||||
depends_on:
|
|
||||||
- imap
|
|
||||||
|
|
||||||
fetchmail:
|
|
||||||
image: mailu/fetchmail:$VERSION
|
|
||||||
restart: always
|
|
||||||
env_file: .env
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
driver: bridge
|
|
||||||
ipam:
|
|
||||||
driver: default
|
|
||||||
config:
|
|
||||||
- subnet: $SUBNET
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# This is just boilerplate stuff you probably have in your own config
|
|
||||||
logLevel = "INFO"
|
|
||||||
defaultEntryPoints = ["https","http"]
|
|
||||||
|
|
||||||
[entryPoints]
|
|
||||||
[entryPoints.http]
|
|
||||||
address = ":80"
|
|
||||||
[entryPoints.http.redirect]
|
|
||||||
entryPoint = "https"
|
|
||||||
[entryPoints.https]
|
|
||||||
address = ":443"
|
|
||||||
[entryPoints.https.tls]
|
|
||||||
|
|
||||||
[docker]
|
|
||||||
endpoint = "unix:///var/run/docker.sock"
|
|
||||||
watch = true
|
|
||||||
exposedByDefault = false
|
|
||||||
|
|
||||||
# Make sure we get acme.json saved, and onHostRule enabled
|
|
||||||
[acme]
|
|
||||||
email = "your@mail.tld"
|
|
||||||
storage = "acme.json"
|
|
||||||
entryPoint = "https"
|
|
||||||
onHostRule = true
|
|
||||||
|
|
||||||
[acme.httpChallenge]
|
|
||||||
entryPoint = "http"
|
|
||||||
|
|
||||||
# This should include all of your mail domains, and main= should be your $TRAEFIK_DOMAIN
|
|
||||||
[[acme.domains]]
|
|
||||||
main = "mail.example.com"
|
|
||||||
sans = ["web.mail.example.com", "smtp.mail.example.com", "imap.mail.example.com"]
|
|
||||||
|
|
||||||
174
docs/reverse.rst
174
docs/reverse.rst
@@ -162,81 +162,127 @@ This will stop redirects (301 and 302) sent by the Webmail, nginx front and admi
|
|||||||
Traefik as reverse proxy
|
Traefik as reverse proxy
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
`Traefik`_ is a popular reverse-proxy aimed at containerized systems.
|
.. code-block:: yaml
|
||||||
As such, many may wish to integrate Mailu into a system which already uses Traefik as its sole ingress/reverse-proxy.
|
reverse-proxy:
|
||||||
|
# The official v2 Traefik docker image
|
||||||
|
image: traefik:v2.10
|
||||||
|
# Enables the web UI and tells Traefik to listen to docker
|
||||||
|
command:
|
||||||
|
- "--providers.docker=true"
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
- "--providers.docker.allowEmptyServices=true"
|
||||||
|
- "--entrypoints.web.address=:http"
|
||||||
|
- "--entrypoints.websecure.address=:https"
|
||||||
|
- "--entrypoints.smtp.address=:smtp"
|
||||||
|
- "--entrypoints.submission.address=:submission"
|
||||||
|
- "--entrypoints.submissions.address=:submissions"
|
||||||
|
- "--entrypoints.imap.address=:imap"
|
||||||
|
- "--entrypoints.imaps.address=:imaps"
|
||||||
|
- "--entrypoints.pop3.address=:pop3"
|
||||||
|
- "--entrypoints.pop3s.address=:pop3s"
|
||||||
|
- "--entrypoints.sieve.address=:sieve"
|
||||||
|
# - "--api.insecure=true"
|
||||||
|
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
|
||||||
|
- "--certificatesresolvers.myresolver.acme.email=test@example.com"
|
||||||
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
|
- "--log.level=DEBUG"
|
||||||
|
ports:
|
||||||
|
# The HTTP port
|
||||||
|
- "25:25"
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "465:465"
|
||||||
|
- "587:587"
|
||||||
|
- "993:993"
|
||||||
|
- "995:995"
|
||||||
|
- "110:110"
|
||||||
|
- "143:143"
|
||||||
|
- "4190:4190"
|
||||||
|
# The Web UI (enabled by --api.insecure=true)
|
||||||
|
#- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
# So that Traefik can listen to the Docker events
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
||||||
As the ``mailu/front`` container uses Nginx not only for ``HTTP`` forwarding, but also for the mail-protocols like ``SMTP``, ``IMAP``, etc
|
and then for front:
|
||||||
, we need to keep this container around even when using another ``HTTP`` reverse-proxy. Furthermore, Traefik is neither able to
|
|
||||||
forward non-HTTP, nor can it easily forward HTTPS-to-HTTPS.
|
|
||||||
|
|
||||||
This, however, means 3 things:
|
|
||||||
|
|
||||||
- ``mailu/front`` needs to listen internally on ``HTTP`` rather than ``HTTPS``
|
|
||||||
- ``mailu/front`` is not exposed to the outside world on ``HTTP``
|
|
||||||
- ``mailu/front`` still needs ``SSL`` certificates (here, we assume ``letsencrypt``) for a well-behaved mail service
|
|
||||||
|
|
||||||
This makes the setup with Traefik a bit harder: Traefik saves its certificates in a proprietary *JSON* file, which is not readable
|
|
||||||
by Nginx in the ``front``-container. To solve this, your ``acme.json`` needs to be exposed to the host or a ``docker-volume``.
|
|
||||||
It will then be read by a script in another container, which will dump the certificates as ``PEM`` files, readable for
|
|
||||||
Nginx. The ``front`` container will automatically reload Nginx whenever these certificates change.
|
|
||||||
|
|
||||||
To set this up, first set ``TLS_FLAVOR=mail`` in your ``.env``. This tells ``mailu/front`` not to try to request certificates using ``letsencrypt``,
|
|
||||||
but to read provided certificates, and use them only for mail-protocols, not for ``HTTP``.
|
|
||||||
Next, in your ``docker-compose.yml``, comment out the ``port`` lines of the ``front`` section for port ``…:80`` and ``…:443``.
|
|
||||||
Add the respective Traefik labels for your domain/configuration, like
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
labels:
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.port=80"
|
|
||||||
- "traefik.frontend.rule=Host:$TRAEFIK_DOMAIN"
|
|
||||||
|
|
||||||
.. note:: Please don’t forget to add ``TRAEFIK_DOMAIN=[...]`` TO YOUR ``.env``
|
# the second part is important to ensure Mailu can get certificates for the main FQDN
|
||||||
|
- "traefik.http.routers.web.rule=Host(`fqdn.example.com`) || Path(`/.well-known/acme-challenge/`)"
|
||||||
|
- "traefik.http.routers.web.entrypoints=web"
|
||||||
|
- "traefik.http.services.web.loadbalancer.server.port=80"
|
||||||
|
|
||||||
If your Traefik is configured to automatically request certificates from *letsencrypt*, then you’ll have a certificate
|
# add other FQDNS here too
|
||||||
for ``mail.your.example.com`` now. However, ``mail.your.example.com`` might only be the location where you want the Mailu web-interfaces
|
- "traefik.tcp.routers.websecure.rule=HostSNI(`fqdn.example.com`) || HostSNI(`autoconfig.example.com`) || HostSNI(`mta-sts.example.com`)"
|
||||||
to live — your mail should be sent/received from ``your.example.com``, and this is the ``DOMAIN`` in your ``.env``?
|
- "traefik.tcp.routers.websecure.entrypoints=websecure"
|
||||||
To support that use-case, Traefik can request ``SANs`` for your domain. The configuration for this will depend on your Traefik version.
|
- "traefik.tcp.routers.websecure.tls.passthrough=true"
|
||||||
|
- "traefik.tcp.routers.websecure.service=websecure"
|
||||||
|
- "traefik.tcp.services.websecure.loadbalancer.server.port=443"
|
||||||
|
- "traefik.tcp.services.websecure.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
Mailu must also be configured with the information what header is used by the reverse proxy for passing the remote
|
- "traefik.tcp.routers.smtp.rule=HostSNI(`*`)"
|
||||||
client IP. This is configured in mailu.env:
|
- "traefik.tcp.routers.smtp.entrypoints=smtp"
|
||||||
|
- "traefik.tcp.routers.smtp.service=smtp"
|
||||||
|
- "traefik.tcp.services.smtp.loadbalancer.server.port=25"
|
||||||
|
- "traefik.tcp.services.smtp.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
|
- "traefik.tcp.routers.submission.rule=HostSNI(`*`)"
|
||||||
|
- "traefik.tcp.routers.submission.entrypoints=submission"
|
||||||
|
- "traefik.tcp.routers.submission.service=submission"
|
||||||
|
- "traefik.tcp.services.submission.loadbalancer.server.port=587"
|
||||||
|
- "traefik.tcp.services.submission.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
|
- "traefik.tcp.routers.submissions.rule=HostSNI(`*`)"
|
||||||
|
- "traefik.tcp.routers.submissions.entrypoints=submissions"
|
||||||
|
- "traefik.tcp.routers.submissions.service=submissions"
|
||||||
|
- "traefik.tcp.services.submissions.loadbalancer.server.port=465"
|
||||||
|
- "traefik.tcp.services.submissions.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
|
- "traefik.tcp.routers.imap.rule=HostSNI(`*`)"
|
||||||
|
- "traefik.tcp.routers.imap.entrypoints=imap"
|
||||||
|
- "traefik.tcp.routers.imap.service=imap"
|
||||||
|
- "traefik.tcp.services.imap.loadbalancer.server.port=143"
|
||||||
|
- "traefik.tcp.services.imap.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
|
- "traefik.tcp.routers.imaps.rule=HostSNI(`*`)"
|
||||||
|
- "traefik.tcp.routers.imaps.entrypoints=imaps"
|
||||||
|
- "traefik.tcp.routers.imaps.service=imaps"
|
||||||
|
- "traefik.tcp.services.imaps.loadbalancer.server.port=993"
|
||||||
|
- "traefik.tcp.services.imaps.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
|
- "traefik.tcp.routers.pop3.rule=HostSNI(`*`)"
|
||||||
|
- "traefik.tcp.routers.pop3.entrypoints=pop3"
|
||||||
|
- "traefik.tcp.routers.pop3.service=pop3"
|
||||||
|
- "traefik.tcp.services.pop3.loadbalancer.server.port=110"
|
||||||
|
- "traefik.tcp.services.pop3.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
|
- "traefik.tcp.routers.pop3s.rule=HostSNI(`*`)"
|
||||||
|
- "traefik.tcp.routers.pop3s.entrypoints=pop3s"
|
||||||
|
- "traefik.tcp.routers.pop3s.service=pop3s"
|
||||||
|
- "traefik.tcp.services.pop3s.loadbalancer.server.port=995"
|
||||||
|
- "traefik.tcp.services.pop3s.loadbalancer.proxyProtocol.version=2"
|
||||||
|
|
||||||
|
- "traefik.tcp.routers.sieve.rule=HostSNI(`*`)"
|
||||||
|
- "traefik.tcp.routers.sieve.entrypoints=sieve"
|
||||||
|
- "traefik.tcp.routers.sieve.service=sieve"
|
||||||
|
- "traefik.tcp.services.sieve.loadbalancer.server.port=4190"
|
||||||
|
- "traefik.tcp.services.sieve.loadbalancer.proxyProtocol.version=2"
|
||||||
|
healthcheck:
|
||||||
|
test: ['NONE']
|
||||||
|
|
||||||
|
in mailu.env:
|
||||||
|
|
||||||
.. code-block:: docker
|
.. code-block:: docker
|
||||||
|
|
||||||
#mailu.env file
|
#mailu.env file
|
||||||
REAL_IP_HEADER=X-Real-Ip
|
REAL_IP_FROM=192.168.203.0/24
|
||||||
REAL_IP_FROM=x.x.x.x,y.y.y.y.y
|
PROXY_PROTOCOL=all-but-http
|
||||||
#x.x.x.x,y.y.y.y.y is the static IP address your reverse proxy uses for connecting to Mailu.
|
TRAEFIK_VERSION=v2
|
||||||
|
TLS_FLAVOR=mail-letsencrypt
|
||||||
For more information see the :ref:`configuration reference <reverse_proxy_headers>` for more information.
|
WEBROOT_REDIRECT=/sso/login
|
||||||
|
|
||||||
Traefik 2.x using labels configuration
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Add the appropriate labels for your domain(s) to the ``front`` container in ``docker-compose.yml``.
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
services:
|
|
||||||
front:
|
|
||||||
labels:
|
|
||||||
# Enable TLS
|
|
||||||
- "traefik.http.routers.mailu-secure.tls"
|
|
||||||
# Your main domain
|
|
||||||
- "traefik.http.routers.mailu-secure.tls.domains[0].main=your.example.com"
|
|
||||||
# Optional SANs for your main domain
|
|
||||||
- "traefik.http.routers.mailu-secure.tls.domains[0].sans=mail.your.example.com,webmail.your.example.com,smtp.your.example.com"
|
|
||||||
# Optionally add other domains
|
|
||||||
- "traefik.http.routers.mailu-secure.tls.domains[1].main=mail.other.example.com"
|
|
||||||
- "traefik.http.routers.mailu-secure.tls.domains[1].sans=mail2.other.example.com,mail3.other.example.com"
|
|
||||||
# Your ACME certificate resolver
|
|
||||||
- "traefik.http.routers.mailu-secure.tls.certResolver=foo"
|
|
||||||
|
|
||||||
Of course, be sure to define the Certificate Resolver ``foo`` in the static configuration as well.
|
|
||||||
|
|
||||||
Alternatively, you can define SANs in the Traefik static configuration using routers, or in the static configuration using entrypoints.
|
|
||||||
Refer to the Traefik documentation for more details.
|
|
||||||
|
|
||||||
.. _`Traefik`: https://traefik.io/
|
.. _`Traefik`: https://traefik.io/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user