1
0
mirror of https://github.com/Mailu/Mailu.git synced 2025-01-18 03:21:36 +02:00
This commit is contained in:
Florent Daigniere 2023-08-09 15:38:27 +02:00
parent f3cd401450
commit b7e7f0d8b6
3 changed files with 110 additions and 241 deletions

View File

@ -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

View File

@ -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"]

View File

@ -162,81 +162,127 @@ This will stop redirects (301 and 302) sent by the Webmail, nginx front and admi
Traefik as reverse proxy
------------------------
`Traefik`_ is a popular reverse-proxy aimed at containerized systems.
As such, many may wish to integrate Mailu into a system which already uses Traefik as its sole ingress/reverse-proxy.
.. code-block:: yaml
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
, 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
and then for front:
.. code-block:: yaml
labels:
labels:
- "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
for ``mail.your.example.com`` now. However, ``mail.your.example.com`` might only be the location where you want the Mailu web-interfaces
to live — your mail should be sent/received from ``your.example.com``, and this is the ``DOMAIN`` in your ``.env``?
To support that use-case, Traefik can request ``SANs`` for your domain. The configuration for this will depend on your Traefik version.
# add other FQDNS here too
- "traefik.tcp.routers.websecure.rule=HostSNI(`fqdn.example.com`) || HostSNI(`autoconfig.example.com`) || HostSNI(`mta-sts.example.com`)"
- "traefik.tcp.routers.websecure.entrypoints=websecure"
- "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
client IP. This is configured in mailu.env:
- "traefik.tcp.routers.smtp.rule=HostSNI(`*`)"
- "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
#mailu.env file
REAL_IP_HEADER=X-Real-Ip
REAL_IP_FROM=x.x.x.x,y.y.y.y.y
#x.x.x.x,y.y.y.y.y is the static IP address your reverse proxy uses for connecting to Mailu.
For more information see the :ref:`configuration reference <reverse_proxy_headers>` for more information.
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.
REAL_IP_FROM=192.168.203.0/24
PROXY_PROTOCOL=all-but-http
TRAEFIK_VERSION=v2
TLS_FLAVOR=mail-letsencrypt
WEBROOT_REDIRECT=/sso/login
.. _`Traefik`: https://traefik.io/