Merge branch 'master' into fix-sender-checks
commit
2d382f2d67
@ -0,0 +1,24 @@
|
||||
""" Add a start day for vacations
|
||||
|
||||
Revision ID: 3b281286c7bd
|
||||
Revises: 25fd6c7bcb4a
|
||||
Create Date: 2018-09-27 22:20:08.158553
|
||||
|
||||
"""
|
||||
|
||||
revision = '3b281286c7bd'
|
||||
down_revision = '25fd6c7bcb4a'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
with op.batch_alter_table('user') as batch:
|
||||
batch.add_column(sa.Column('reply_startdate', sa.Date(), nullable=False,
|
||||
server_default="1900-01-01"))
|
||||
|
||||
|
||||
def downgrade():
|
||||
with op.batch_alter_table('user') as batch:
|
||||
batch.drop_column('reply_startdate')
|
@ -1,2 +1,9 @@
|
||||
{% set version=github_version %}
|
||||
{% extends "!layout.html" %}
|
||||
{% block document %}
|
||||
{% if version != stable_version %}
|
||||
<div class="wy-alert info">
|
||||
<p>You are currently browsing documentation for the <b>{{ version }}</b> branch. Documentation for the stable <b>{{ stable_version }}</b> branch can be found <a href="/{{ stable_version }}/">here</a>.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
|
@ -1,4 +0,0 @@
|
||||
{%- extends "layout.html" %}
|
||||
{% block body %}
|
||||
{{ body|replace("VERSION_TAG", version) }}
|
||||
{% endblock %}
|
@ -0,0 +1,16 @@
|
||||
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
|
||||
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||
<span class="fa fa-book"> Versions</span>
|
||||
v: {{ version }}
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div class="rst-other-versions">
|
||||
<dl>
|
||||
<dt>{{ _('Versions') }}</dt>
|
||||
{% for slug, url in versions %}
|
||||
<dd><a href="{{ url }}">{{ slug }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,21 @@
|
||||
version: '3'
|
||||
|
||||
|
||||
services:
|
||||
docs_master:
|
||||
image: mailu/docs:master
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.port=80
|
||||
- traefik.main.frontend.rule=Host:${hostname};PathPrefix:/master/
|
||||
|
||||
docs_15:
|
||||
image: mailu/docs:1.5
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.port=80
|
||||
- traefik.root.frontend.redirect.regex=.*
|
||||
- traefik.root.frontend.redirect.replacement=/1.5/
|
||||
- traefik.root.frontend.rule=Host:${hostname};PathPrefix:/
|
||||
- traefik.main.frontend.rule=Host:${hostname};PathPrefix:/1.5/
|
||||
|
@ -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
|
||||
kind: Deployment
|
||||
metadata:
|
@ -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
|
@ -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
|
@ -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
|
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$(echo PING | nc localhost 3310)" = "PONG" ]; then
|
||||
echo "ping successful"
|
||||
else
|
||||
echo "ping failed"
|
||||
exit 1
|
||||
fi
|
@ -1,124 +1,106 @@
|
||||
{% set env='mailu.env' %}
|
||||
# This file is auto-generated by the Mailu configuration wizard.
|
||||
# Please read the documentation before attempting any change.
|
||||
# Generated for {{ flavor }} flavor
|
||||
|
||||
version: '2'
|
||||
version: '3.6'
|
||||
|
||||
services:
|
||||
|
||||
# External dependencies
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: always
|
||||
volumes:
|
||||
- "$ROOT/redis:/data"
|
||||
- "{{ root }}/redis:/data"
|
||||
|
||||
# Core services
|
||||
front:
|
||||
image: mailu/nginx:{{ version }}
|
||||
restart: always
|
||||
env_file: {{ env }}
|
||||
env:
|
||||
- TLS_FLAVOR={{ tls_flavor or 'letsencrypt' }}
|
||||
- ADMIN={{ expose_admin or 'no' }}
|
||||
ports:
|
||||
{% for port in (80, 443, 25, 465, 587, 110, 995, 143, 993) %}
|
||||
{% if bind4 %}
|
||||
- "$PUBLIC_IPV4:{{ port }}:{{ port }}"
|
||||
- "{{ bind4 }}:{{ port }}:{{ port }}"
|
||||
{% endif %}
|
||||
{% if bind6 %}
|
||||
- "$PUBLIC_IPV6:{{ port }}:{{ port }}"
|
||||
- "{{ bind6 }}:{{ port }}:{{ port }}"
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if flavor in ('cert', 'mail') %}
|
||||
volumes:
|
||||
- "$ROOT/certs:/certs"
|
||||
{% endif %}
|
||||
- "{{ root }}/certs:/certs"
|
||||
|
||||
admin:
|
||||
image: mailu/admin:{{ version }}
|
||||
restart: always
|
||||
env_file: {{ env }}
|
||||
{% if not expose_admin %}
|
||||
{% if not admin_enabled %}
|
||||
ports:
|
||||
- 127.0.0.1:8080:80
|
||||
{% endif %}
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
- "$ROOT/dkim:/dkim"
|
||||
- "{{ root }}/data:/data"
|
||||
- "{{ root }}/dkim:/dkim"
|
||||
depends_on:
|
||||
- redis
|
||||
|
||||
imap:
|
||||
image: mailu/dovecot:{{ version }}
|
||||
restart: always
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
- "$ROOT/mail:/mail"
|
||||
- "$ROOT/overrides:/overrides"
|
||||
- "{{ root }}/mail:/mail"
|
||||
- "{{ root }}/overrides:/overrides"
|
||||
depends_on:
|
||||
- front
|
||||
|
||||
smtp:
|
||||
image: mailu/postfix:{{ version }}
|
||||
restart: always
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
- "$ROOT/overrides:/overrides"
|
||||
- "{{ root }}/overrides:/overrides"
|
||||
depends_on:
|
||||
- front
|
||||
|
||||
# Optional services
|
||||
{% if enable_antispam %}
|
||||
{% if antispam_enabled %}
|
||||
antispam:
|
||||
image: mailu/rspamd:{{ version }}
|
||||
restart: always
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "$ROOT/filter:/var/lib/rspamd"
|
||||
- "$ROOT/dkim:/dkim"
|
||||
- "$ROOT/overrides/rspamd:/etc/rspamd/override.d"
|
||||
- "{{ root }}/filter:/var/lib/rspamd"
|
||||
- "{{ root }}/dkim:/dkim"
|
||||
- "{{ root }}/overrides/rspamd:/etc/rspamd/override.d"
|
||||
depends_on:
|
||||
- front
|
||||
{% endif %}
|
||||
|
||||
{% if enable_antivirus %}
|
||||
{% if antivirus_enabled %}
|
||||
antivirus:
|
||||
image: mailu/clamav:{{ version }}
|
||||
restart: always
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "$ROOT/filter:/data"
|
||||
- "{{ root }}/filter:/data"
|
||||
{% endif %}
|
||||
|
||||
{% if enable_webdav %}
|
||||
{% if webdav_enabled %}
|
||||
webdav:
|
||||
image: mailu/radivale:{{ version }}
|
||||
restart: always
|
||||
image: mailu/radicale:{{ version }}
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "$ROOT/dav:/data"
|
||||
- "{{ root }}/dav:/data"
|
||||
{% endif %}
|
||||
|
||||
{% if enable_fetchmail %}
|
||||
{% if fetchmail_enabled %}
|
||||
fetchmail:
|
||||
image: mailu/fetchmail:{{ version }}
|
||||
restart: always
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "$ROOT/data:/data"
|
||||
{% endif %}
|
||||
|
||||
# Webmail
|
||||
{% if enable_webmail %}
|
||||
{% if webmail_type != 'none' %}
|
||||
webmail:
|
||||
image: mailu/{{ webmail }}:{{ version }}
|
||||
restart: always
|
||||
image: mailu/{{ webmail_type }}:{{ version }}
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "$ROOT/webmail:/data"
|
||||
- "{{ root }}/webmail:/data"
|
||||
depends_on:
|
||||
- imap
|
||||
{% endif %}
|
||||
|
@ -0,0 +1,128 @@
|
||||
{% set env='mailu.env' %}
|
||||
# This file is auto-generated by the Mailu configuration wizard.
|
||||
# Please read the documentation before attempting any change.
|
||||
# Generated for {{ flavor }} flavor
|
||||
|
||||
version: '3.6'
|
||||
|
||||
services:
|
||||
|
||||
# External dependencies
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: always
|
||||
volumes:
|
||||
- "{{ root }}/redis:/data"
|
||||
|
||||
# Core services
|
||||
front:
|
||||
image: mailu/nginx:{{ version }}
|
||||
env_file: {{ env }}
|
||||
ports:
|
||||
{% for port in (80, 443, 25, 465, 587, 110, 995, 143, 993) %}
|
||||
- target: {{ port }}
|
||||
published: {{ port }}
|
||||
mode: overlay
|
||||
{% endfor %}
|
||||
volumes:
|
||||
- "{{ root }}/certs:/certs"
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
admin:
|
||||
image: mailu/admin:{{ version }}
|
||||
env_file: {{ env }}
|
||||
{% if not admin_enabled %}
|
||||
ports:
|
||||
- 127.0.0.1:8080:80
|
||||
{% endif %}
|
||||
volumes:
|
||||
- "{{ root }}/data:/data"
|
||||
- "{{ root }}/dkim:/dkim"
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
imap:
|
||||
image: mailu/dovecot:{{ version }}
|
||||
env_file: {{ env }}
|
||||
environment:
|
||||
# Default to 10.0.1.0/24
|
||||
- POD_ADDRESS_RANGE={{ subnet }}
|
||||
volumes:
|
||||
- "{{ root }}/mail:/mail"
|
||||
- "{{ root }}/overrides:/overrides"
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
smtp:
|
||||
image: mailu/postfix:{{ version }}
|
||||
env_file: {{ env }}
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE={{ subnet }}
|
||||
volumes:
|
||||
- "{{ root }}/overrides:/overrides"
|
||||
deploy:
|
||||
replicas: 1
|
||||
|
||||
# Optional services
|
||||
{% if antispam_enabled %}
|
||||
antispam:
|
||||
image: mailu/rspamd:{{ version }}
|
||||
env_file: {{ env }}
|
||||
environment:
|
||||
- POD_ADDRESS_RANGE={{ subnet }}
|
||||
volumes:
|
||||
- "{{ root }}/filter:/var/lib/rspamd"
|
||||
- "{{ root }}/dkim:/dkim"
|
||||
- "{{ root }}/overrides/rspamd:/etc/rspamd/override.d"
|
||||
deploy:
|
||||
replicas: 1
|
||||
{% endif %}
|
||||
|
||||
{% if antivirus_enabled %}
|
||||
antivirus:
|
||||
image: mailu/clamav:{{ version }}
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "{{ root }}/filter:/data"
|
||||
deploy:
|
||||
replicas: 1
|
||||
{% endif %}
|
||||
|
||||
{% if webdav_enabled %}
|
||||
webdav:
|
||||
image: mailu/none:{{ version }}
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "{{ root }}/dav:/data"
|
||||
deploy:
|
||||
replicas: 1
|
||||
{% endif %}
|
||||
|
||||
{% if fetchmail_enabled %}
|
||||
fetchmail:
|
||||
image: mailu/fetchmail:{{ version }}
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "{{ root }}/data:/data"
|
||||
deploy:
|
||||
replicas: 1
|
||||
{% endif %}
|
||||
|
||||
{% if webmail_type != 'none' %}
|
||||
webmail:
|
||||
image: mailu/roundcube:{{ version }}
|
||||
env_file: {{ env }}
|
||||
volumes:
|
||||
- "{{ root }}/webmail:/data"
|
||||
deploy:
|
||||
replicas: 1
|
||||
{% endif %}
|
||||
|
||||
networks:
|
||||
default:
|
||||
driver: overlay
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: {{ subnet }}
|
@ -0,0 +1 @@
|
||||
../compose/mailu.env
|
@ -0,0 +1,60 @@
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% call macros.panel("info", "Step 1 - Download your configuration files") %}
|
||||
<p>Docker Stack expects a project file, named <code>docker-compose.yml</code>
|
||||
in a project directory. First create your project directory.</p>
|
||||
|
||||
<pre><code>mkdir -p /{{ root }}/{redis,certs,data,dkim,mail,overrides/rspamd,filter,dav,webmail}
|
||||
</pre></code>
|
||||
|
||||
<p>Then download the project file. A side configuration file makes it easier
|
||||
to read and check the configuration variables generated by the wizard.</p>
|
||||
|
||||
<pre><code>cd {{ root }}
|
||||
curl {{ url_for('.file', uid=uid, filepath='docker-compose.yml', _external=True) }} > docker-compose.yml
|
||||
curl {{ url_for('.file', uid=uid, filepath='mailu.env', _external=True) }} > mailu.env
|
||||
</pre></code>
|
||||
{% endcall %}
|
||||
|
||||
|
||||
{% call macros.panel("info", "Step 2 - Review the configuration") %}
|
||||
<p>We did not insert any malicious code on purpose in the configurations we
|
||||
distribute, but your download could have been intercepted, or our wizard
|
||||
website could have been compromised, so make sure you check the configuration
|
||||
files before going any further.</p>
|
||||
|
||||
<p>When you are done checking them, check them one last time.</p>
|
||||
{% endcall %}
|
||||
|
||||
{% call macros.panel("info", "Step 3 - Deploy docker stack") %}
|
||||
<p>To deploy the docker stack use the following commands. For more information about setting up docker swarm nodes read the
|
||||
<a href="https://docs.docker.com/get-started">docker documentation</a></p>
|
||||
|
||||
<pre><code>cd {{ root }}
|
||||
docker swarm init
|
||||
docker stack deploy -c docker-compose.yml mailu
|
||||
</pre></code>
|
||||
|
||||
In the docker stack deploy command, mailu is the app name. Feel free to change it.<br/>
|
||||
In order to display the running container you can use<br/>
|
||||
<pre><code>docker ps</code></pre>
|
||||
or
|
||||
<pre><code>docker stack ps --no-trunc mailu</code></pre>
|
||||
Command for removing docker stack is
|
||||
<pre><code>docker stack rm mailu</code></pre>
|
||||
|
||||
Before you can use Mailu, you must create the primary administrator user account. This should be {{ postmaster }}@{{ domain }}. Use the following command, changing PASSWORD to your liking:
|
||||
|
||||
<pre><code>docker exec $(docker ps | grep admin | cut -d ' ' -f1) python manage.py admin {{ postmaster }} {{ domain }} PASSWORD
|
||||
</pre></code>
|
||||
|
||||
<p>Login to the admin interface to change the password for a safe one, at
|
||||
{% if admin_enabled %}
|
||||
one of the hostnames
|
||||
<a href="https://{{ hostnames.split(',')[0] }}{{ admin_path }}">{{ hostnames.split(',')[0] }}{{ admin_path }}</a>.
|
||||
{% else %}
|
||||
<a href="http://127.0.0.1:8080">http://127.0.0.1:8080</a> (only directly from the host running docker).
|
||||
{% endif %}
|
||||
And choose the "Update password" option in the left menu.
|
||||
</p>
|
||||
{% endcall %}
|
@ -0,0 +1,39 @@
|
||||
{% call macros.panel("info", "Step 4 - expose Mailu to the world") %}
|
||||
<p>A mail server must be exposed to the world to receive emails, send emails,
|
||||
and let users access their mailboxes. Mailu has some flexibility in the way
|
||||
you expose it to the world.</p>
|
||||
|
||||
<p>Among Mailu services, the <em>front</em> server is the one accepting connections,
|
||||
be it directly from the outside world, through a reverse proxy or in any
|
||||
complex configuration that you might want to setup. It needs to listen on some
|
||||
IP addresses in order to expose its public services. You must at least setup
|
||||
an IPv4 or an IPv6 address if you wish to access Mailu.</p>
|
||||
|
||||
<p><span class="label label-warning">Warning</span> You must use specific addresses, please
|
||||
avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</code>.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IPv4 listen address</label>
|
||||
<!-- Validates IPv4 address -->
|
||||
<input class="form-control" type="text" name="bind4" value="127.0.0.1"
|
||||
pattern="^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IPv6 listen address</label>
|
||||
<!-- Validates IPv6 address -->
|
||||
<input class="form-control" type="text" name="bind6" value="::1"
|
||||
pattern="^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$">
|
||||
</div>
|
||||
|
||||
<p>You server will be available under a main hostname but may expose multiple public
|
||||
hostnames. Every e-mail domain that points to this server must have one of the
|
||||
hostnames in its <code>MX</code> record. Hostnames must be coma-separated.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Public hostnames</label>
|
||||
<!-- Validates hostname or list of hostnames -->
|
||||
<input class="form-control" type="text" name="hostnames" placeholder="my.host.name,other.host.name" multiple required
|
||||
pattern="^(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)*(?:,(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)\s*)*$">
|
||||
</div>
|
||||
{% endcall %}
|
@ -0,0 +1,78 @@
|
||||
{% call macros.panel("info", "Step 2 - Initial configuration") %}
|
||||
<p>Before starting some variables must be set</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Root path: </label>
|
||||
<!-- Validates path -->
|
||||
<input class="form-control" type="text" name="root" value="/mailu" required pattern="^/[-_A-Za-z0-9]+(/[-_A-Za-z0-9]*)*">
|
||||
</div>
|
||||
|
||||
<p>In the next sections we need to set the postmaster address. This is a combination from the <i>postmaster</i> local part and the <i>main mail domain</i>.
|
||||
The <i>main mail domain</i> is also used as </i>"server display name"</i>. This is the way the SMTP server identifies himself when connecting to others.
|
||||
The Postmaster will get an e-mail address <postmaster>@<main_domain>. This address will receive the DMARC "rua" and "ruf" reports.
|
||||
Or in plain english: if receivers start to classify your mail as spam, this postmaster will be informed.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>
|
||||
Main mail domain and server display name.
|
||||
</label>
|
||||
<!-- Validates domain name -->
|
||||
<input class="form-control" type="text" name="domain" placeholder="e.g. mailu.io"
|
||||
required pattern="^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Postmaster local part</label>
|
||||
<input class="form-control" type="text" name="postmaster" value="admin" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Choose how you wish to handle security (TLS) certificates</label>
|
||||
<br/>
|
||||
<select class="btn btn-primary dropdown-toggle" name="tls_flavor">
|
||||
{% for tlsflavor in ["letsencrypt", "cert", "notls", "mail", "mail-letsencrypt"] %}
|
||||
<option value="{{ tlsflavor }}" >{{ tlsflavor }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Authentication rate limit (per source IP address)</label>
|
||||
<!-- Validates number input only -->
|
||||
<p><input class="form-control" style="width: 7%; display: inline;" type="number" name="auth_ratelimit_pm"
|
||||
value="10" required >/minute;
|
||||
<input class="form-control" style="width: 7%; display: inline;;" type="number" name="auth_ratelimit_ph"
|
||||
value="1000" required >/hour</p>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-check-inline">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" type="checkbox" name="disable_statistics" value="True">
|
||||
Opt-out of statistics
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Website name</label>
|
||||
<input class="form-control" type="text" name="site_name" value="Mailu" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Linked Website URL</label>
|
||||
<!-- Validates url with or without https:// -->
|
||||
<input class="form-control" type="url" name="website" value="https://mailu.io" required
|
||||
pattern="^(https?://)?([a-zA-Z0-9]([a-zA-ZäöüÄÖÜ0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$">
|
||||
</div>
|
||||
|
||||
<p>The admin interface is the main Mailu-specific bit, it provides tools to
|
||||
manage your email domains, users, etc.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Enable the admin UI (and path to the admin UI)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><input type="checkbox" name="admin_enabled" value="true"></div>
|
||||
<input class="form-control" type="text" name="admin_path" value="/admin">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endcall %}
|
@ -1,33 +0,0 @@
|
||||
{% call macros.panel("info", "Step 2 - expose Mailu to the world") %}
|
||||
<p>A mail server must be exposed to the world to receive emails, send emails,
|
||||
and let users access their mailboxes. Mailu has some flexibility in the way
|
||||
you expose it to the world.</p>
|
||||
|
||||
<p>Among Mailu services, the <em>front</em> server is the one accepting connections,
|
||||
be it directly from the outside world, through a reverse proxy or in any
|
||||
complex configuration that you might want to setup. It needs to listen on some
|
||||
IP addresses in order to expose its public services. You must at least setup
|
||||
an IPv4 or an IPv6 address if you wish to access Mailu.</p>
|
||||
|
||||
<p><span class="label label-warning">Warning</span> You must use specific addresses, please
|
||||
avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</code>.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IPv4 listen address</label>
|
||||
<input class="form-control" type="text" name="ip4" placeholder="1.2.3.4">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IPv6 listen address</label>
|
||||
<input class="form-control" type="text" name="ip6" placeholder="2001:be4:1234::1">
|
||||
</div>
|
||||
|
||||
<p>You server will be available under a main hostname but may expose multiple public
|
||||
hostnames. Every e-mail domain that points to this server must have one of the
|
||||
hostnames in its <code>MX</code> record. Hostnames must be coma-separated.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Public hostnames</label>
|
||||
<input class="form-control" type="text" name="hostnames" placeholder="my.host.name,other.host.name" multiple>
|
||||
</div>
|
||||
{% endcall %}
|
@ -1,16 +0,0 @@
|
||||
{% call macros.panel("info", "Step 4 - enable optional features") %}
|
||||
<p>Mailu also comes with less common optional features that you might wish
|
||||
to enable.</p>
|
||||
|
||||
<p>The DAV service enables contacts and calendar storage through Mailu,
|
||||
it is especially userful when synchronizing your desktop and mobile devices.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Enable the DAV service (and path to the DAV service)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><input type="checkbox" name="dav_enabled" checked></div>
|
||||
<input class="form-control" type="text" name="admin_path" value="/webdav">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endcall %}
|
@ -0,0 +1,62 @@
|
||||
{% call macros.panel("info", "Step 3 - pick some features") %}
|
||||
<p>Mailu comes with multiple base features, including a specific admin
|
||||
interface, Web email clients (webmails), antispam, antivirus, etc. If you
|
||||
wish to disable some of these features, you are free to do so.</p>
|
||||
|
||||
<p>Emails will be available through IMAP and POP3. You may also enable a Web
|
||||
email client. These do add some complexity but provide an easier way of
|
||||
accessing messages for beginner users.</p>
|
||||
|
||||
<!-- Switched from radio buttons to dropdown menu in order to remove the checkbox -->
|
||||
<div class="form-group">
|
||||
<label>Enable Web email client (and path to the Web email client)</label>
|
||||
<!-- <div class="radio"> -->
|
||||
<!-- {{ macros.radio("webmail_type", "roundcube", "RoundCube", "popular Webmail running on top of PHP") }} -->
|
||||
<!-- {{ macros.radio("webmail_type", "rainloop", "Rainloop", "lightweight Webmail based on PHP, no database") }} -->
|
||||
<!-- </div> -->
|
||||
<br/>
|
||||
<select class="btn btn-primary dropdown-toggle" name="webmail_type">
|
||||
{% for webmailtype in ["none", "roundcube", "rainloop"] %}
|
||||
<option value="{{ webmailtype }}" >{{ webmailtype }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<p></p>
|
||||
<div class="input-group">
|
||||
<!-- <div class="input-group-addon"><input type="checkbox" name="webmail_enabled" value="true"></div> -->
|
||||
<input class="form-control" type="text" name="webmail_path" value="/webmail">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Email filtering is a really important features. You can still disable it, which
|
||||
will prevent Mailu from doing spam filtering, virus filtering, and from applying
|
||||
white and blacklists that you may configure in the admin interface. You may
|
||||
also disable the antivirus if required (it does use aroung 1GB of ram).</p>
|
||||
|
||||
<div class="form-check form-check-inline">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" type="checkbox" name="antispam_enabled" value="rspamd" checked>
|
||||
Enable the spam filtering service
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" type="checkbox" name="antivirus_enabled" value="clamav">
|
||||
Enable the antivirus service
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-check-inline">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" type="checkbox" name="webdav_enabled" value="radicale">
|
||||
Enable the webdav service
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-check-inline">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" type="checkbox" name="fetchmail_enabled" value="true">
|
||||
Enable fetchmail
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{% endcall %}
|
@ -0,0 +1,21 @@
|
||||
{% call macros.panel("info", "Step 4 - expose Mailu to the world") %}
|
||||
<p>A mail server must be exposed to the world to receive emails, send emails,
|
||||
and let users access their mailboxes. Mailu has some flexibility in the way
|
||||
you expose it to the world.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Subnet</label>
|
||||
<input class="form-control" type="text" name="subnet" required pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))$">
|
||||
</div>
|
||||
|
||||
<p>You server will be available under a main hostname but may expose multiple public
|
||||
hostnames. Every e-mail domain that points to this server must have one of the
|
||||
hostnames in its <code>MX</code> record. Hostnames must be coma-separated.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Public hostnames</label>
|
||||
<!-- Validates hostname or list of hostnames -->
|
||||
<input class="form-control" type="text" name="hostnames" placeholder="my.host.name,other.host.name" multiple required
|
||||
pattern="^(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)*(?:,(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)\s*)*$">
|
||||
</div>
|
||||
{% endcall %}
|
Loading…
Reference in New Issue