One of Mailu's use cases is as part of a larger services platform, where maybe
One of Mailu's use cases is as part of a larger services platform, where maybe
other Web services are available than just Mailu Webmail and Admin interfaces.
other Web services are available than just Mailu Webmail and Admin interfaces.
In such a configuration, one would usually run a frontend reverse proxy to serve all
In such a configuration, one would usually run a frontend reverse proxy to serve all
Web contents based on criteria like the requested hostname (virtual hosts)
Web contents based on criteria like the requested hostname (virtual hosts)
and/or the requested path.
and/or the requested path.
The Mailu Admin Web frontend is disabled in the default setup for security reasons,
The Mailu Admin Web frontend is disabled in the default setup for security reasons,
it is however expected that most users will enable it at some point. Also, due
it is however expected that most users will enable it at some point. Also, due
to the Docker Compose configuration structure, it is impossible for us to facilitate
to the Docker Compose configuration structure, it is impossible for us to facilitate
disabling the Web frontend with a configuration variable. This guide was written to
disabling the Web frontend with a configuration variable. This guide was written to
help users setup such an architecture.
help users setup such an architecture.
There are basically three options, from the most to the least recommended one:
There are basically three options, from the most to the least recommended one:
@ -22,13 +22,13 @@ There are basically three options, from the most to the least recommended one:
All options will require that you modify the ``docker-compose.yml`` and ``mailu.env`` file.
All options will require that you modify the ``docker-compose.yml`` and ``mailu.env`` file.
Mailu must also be configured with the information what header is used by the reverse proxy for passing the remote client IP.
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 the mailu.env file. See the :ref:`configuration reference <reverse_proxy_headers>` for more information.
This is configured in the mailu.env file. See the :ref:`configuration reference <reverse_proxy_headers>` for more information.
Have Mailu Web frontend listen locally
Have Mailu Web frontend listen locally
--------------------------------------
--------------------------------------
The simplest and safest option is to modify the port forwards for Mailu Web frontend and have your own frontend point there.
The simplest and safest option is to modify the port forwards for Mailu Web frontend and have your own frontend point there.
For instance, in the ``front`` section of Mailu ``docker-compose.yml``, use local ports 8080 and 8443 respectively for HTTP and HTTPS:
For instance, in the ``front`` section of Mailu ``docker-compose.yml``, use local ports 8080 and 8443 respectively for HTTP and HTTPS:
..code-block:: yaml
..code-block:: yaml
@ -45,7 +45,7 @@ For instance, in the ``front`` section of Mailu ``docker-compose.yml``, use loca
volumes:
volumes:
- "$ROOT/certs:/certs"
- "$ROOT/certs:/certs"
Then on your own frontend, point to these local ports. In practice, you only need to point to the HTTPS port
Then on your own frontend, point to these local ports. In practice, you only need to point to the HTTPS port
(as the HTTP port simply redirects there). Here is an example Nginx configuration:
(as the HTTP port simply redirects there). Here is an example Nginx configuration:
..code-block:: nginx
..code-block:: nginx
@ -68,19 +68,19 @@ Then on your own frontend, point to these local ports. In practice, you only nee
#mailu.env file
#mailu.env file
REAL_IP_HEADER=X-Real-IP
REAL_IP_HEADER=X-Real-IP
REAL_IP_FROM=x.x.x.x,y.y.y.y.y
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.
#x.x.x.x,y.y.y.y.y is the static IP address your reverse proxy uses for connecting to Mailu.
Because the admin interface is served as ``/admin``, the Webmail as ``/webmail``, the single sign on page as ``/sso``, webdav as ``/webdav``, the client-autoconfiguration and the static files endpoint as ``/static``, you may also want to use a single virtual host and serve other applications (still Nginx):
Because the admin interface is served as ``/admin``, the RESTful API as ``/api``, the Webmail as ``/webmail``, the single sign on page as ``/sso``, webdav as ``/webdav``, the client-autoconfiguration and the static files endpoint as ``/static``, you may also want to use a single virtual host and serve other applications (still Nginx):
@ -103,13 +103,13 @@ Because the admin interface is served as ``/admin``, the Webmail as ``/webmail``
..note:: Please don’t add a ``/`` at the end of the location pattern or all your redirects will fail with 404 because the ``/`` would be missing, and you would have to add it manually to move on
..note:: Please don’t add a ``/`` at the end of the location pattern or all your redirects will fail with 404 because the ``/`` would be missing, and you would have to add it manually to move on
..code-block:: docker
..code-block:: docker
#mailu.env file
#mailu.env file
REAL_IP_HEADER=X-Real-IP
REAL_IP_HEADER=X-Real-IP
REAL_IP_FROM=x.x.x.x,y.y.y.y.y
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.
#x.x.x.x,y.y.y.y.y is the static IP address your reverse proxy uses for connecting to Mailu.
Finally, you might want to serve the admin interface on a separate virtual host but not expose the admin container
Finally, you might want to serve the admin interface on a separate virtual host but not expose the admin container
directly (have your own HTTPS virtual hosts on top of Mailu, one public for the Webmail and one internal for administration for instance).
directly (have your own HTTPS virtual hosts on top of Mailu, one public for the Webmail and one internal for administration for instance).
Here is an example configuration :
Here is an example configuration :
@ -147,7 +147,7 @@ Here is an example configuration :
#mailu.env file
#mailu.env file
REAL_IP_HEADER=X-Real-IP
REAL_IP_HEADER=X-Real-IP
REAL_IP_FROM=x.x.x.x,y.y.y.y.y
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.
#x.x.x.x,y.y.y.y.y is the static IP address your reverse proxy uses for connecting to Mailu.
Depending on how you access the front server, you might want to add a ``proxy_redirect`` directive to your ``location`` blocks:
Depending on how you access the front server, you might want to add a ``proxy_redirect`` directive to your ``location`` blocks:
@ -166,8 +166,8 @@ Traefik as reverse proxy
As such, many may wish to integrate Mailu into a system which already uses Traefik as its sole ingress/reverse-proxy.
As such, many may wish to integrate Mailu into a system which already uses Traefik as its sole ingress/reverse-proxy.
As the ``mailu/front`` container uses Nginx not only for ``HTTP`` forwarding, but also for the mail-protocols like ``SMTP``, ``IMAP``, etc
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
, 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.
forward non-HTTP, nor can it easily forward HTTPS-to-HTTPS.
This, however, means 3 things:
This, however, means 3 things:
@ -175,9 +175,9 @@ This, however, means 3 things:
- ``mailu/front`` is not exposed to the outside world on ``HTTP``
- ``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
- ``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
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``.
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
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.
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``,
To set this up, first set ``TLS_FLAVOR=mail`` in your ``.env``. This tells ``mailu/front`` not to try to request certificates using ``letsencrypt``,
@ -194,20 +194,20 @@ Add the respective Traefik labels for your domain/configuration, like
..note:: Please don’t forget to add ``TRAEFIK_DOMAIN=[...]`` TO YOUR ``.env``
..note:: Please don’t forget to add ``TRAEFIK_DOMAIN=[...]`` TO YOUR ``.env``
If your Traefik is configured to automatically request certificates from *letsencrypt*, then you’ll have a certificate
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
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 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.
To support that use-case, Traefik can request ``SANs`` for your domain. The configuration for this will depend on your Traefik version.
Mailu must also be configured with the information what header is used by the reverse proxy for passing the remote
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:
client IP. This is configured in mailu.env:
..code-block:: docker
..code-block:: docker
#mailu.env file
#mailu.env file
REAL_IP_HEADER=X-Real-Ip
REAL_IP_HEADER=X-Real-Ip
REAL_IP_FROM=x.x.x.x,y.y.y.y.y
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.
#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.
For more information see the :ref:`configuration reference <reverse_proxy_headers>` for more information.
@ -235,7 +235,7 @@ Add the appropriate labels for your domain(s) to the ``front`` container in ``do
Of course, be sure to define the Certificate Resolver ``foo`` in the static configuration as well.
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.
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.
Refer to the Traefik documentation for more details.