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; '' $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 {
# Favicon stuff # Favicon stuff
@ -54,8 +52,8 @@ http {
listen 80; listen 80;
listen [::]:80; listen [::]:80;
# Only enable HTTPS if TLS is enabled with no error # Only enable HTTPS if TLS is enabled with no error and not on kubernetes
{% if TLS and not TLS_ERROR %} {% if KUBERNETES_INGRESS != 'true' and TLS and not TLS_ERROR %}
listen 443 ssl http2; listen 443 ssl http2;
listen [::]:443 ssl http2; listen [::]:443 ssl http2;
@ -76,15 +74,15 @@ http {
add_header X-XSS-Protection '1; mode=block'; add_header X-XSS-Protection '1; mode=block';
add_header Referrer-Policy 'same-origin'; add_header Referrer-Policy 'same-origin';
# In any case, enable the proxy for certbot if the flavor is letsencrypt # In any case, enable the proxy for certbot if the flavor is letsencrypt and not on kubernetes
{% if TLS_FLAVOR in [ 'letsencrypt', 'mail-letsencrypt' ] %} {% if KUBERNETES_INGRESS != 'true' and TLS_FLAVOR in [ 'letsencrypt', 'mail-letsencrypt' ] %}
location ^~ /.well-known/acme-challenge/ { location ^~ /.well-known/acme-challenge/ {
proxy_pass http://127.0.0.1:8008; proxy_pass http://127.0.0.1:8008;
} }
{% endif %} {% endif %}
# If TLS is failing, prevent access to anything except certbot # 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 / { location / {
return 403; return 403;
} }
@ -167,7 +165,6 @@ http {
return 204; return 204;
} }
} }
{% endif %}
# Forwarding authentication server # Forwarding authentication server
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: - matchExpressions:
- key: node-role.kubernetes.io/node - key: node-role.kubernetes.io/node
operator: Exists operator: Exists
hostNetwork: true
nodeSelector: nodeSelector:
node-role.kubernetes.io/node: "" node-role.kubernetes.io/node: ""
dnsPolicy: ClusterFirstWithHostNet dnsPolicy: ClusterFirstWithHostNet
@ -46,34 +45,45 @@ spec:
ports: ports:
- name: pop3 - name: pop3
containerPort: 110 containerPort: 110
hostPort: 110
protocol: TCP protocol: TCP
- name: pop3s - name: pop3s
containerPort: 995 containerPort: 995
hostPort: 995
protocol: TCP protocol: TCP
- name: imap - name: imap
containerPort: 143 containerPort: 143
hostPort: 143
protocol: TCP protocol: TCP
- name: imaps - name: imaps
containerPort: 993 containerPort: 993
hostPort: 993
protocol: TCP protocol: TCP
- name: smtp - name: smtp
containerPort: 25 containerPort: 25
hostPort: 25
protocol: TCP 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 - name: smtp-auth
containerPort: 10025 containerPort: 10025
protocol: TCP protocol: TCP
- name: imap-auth - name: imap-auth
containerPort: 10143 containerPort: 10143
protocol: TCP protocol: TCP
- name: smtps
containerPort: 465
protocol: TCP
- name: smtpd
containerPort: 587
protocol: TCP
- name: auth - name: auth
containerPort: 8000 containerPort: 8000
protocol: TCP protocol: TCP
- name: http
containerPort: 80
protocol: TCP
resources: resources:
requests: requests:
memory: 100Mi memory: 100Mi
@ -133,3 +143,6 @@ spec:
- name: imap-auth - name: imap-auth
port: 10143 port: 10143
protocol: TCP 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. - ``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. - ``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 - ``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 What you need
@ -24,7 +24,9 @@ What you need
- A working Kubernetes cluster (tested with 1.10.5) - A working Kubernetes cluster (tested with 1.10.5)
- A working `cert-manager`_ installation - A working `cert-manager`_ installation
- A working nginx-ingress controller needed for the lets-encrypt - 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 Cert manager
^^^^^^^^^^^^ ^^^^^^^^^^^^
@ -67,8 +69,8 @@ An example of a production and a staging ``clusterIssuer``:
name: letsencrypt-prod name: letsencrypt-prod
server: https://acme-v02.api.letsencrypt.org/directory server: https://acme-v02.api.letsencrypt.org/directory
**IMPORTANT**: All ``*-ingress.yaml`` files use the ``letsencrypt-stage`` ``clusterIssuer``. If you are ready for production, **IMPORTANT**: ``ingress.yaml`` uses 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. 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`` 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 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 - 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 ``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 ``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 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 fetchmail.yaml
kubectl create -f admin.yaml kubectl create -f admin.yaml
kubectl create -f webdav.yaml kubectl create -f webdav.yaml
kubectl create -f admin-ingress.yaml kubectl create -f 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 Create the first admin account

@ -1,20 +1,15 @@
apiVersion: extensions/v1beta1 apiVersion: extensions/v1beta1
kind: Ingress kind: Ingress
metadata: metadata:
name: mailu-antispam-ingress name: mailu-ingress
namespace: mailu-mailserver namespace: mailu-mailserver
annotations: annotations:
kubernetes.io/tls-acme: "true" kubernetes.io/tls-acme: "true"
certmanager.k8s.io/cluster-issuer: letsencrypt-stage 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: labels:
app: mailu app: mailu
role: mail role: mail
tier: frontend tier: backend
spec: spec:
tls: tls:
- hosts: - hosts:
@ -24,7 +19,7 @@ spec:
- host: "mail.example.com" - host: "mail.example.com"
http: http:
paths: paths:
- path: "/admin/antispam" - path: "/"
backend: backend:
serviceName: antispam serviceName: front
servicePort: 11334 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