Merge remote-tracking branch 'upstream/master' into feat-unbound-dns
This commit is contained in:
@@ -2,13 +2,21 @@ FROM python:3-alpine
|
||||
|
||||
COPY requirements.txt /requirements.txt
|
||||
|
||||
ARG version=master
|
||||
ENV VERSION=$version
|
||||
|
||||
RUN pip install -r /requirements.txt \
|
||||
&& apk add --no-cache nginx \
|
||||
&& apk add --no-cache nginx curl \
|
||||
&& mkdir /run/nginx
|
||||
|
||||
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY . /docs
|
||||
|
||||
RUN sphinx-build /docs /build
|
||||
RUN mkdir -p /build/$VERSION \
|
||||
&& sphinx-build /docs /build/$VERSION
|
||||
|
||||
CMD nginx -g "daemon off;"
|
||||
EXPOSE 80/tcp
|
||||
|
||||
CMD nginx -g "daemon off;"
|
||||
|
||||
HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1
|
||||
|
||||
9
docs/_templates/layout.html
vendored
9
docs/_templates/layout.html
vendored
@@ -1,2 +1,9 @@
|
||||
{% set version=github_version %}
|
||||
{% extends "!layout.html" %}
|
||||
{% block document %}
|
||||
{% if version != stable_version %}
|
||||
<div class="wy-alert info">
|
||||
<p>You are currently browsing documentation for the <b>{{ version }}</b> branch. Documentation for the stable <b>{{ stable_version }}</b> branch can be found <a href="/{{ stable_version }}/">here</a>.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
|
||||
4
docs/_templates/page.html
vendored
4
docs/_templates/page.html
vendored
@@ -1,4 +0,0 @@
|
||||
{%- extends "layout.html" %}
|
||||
{% block body %}
|
||||
{{ body|replace("VERSION_TAG", version) }}
|
||||
{% endblock %}
|
||||
16
docs/_templates/versions.html
vendored
Normal file
16
docs/_templates/versions.html
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
|
||||
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||
<span class="fa fa-book"> Versions</span>
|
||||
v: {{ version }}
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div class="rst-other-versions">
|
||||
<dl>
|
||||
<dt>{{ _('Versions') }}</dt>
|
||||
{% for slug, url in versions %}
|
||||
<dd><a href="{{ url }}">{{ slug }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -120,12 +120,18 @@ WEBSITE=https://mailu.io
|
||||
# Advanced settings
|
||||
###################################
|
||||
|
||||
# Log driver for front service. Possible values:
|
||||
# json-file (default)
|
||||
# journald (On systemd platforms, useful for Fail2Ban integration)
|
||||
# syslog (Non systemd platforms, Fail2Ban integration. Disables `docker-compose log` for front!)
|
||||
LOG_DRIVER=json-file
|
||||
|
||||
# Docker-compose project name, this will prepended to containers names.
|
||||
COMPOSE_PROJECT_NAME=mailu
|
||||
|
||||
# Default password scheme used for newly created accounts and changed passwords
|
||||
# (value: SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT)
|
||||
PASSWORD_SCHEME=SHA512-CRYPT
|
||||
# (value: PBKDF2, BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT)
|
||||
PASSWORD_SCHEME=PBKDF2
|
||||
|
||||
# Header to take the real ip from
|
||||
REAL_IP_HEADER=
|
||||
|
||||
@@ -6,6 +6,8 @@ services:
|
||||
image: mailu/nginx:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
logging:
|
||||
driver: $LOG_DRIVER
|
||||
ports:
|
||||
- "$BIND_ADDRESS4:80:80"
|
||||
- "$BIND_ADDRESS4:443:443"
|
||||
@@ -54,7 +56,6 @@ services:
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
- "$ROOT/mail:/mail"
|
||||
- "$ROOT/overrides:/overrides"
|
||||
depends_on:
|
||||
@@ -68,7 +69,6 @@ services:
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
- "$ROOT/overrides:/overrides"
|
||||
depends_on:
|
||||
- front
|
||||
@@ -142,8 +142,6 @@ services:
|
||||
image: mailu/fetchmail:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
depends_on:
|
||||
- unbound
|
||||
dns:
|
||||
@@ -156,3 +154,4 @@ networks:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: 10.177.20.0/24
|
||||
|
||||
|
||||
@@ -26,36 +26,61 @@ for the ``VERSION_TAG`` branch, use:
|
||||
wget https://mailu.io/VERSION_TAG/_downloads/docker-compose.yml
|
||||
wget https://mailu.io/VERSION_TAG/_downloads/.env
|
||||
|
||||
Then open the ``.env`` file to setup the mail server. Modify the ``ROOT`` setting
|
||||
to match your setup directory if different from ``/mailu``.
|
||||
Important configuration variables
|
||||
---------------------------------
|
||||
|
||||
Modify the ``VERSION`` configuration in the ``.env`` file to reflect the version you picked.
|
||||
Open the ``.env`` file and review the following variable settings:
|
||||
|
||||
Set the common configuration values
|
||||
-----------------------------------
|
||||
- Change ``ROOT`` if you have your setup directory in a different location then ``/mailu``.
|
||||
- Check ``VERSION`` to reflect the version you picked. (``master`` or ``1.5``).
|
||||
|
||||
Open the ``.env`` file and set configuration settings after reading the configuration
|
||||
documentation. Some settings are specific to the Docker Compose setup.
|
||||
Make sure to read the comments in the file and instructions from the :ref:`common_cfg` section.
|
||||
|
||||
Modify ``BIND_ADDRESS4`` to match the public IP address assigned to your server.
|
||||
This address should be configured on one of the network interfaces of the server.
|
||||
If the address is not configured directly (NAT) on any of the network interfaces or if
|
||||
you would simply like the server to listen on all interfaces, use ``0.0.0.0``.
|
||||
|
||||
Modify ``BIND_ADDRESS6`` to match the public IPv6 address assigned to your server.
|
||||
The behavior is identical to ``BIND_ADDRESS4``.
|
||||
TLS certificates
|
||||
````````````````
|
||||
|
||||
Set the ``TLS_FLAVOR`` to one of the following
|
||||
values:
|
||||
|
||||
- ``cert`` is the default and requires certificates to be setup manually;
|
||||
- ``letsencrypt`` will use the Letsencrypt! CA to generate automatic ceriticates;
|
||||
- ``letsencrypt`` will use the *Letsencrypt!* CA to generate automatic ceriticates;
|
||||
- ``mail`` is similar to ``cert`` except that TLS will only be served for
|
||||
emails (IMAP and SMTP), not HTTP (use it behind reverse proxies);
|
||||
- ``mail-letsencrypt`` is similar to ``letsencrypt`` except that TLS will only be served for
|
||||
emails (IMAP and SMTP), not HTTP (use it behind reverse proxies);
|
||||
- ``notls`` will disable TLS, this is not recommended except for testing.
|
||||
|
||||
.. note::
|
||||
|
||||
When using *Letsencrypt!* you have to make sure that the DNS ``A`` and ``AAAA`` records for the
|
||||
all hostnames mentioned in the ``HOSTNAMES`` variable match with the ip adresses of you server.
|
||||
Or else certificate generation will fail! See also: :ref:`dns_setup`.
|
||||
|
||||
Bind address
|
||||
````````````
|
||||
|
||||
Modify ``BIND_ADDRESS4`` and ``BIND_ADDRESS6`` to match the public IP addresses assigned to your server. For IPv6 you will need the ``<global>`` scope address.
|
||||
|
||||
You can find those addresses by running the following:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
[root@mailu ~]$ ifconfig eth0
|
||||
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 125.189.138.127 netmask 255.255.255.0 broadcast 5.189.138.255
|
||||
inet6 fd21:aab2:717c:cc5a::1 prefixlen 64 scopeid 0x0<global>
|
||||
inet6 fe2f:2a73:43a8:7a1b::1 prefixlen 64 scopeid 0x20<link>
|
||||
ether 00:50:56:3c:b2:23 txqueuelen 1000 (Ethernet)
|
||||
RX packets 174866612 bytes 127773819607 (118.9 GiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 19905110 bytes 2191519656 (2.0 GiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
If the address is not configured directly (NAT) on any of the network interfaces or if
|
||||
you would simply like the server to listen on all interfaces, use ``0.0.0.0`` and ``::``. Note that running is this mode is not supported and can lead to `issues`_.
|
||||
|
||||
.. _issues: https://github.com/Mailu/Mailu/issues/641
|
||||
|
||||
Enable optional features
|
||||
------------------------
|
||||
|
||||
|
||||
13
docs/conf.py
13
docs/conf.py
@@ -2,6 +2,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
extensions = ['sphinx.ext.imgmath', 'sphinx.ext.viewcode']
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
@@ -9,9 +11,9 @@ master_doc = 'index'
|
||||
project = 'Mailu'
|
||||
copyright = '2018, Mailu authors'
|
||||
author = 'Mailu authors'
|
||||
version = release = 'latest'
|
||||
version = release = os.environ.get('VERSION', 'master')
|
||||
language = None
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'Dockerfile', 'docker-compose.yml']
|
||||
pygments_style = 'sphinx'
|
||||
todo_include_todos = False
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
@@ -33,6 +35,11 @@ html_context = {
|
||||
'display_github': True,
|
||||
'github_user': 'mailu',
|
||||
'github_repo': 'mailu',
|
||||
'github_version': 'master',
|
||||
'github_version': version,
|
||||
'stable_version': '1.5',
|
||||
'versions': [
|
||||
('1.5', '/1.5/'),
|
||||
('master', '/master/')
|
||||
],
|
||||
'conf_py_path': '/docs/'
|
||||
}
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
Mailu configuration settings
|
||||
============================
|
||||
|
||||
.. _common_cfg:
|
||||
|
||||
Common configuration
|
||||
--------------------
|
||||
|
||||
The ``SECRET_KEY`` **must** be changed for every setup and set to a 16 bytes
|
||||
randomly generated value. It is intended to secure authentication cookies
|
||||
among other critical uses.
|
||||
among other critical uses. This can be generated with a utility such as *pwgen*,
|
||||
which can be installed on most Linux systems:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
apt-get install pwgen
|
||||
pwgen 16 1
|
||||
|
||||
The ``DOMAIN`` holds the main e-mail domain for the server. This email domain
|
||||
is used for bounce emails, for generating the postmaster email and other
|
||||
|
||||
@@ -5,39 +5,51 @@ Docker containers
|
||||
-----------------
|
||||
|
||||
The development environment is quite similar to the production one. You should always use
|
||||
the ``master`` version when developing. Simply add a build directive to the images
|
||||
you are working on in the ``docker-compose.yml``:
|
||||
the ``master`` version when developing.
|
||||
|
||||
.. code-block:: yaml
|
||||
Building images
|
||||
```````````````
|
||||
|
||||
webdav:
|
||||
build: ./optional/radicale
|
||||
image: mailu/$WEBDAV:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/dav:/data"
|
||||
|
||||
admin:
|
||||
build: ./core/admin
|
||||
image: mailu/admin:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
- "$ROOT/dkim:/dkim"
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
depends_on:
|
||||
- redis
|
||||
|
||||
|
||||
The build these containers.
|
||||
We supply a separate ``test/build.yml`` file for
|
||||
convenience. To build all Mailu containers:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker-compose build admin webdav
|
||||
docker-compose -f tests/build.yml build
|
||||
|
||||
Then you can simply start the stack as normal, newly-built images will be used.
|
||||
The ``build.yml`` file has two variables:
|
||||
|
||||
#. ``$DOCKER_ORG``: First part of the image tag. Defaults to *mailu* and needs to be changed
|
||||
only when pushing to your own Docker hub account.
|
||||
#. ``$VERSION``: Last part of the image tag. Defaults to *local* to differentiate from pulled
|
||||
images.
|
||||
|
||||
To re-build only specific containers at a later time.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker-compose -f tests/build.yml build admin webdav
|
||||
|
||||
If you have to push the images to Docker Hub for testing in Docker Swarm or a remote
|
||||
host, you have to define ``DOCKER_ORG`` (usually your Docker user-name) and login to
|
||||
the hub.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker login
|
||||
Username: Foo
|
||||
Password: Bar
|
||||
export DOCKER_ORG="Foo"
|
||||
export VERSION="feat-extra-app"
|
||||
docker-compose -f tests/build.yml build
|
||||
docker-compose -f tests/build.yml push
|
||||
|
||||
Running containers
|
||||
``````````````````
|
||||
|
||||
To run the newly created images: ``cd`` to your project directory. Edit ``.env`` to set
|
||||
``VERSION`` to the same value as used during the build, which defaults to ``local``.
|
||||
After that you can run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -101,7 +113,8 @@ Documentation is maintained in the ``docs`` directory and are maintained as `reS
|
||||
docker build -t docs docs
|
||||
docker run -p 127.0.0.1:8080:80 docs
|
||||
|
||||
You can now read the local documentation by navigating to http://localhost:8080.
|
||||
In a local build Docker always assumes the version to be master.
|
||||
You can read the local documentation by navigating to http://localhost:8080/master.
|
||||
|
||||
.. note:: After modifying the documentation, the image needs to be rebuild and the container restarted for the changes to become visible.
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _dns_setup:
|
||||
|
||||
Setting up your DNS
|
||||
===================
|
||||
|
||||
|
||||
21
docs/docker-compose.yml
Normal file
21
docs/docker-compose.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
version: '3'
|
||||
|
||||
|
||||
services:
|
||||
docs_master:
|
||||
image: mailu/docs:master
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.port=80
|
||||
- traefik.main.frontend.rule=Host:${hostname};PathPrefix:/master/
|
||||
|
||||
docs_15:
|
||||
image: mailu/docs:1.5
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.port=80
|
||||
- traefik.root.frontend.redirect.regex=.*
|
||||
- traefik.root.frontend.redirect.replacement=/1.5/
|
||||
- traefik.root.frontend.rule=Host:${hostname};PathPrefix:/
|
||||
- traefik.main.frontend.rule=Host:${hostname};PathPrefix:/1.5/
|
||||
|
||||
@@ -55,7 +55,7 @@ the version of Mailu that you are running.
|
||||
configuration
|
||||
compose/requirements
|
||||
compose/setup
|
||||
kubernetes/stable/index
|
||||
kubernetes/mailu/index
|
||||
dns
|
||||
reverse
|
||||
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
# Install Mailu master on kubernetes
|
||||
|
||||
## Prequisites
|
||||
|
||||
### Structure
|
||||
|
||||
There's chosen to have a double NGINX stack for Mailu, this way the main ingress can still be used to access other websites/domains on your cluster. This is the current structure:
|
||||
|
||||
- `NGINX Ingress controller`: Listens to the nodes ports 80 & 443 and directly forwards all TCP traffic on the E-amail ports (993,143,25,587,...). This is because this `DaemonSet` already consumes ports 80 & 443 and uses `hostNetwork: true`
|
||||
- `Cert manager`: Creates automatic Lets Encrypt certificates based on an `Ingress`-objects domain name.
|
||||
- `Mailu NGINX Front container`: This container receives all the mail traffic forwarded from the ingress controller. The web traffic is also forwarded based on an ingress
|
||||
- `Mailu components`: All Mailu components are split into separate files to make them more
|
||||
|
||||
### What you need
|
||||
- A working Kubernetes cluster (tested with 1.10.5)
|
||||
- A working [cert-manager](https://github.com/jetstack/cert-manager) installation
|
||||
- A working nginx-ingress controller needed for the lets-encrypt certificates. You can find those files in the `nginx` subfolder
|
||||
|
||||
#### Cert manager
|
||||
|
||||
The `Cert-manager` is quite easy to deploy using Helm when reading the [docs](https://cert-manager.readthedocs.io/en/latest/getting-started/2-installing.html).
|
||||
After booting the `Cert-manager` you'll need a `ClusterIssuer` which takes care of all required certificates through `Ingress` items. An example:
|
||||
|
||||
```yaml
|
||||
apiVersion: certmanager.k8s.io/v1alpha1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
email: something@example.com
|
||||
http01: {}
|
||||
privateKeySecretRef:
|
||||
key: ""
|
||||
name: letsencrypt-stage
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
```
|
||||
|
||||
## Deploying Mailu
|
||||
|
||||
All manifests can be found in the `mailu` subdirectory. All commands below need to be run from this subdirectory
|
||||
|
||||
### Personalization
|
||||
- All services run in the same namespace, currently `mailu-mailserver`. So if you want to use a different one, change the `namespace` value in **every** file
|
||||
- Check the `storage-class` field in the `pvc.yaml` file, you can also change the sizes to your liking. Note that you need `RWX` (read-write-many) and `RWO` (read-write-once) storageclasses.
|
||||
- Check the `configmap.yaml` and adapt it to your needs. Be sure to check the kubernetes DNS values at the end (if you use a different namespace)
|
||||
- Check the `ingress-ssl.yaml` and change it to the domain you want (this is for the kubernetes ingress controller, it will forward to `mailu/nginx` a.k.a. the `front` pod)
|
||||
|
||||
## Installation
|
||||
First run the command to start Mailu:
|
||||
|
||||
```bash
|
||||
kubectl create -f rbac.yaml
|
||||
kubectl create -f configmap.yaml
|
||||
kubectl create -f pvc.yaml
|
||||
kubectl create -f ingress-ssl.yaml
|
||||
kubectl create -f redis.yaml
|
||||
kubectl create -f front.yaml
|
||||
kubectl create -f webmail.yaml
|
||||
kubectl create -f imap.yaml
|
||||
kubectl create -f security.yaml
|
||||
kubectl create -f smtp.yaml
|
||||
kubectl create -f fetchmail.yaml
|
||||
kubectl create -f admin.yaml
|
||||
kubectl create -f webdav.yaml
|
||||
```
|
||||
|
||||
## Create the first admin account
|
||||
|
||||
When the cluster is online you need to create you master user to access `https://mail.example.com/admin`.
|
||||
Enter the main `admin` pod to create the root account:
|
||||
|
||||
```bash
|
||||
kubectl -n mailu-mailserver get po
|
||||
kubectl -n mailu-mailserver exec -it mailu-admin-.... /bin/sh
|
||||
```
|
||||
|
||||
And in the pod run the following command. The command uses following entries:
|
||||
- `admin` Make it an admin user
|
||||
- `root` The first part of the e-mail adres (ROOT@example.com)
|
||||
- `example.com` the domain appendix
|
||||
- `password` the chosen password for the user
|
||||
|
||||
```bash
|
||||
python manage.py admin root example.com password
|
||||
```
|
||||
|
||||
Now you should be able to login on the mail account: `https://mail.example.com/admin`
|
||||
|
||||
## Adaptations
|
||||
|
||||
### Postfix
|
||||
I noticed you need an override for the `postfix` server in order to be able to send mail. I noticed Google wasn't able to deliver mail to my account and it had to do with the `smtpd_authorized_xclient_hosts` value in the config file. The config can be read [here](https://github.com/hacor/Mailu/blob/master/core/postfix/conf/main.cf#L35) and is pointing to a single IP of the service. But the requests come from the host IPs (the NGINX Ingress proxy) and they don't use the service specific IP.
|
||||
|
||||
Enter the `postfix` pod:
|
||||
|
||||
```bash
|
||||
kubectl -n mailu-mailserver get po
|
||||
kubectl -n mailu-mailserver exec -it mailu-smtp-.... /bin/sh
|
||||
```
|
||||
|
||||
Now you're in the pod, create an override file like so:
|
||||
|
||||
```bash
|
||||
vi /overrides/postfix.cf
|
||||
```
|
||||
|
||||
And give it the following contents, off course replacing `10.2.0.0/16` with the CIDR of your pod range. This way the NGINX pods can also restart and your mail server will still operate
|
||||
|
||||
```bash
|
||||
not_needed = true
|
||||
smtpd_authorized_xclient_hosts = 10.2.0.0/16
|
||||
```
|
||||
|
||||
The first line seems stupid, but is needed because its pasted after a #, so from the second line we're really in action.
|
||||
Save and close the file and exit. Now you need to delete the pod in order to recreate the config file.
|
||||
|
||||
```bash
|
||||
kubectl -n mailu-mailserver delete po/mailu-smtp-....
|
||||
```
|
||||
|
||||
### Dovecot
|
||||
- If you are using Dovecot on a shared file system (Glusterfs, NFS,...), you need to create a special override otherwise a lot of indexing errors will occur on your Dovecot pod.
|
||||
- I also higher the number of max connections per IP. Now it's limited to 10.
|
||||
Enter the dovecot pod:
|
||||
|
||||
```bash
|
||||
kubectl -n mailu-mailserver get po
|
||||
kubectl -n mailu-mailserver exec -it mailu-imap-.... /bin/sh
|
||||
```
|
||||
|
||||
Create the file `/overrides/dovecot.conf`
|
||||
|
||||
```bash
|
||||
vi /overrides/dovecot.conf
|
||||
```
|
||||
|
||||
And enter following contents:
|
||||
```bash
|
||||
mail_nfs_index = yes
|
||||
mail_nfs_storage = yes
|
||||
mail_fsync = always
|
||||
mmap_disable = yes
|
||||
mail_max_userip_connections=100
|
||||
```
|
||||
|
||||
Save and close the file and delete the imap pod to get it recreated.
|
||||
|
||||
```bash
|
||||
kubectl -n mailu-mailserver delete po/mailu-imap-....
|
||||
```
|
||||
|
||||
Wait for the pod to recreate and you're online!
|
||||
Happy mailing!
|
||||
|
||||
Wait for the pod to recreate and you're online!
|
||||
Happy mailing!
|
||||
@@ -1,32 +0,0 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-ssl-ingress
|
||||
namespace: mailu-mailserver
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: tectonic
|
||||
kubernetes.io/tls-acme: "true"
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||
ingress.kubernetes.io/ssl-redirect: "true"
|
||||
# Replace letsencrypt-prod with the name of the certificate issuer
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
|
||||
#ingress.kubernetes.io/rewrite-target: "/"
|
||||
#ingress.kubernetes.io/app-root: "/ui"
|
||||
#ingress.kubernetes.io/follow-redirects: "true"
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "mail.example.com"
|
||||
secretName: letsencrypt-certs-all # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "mail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/"
|
||||
backend:
|
||||
serviceName: front
|
||||
servicePort: 80
|
||||
86
docs/kubernetes/mailu/admin-ingress.yaml
Normal file
86
docs/kubernetes/mailu/admin-ingress.yaml
Normal file
@@ -0,0 +1,86 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-admin-ingress
|
||||
namespace: mailu-mailserver
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-stage
|
||||
ingress.kubernetes.io/permanent-redirect: "https://mail.example.com/admin/ui/"
|
||||
ingress.kubernetes.io/follow-redirects: "true"
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "mail.example.com"
|
||||
secretName: letsencrypt-certs-all # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "mail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/admin"
|
||||
backend:
|
||||
serviceName: admin
|
||||
servicePort: 80
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-admin-ui-ingress
|
||||
namespace: mailu-mailserver
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-stage
|
||||
ingress.kubernetes.io/rewrite-target: "/ui"
|
||||
ingress.kubernetes.io/configuration-snippet: |
|
||||
proxy_set_header X-Forwarded-Prefix /admin;
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "mail.example.com"
|
||||
secretName: letsencrypt-certs-all # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "mail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/admin/ui"
|
||||
backend:
|
||||
serviceName: admin
|
||||
servicePort: 80
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-admin-static-ingress
|
||||
namespace: mailu-mailserver
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-stage
|
||||
ingress.kubernetes.io/rewrite-target: "/static"
|
||||
ingress.kubernetes.io/configuration-snippet: |
|
||||
proxy_set_header X-Forwarded-Prefix /admin;
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "mail.example.com"
|
||||
secretName: letsencrypt-certs-all # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "mail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/admin/static"
|
||||
backend:
|
||||
serviceName: admin
|
||||
servicePort: 80
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
@@ -21,7 +21,7 @@
|
||||
VERSION: "master"
|
||||
|
||||
# Set to a randomly generated 16 bytes string
|
||||
SECRET_KEY: "YourKeyHere"
|
||||
SECRET_KEY: "MySup3rS3cr3tPas"
|
||||
|
||||
# Address where listening ports should bind
|
||||
BIND_ADDRESS4: "127.0.0.1"
|
||||
@@ -45,6 +45,14 @@
|
||||
# Opt-out of statistics, replace with "True" to opt out
|
||||
DISABLE_STATISTICS: "False"
|
||||
|
||||
###################################
|
||||
# Kubernetes configuration
|
||||
###################################
|
||||
|
||||
# Use Kubernetes Ingress Controller to handle all actions on port 80 and 443
|
||||
# This way we can make use of the advantages of the cert-manager deployment
|
||||
KUBERNETES_INGRESS: "true"
|
||||
|
||||
###################################
|
||||
# Optional features
|
||||
###################################
|
||||
@@ -71,19 +79,18 @@
|
||||
# Default: accept messages up to 50MB
|
||||
MESSAGE_SIZE_LIMIT: "50000000"
|
||||
|
||||
# Networks granted relay permissions, make sure that you include your Docker
|
||||
# internal network (default to 172.17.0.0/16)
|
||||
# For kubernetes this is the CIDR of the pod network
|
||||
RELAYNETS: "10.2.0.0/16"
|
||||
POD_ADDRESS_RANGE: "10.2.0.0/16"
|
||||
|
||||
|
||||
# Will relay all outgoing mails if configured
|
||||
#RELAYHOST=
|
||||
|
||||
# This part is needed for the XCLIENT login for postfix. This should be the POD ADDRESS range
|
||||
FRONT_ADDRESS: "front.mailu-mailserver.svc.cluster.local"
|
||||
|
||||
# This value is needed by the webmail to find the correct imap backend
|
||||
IMAP_ADDRESS: "imap.mailu-mailserver.svc.cluster.local"
|
||||
|
||||
# This value is used by Dovecot to find the Redis server in the cluster
|
||||
REDIS_ADDRESS: "redis.mailu-mailserver.svc.cluster.local"
|
||||
|
||||
# Fetchmail delay
|
||||
FETCHMAIL_DELAY: "600"
|
||||
|
||||
@@ -106,13 +113,16 @@
|
||||
###################################
|
||||
|
||||
# Path to the admin interface if enabled
|
||||
# Kubernetes addition: You need to change ALL the ingresses, when you want this URL to be different!!!
|
||||
WEB_ADMIN: "/admin"
|
||||
|
||||
# Path to the webmail if enabled
|
||||
# Currently, this is not used, because we intended to use a different subdomain: webmail.example.com
|
||||
# This option can be added in a feature release
|
||||
WEB_WEBMAIL: "/webmail"
|
||||
|
||||
# Website name
|
||||
SITENAME: "AppSynth"
|
||||
SITENAME: "Mailu"
|
||||
|
||||
# Linked Website URL
|
||||
WEBSITE: "https://example.com"
|
||||
@@ -1,23 +1,41 @@
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1beta2
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: mailu-front
|
||||
namespace: mailu-mailserver
|
||||
labels:
|
||||
k8s-app: mail-loadbalancer
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: mail-loadbalancer
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mailu-front
|
||||
role: mail
|
||||
tier: backend
|
||||
k8s-app: mail-loadbalancer
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: node-role.kubernetes.io/node
|
||||
operator: Exists
|
||||
hostNetwork: true
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/node: ""
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
restartPolicy: Always
|
||||
terminationGracePeriodSeconds: 60
|
||||
containers:
|
||||
- name: front
|
||||
image: mailu/nginx:latest
|
||||
image: mailu/nginx:master
|
||||
imagePullPolicy: Always
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
@@ -26,12 +44,6 @@ spec:
|
||||
- name: certs
|
||||
mountPath: /certs
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
- name: https
|
||||
containerPort: 443
|
||||
protocol: TCP
|
||||
- name: pop3
|
||||
containerPort: 110
|
||||
protocol: TCP
|
||||
@@ -85,21 +97,15 @@ metadata:
|
||||
name: front
|
||||
namespace: mailu-mailserver
|
||||
labels:
|
||||
app: mailu-admin
|
||||
role: mail
|
||||
tier: backend
|
||||
k8s-app: mail-loadbalancer
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
spec:
|
||||
selector:
|
||||
app: mailu-front
|
||||
role: mail
|
||||
tier: backend
|
||||
k8s-app: mail-loadbalancer
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
- name: https
|
||||
port: 443
|
||||
protocol: TCP
|
||||
- name: pop3
|
||||
port: 110
|
||||
protocol: TCP
|
||||
@@ -37,8 +37,8 @@ spec:
|
||||
- containerPort: 4190
|
||||
resources:
|
||||
requests:
|
||||
memory: 500Mi
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
cpu: 1000m
|
||||
limits:
|
||||
memory: 1Gi
|
||||
cpu: 1000m
|
||||
193
docs/kubernetes/mailu/index.rst
Normal file
193
docs/kubernetes/mailu/index.rst
Normal file
@@ -0,0 +1,193 @@
|
||||
Install Mailu master on kubernetes
|
||||
==================================
|
||||
|
||||
Prequisites
|
||||
-----------
|
||||
|
||||
Structure
|
||||
~~~~~~~~~
|
||||
|
||||
There’s chosen to have a double NGINX stack for Mailu, this way the main
|
||||
ingress can still be used to access other websites/domains on your
|
||||
cluster. This is the current structure:
|
||||
|
||||
- ``NGINX Ingress controller``: Listens to the nodes ports 80 & 443. We have chosen to have a double NGINX stack for Mailu.
|
||||
- ``Cert manager``: Creates automatic Lets Encrypt certificates based on an ``Ingress``-objects domain name.
|
||||
- ``Mailu NGINX Front daemonset``: This daemonset runs in parallel with the Nginx Ingress Controller and only listens on all E-mail specific ports (25, 110, 143, 587,...)
|
||||
- ``Mailu components``: All Mailu components (imap, smtp, security, webmail,...) are split into separate files to make them more handy to use, you can find the ``YAML`` files in this directory
|
||||
|
||||
What you need
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
- A working Kubernetes cluster (tested with 1.10.5)
|
||||
- A working `cert-manager`_ installation
|
||||
- A working nginx-ingress controller needed for the lets-encrypt
|
||||
certificates. You can find those files in the ``nginx`` subfolder
|
||||
|
||||
Cert manager
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The ``Cert-manager`` is quite easy to deploy using Helm when reading the
|
||||
`docs`_. After booting the ``Cert-manager`` you’ll need a
|
||||
``ClusterIssuer`` which takes care of all required certificates through
|
||||
``Ingress`` items. We chose to provide a ``clusterIssuer`` so you can provide SSL certificates
|
||||
for other namespaces (different websites/services), if you don't need this option, you can easily change this by
|
||||
changing ``clusterIssuer`` to ``Issuer`` and adding the ``namespace: mailu-mailserver`` to the metadata.
|
||||
An example of a production and a staging ``clusterIssuer``:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
# This clusterIssuer example uses the staging environment for testing first
|
||||
apiVersion: certmanager.k8s.io/v1alpha1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-stage
|
||||
spec:
|
||||
acme:
|
||||
email: something@example.com
|
||||
http01: {}
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-stage
|
||||
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
# This clusterIssuer example uses the production environment
|
||||
apiVersion: certmanager.k8s.io/v1alpha1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
email: something@example.com
|
||||
http01: {}
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
|
||||
**IMPORTANT**: All ``*-ingress.yaml`` files use the ``letsencrypt-stage`` ``clusterIssuer``. If you are ready for production,
|
||||
change this field in all ``*-ingress.yaml`` files to ``letsencrypt-prod`` or whatever name you chose for the production.
|
||||
If you choose for ``Issuer`` instead of ``clusterIssuer`` you also need to change the annotation to ``certmanager.k8s.io/issuer`` instead of ``certmanager.k8s.io/cluster-issuer``
|
||||
|
||||
Deploying Mailu
|
||||
---------------
|
||||
|
||||
All manifests can be found in the ``mailu`` subdirectory. All commands
|
||||
below need to be run from this subdirectory
|
||||
|
||||
Personalization
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- All services run in the same namespace, currently ``mailu-mailserver``. So if you want to use a different one, change the ``namespace`` value in **every** file
|
||||
- Check the ``storage-class`` field in the ``pvc.yaml`` file, you can also change the sizes to your liking. Note that you need ``RWX`` (read-write-many) and ``RWO`` (read-write-once) storageclasses.
|
||||
- Check the ``configmap.yaml`` and adapt it to your needs. Be sure to check the kubernetes DNS values at the end (if you use a different namespace)
|
||||
- Check the ``*-ingress.yaml`` files and change it to the domain you want (this is for the kubernetes ingress controller to handle the admin, webmail, webdav and auth connections)
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Boot the Mailu components
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To start Mailu, run the following commands from the ``docs/kubernetes/mailu`` directory
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl create -f rbac.yaml
|
||||
kubectl create -f configmap.yaml
|
||||
kubectl create -f pvc.yaml
|
||||
kubectl create -f redis.yaml
|
||||
kubectl create -f front.yaml
|
||||
kubectl create -f webmail.yaml
|
||||
kubectl create -f imap.yaml
|
||||
kubectl create -f security.yaml
|
||||
kubectl create -f smtp.yaml
|
||||
kubectl create -f fetchmail.yaml
|
||||
kubectl create -f admin.yaml
|
||||
kubectl create -f webdav.yaml
|
||||
kubectl create -f admin-ingress.yaml
|
||||
kubectl create -f webdav-ingress.yaml
|
||||
kubectl create -f security-ingress.yaml
|
||||
kubectl create -f webmail-ingress.yaml
|
||||
|
||||
|
||||
Create the first admin account
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When the cluster is online you need to create you master user to access https://mail.example.com/admin
|
||||
Enter the main ``admin`` pod to create the root account:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
kubectl -n mailu-mailserver get po
|
||||
kubectl -n mailu-mailserver exec -it mailu-admin-.... /bin/sh
|
||||
|
||||
And in the pod run the following command. The command uses following entries:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python manage.py admin root example.com password
|
||||
|
||||
- ``admin`` Make it an admin user
|
||||
- ``root`` The first part of the e-mail adres (ROOT@example.com)
|
||||
- ``example.com`` the domain appendix
|
||||
- ``password`` the chosen password for the user
|
||||
|
||||
|
||||
Now you should be able to login on the mail account: https://mail.example.com/admin
|
||||
|
||||
Adaptations
|
||||
-----------
|
||||
|
||||
Dovecot
|
||||
~~~~~~~
|
||||
|
||||
- If you are using Dovecot on a shared file system (Glusterfs, NFS,...), you need to create a special override otherwise a lot of indexing errors will occur on your Dovecot pod.
|
||||
- I also higher the number of max connections per IP. Now it's limited to 10.
|
||||
|
||||
Enter the dovecot pod:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
kubectl -n mailu-mailserver get po
|
||||
kubectl -n mailu-mailserver exec -it mailu-imap-.... /bin/sh
|
||||
|
||||
Create the file ``overrides/dovecot.conf``
|
||||
|
||||
.. code:: bash
|
||||
|
||||
vi /overrides/dovecot.conf
|
||||
|
||||
And enter following contents:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mail_nfs_index = yes
|
||||
mail_nfs_storage = yes
|
||||
mail_fsync = always
|
||||
mmap_disable = yes
|
||||
mail_max_userip_connections=100
|
||||
|
||||
Save and close the file and delete the imap pod to get it recreated.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
kubectl -n mailu-mailserver delete po/mailu-imap-....
|
||||
|
||||
Wait for the pod to recreate and you're online!
|
||||
Happy mailing!
|
||||
|
||||
.. _here: https://github.com/hacor/Mailu/blob/master/core/postfix/conf/main.cf#L35
|
||||
.. _cert-manager: https://github.com/jetstack/cert-manager
|
||||
.. _docs: https://cert-manager.readthedocs.io/en/latest/getting-started/2-installing.html
|
||||
|
||||
Imap login fix
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
If it seems you're not able to login using IMAP on your Mailu accounts, check the logs of the imap container to see whether it's a permissions problem on the database.
|
||||
This problem can be easily fixed by running following commands:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
kubectl -n mailu-mailserver exec -it maolu-imap-... /bin/sh
|
||||
chmod 777 /data/main.db
|
||||
30
docs/kubernetes/mailu/security-ingress.yaml
Normal file
30
docs/kubernetes/mailu/security-ingress.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-antispam-ingress
|
||||
namespace: mailu-mailserver
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-stage
|
||||
ingress.kubernetes.io/configuration-snippet: |
|
||||
rewrite ^/admin/antispam/(.*) /$1 break;
|
||||
auth_request /internal/auth/admin;
|
||||
proxy_set_header X-Real-IP "";
|
||||
proxy_set_header X-Forwarded-For "";
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: frontend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "mail.example.com"
|
||||
secretName: letsencrypt-certs-all # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "mail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/admin/antispam"
|
||||
backend:
|
||||
serviceName: antispam
|
||||
servicePort: 11334
|
||||
@@ -31,6 +31,9 @@ spec:
|
||||
- name: antispam
|
||||
containerPort: 11332
|
||||
protocol: TCP
|
||||
- name: antispam-http
|
||||
containerPort: 11334
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: filter
|
||||
subPath: filter
|
||||
@@ -87,6 +90,9 @@ spec:
|
||||
- name: antispam
|
||||
port: 11332
|
||||
protocol: TCP
|
||||
- name: antispam-http
|
||||
protocol: TCP
|
||||
port: 11334
|
||||
|
||||
---
|
||||
|
||||
@@ -21,10 +21,10 @@ spec:
|
||||
name: mailu-config
|
||||
resources:
|
||||
requests:
|
||||
memory: 500Mi
|
||||
cpu: 200m
|
||||
memory: 2Gi
|
||||
cpu: 500m
|
||||
limits:
|
||||
memory: 1Gi
|
||||
memory: 2Gi
|
||||
cpu: 500m
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
46
docs/kubernetes/mailu/webdav-ingress.yaml
Normal file
46
docs/kubernetes/mailu/webdav-ingress.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-webdav-ingress
|
||||
namespace: mailu-mailserver
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-stage
|
||||
#ingress.kubernetes.io/auth-url: http://admin.mailu-mailserver.svc.cluster.local/internal/auth/basic
|
||||
ingress.kubernetes.io/configuration-snippet: |
|
||||
rewrite ^/webdav/(.*) /$1 break;
|
||||
auth_request /internal/auth/basic;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
auth_request_set $user $upstream_http_x_user;
|
||||
proxy_set_header X-Remote-User $user;
|
||||
proxy_set_header X-Script-Name /webdav;
|
||||
ingress.kubernetes.io/server-snippet: |
|
||||
location /internal {
|
||||
internal;
|
||||
|
||||
proxy_set_header Authorization $http_authorization;
|
||||
proxy_pass_header Authorization;
|
||||
proxy_pass http://admin.mailu-mailserver.svc.cluster.local;
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
}
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: frontend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "mail.example.com"
|
||||
secretName: letsencrypt-certs-all # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "mail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/webdav"
|
||||
backend:
|
||||
serviceName: webdav
|
||||
servicePort: 5232
|
||||
31
docs/kubernetes/mailu/webmail-ingress.yaml
Normal file
31
docs/kubernetes/mailu/webmail-ingress.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-webmail-ingress
|
||||
namespace: mailu-mailserver
|
||||
annotations:
|
||||
kubernetes.io/tls-acme: "true"
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||
certmanager.k8s.io/cluster-issuer: letsencrypt-stage
|
||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "webmail.example.com"
|
||||
secretName: letsencrypt-webmail # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "webmail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/"
|
||||
backend:
|
||||
serviceName: webmail
|
||||
servicePort: 80
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: roundcube
|
||||
image: mailu/roundcube:1.5
|
||||
image: mailu/roundcube:master
|
||||
imagePullPolicy: Always
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
@@ -2,15 +2,15 @@ apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# keep it under 24 chars
|
||||
name: appsynth-lb
|
||||
name: ingress-lb
|
||||
namespace: kube-ingress
|
||||
labels:
|
||||
k8s-app: appsynth-lb
|
||||
k8s-app: ingress-lb
|
||||
component: ingress-controller
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
k8s-app: appsynth-lb
|
||||
k8s-app: ingress-lb
|
||||
component: ingress-controller
|
||||
ports:
|
||||
- name: http
|
||||
@@ -35,13 +35,6 @@ metadata:
|
||||
name: tcp-services
|
||||
namespace: kube-ingress
|
||||
data:
|
||||
25: "mailu-mailserver/front:25"
|
||||
110: "mailu-mailserver/front:110"
|
||||
465: "mailu-mailserver/front:465"
|
||||
587: "mailu-mailserver/front:587"
|
||||
143: "mailu-mailserver/front:143"
|
||||
993: "mailu-mailserver/front:993"
|
||||
995: "mailu-mailserver/front:995"
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
@@ -61,7 +54,7 @@ metadata:
|
||||
prometheus.io/port: "10254"
|
||||
prometheus.io/scrape: "true"
|
||||
labels:
|
||||
k8s-app: appsynth-lb
|
||||
k8s-app: ingress-lb
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
spec:
|
||||
@@ -71,13 +64,13 @@ spec:
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: appsynth-lb
|
||||
k8s-app: ingress-lb
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: appsynth-lb
|
||||
k8s-app: ingress-lb
|
||||
component: ingress-controller
|
||||
type: nginx
|
||||
spec:
|
||||
@@ -94,14 +87,11 @@ spec:
|
||||
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.2
|
||||
args:
|
||||
- /nginx-ingress-controller
|
||||
- --configmap=$(POD_NAMESPACE)/tectonic-custom-error
|
||||
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
|
||||
#- --default-ssl-certificate=tectonic-system/tectonic-ingress-tls-secret
|
||||
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
|
||||
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
|
||||
- --annotations-prefix=ingress.kubernetes.io
|
||||
- --enable-ssl-passthrough
|
||||
- --ingress-class=tectonic
|
||||
# use downward API
|
||||
env:
|
||||
- name: POD_NAME
|
||||
@@ -115,10 +105,8 @@ spec:
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
hostPort: 80
|
||||
- name: https
|
||||
containerPort: 443
|
||||
hostPort: 443
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
@@ -134,6 +122,6 @@ spec:
|
||||
hostNetwork: true
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/node: ""
|
||||
dnsPolicy: ClusterFirst
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
restartPolicy: Always
|
||||
terminationGracePeriodSeconds: 60
|
||||
@@ -1,26 +0,0 @@
|
||||
Kubernetes setup
|
||||
================
|
||||
|
||||
Please note that Kubernetes setup is not yet well supported or documented, all
|
||||
tests currently run on Docker Compose. The configuration has not yet been updated
|
||||
to work properly with ngin authentication proxy.
|
||||
|
||||
Prepare the environment
|
||||
-----------------------
|
||||
|
||||
The resource configurations in this folder assume that you have `Kubernetes Ingress`_
|
||||
set up for your cluster. If you are not using the `NGINX Ingress Controller for Kubernetes`_,
|
||||
please ensure that the configuration specified in the file matches your set up.
|
||||
|
||||
.. _`Kubernetes Ingress`: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||
.. _`NGINX Ingress Controller for Kubernetes`: https://github.com/kubernetes/ingress/tree/master/controllers/nginx
|
||||
|
||||
Setup the Kubernetes service
|
||||
----------------------------
|
||||
|
||||
Using the resource configurations is simple:
|
||||
|
||||
1. ``kubectl apply -f kubernetes-nginx-ingress-controller.yaml`` to configure an ingress controller with the proper settings. (If you have one set up already you may need to port the configuration to your own ingress).
|
||||
2. ``kubectl apply -f kubernetes-mailu.yaml`` to create the resources required to run Mailu.
|
||||
|
||||
Based on the configuration, your Mailu instance should be available at ``mail.<hostname>.tld/admin`` (note that visiting just ``mail.<hostname>.tld`` will likely result in a 404 error).
|
||||
@@ -1,419 +0,0 @@
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mailu-admin-ing
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "mail.example.com"
|
||||
secretName: letsencrypt-certs-all # If unsure how to generate these, check out https://github.com/ployst/docker-letsencrypt
|
||||
rules:
|
||||
- host: "mail.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: "/admin"
|
||||
backend:
|
||||
serviceName: mailu-admin
|
||||
servicePort: 80
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mailu-redis
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mailu-redis
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:4.0-alpine
|
||||
imagePullPolicy: Always
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: redisdata
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
name: redis
|
||||
protocol: TCP
|
||||
volumes:
|
||||
- name: redisdata
|
||||
hostPath:
|
||||
path: /var/data/mailu/redisdata
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis
|
||||
labels:
|
||||
app: mailu-redis
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
selector:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mailu-imap
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mailu-imap
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: imap
|
||||
image: mailu/dovecot:stable
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name : DOMAIN
|
||||
value : example.com
|
||||
- name : HOSTNAME
|
||||
value : mail.example.com
|
||||
- name : POSTMASTER
|
||||
value : admin
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: maildata
|
||||
- mountPath: /mail
|
||||
name: mailstate
|
||||
- mountPath: /overrides
|
||||
name: overrides
|
||||
- mountPath: /certs
|
||||
name: certs
|
||||
readOnly: true
|
||||
ports:
|
||||
- containerPort: 2102
|
||||
- containerPort: 2525
|
||||
- containerPort: 143
|
||||
- containerPort: 993
|
||||
- containerPort: 4190
|
||||
volumes:
|
||||
- name: maildata
|
||||
hostPath:
|
||||
path: /var/data/mailu/maildata
|
||||
- name: mailstate
|
||||
hostPath:
|
||||
path: /var/data/mailu/mailstate
|
||||
- name: overrides
|
||||
hostPath:
|
||||
path: /var/data/mailu/overrides
|
||||
- name: certs
|
||||
secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: cert.pem
|
||||
- key: tls.key
|
||||
path: key.pem
|
||||
secretName: letsencrypt-certs-all
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: imap
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
selector:
|
||||
app: mailu-imap
|
||||
role: mail
|
||||
tier: backend
|
||||
ports:
|
||||
ports:
|
||||
- name: imap-auth
|
||||
port: 2102
|
||||
protocol: TCP
|
||||
- name: imap-transport
|
||||
port: 2525
|
||||
protocol: TCP
|
||||
- name: imap-default
|
||||
port: 143
|
||||
protocol: TCP
|
||||
- name: imap-ssl
|
||||
port: 993
|
||||
protocol: TCP
|
||||
- name: sieve
|
||||
port: 4190
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mailu-smtp
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mailu-smtp
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: smtp
|
||||
image: mailu/postfix:stable
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name : DOMAIN
|
||||
value : example.com
|
||||
- name : HOSTNAME
|
||||
value : mail.example.com
|
||||
- name : MESSAGE_SIZE_LIMIT
|
||||
value : "50000000"
|
||||
- name : RELAYHOST
|
||||
value : ""
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: maildata
|
||||
- mountPath: /overrides
|
||||
name: overrides
|
||||
- mountPath: /certs
|
||||
name: certs
|
||||
readOnly: true
|
||||
ports:
|
||||
- name: smtp
|
||||
containerPort: 25
|
||||
protocol: TCP
|
||||
- name: smtp-ssl
|
||||
containerPort: 465
|
||||
protocol: TCP
|
||||
- name: smtp-starttls
|
||||
containerPort: 587
|
||||
protocol: TCP
|
||||
volumes:
|
||||
- name: maildata
|
||||
hostPath:
|
||||
path: /var/data/mailu/maildata
|
||||
- name: overrides
|
||||
hostPath:
|
||||
path: /var/data/mailu/overrides
|
||||
- name: certs
|
||||
secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: cert.pem
|
||||
- key: tls.key
|
||||
path: key.pem
|
||||
secretName: letsencrypt-certs-all
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: smtp
|
||||
labels:
|
||||
app: mailu
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
selector:
|
||||
app: mailu-smtp
|
||||
role: mail
|
||||
tier: backend
|
||||
ports:
|
||||
- name: smtp
|
||||
port: 25
|
||||
protocol: TCP
|
||||
- name: smtp-ssl
|
||||
port: 465
|
||||
protocol: TCP
|
||||
- name: smtp-starttls
|
||||
port: 587
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mailu-security
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mailu-security
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: antispam
|
||||
image: mailu/rspamd:stable
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: antispam
|
||||
containerPort: 11333
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: filter
|
||||
mountPath: /var/lib/rspamd
|
||||
- name: antivirus
|
||||
image: mailu/clamav:stable
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: antivirus
|
||||
containerPort: 3310
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: filter
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: filter
|
||||
hostPath:
|
||||
path: /var/data/mailu/filter
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: antispam
|
||||
labels:
|
||||
app: mailu-antispam
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
selector:
|
||||
app: mailu-security
|
||||
role: mail
|
||||
tier: backend
|
||||
ports:
|
||||
- name: antispam
|
||||
port: 11333
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: antivirus
|
||||
labels:
|
||||
app: mailu-antivirus
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
selector:
|
||||
app: mailu-security
|
||||
role: mail
|
||||
tier: backend
|
||||
ports:
|
||||
- name: antivirus
|
||||
port: 3310
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mailu-admin
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mailu-admin
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: admin
|
||||
image: mailu/admin:stable
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name : DOMAIN
|
||||
value : example.com
|
||||
- name : HOSTNAME
|
||||
value : mail.example.com
|
||||
- name : POSTMASTER
|
||||
value : core
|
||||
- name : SECRET_KEY
|
||||
value : pleasereplacethiswithabetterkey
|
||||
- name : DEBUG
|
||||
value : "True"
|
||||
volumeMounts:
|
||||
- name: maildata
|
||||
mountPath: /data
|
||||
- name: dkim
|
||||
mountPath: /dkim
|
||||
- name: certs
|
||||
mountPath: /certs
|
||||
readOnly: true
|
||||
# - name: docker
|
||||
# mountPath: /var/run/docker.sock
|
||||
# readOnly: true
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
volumes:
|
||||
- name: maildata
|
||||
hostPath:
|
||||
path: /var/data/mailu/maildata
|
||||
- name: dkim
|
||||
hostPath:
|
||||
path: /var/data/mailu/dkim
|
||||
- name: certs
|
||||
secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: cert.pem
|
||||
- key: tls.key
|
||||
path: key.pem
|
||||
secretName: letsencrypt-certs-all
|
||||
# - name: docker
|
||||
# hostPath:
|
||||
# path: /var/run/docker.sock
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mailu-admin
|
||||
labels:
|
||||
app: mailu-admin
|
||||
role: mail
|
||||
tier: backend
|
||||
spec:
|
||||
selector:
|
||||
app: mailu-admin
|
||||
role: mail
|
||||
tier: backend
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: nginx-configuration
|
||||
namespace: ingress-nginx
|
||||
labels:
|
||||
app: ingress-nginx
|
||||
|
||||
---
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: udp-services
|
||||
namespace: ingress-nginx
|
||||
|
||||
---
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: tcp-services
|
||||
namespace: ingress-nginx
|
||||
data:
|
||||
25: "mailu/smtp:25"
|
||||
465: "mailu/smtp:465"
|
||||
587: "mailu/smtp:587"
|
||||
143: "mailu/imap:143"
|
||||
993: "mailu/imap:993"
|
||||
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-ingress-controller
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: nginx-ingress-controller
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: nginx-ingress-controller
|
||||
annotations:
|
||||
prometheus.io/port: '10254'
|
||||
prometheus.io/scrape: 'true'
|
||||
spec:
|
||||
# hostNetwork makes it possible to use ipv6 and to preserve the source IP correctly regardless of docker configuration
|
||||
# however, it is not a hard dependency of the nginx-ingress-controller itself and it may cause issues if port 10254 already is taken on the host
|
||||
# that said, since hostPort is broken on CNI (https://github.com/kubernetes/kubernetes/issues/31307) we have to use hostNetwork where CNI is used
|
||||
# like with kubeadm
|
||||
# hostNetwork: true
|
||||
terminationGracePeriodSeconds: 60
|
||||
containers:
|
||||
- image: gcr.io/google_containers/nginx-ingress-controller:0.11.0
|
||||
name: nginx-ingress-controller
|
||||
args:
|
||||
- /nginx-ingress-controller
|
||||
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
|
||||
- --configmap=$(POD_NAMESPACE)/nginx-configuration
|
||||
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
|
||||
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
|
||||
- --annotations-prefix=nginx.ingress.kubernetes.io
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10254
|
||||
scheme: HTTP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10254
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 1
|
||||
env:
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
@@ -6,6 +6,7 @@ One of Mailu use cases is as part of a larger services platform, where maybe oth
|
||||
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) and/or the requested path. Mailu 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 to Docker Compose configuration structure, it is impossible for us to make disabling the Web frontend completely available through a configuration variable. This guide was written to help users setup such an architecture.
|
||||
|
||||
There are basically three options, from the most to the least recommended one:
|
||||
|
||||
- have Mailu Web frontend listen locally and use your own Web frontend on top of it
|
||||
- override Mailu Web frontend configuration
|
||||
- disable Mailu Web frontend completely and use your own
|
||||
|
||||
@@ -32,7 +32,7 @@ user. Make sure you complete the requirements for the flavor you chose.
|
||||
|
||||
You should also have at least a DNS hostname and a DNS name for receiving
|
||||
emails. Some instructions are provided on the matter in the article
|
||||
[Setup your DNS](dns).
|
||||
:ref:`dns_setup`.
|
||||
|
||||
.. _`MFAshby's fork`: https://github.com/MFAshby/Mailu
|
||||
|
||||
@@ -68,10 +68,9 @@ Make sure that you test properly before going live!
|
||||
- Try to receive an email from an external service
|
||||
- Check the logs (``docker-compose logs -f servicenamehere``) to look for
|
||||
warnings or errors
|
||||
- Use an open relay checker like `mailradar`_
|
||||
- Use an open relay checker like `mxtoolbox`_
|
||||
to ensure you're not contributing to the spam problem on the internet.
|
||||
All tests there should result in "Relay denied".
|
||||
- If using DMARC, be sure to check the reports you get to verify that legitimate
|
||||
email is getting through and forgeries are being properly blocked.
|
||||
|
||||
.. _mailradar: http://www.mailradar.com/openrelay/
|
||||
.. _mxtoolbox: https://mxtoolbox.com/diagnostic.aspx
|
||||
|
||||
252
docs/swarm/master/README.md
Normal file
252
docs/swarm/master/README.md
Normal file
@@ -0,0 +1,252 @@
|
||||
# Install Mailu on a docker swarm
|
||||
|
||||
## Prequisites
|
||||
|
||||
### Swarm
|
||||
|
||||
In order to deploy Mailu on a swarm, you will first need to initialize the swarm:
|
||||
|
||||
The main command will be:
|
||||
```bash
|
||||
docker swarm init --advertise-addr <IP_ADDR>
|
||||
```
|
||||
See https://docs.docker.com/engine/swarm/swarm-tutorial/create-swarm/
|
||||
|
||||
If you want to add other managers or workers, please use:
|
||||
```bash
|
||||
docker swarm join --token xxxxx
|
||||
```
|
||||
See https://docs.docker.com/engine/swarm/join-nodes/
|
||||
|
||||
You have now a working swarm, and you can check its status with:
|
||||
```bash
|
||||
core@coreos-01 ~/git/Mailu/docs/swarm/1.5 $ docker node ls
|
||||
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
|
||||
xhgeekkrlttpmtgmapt5hyxrb black-pearl Ready Active 18.06.0-ce
|
||||
sczlqjgfhehsfdjhfhhph1nvb * coreos-01 Ready Active Leader 18.03.1-ce
|
||||
mzrm9nbdggsfz4sgq6dhs5i6n flying-dutchman Ready Active 18.06.0-ce
|
||||
```
|
||||
|
||||
### Volume definition
|
||||
For data persistance (the Mailu services might be launched/relaunched on any of the swarm nodes), we need to have Mailu data stored in a manner accessible by every manager or worker in the swarm.
|
||||
|
||||
Hereafter we will assume that "Mailu Data" is available on every node at "$ROOT/certs:/certs" (GlusterFS and nfs shares have been successfully used).
|
||||
|
||||
On this example, we are using:
|
||||
- the mesh routing mode (default mode). With this mode, each service is given a virtual IP adress and docker manages the routing between this virtual IP and the container(s) providing this service.
|
||||
- the default ingress mode.
|
||||
|
||||
### Allow authentification with the mesh routing
|
||||
In order to allow every (front & webmail) container to access the other services, we will use the variable POD_ADDRESS_RANGE.
|
||||
|
||||
Let's create the mailu_default network:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker network create -d overlay --attachable mailu_default
|
||||
core@coreos-01 ~ $ docker network inspect mailu_default | grep Subnet
|
||||
"Subnet": "10.0.1.0/24",
|
||||
```
|
||||
In the docker-compose.yml file, we will then use POD_ADDRESS_RANGE = 10.0.1.0/24
|
||||
In fact, imap & smtp logs doesn't show the IPs from the front(s) container(s), but the IP of "mailu_default-endpoint". So it is sufficient to set POD_ADDRESS_RANGE to this specific ip (which can be found by inspecting mailu_default network). The issue is that this endpoint is created while the stack is created, I did'nt figure a way to determine this IP before the stack creation...
|
||||
|
||||
### Limitation with the ingress mode
|
||||
With the default ingress mode, the front(s) container(s) will see origin IP(s) all being 10.255.0.x (which is the ingress-endpoint, can be found by inspecting the ingress network)
|
||||
|
||||
This issue is known and discussed here:
|
||||
|
||||
https://github.com/moby/moby/issues/25526
|
||||
|
||||
A workaround (using network host mode and global deployment) is discussed here:
|
||||
|
||||
https://github.com/moby/moby/issues/25526#issuecomment-336363408
|
||||
|
||||
### Don't create an open relay !
|
||||
As a side effect of this ingress mode "feature", make sure that the ingress subnet is not in your RELAYHOST, otherwise you would create an smtp open relay :-(
|
||||
|
||||
|
||||
## Scalability
|
||||
- smtp and imap are scalable
|
||||
- front and webmail are scalable (pending POD_ADDRESS_RANGE is used), although the let's encrypt magic might not like it (race condidtion ? or risk to be banned by let's encrypt server if too many front containers attemps to renew the certs at the same time)
|
||||
- redis, antispam, antivirus, fetchmail, admin, webdav have not been tested (hence replicas=1 in the following docker-compose.yml file)
|
||||
|
||||
## Variable substitution and docker-compose.yml
|
||||
The docker stack deploy command doesn't support variable substitution in the .yml file itself.
|
||||
As a consequence, we cannot simply use ``` docker stack deploy -c docker.compose.yml mailu ```
|
||||
Instead, we will use the following work-around:
|
||||
``` echo "$(docker-compose -f /mnt/docker/apps/mailu/docker-compose.yml config 2>/dev/null)" | docker stack deploy -c- mailu ```
|
||||
|
||||
We need also to:
|
||||
- add a deploy section for every service
|
||||
- modify the way the ports are defined for the front service
|
||||
- add the POD_ADDRESS_RANGE definition for imap, smtp and antispam services
|
||||
|
||||
## Docker compose
|
||||
An example of docker-compose-stack.yml file is available here:
|
||||
|
||||
```yaml
|
||||
|
||||
version: '3.2'
|
||||
|
||||
services:
|
||||
|
||||
front:
|
||||
image: mailu/nginx:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
ports:
|
||||
- target: 80
|
||||
published: 80
|
||||
- target: 443
|
||||
published: 443
|
||||
- target: 110
|
||||
published: 110
|
||||
- target: 143
|
||||
published: 143
|
||||
- target: 993
|
||||
published: 993
|
||||
- target: 995
|
||||
published: 995
|
||||
- target: 25
|
||||
published: 25
|
||||
- target: 465
|
||||
published: 465
|
||||
- target: 587
|
||||
published: 587
|
||||
volumes:
|
||||
- "$ROOT/certs:/certs"
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: always
|
||||
volumes:
|
||||
- "$ROOT/redis:/data"
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
imap:
|
||||
image: mailu/dovecot:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE=10.0.1.0/24
|
||||
volumes:
|
||||
- "$ROOT/mail:/mail"
|
||||
- "$ROOT/overrides:/overrides"
|
||||
depends_on:
|
||||
- front
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
smtp:
|
||||
image: mailu/postfix:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE=10.0.1.0/24
|
||||
volumes:
|
||||
- "$ROOT/overrides:/overrides"
|
||||
depends_on:
|
||||
- front
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
antispam:
|
||||
image: mailu/rspamd:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE=10.0.1.0/24
|
||||
volumes:
|
||||
- "$ROOT/filter:/var/lib/rspamd"
|
||||
- "$ROOT/dkim:/dkim"
|
||||
- "$ROOT/overrides/rspamd:/etc/rspamd/override.d"
|
||||
depends_on:
|
||||
- front
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
antivirus:
|
||||
image: mailu/none:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/filter:/data"
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
webdav:
|
||||
image: mailu/none:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/dav:/data"
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
admin:
|
||||
image: mailu/admin:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
- "$ROOT/dkim:/dkim"
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
depends_on:
|
||||
- redis
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
webmail:
|
||||
image: mailu/roundcube:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
- "$ROOT/webmail:/data"
|
||||
depends_on:
|
||||
- imap
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
fetchmail:
|
||||
image: mailu/fetchmail:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mailu_default
|
||||
```
|
||||
|
||||
## Deploy Mailu on the docker swarm
|
||||
Run the following command:
|
||||
```bash
|
||||
echo "$(docker-compose -f /mnt/docker/apps/mailu/docker-compose.yml config 2>/dev/null)" | docker stack deploy -c- mailu
|
||||
```
|
||||
See how the services are being deployed:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker service ls
|
||||
ID NAME MODE REPLICAS IMAGE PORTS
|
||||
ywnsetmtkb1l mailu_antivirus replicated 1/1 mailu/none:master
|
||||
pqokiaz0q128 mailu_fetchmail replicated 1/1 mailu/fetchmail:master
|
||||
```
|
||||
check a specific service:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker service ps mailu_fetchmail
|
||||
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
|
||||
tbu8ppgsdffj mailu_fetchmail.1 mailu/fetchmail:master coreos-01 Running Running 11 days ago
|
||||
```
|
||||
You might also have a look on the logs:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker service logs -f mailu_fetchmail
|
||||
```
|
||||
|
||||
## Remove the stack
|
||||
Run the follwoing command:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker stack rm mailu
|
||||
```
|
||||
357
docs/swarm/master/README_nfs_example.md
Normal file
357
docs/swarm/master/README_nfs_example.md
Normal file
@@ -0,0 +1,357 @@
|
||||
# Install Mailu on a docker swarm
|
||||
|
||||
## Prequisites
|
||||
|
||||
### Swarm
|
||||
|
||||
In order to deploy Mailu on a swarm, you will first need to initialize the swarm:
|
||||
|
||||
The main command will be:
|
||||
```bash
|
||||
docker swarm init --advertise-addr <IP_ADDR>
|
||||
```
|
||||
See https://docs.docker.com/engine/swarm/swarm-tutorial/create-swarm/
|
||||
|
||||
If you want to add other managers or workers, please use:
|
||||
```bash
|
||||
docker swarm join --token xxxxx
|
||||
```
|
||||
See https://docs.docker.com/engine/swarm/join-nodes/
|
||||
|
||||
You have now a working swarm, and you can check its status with:
|
||||
```bash
|
||||
core@coreos-01 ~/git/Mailu/docs/swarm/1.5 $ docker node ls
|
||||
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
|
||||
xhgeekkrlttpmtgmapt5hyxrb black-pearl Ready Active 18.06.0-ce
|
||||
sczlqjgfhehsfdjhfhhph1nvb * coreos-01 Ready Active Leader 18.03.1-ce
|
||||
mzrm9nbdggsfz4sgq6dhs5i6n flying-dutchman Ready Active 18.06.0-ce
|
||||
```
|
||||
|
||||
### Volume definition
|
||||
For data persistance (the Mailu services might be launched/relaunched on any of the swarm nodes), we need to have Mailu data stored in a manner accessible by every manager or worker in the swarm.
|
||||
Hereafter we will use a NFS share:
|
||||
```bash
|
||||
core@coreos-01 ~ $ showmount -e 192.168.0.30
|
||||
Export list for 192.168.0.30:
|
||||
/mnt/Pool1/pv 192.168.0.0
|
||||
```
|
||||
|
||||
on the nfs server, I am using the following /etc/exports
|
||||
```bash
|
||||
$more /etc/exports
|
||||
/mnt/Pool1/pv -alldirs -mapall=root -network 192.168.0.0 -mask 255.255.255.0
|
||||
```
|
||||
on the nfs server, I created the Mailu directory (in fact I copied a working Mailu set-up)
|
||||
```bash
|
||||
$mkdir /mnt/Pool1/pv/mailu
|
||||
```
|
||||
|
||||
On your manager node, mount the nfs share to check that the share is available:
|
||||
```bash
|
||||
core@coreos-01 ~ $ sudo mount -t nfs 192.168.0.30:/mnt/Pool1/pv/mailu /mnt/local/
|
||||
```
|
||||
If this is ok, you can umount it:
|
||||
```bash
|
||||
core@coreos-01 ~ $ sudo umount /mnt/local/
|
||||
```
|
||||
|
||||
|
||||
## Networking mode
|
||||
On this example, we are using:
|
||||
- the mesh routing mode (default mode). With this mode, each service is given a virtual IP adress and docker manages the routing between this virtual IP and the container(s) providing this service.
|
||||
- the default ingress mode.
|
||||
|
||||
### Allow authentification with the mesh routing
|
||||
In order to allow every (front & webmail) container to access the other services, we will use the variable POD_ADDRESS_RANGE.
|
||||
|
||||
Let's create the mailu_default network:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker network create -d overlay --attachable mailu_default
|
||||
core@coreos-01 ~ $ docker network inspect mailu_default | grep Subnet
|
||||
"Subnet": "10.0.1.0/24",
|
||||
```
|
||||
In the docker-compose.yml file, we will then use POD_ADDRESS_RANGE = 10.0.1.0/24
|
||||
In fact, imap & smtp logs doesn't show the IPs from the front(s) container(s), but the IP of "mailu_default-endpoint". So it is sufficient to set POD_ADDRESS_RANGE to this specific ip (which can be found by inspecting mailu_default network). The issue is that this endpoint is created while the stack is created, I did'nt figure a way to determine this IP before the stack creation...
|
||||
|
||||
### Limitation with the ingress mode
|
||||
With the default ingress mode, the front(s) container(s) will see origin IP(s) all being 10.255.0.x (which is the ingress-endpoint, can be found by inspecting the ingress network)
|
||||
|
||||
This issue is known and discussed here:
|
||||
|
||||
https://github.com/moby/moby/issues/25526
|
||||
|
||||
A workaround (using network host mode and global deployment) is discussed here:
|
||||
|
||||
https://github.com/moby/moby/issues/25526#issuecomment-336363408
|
||||
|
||||
### Don't create an open relay !
|
||||
As a side effect of this ingress mode "feature", make sure that the ingress subnet is not in your RELAYHOST, otherwise you would create an smtp open relay :-(
|
||||
|
||||
|
||||
## Scalability
|
||||
- smtp and imap are scalable
|
||||
- front and webmail are scalable (pending POD_ADDRESS_RANGE is used), although the let's encrypt magic might not like it (race condidtion ? or risk to be banned by let's encrypt server if too many front containers attemps to renew the certs at the same time)
|
||||
- redis, antispam, antivirus, fetchmail, admin, webdav have not been tested (hence replicas=1 in the following docker-compose.yml file)
|
||||
|
||||
## Variable substitution and docker-compose.yml
|
||||
The docker stack deploy command doesn't support variable substitution in the .yml file itself. As a consequence, we need to use the following work-around:
|
||||
``` echo "$(docker-compose -f /mnt/docker/apps/mailu/docker-compose.yml config 2>/dev/null)" | docker stack deploy -c- mailu ```
|
||||
|
||||
We need also to:
|
||||
- change the way we define the volumes (nfs share in our case)
|
||||
- add a deploy section for every service
|
||||
- the way the ports are defined for the front service
|
||||
|
||||
## Docker compose
|
||||
An example of docker-compose-stack.yml file is available here:
|
||||
|
||||
```yaml
|
||||
|
||||
version: '3.2'
|
||||
|
||||
services:
|
||||
|
||||
front:
|
||||
image: mailu/nginx:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
ports:
|
||||
- target: 80
|
||||
published: 80
|
||||
- target: 443
|
||||
published: 443
|
||||
- target: 110
|
||||
published: 110
|
||||
- target: 143
|
||||
published: 143
|
||||
- target: 993
|
||||
published: 993
|
||||
- target: 995
|
||||
published: 995
|
||||
- target: 25
|
||||
published: 25
|
||||
- target: 465
|
||||
published: 465
|
||||
- target: 587
|
||||
published: 587
|
||||
volumes:
|
||||
# - "$ROOT/certs:/certs"
|
||||
- type: volume
|
||||
source: mailu_certs
|
||||
target: /certs
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: always
|
||||
volumes:
|
||||
# - "$ROOT/redis:/data"
|
||||
- type: volume
|
||||
source: mailu_redis
|
||||
target: /data
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
imap:
|
||||
image: mailu/dovecot:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE=10.0.1.0/24
|
||||
volumes:
|
||||
# - "$ROOT/mail:/mail"
|
||||
- type: volume
|
||||
source: mailu_mail
|
||||
target: /mail
|
||||
# - "$ROOT/overrides:/overrides"
|
||||
- type: volume
|
||||
source: mailu_overrides
|
||||
target: /overrides
|
||||
depends_on:
|
||||
- front
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
smtp:
|
||||
image: mailu/postfix:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE=10.0.1.0/24
|
||||
volumes:
|
||||
# - "$ROOT/overrides:/overrides"
|
||||
- type: volume
|
||||
source: mailu_overrides
|
||||
target: /overrides
|
||||
depends_on:
|
||||
- front
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
antispam:
|
||||
image: mailu/rspamd:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE=10.0.1.0/24
|
||||
depends_on:
|
||||
- front
|
||||
volumes:
|
||||
# - "$ROOT/filter:/var/lib/rspamd"
|
||||
- type: volume
|
||||
source: mailu_filter
|
||||
target: /var/lib/rspamd
|
||||
# - "$ROOT/dkim:/dkim"
|
||||
- type: volume
|
||||
source: mailu_dkim
|
||||
target: /dkim
|
||||
# - "$ROOT/overrides/rspamd:/etc/rspamd/override.d"
|
||||
- type: volume
|
||||
source: mailu_overrides_rspamd
|
||||
target: /etc/rspamd/override.d
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
antivirus:
|
||||
image: mailu/none:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
# - "$ROOT/filter:/data"
|
||||
- type: volume
|
||||
source: mailu_filter
|
||||
target: /data
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
webdav:
|
||||
image: mailu/none:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
# - "$ROOT/dav:/data"
|
||||
- type: volume
|
||||
source: mailu_dav
|
||||
target: /data
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
admin:
|
||||
image: mailu/admin:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
# - "$ROOT/data:/data"
|
||||
- type: volume
|
||||
source: mailu_data
|
||||
target: /data
|
||||
# - "$ROOT/dkim:/dkim"
|
||||
- type: volume
|
||||
source: mailu_dkim
|
||||
target: /dkim
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
depends_on:
|
||||
- redis
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
webmail:
|
||||
image: mailu/roundcube:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
# - "$ROOT/webmail:/data"
|
||||
- type: volume
|
||||
source: mailu_data
|
||||
target: /data
|
||||
depends_on:
|
||||
- imap
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
fetchmail:
|
||||
image: mailu/fetchmail:$VERSION
|
||||
restart: always
|
||||
env_file: .env
|
||||
volumes:
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
networks:
|
||||
default:
|
||||
external:
|
||||
name: mailu_default
|
||||
|
||||
volumes:
|
||||
mailu_filter:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/filter"
|
||||
mailu_dkim:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/dkim"
|
||||
mailu_overrides_rspamd:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/overrides/rspamd"
|
||||
mailu_data:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/data"
|
||||
mailu_mail:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/mail"
|
||||
mailu_overrides:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/overrides"
|
||||
mailu_dav:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/dav"
|
||||
mailu_certs:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/certs"
|
||||
mailu_redis:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.0.30,soft,rw"
|
||||
device: ":/mnt/Pool1/pv/mailu/redis"
|
||||
```
|
||||
|
||||
## Deploy Mailu on the docker swarm
|
||||
Run the following command:
|
||||
```bash
|
||||
echo "$(docker-compose -f /mnt/docker/apps/mailu/docker-compose.yml config 2>/dev/null)" | docker stack deploy -c- mailu
|
||||
```
|
||||
See how the services are being deployed:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker service ls
|
||||
ID NAME MODE REPLICAS IMAGE PORTS
|
||||
ywnsetmtkb1l mailu_antivirus replicated 1/1 mailu/none:master
|
||||
pqokiaz0q128 mailu_fetchmail replicated 1/1 mailu/fetchmail:master
|
||||
```
|
||||
check a specific service:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker service ps mailu_fetchmail
|
||||
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
|
||||
tbu8ppgsdffj mailu_fetchmail.1 mailu/fetchmail:master coreos-01 Running Running 11 days ago
|
||||
```
|
||||
|
||||
## Remove the stack
|
||||
Run the follwoing command:
|
||||
```bash
|
||||
core@coreos-01 ~ $ docker stack rm mailu
|
||||
```
|
||||
Reference in New Issue
Block a user