Merge pull request #576 from hacor/master

Kubernetes fixed for production
master
mergify[bot] 6 years ago committed by GitHub
commit bce1487338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,6 +34,8 @@ http {
'' $scheme; '' $scheme;
} }
# Disable the main http server when on kubernetes (port 80 and 443)
{% if KUBERNETES_INGRESS != 'true' %}
# Main HTTP server # Main HTTP server
server { server {
# Variables for proxifying # Variables for proxifying
@ -149,6 +151,7 @@ http {
proxy_set_header Content-Length ""; proxy_set_header Content-Length "";
} }
} }
{% endif %}
# Forwarding authentication server # Forwarding authentication server
server { server {

@ -55,7 +55,7 @@ the version of Mailu that you are running.
configuration configuration
compose/requirements compose/requirements
compose/setup compose/setup
kubernetes/stable/index kubernetes/mailu/index
dns dns
reverse 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

@ -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 apiVersion: extensions/v1beta1
kind: Deployment kind: Deployment
metadata: metadata:

@ -21,7 +21,7 @@
VERSION: "master" VERSION: "master"
# Set to a randomly generated 16 bytes string # Set to a randomly generated 16 bytes string
SECRET_KEY: "YourKeyHere" SECRET_KEY: "MySup3rS3cr3tPas"
# Address where listening ports should bind # Address where listening ports should bind
BIND_ADDRESS4: "127.0.0.1" BIND_ADDRESS4: "127.0.0.1"
@ -45,6 +45,14 @@
# Opt-out of statistics, replace with "True" to opt out # Opt-out of statistics, replace with "True" to opt out
DISABLE_STATISTICS: "False" 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 # Optional features
################################### ###################################
@ -71,19 +79,18 @@
# Default: accept messages up to 50MB # Default: accept messages up to 50MB
MESSAGE_SIZE_LIMIT: "50000000" 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 # Will relay all outgoing mails if configured
#RELAYHOST= #RELAYHOST=
# This part is needed for the XCLIENT login for postfix. This should be the POD ADDRESS range # 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" 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
FETCHMAIL_DELAY: "600" FETCHMAIL_DELAY: "600"
@ -106,13 +113,16 @@
################################### ###################################
# Path to the admin interface if enabled # 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" WEB_ADMIN: "/admin"
# Path to the webmail if enabled # 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" WEB_WEBMAIL: "/webmail"
# Website name # Website name
SITENAME: "AppSynth" SITENAME: "Mailu"
# Linked Website URL # Linked Website URL
WEBSITE: "https://example.com" WEBSITE: "https://example.com"

@ -1,23 +1,41 @@
apiVersion: apps/v1beta2
apiVersion: extensions/v1beta1 kind: DaemonSet
kind: Deployment
metadata: metadata:
name: mailu-front name: mailu-front
namespace: mailu-mailserver namespace: mailu-mailserver
labels:
k8s-app: mail-loadbalancer
component: ingress-controller
type: nginx
spec: spec:
replicas: 1 selector:
matchLabels:
k8s-app: mail-loadbalancer
component: ingress-controller
type: nginx
template: template:
metadata: metadata:
labels: labels:
app: mailu-front k8s-app: mail-loadbalancer
role: mail component: ingress-controller
tier: backend type: nginx
spec: 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 restartPolicy: Always
terminationGracePeriodSeconds: 60 terminationGracePeriodSeconds: 60
containers: containers:
- name: front - name: front
image: mailu/nginx:latest image: mailu/nginx:master
imagePullPolicy: Always imagePullPolicy: Always
envFrom: envFrom:
- configMapRef: - configMapRef:
@ -26,12 +44,6 @@ spec:
- name: certs - name: certs
mountPath: /certs mountPath: /certs
ports: ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
- name: pop3 - name: pop3
containerPort: 110 containerPort: 110
protocol: TCP protocol: TCP
@ -85,21 +97,15 @@ metadata:
name: front name: front
namespace: mailu-mailserver namespace: mailu-mailserver
labels: labels:
app: mailu-admin k8s-app: mail-loadbalancer
role: mail component: ingress-controller
tier: backend type: nginx
spec: spec:
selector: selector:
app: mailu-front k8s-app: mail-loadbalancer
role: mail component: ingress-controller
tier: backend type: nginx
ports: ports:
- name: http
port: 80
protocol: TCP
- name: https
port: 443
protocol: TCP
- name: pop3 - name: pop3
port: 110 port: 110
protocol: TCP protocol: TCP

@ -37,8 +37,8 @@ spec:
- containerPort: 4190 - containerPort: 4190
resources: resources:
requests: requests:
memory: 500Mi memory: 1Gi
cpu: 500m cpu: 1000m
limits: limits:
memory: 1Gi memory: 1Gi
cpu: 1000m cpu: 1000m

@ -0,0 +1,193 @@
Install Mailu master on kubernetes
==================================
Prequisites
-----------
Structure
~~~~~~~~~
Theres 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`` youll 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

@ -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 - name: antispam
containerPort: 11332 containerPort: 11332
protocol: TCP protocol: TCP
- name: antispam-http
containerPort: 11334
protocol: TCP
volumeMounts: volumeMounts:
- name: filter - name: filter
subPath: filter subPath: filter
@ -87,6 +90,9 @@ spec:
- name: antispam - name: antispam
port: 11332 port: 11332
protocol: TCP protocol: TCP
- name: antispam-http
protocol: TCP
port: 11334
--- ---

@ -21,10 +21,10 @@ spec:
name: mailu-config name: mailu-config
resources: resources:
requests: requests:
memory: 500Mi memory: 2Gi
cpu: 200m cpu: 500m
limits: limits:
memory: 1Gi memory: 2Gi
cpu: 500m cpu: 500m
volumeMounts: volumeMounts:
- mountPath: /data - mountPath: /data

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

@ -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: spec:
containers: containers:
- name: roundcube - name: roundcube
image: mailu/roundcube:1.5 image: mailu/roundcube:master
imagePullPolicy: Always imagePullPolicy: Always
envFrom: envFrom:
- configMapRef: - configMapRef:

@ -2,15 +2,15 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
# keep it under 24 chars # keep it under 24 chars
name: appsynth-lb name: ingress-lb
namespace: kube-ingress namespace: kube-ingress
labels: labels:
k8s-app: appsynth-lb k8s-app: ingress-lb
component: ingress-controller component: ingress-controller
spec: spec:
type: ClusterIP type: ClusterIP
selector: selector:
k8s-app: appsynth-lb k8s-app: ingress-lb
component: ingress-controller component: ingress-controller
ports: ports:
- name: http - name: http
@ -35,13 +35,6 @@ metadata:
name: tcp-services name: tcp-services
namespace: kube-ingress namespace: kube-ingress
data: 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 apiVersion: v1
@ -61,7 +54,7 @@ metadata:
prometheus.io/port: "10254" prometheus.io/port: "10254"
prometheus.io/scrape: "true" prometheus.io/scrape: "true"
labels: labels:
k8s-app: appsynth-lb k8s-app: ingress-lb
component: ingress-controller component: ingress-controller
type: nginx type: nginx
spec: spec:
@ -71,13 +64,13 @@ spec:
type: RollingUpdate type: RollingUpdate
selector: selector:
matchLabels: matchLabels:
k8s-app: appsynth-lb k8s-app: ingress-lb
component: ingress-controller component: ingress-controller
type: nginx type: nginx
template: template:
metadata: metadata:
labels: labels:
k8s-app: appsynth-lb k8s-app: ingress-lb
component: ingress-controller component: ingress-controller
type: nginx type: nginx
spec: spec:
@ -94,14 +87,11 @@ spec:
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.2 image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.2
args: args:
- /nginx-ingress-controller - /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/tectonic-custom-error
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
#- --default-ssl-certificate=tectonic-system/tectonic-ingress-tls-secret
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --annotations-prefix=ingress.kubernetes.io - --annotations-prefix=ingress.kubernetes.io
- --enable-ssl-passthrough - --enable-ssl-passthrough
- --ingress-class=tectonic
# use downward API # use downward API
env: env:
- name: POD_NAME - name: POD_NAME
@ -115,10 +105,8 @@ spec:
ports: ports:
- name: http - name: http
containerPort: 80 containerPort: 80
hostPort: 80
- name: https - name: https
containerPort: 443 containerPort: 443
hostPort: 443
readinessProbe: readinessProbe:
httpGet: httpGet:
path: /healthz path: /healthz
@ -134,6 +122,6 @@ spec:
hostNetwork: true hostNetwork: true
nodeSelector: nodeSelector:
node-role.kubernetes.io/node: "" node-role.kubernetes.io/node: ""
dnsPolicy: ClusterFirst dnsPolicy: ClusterFirstWithHostNet
restartPolicy: Always restartPolicy: Always
terminationGracePeriodSeconds: 60 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
Loading…
Cancel
Save