1158: Use nginx for kubernetes ingress r=kaiyou a=micw

## What type of PR?

enhancement

## What does this PR do?

Currently, kubernetes uses a complex ingress setting which is not portable across different ingress controllers. This PR simplifies the ingress and delegates everythins special to Mailu to the front container,

### Related issue(s)
- closes #1121
- closes #1117
- closes #1021
- closes #1045

## Prerequistes

- [x] In case of feature or enhancement: documentation updated accordingly
- [x] Unless it's docs or a minor change: add [changelog]

Co-authored-by: Michael Wyraz <michael@wyraz.de>
master
bors[bot] 5 years ago committed by GitHub
commit 20e00ac0c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,8 +34,6 @@ http {
'' $scheme;
}
# Disable the main http server when on kubernetes (port 80 and 443)
{% if KUBERNETES_INGRESS != 'true' %}
# Main HTTP server
server {
# Favicon stuff
@ -54,8 +52,8 @@ http {
listen 80;
listen [::]:80;
# Only enable HTTPS if TLS is enabled with no error
{% if TLS and not TLS_ERROR %}
# Only enable HTTPS if TLS is enabled with no error and not on kubernetes
{% if KUBERNETES_INGRESS != 'true' and TLS and not TLS_ERROR %}
listen 443 ssl http2;
listen [::]:443 ssl http2;
@ -76,15 +74,15 @@ http {
add_header X-XSS-Protection '1; mode=block';
add_header Referrer-Policy 'same-origin';
# In any case, enable the proxy for certbot if the flavor is letsencrypt
{% if TLS_FLAVOR in [ 'letsencrypt', 'mail-letsencrypt' ] %}
# In any case, enable the proxy for certbot if the flavor is letsencrypt and not on kubernetes
{% if KUBERNETES_INGRESS != 'true' and TLS_FLAVOR in [ 'letsencrypt', 'mail-letsencrypt' ] %}
location ^~ /.well-known/acme-challenge/ {
proxy_pass http://127.0.0.1:8008;
}
{% endif %}
# If TLS is failing, prevent access to anything except certbot
{% if TLS_ERROR and not TLS_FLAVOR == "mail" %}
{% if KUBERNETES_INGRESS != 'true' and TLS_ERROR and not TLS_FLAVOR == "mail" %}
location / {
return 403;
}
@ -167,7 +165,6 @@ http {
return 204;
}
}
{% endif %}
# Forwarding authentication server
server {

@ -1,86 +0,0 @@
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

@ -27,7 +27,6 @@ spec:
- matchExpressions:
- key: node-role.kubernetes.io/node
operator: Exists
hostNetwork: true
nodeSelector:
node-role.kubernetes.io/node: ""
dnsPolicy: ClusterFirstWithHostNet
@ -46,34 +45,45 @@ spec:
ports:
- name: pop3
containerPort: 110
hostPort: 110
protocol: TCP
- name: pop3s
containerPort: 995
hostPort: 995
protocol: TCP
- name: imap
containerPort: 143
hostPort: 143
protocol: TCP
- name: imaps
containerPort: 993
hostPort: 993
protocol: TCP
- name: smtp
containerPort: 25
hostPort: 25
protocol: TCP
- name: smtps
containerPort: 465
hostPort: 465
protocol: TCP
- name: smtpd
containerPort: 587
hostPort: 587
protocol: TCP
# internal services (not exposed externally)
- name: smtp-auth
containerPort: 10025
protocol: TCP
- name: imap-auth
containerPort: 10143
protocol: TCP
- name: smtps
containerPort: 465
protocol: TCP
- name: smtpd
containerPort: 587
protocol: TCP
- name: auth
containerPort: 8000
protocol: TCP
- name: http
containerPort: 80
protocol: TCP
resources:
requests:
memory: 100Mi
@ -133,3 +143,6 @@ spec:
- name: imap-auth
port: 10143
protocol: TCP
- name: http
port: 80
protocol: TCP

@ -15,7 +15,7 @@ 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 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,...). It also listens on 80 and delegates the various http endpoints to the correct services.
- ``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
@ -24,7 +24,9 @@ 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
certificates. You can find those files in the ``nginx`` subfolder.
Other ingress controllers that support cert-manager (e.g. traefik)
should also work.
Cert manager
^^^^^^^^^^^^
@ -67,8 +69,8 @@ An example of a production and a staging ``clusterIssuer``:
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.
**IMPORTANT**: ``ingress.yaml`` uses the ``letsencrypt-stage`` ``clusterIssuer``. If you are ready for production,
change this field in ``ingress.yaml`` file 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
@ -83,7 +85,7 @@ 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)
- Check the ``ingress.yaml`` file 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
------------
@ -107,10 +109,7 @@ To start Mailu, run the following commands from the ``docs/kubernetes/mailu`` di
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
kubectl create -f ingress.yaml
Create the first admin account

@ -1,20 +1,15 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mailu-antispam-ingress
name: mailu-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
tier: backend
spec:
tls:
- hosts:
@ -24,7 +19,7 @@ spec:
- host: "mail.example.com"
http:
paths:
- path: "/admin/antispam"
- path: "/"
backend:
serviceName: antispam
servicePort: 11334
serviceName: front
servicePort: 80

@ -1,46 +0,0 @@
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

@ -1,31 +0,0 @@
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

@ -0,0 +1 @@
- Use nginx as http endpoint on kubernetes to simplify ingress
Loading…
Cancel
Save