Merge pull request #576 from hacor/master
Kubernetes fixed for production
This commit is contained in:
@@ -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
|
|
||||||
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
|
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
|
||||||
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
|
- 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
|
||||||
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:
|
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
|
|
||||||
Reference in New Issue
Block a user