From d0f759accae612eec2520de97eaad3fa8aebc527 Mon Sep 17 00:00:00 2001 From: Patrick Oberdorf Date: Wed, 14 Feb 2018 12:15:45 +0100 Subject: [PATCH 01/93] Adding unbound as dns resolver --- core/unbound/Dockerfile | 14 +++++ core/unbound/unbound.conf | 19 +++++++ docs/compose/.env | 3 ++ docs/compose/docker-compose.yml | 94 ++++++++++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 core/unbound/Dockerfile create mode 100644 core/unbound/unbound.conf diff --git a/core/unbound/Dockerfile b/core/unbound/Dockerfile new file mode 100644 index 00000000..6ae8a6ee --- /dev/null +++ b/core/unbound/Dockerfile @@ -0,0 +1,14 @@ +FROM alpine:edge + +RUN apk add --no-cache unbound curl \ + && curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache \ + && chown root:unbound /etc/unbound \ + && chmod 775 /etc/unbound \ + && apk del --no-cache curl \ + && /usr/sbin/unbound-anchor -a /etc/unbound/trusted-key.key | true + +COPY unbound.conf /etc/unbound/unbound.conf + +EXPOSE 53/udp 53/tcp + +CMD /usr/sbin/unbound diff --git a/core/unbound/unbound.conf b/core/unbound/unbound.conf new file mode 100644 index 00000000..d2d9ce74 --- /dev/null +++ b/core/unbound/unbound.conf @@ -0,0 +1,19 @@ +server: + verbosity: 1 + interface: 0.0.0.0 + interface: ::0 + logfile: /dev/stdout + do-ip4: yes + do-ip6: yes + do-udp: yes + do-tcp: yes + do-daemonize: no + access-control: 0.0.0.0/0 allow + directory: "/etc/unbound" + username: unbound + auto-trust-anchor-file: trusted-key.key + root-hints: "/etc/unbound/root.hints" + hide-identity: yes + hide-version: yes + max-udp-size: 4096 + msg-buffer-size: 65552 diff --git a/docs/compose/.env b/docs/compose/.env index 6f330b64..e4c6dff9 100644 --- a/docs/compose/.env +++ b/docs/compose/.env @@ -21,6 +21,9 @@ SECRET_KEY=ChangeMeChangeMe BIND_ADDRESS4=127.0.0.1 BIND_ADDRESS6=::1 +# Internal Docker network +IPV4_NETWORK=172.22.1 + # Main mail domain DOMAIN=mailu.io diff --git a/docs/compose/docker-compose.yml b/docs/compose/docker-compose.yml index 740a5ffc..dc674a2b 100644 --- a/docs/compose/docker-compose.yml +++ b/docs/compose/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2' +version: '2.1' services: @@ -27,12 +27,37 @@ services: - "$BIND_ADDRESS6:587:587" volumes: - "$ROOT/certs:/certs" + depends_on: + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - front + + unbound: + image: mailu/unbound:$VERSION + restart: always + networks: + backend: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.254 + aliases: + - unbound redis: image: redis:alpine restart: always volumes: - "$ROOT/redis:/data" + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + depends_on: + - unbound + networks: + backend: + aliases: + - redis imap: image: mailu/dovecot:$VERSION @@ -44,6 +69,13 @@ services: - "$ROOT/overrides:/overrides" depends_on: - front + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - imap smtp: image: mailu/postfix:$VERSION @@ -54,6 +86,13 @@ services: - "$ROOT/overrides:/overrides" depends_on: - front + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - smtp antispam: image: mailu/rspamd:$VERSION @@ -65,6 +104,13 @@ services: - "$ROOT/overrides/rspamd:/etc/rspamd/override.d" depends_on: - front + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - antispam antivirus: image: mailu/$ANTIVIRUS:$VERSION @@ -72,6 +118,14 @@ services: env_file: .env volumes: - "$ROOT/filter:/data" + depends_on: + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - antivirus webdav: image: mailu/$WEBDAV:$VERSION @@ -79,6 +133,14 @@ services: env_file: .env volumes: - "$ROOT/dav:/data" + depends_on: + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - webdav admin: image: mailu/admin:$VERSION @@ -90,6 +152,13 @@ services: - /var/run/docker.sock:/var/run/docker.sock:ro depends_on: - redis + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - admin webmail: image: "mailu/$WEBMAIL:$VERSION" @@ -99,6 +168,13 @@ services: - "$ROOT/webmail:/data" depends_on: - imap + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - webmail fetchmail: image: mailu/fetchmail:$VERSION @@ -106,3 +182,19 @@ services: env_file: .env volumes: - "$ROOT/data:/data" + depends_on: + - unbound + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + networks: + backend: + aliases: + - fetchmail + +networks: + backend: + driver: bridge + ipam: + driver: default + config: + - subnet: ${IPV4_NETWORK:-172.22.1}.0/24 From 12294a6e5aa3c57c8c603d97a35fa443a962a8e2 Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Wed, 6 Jun 2018 18:40:51 +0000 Subject: [PATCH 02/93] Trying to enable fuzzy hashes for rspamd --- services/rspamd/Dockerfile | 5 +--- services/rspamd/conf/fuzzy_check.conf | 34 ++++++++++++++++++++++ services/rspamd/conf/metrics.conf | 19 ++++++++++++ services/rspamd/conf/worker-controller.inc | 1 + services/rspamd/conf/worker-fuzzy.inc | 5 ++++ services/rspamd/conf/worker-normal.inc | 1 + 6 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 services/rspamd/conf/fuzzy_check.conf create mode 100644 services/rspamd/conf/metrics.conf create mode 100644 services/rspamd/conf/worker-fuzzy.inc diff --git a/services/rspamd/Dockerfile b/services/rspamd/Dockerfile index c6c2afdd..1b8d7e6b 100644 --- a/services/rspamd/Dockerfile +++ b/services/rspamd/Dockerfile @@ -1,15 +1,12 @@ FROM alpine:edge -RUN apk add --no-cache python py-jinja2 rspamd rspamd-controller rspamd-proxy ca-certificates +RUN apk add --no-cache python py-jinja2 rspamd rspamd-controller rspamd-proxy rspamd-fuzzy ca-certificates RUN mkdir /run/rspamd COPY conf/ /conf COPY start.py /start.py -# Temporary fix to remove references to rspamd-fuzzy for now -RUN sed -i '/fuzzy/,$d' /etc/rspamd/rspamd.conf - EXPOSE 11332/tcp 11334/tcp CMD /start.py diff --git a/services/rspamd/conf/fuzzy_check.conf b/services/rspamd/conf/fuzzy_check.conf new file mode 100644 index 00000000..7c87e1c3 --- /dev/null +++ b/services/rspamd/conf/fuzzy_check.conf @@ -0,0 +1,34 @@ +rule "local" { + # Fuzzy storage server list + servers = "localhost:11335"; + # Default symbol for unknown flags + symbol = "LOCAL_FUZZY_UNKNOWN"; + # Additional mime types to store/check + mime_types = ["application/*"]; + # Hash weight threshold for all maps + max_score = 20.0; + # Whether we can learn this storage + read_only = no; + # Ignore unknown flags + skip_unknown = yes; + # Hash generation algorithm + algorithm = "mumhash"; + + # Map flags to symbols + fuzzy_map = { + LOCAL_FUZZY_DENIED { + # Local threshold + max_score = 20.0; + # Flag to match + flag = 11; + } + LOCAL_FUZZY_PROB { + max_score = 10.0; + flag = 12; + } + LOCAL_FUZZY_WHITE { + max_score = 2.0; + flag = 13; + } + } +} diff --git a/services/rspamd/conf/metrics.conf b/services/rspamd/conf/metrics.conf new file mode 100644 index 00000000..6a31964f --- /dev/null +++ b/services/rspamd/conf/metrics.conf @@ -0,0 +1,19 @@ +group "fuzzy" { + max_score = 12.0; + symbol "LOCAL_FUZZY_UNKNOWN" { + weight = 5.0; + description = "Generic fuzzy hash match"; + } + symbol "LOCAL_FUZZY_DENIED" { + weight = 12.0; + description = "Denied fuzzy hash"; + } + symbol "LOCAL_FUZZY_PROB" { + weight = 5.0; + description = "Probable fuzzy hash"; + } + symbol "LOCAL_FUZZY_WHITE" { + weight = -2.1; + description = "Whitelisted fuzzy hash"; + } +} diff --git a/services/rspamd/conf/worker-controller.inc b/services/rspamd/conf/worker-controller.inc index 6a020672..dd143942 100644 --- a/services/rspamd/conf/worker-controller.inc +++ b/services/rspamd/conf/worker-controller.inc @@ -1,3 +1,4 @@ +type = "controller"; bind_socket = "*:11334"; password = "mailu"; secure_ip = "{{ FRONT_ADDRESS }}"; diff --git a/services/rspamd/conf/worker-fuzzy.inc b/services/rspamd/conf/worker-fuzzy.inc new file mode 100644 index 00000000..a0021a03 --- /dev/null +++ b/services/rspamd/conf/worker-fuzzy.inc @@ -0,0 +1,5 @@ +type = "fuzzy"; +count = 1; +backend = "redis"; +expire = 90d; +allow_update = ["127.0.0.1"]; diff --git a/services/rspamd/conf/worker-normal.inc b/services/rspamd/conf/worker-normal.inc index a6ee8317..ab996fb8 100644 --- a/services/rspamd/conf/worker-normal.inc +++ b/services/rspamd/conf/worker-normal.inc @@ -1 +1,2 @@ +type = "normal"; enabled = false; From 23e288aadcf7d5df941c8516fae9d0cbd6b1e054 Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Mon, 24 Sep 2018 17:29:31 +0000 Subject: [PATCH 03/93] Enabling swarm deployment on master branch: -Extends the usage of POD_ADDRESS_RANGE -Provides documentation --- core/dovecot/conf/dovecot.conf | 2 +- core/postfix/conf/main.cf | 2 +- docs/swarm/master/README.md | 349 +++++++++++++++++++++ services/rspamd/conf/worker-controller.inc | 2 +- 4 files changed, 352 insertions(+), 3 deletions(-) create mode 100644 docs/swarm/master/README.md diff --git a/core/dovecot/conf/dovecot.conf b/core/dovecot/conf/dovecot.conf index a5973bf8..7cf10774 100644 --- a/core/dovecot/conf/dovecot.conf +++ b/core/dovecot/conf/dovecot.conf @@ -5,7 +5,7 @@ log_path = /dev/stderr protocols = imap pop3 lmtp sieve postmaster_address = {{ POSTMASTER }}@{{ DOMAIN }} hostname = {{ HOSTNAMES.split(",")[0] }} -submission_host = {{ FRONT_ADDRESS }} +submission_host = {{ FRONT_ADDRESS }} {{ POD_ADDRESS_RANGE }} service dict { unix_listener dict { diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index 2f2c6990..bde42dd1 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -32,7 +32,7 @@ relayhost = {{ RELAYHOST }} recipient_delimiter = {{ RECIPIENT_DELIMITER }} # Only the front server is allowed to perform xclient -smtpd_authorized_xclient_hosts={{ FRONT_ADDRESS }} +smtpd_authorized_xclient_hosts={{ FRONT_ADDRESS }} {{ POD_ADDRESS_RANGE }} ############### # TLS diff --git a/docs/swarm/master/README.md b/docs/swarm/master/README.md new file mode 100644 index 00000000..1406e05c --- /dev/null +++ b/docs/swarm/master/README.md @@ -0,0 +1,349 @@ +# Install Mailu on a docker swarm + +## Prequisites + +### Swarm + +In order to deploy Mailu on a swarm, you will first need to initialize the swarm: + +The main command will be: +```bash +docker swarm init --advertise-addr +``` +See https://docs.docker.com/engine/swarm/swarm-tutorial/create-swarm/ + +If you want to add other managers or workers, please use: +```bash +docker swarm join --token xxxxx +``` +See https://docs.docker.com/engine/swarm/join-nodes/ + +You have now a working swarm, and you can check its status with: +```bash +core@coreos-01 ~/git/Mailu/docs/swarm/1.5 $ docker node ls +ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION +xhgeekkrlttpmtgmapt5hyxrb black-pearl Ready Active 18.06.0-ce +sczlqjgfhehsfdjhfhhph1nvb * coreos-01 Ready Active Leader 18.03.1-ce +mzrm9nbdggsfz4sgq6dhs5i6n flying-dutchman Ready Active 18.06.0-ce +``` + +### Volume definition +For data persistance (the Mailu services might be launched/relaunched on any of the swarm nodes), we need to have Mailu data stored in a manner accessible by every manager or worker in the swarm. +Hereafter we will use a NFS share: +```bash +core@coreos-01 ~ $ showmount -e 192.168.0.30 +Export list for 192.168.0.30: +/mnt/Pool1/pv 192.168.0.0 +``` + +on the nfs server, I am using the following /etc/exports +```bash +$more /etc/exports +/mnt/Pool1/pv -alldirs -mapall=root -network 192.168.0.0 -mask 255.255.255.0 +``` +on the nfs server, I created the Mailu directory (in fact I copied a working Mailu set-up) +```bash +$mkdir /mnt/Pool1/pv/mailu +``` + +On your manager node, mount the nfs share to check that the share is available: +```bash +core@coreos-01 ~ $ sudo mount -t nfs 192.168.0.30:/mnt/Pool1/pv/mailu /mnt/local/ +``` +If this is ok, you can umount it: +```bash +core@coreos-01 ~ $ sudo umount /mnt/local/ +``` + + +### Networking mode +On a swarm, the services are available (default mode) through a routing mesh managed by docker itself. With this mode, each service is given a virtual IP adress and docker manages the routing between this virtual IP and the container(s) providing this service. + +In order to allow every (front & webmail) container to access the other services, we will use the variable POD_ADDRESS_RANGE. + +Let's create the mailu_default network: +```bash +core@coreos-01 ~ $ docker network create -d overlay --attachable mailu_default +core@coreos-01 ~ $ docker network inspect mailu_default | grep Subnet + "Subnet": "10.0.1.0/24", +``` +In the docker-compose.yml file, we will then use POD_ADDRESS_RANGE = 10.0.1.0/24 + +Nota: on my setup, imap & smtp logs doesn't show the IPs from the front(s) container(s), but the IP of "mailu_default-endpoint". So it might be sufficient to set POD_ADDRESS_RANGE to this specific ip (which can be found by inspecting mailu_default network) + +### Scalability +- smtp and imap are scalable +- front and webmail are scalable (pending POD_ADDRESS_RANGE is used), although the let's encrypt magic might not like it (race condidtion ? or risk to be banned by let's encrypt server if too many front containers attemps to renew the certs at the same time) +- redis, antispam, antivirus, fetchmail, admin, webdav have not been tested (hence replicas=1 in the following docker-compose.yml file) + +### Variable substitution and docker-compose.yml +The docker stack deploy command doesn't support variable substitution in the .yml file itself (but we still can use .env file to pass variables to the services). As a consequence we need to adjust the docker-compose file in order to : +- remove all variables : $VERSION , $BIND_ADDRESS4 , $BIND_ADDRESS6 , $ANTIVIRUS , $WEBMAIL , etc +- change the way we define the volumes (nfs share in our case) +- add a deploy section for every service + +### Docker compose +An example of docker-compose-stack.yml file is available here: + +```yaml + +version: '3.2' + +services: + + front: + image: mailu/nginx:master + restart: always + env_file: .env + ports: + - target: 80 + published: 80 + - target: 443 + published: 443 + - target: 110 + published: 110 + - target: 143 + published: 143 + - target: 993 + published: 993 + - target: 995 + published: 995 + - target: 25 + published: 25 + - target: 465 + published: 465 + - target: 587 + published: 587 + volumes: +# - "$ROOT/certs:/certs" + - type: volume + source: mailu_certs + target: /certs + deploy: + replicas: 2 + + redis: + image: redis:alpine + restart: always + volumes: +# - "$ROOT/redis:/data" + - type: volume + source: mailu_redis + target: /data + deploy: + replicas: 1 + + imap: + image: mailu/dovecot:master + restart: always + env_file: .env + environment: + - POD_ADDRESS_RANGE=10.0.1.0/24 + volumes: +# - "$ROOT/data:/data" + - type: volume + source: mailu_data + target: /data +# - "$ROOT/mail:/mail" + - type: volume + source: mailu_mail + target: /mail +# - "$ROOT/overrides:/overrides" + - type: volume + source: mailu_overrides + target: /overrides + depends_on: + - front + deploy: + replicas: 2 + + smtp: + image: mailu/postfix:master + restart: always + env_file: .env + environment: + - POD_ADDRESS_RANGE=10.0.1.0/24 + volumes: +# - "$ROOT/data:/data" + - type: volume + source: mailu_data + target: /data +# - "$ROOT/overrides:/overrides" + - type: volume + source: mailu_overrides + target: /overrides + depends_on: + - front + deploy: + replicas: 2 + + antispam: + image: mailu/rspamd:master + restart: always + env_file: .env + environment: + - POD_ADDRESS_RANGE=10.0.1.0/24 + depends_on: + - front + volumes: +# - "$ROOT/filter:/var/lib/rspamd" + - type: volume + source: mailu_filter + target: /var/lib/rspamd +# - "$ROOT/dkim:/dkim" + - type: volume + source: mailu_dkim + target: /dkim +# - "$ROOT/overrides/rspamd:/etc/rspamd/override.d" + - type: volume + source: mailu_overrides_rspamd + target: /etc/rspamd/override.d + deploy: + replicas: 1 + + antivirus: + image: mailu/none:master + restart: always + env_file: .env + volumes: +# - "$ROOT/filter:/data" + - type: volume + source: mailu_filter + target: /data + deploy: + replicas: 1 + + webdav: + image: mailu/none:master + restart: always + env_file: .env + volumes: +# - "$ROOT/dav:/data" + - type: volume + source: mailu_dav + target: /data + deploy: + replicas: 1 + + admin: + image: mailu/admin:master + restart: always + env_file: .env + volumes: +# - "$ROOT/data:/data" + - type: volume + source: mailu_data + target: /data +# - "$ROOT/dkim:/dkim" + - type: volume + source: mailu_dkim + target: /dkim + - /var/run/docker.sock:/var/run/docker.sock:ro + depends_on: + - redis + deploy: + replicas: 1 + + webmail: + image: "mailu/roundcube:master" + restart: always + env_file: .env + volumes: +# - "$ROOT/webmail:/data" + - type: volume + source: mailu_data + target: /data + depends_on: + - imap + deploy: + replicas: 2 + + fetchmail: + image: mailu/fetchmail:master + restart: always + env_file: .env + volumes: +# - "$ROOT/data:/data" + - type: volume + source: mailu_data + target: /data + deploy: + replicas: 1 + +networks: + default: + external: + name: mailu_default + +volumes: + mailu_filter: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/filter" + mailu_dkim: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/dkim" + mailu_overrides_rspamd: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/overrides/rspamd" + mailu_data: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/data" + mailu_mail: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/mail" + mailu_overrides: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/overrides" + mailu_dav: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/dav" + mailu_certs: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/certs" + mailu_redis: + driver_opts: + type: "nfs" + o: "addr=192.168.0.30,nolock,soft,rw" + device: ":/mnt/Pool1/pv/mailu/redis" +``` + +### Deploy Mailu on the docker swarm +Run the following command: +```bash +docker stack deploy -c docker-compose-stack.yml mailu +``` +See how the services are being deployed: +```bash +core@coreos-01 ~ $ docker service ls +ID NAME MODE REPLICAS IMAGE PORTS +ywnsetmtkb1l mailu_antivirus replicated 1/1 mailu/none:1.5 +pqokiaz0q128 mailu_fetchmail replicated 1/1 mailu/fetchmail:1.5 +``` +check a specific service: +```bash +core@coreos-01 ~ $ docker service ps mailu_fetchmail +ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS +tbu8ppgsdffj mailu_fetchmail.1 mailu/fetchmail:1.5 coreos-01 Running Running 11 days ago +``` + +### Remove the stack +Run the follwoing command: +```bash +core@coreos-01 ~ $ docker stack rm mailu +``` diff --git a/services/rspamd/conf/worker-controller.inc b/services/rspamd/conf/worker-controller.inc index 6a020672..0cb0d5c0 100644 --- a/services/rspamd/conf/worker-controller.inc +++ b/services/rspamd/conf/worker-controller.inc @@ -1,3 +1,3 @@ bind_socket = "*:11334"; password = "mailu"; -secure_ip = "{{ FRONT_ADDRESS }}"; +secure_ip = "{{ FRONT_ADDRESS }} {{ POD_ADDRESS_RANGE }}"; From f5f09fad6ecc41e64b90dc4044450b61ea19ae4a Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Tue, 25 Sep 2018 18:54:40 +0000 Subject: [PATCH 04/93] Reverting the patch for dovecot.conf, as it is not needed --- core/dovecot/conf/dovecot.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dovecot/conf/dovecot.conf b/core/dovecot/conf/dovecot.conf index 7cf10774..a5973bf8 100644 --- a/core/dovecot/conf/dovecot.conf +++ b/core/dovecot/conf/dovecot.conf @@ -5,7 +5,7 @@ log_path = /dev/stderr protocols = imap pop3 lmtp sieve postmaster_address = {{ POSTMASTER }}@{{ DOMAIN }} hostname = {{ HOSTNAMES.split(",")[0] }} -submission_host = {{ FRONT_ADDRESS }} {{ POD_ADDRESS_RANGE }} +submission_host = {{ FRONT_ADDRESS }} service dict { unix_listener dict { From fcad52b1454aeeb5b11d64fe0186f644922f96b2 Mon Sep 17 00:00:00 2001 From: kaiyou Date: Thu, 27 Sep 2018 22:45:16 +0200 Subject: [PATCH 05/93] Implement a start date filter for autoreply, fixes #362 --- core/admin/mailu/models.py | 2 ++ core/admin/mailu/ui/forms.py | 1 + core/admin/mailu/ui/templates/user/reply.html | 7 ++++-- .../migrations/versions/3b281286c7bd_.py | 24 +++++++++++++++++++ core/dovecot/conf/pigeonhole-sieve.dict | 8 +++++++ core/dovecot/sieve/before.sieve | 1 + 6 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 core/admin/migrations/versions/3b281286c7bd_.py diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 71c5f4d7..1be4c8e6 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -249,6 +249,8 @@ class User(Base, Email): reply_enabled = db.Column(db.Boolean(), nullable=False, default=False) reply_subject = db.Column(db.String(255), nullable=True, default=None) reply_body = db.Column(db.Text(), nullable=True, default=None) + reply_startdate = db.Column(db.Date, nullable=False, + default=date(1900, 1, 1)) reply_enddate = db.Column(db.Date, nullable=False, default=date(2999, 12, 31)) diff --git a/core/admin/mailu/ui/forms.py b/core/admin/mailu/ui/forms.py index 326d721b..4f7a30ae 100644 --- a/core/admin/mailu/ui/forms.py +++ b/core/admin/mailu/ui/forms.py @@ -117,6 +117,7 @@ class UserReplyForm(flask_wtf.FlaskForm): reply_subject = fields.StringField(_('Reply subject')) reply_body = fields.StringField(_('Reply body'), widget=widgets.TextArea()) + reply_startdate = fields.html5.DateField(_('Start of vacation')) reply_enddate = fields.html5.DateField(_('End of vacation')) submit = fields.SubmitField(_('Update')) diff --git a/core/admin/mailu/ui/templates/user/reply.html b/core/admin/mailu/ui/templates/user/reply.html index 7906bc42..7225a178 100644 --- a/core/admin/mailu/ui/templates/user/reply.html +++ b/core/admin/mailu/ui/templates/user/reply.html @@ -13,14 +13,17 @@
{{ form.hidden_tag() }} {{ macros.form_field(form.reply_enabled, - onchange="if(this.checked){$('#reply_subject,#reply_body,#reply_enddate').removeAttr('readonly')} + onchange="if(this.checked){$('#reply_subject,#reply_body,#reply_enddate,#reply_startdate').removeAttr('readonly')} else{$('#reply_subject,#reply_body,#reply_enddate').attr('readonly', '')}") }} {{ macros.form_field(form.reply_subject, **{("rw" if user.reply_enabled else "readonly"): ""}) }} {{ macros.form_field(form.reply_body, rows=10, **{("rw" if user.reply_enabled else "readonly"): ""}) }} {{ macros.form_field(form.reply_enddate, - **{("rw" if user.reply_enabled else "readonly"): ""}) }} + **{("rw" if user.reply_enabled else "readonly"): ""}) }} + {{ macros.form_field(form.reply_startdate, + **{("rw" if user.reply_enabled else "readonly"): ""}) }} + {{ macros.form_field(form.submit) }}
{% endcall %} diff --git a/core/admin/migrations/versions/3b281286c7bd_.py b/core/admin/migrations/versions/3b281286c7bd_.py new file mode 100644 index 00000000..78e44a4c --- /dev/null +++ b/core/admin/migrations/versions/3b281286c7bd_.py @@ -0,0 +1,24 @@ +""" Add a start day for vacations + +Revision ID: 3b281286c7bd +Revises: 049fed905da7 +Create Date: 2018-09-27 22:20:08.158553 + +""" + +revision = '3b281286c7bd' +down_revision = '049fed905da7' + +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') diff --git a/core/dovecot/conf/pigeonhole-sieve.dict b/core/dovecot/conf/pigeonhole-sieve.dict index 917fce83..604371a8 100644 --- a/core/dovecot/conf/pigeonhole-sieve.dict +++ b/core/dovecot/conf/pigeonhole-sieve.dict @@ -41,3 +41,11 @@ map { username_field = email value_field = reply_enddate } + +map { + pattern = priv/reply_startdate + table = user + username_field = email + value_field = reply_startdate +} + diff --git a/core/dovecot/sieve/before.sieve b/core/dovecot/sieve/before.sieve index 6ebc20c5..81d20f30 100644 --- a/core/dovecot/sieve/before.sieve +++ b/core/dovecot/sieve/before.sieve @@ -34,6 +34,7 @@ if exists "X-Virus" { } if allof (string :is "${extdata.reply_enabled}" "1", + currentdate :value "ge" "date" "${extdata.reply_startdate}", currentdate :value "le" "date" "${extdata.reply_enddate}") { vacation :days 1 :subject "${extdata.reply_subject}" "${extdata.reply_body}"; From 6b34b2728ece020918dcb10a901afdd9894a69e3 Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Sun, 7 Oct 2018 16:38:41 +0000 Subject: [PATCH 06/93] Declare fuzzy_worker port 11335 in EXPOSE section --- services/rspamd/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/rspamd/Dockerfile b/services/rspamd/Dockerfile index 7dff8c1f..cfb4d0eb 100644 --- a/services/rspamd/Dockerfile +++ b/services/rspamd/Dockerfile @@ -9,7 +9,7 @@ RUN mkdir /run/rspamd COPY conf/ /conf COPY start.py /start.py -EXPOSE 11332/tcp 11334/tcp +EXPOSE 11332/tcp 11334/tcp 11335/tcp VOLUME ["/var/lib/rspamd"] From 1f71d10899d72571b39a60448a23adc41d5f10f2 Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Sun, 7 Oct 2018 16:46:42 +0000 Subject: [PATCH 07/93] Change POD_ADDRESS_RANGE introduction like it is done on deovecot-sql.conf.ext --- services/rspamd/conf/worker-controller.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/rspamd/conf/worker-controller.inc b/services/rspamd/conf/worker-controller.inc index 0cb0d5c0..4b23a897 100644 --- a/services/rspamd/conf/worker-controller.inc +++ b/services/rspamd/conf/worker-controller.inc @@ -1,3 +1,3 @@ bind_socket = "*:11334"; password = "mailu"; -secure_ip = "{{ FRONT_ADDRESS }} {{ POD_ADDRESS_RANGE }}"; +secure_ip = "{% if POD_ADDRESS_RANGE %}{{ POD_ADDRESS_RANGE }}{% else %}{{ FRONT_ADDRESS }}{% endif %}"; From 9d610f56f7ff39232cb15ce02b42f8aca94d846a Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Mon, 8 Oct 2018 18:53:44 +0000 Subject: [PATCH 08/93] Added some lines around ingress mode --- docs/swarm/master/README.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/swarm/master/README.md b/docs/swarm/master/README.md index 1406e05c..c09f1dd3 100644 --- a/docs/swarm/master/README.md +++ b/docs/swarm/master/README.md @@ -57,8 +57,11 @@ core@coreos-01 ~ $ sudo umount /mnt/local/ ### Networking mode -On a swarm, the services are available (default mode) through a routing mesh managed by docker itself. With this mode, each service is given a virtual IP adress and docker manages the routing between this virtual IP and the container(s) providing this service. +On this example, we are using: +- the mesh routing mode (default mode). With this mode, each service is given a virtual IP adress and docker manages the routing between this virtual IP and the container(s) providing this service. +- the default ingress mode. +## Allow authentification with the mesh routing In order to allow every (front & webmail) container to access the other services, we will use the variable POD_ADDRESS_RANGE. Let's create the mailu_default network: @@ -68,8 +71,22 @@ core@coreos-01 ~ $ docker network inspect mailu_default | grep Subnet "Subnet": "10.0.1.0/24", ``` In the docker-compose.yml file, we will then use POD_ADDRESS_RANGE = 10.0.1.0/24 +In fact, imap & smtp logs doesn't show the IPs from the front(s) container(s), but the IP of "mailu_default-endpoint". So it is sufficient to set POD_ADDRESS_RANGE to this specific ip (which can be found by inspecting mailu_default network). The issue is that this endpoint is created while the stack is created, I did'nt figure a way to determine this IP before the stack creation... + +## Limitation with the ingress mode +With the default ingress mode, the front(s) container(s) will see origin IP(s) all being 10.255.0.x (which is the ingress-endpoint, can be found by inspecting the ingress network) + +This issue is known and discussed here: + +https://github.com/moby/moby/issues/25526 + +A workaround (using network host mode and global deployment) is discussed here: + +https://github.com/moby/moby/issues/25526#issuecomment-336363408 + +## Don't create an open relay ! +As a side effect of this ingress mode "feature", make sure that the ingress subnet is not in your RELAYHOST, otherwise you would create an smtp open relay :-( -Nota: on my setup, imap & smtp logs doesn't show the IPs from the front(s) container(s), but the IP of "mailu_default-endpoint". So it might be sufficient to set POD_ADDRESS_RANGE to this specific ip (which can be found by inspecting mailu_default network) ### Scalability - smtp and imap are scalable From 6bd365e7714e765c75d8fdd93bc04065a53eae14 Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Mon, 8 Oct 2018 21:00:44 +0000 Subject: [PATCH 09/93] Change title layout --- docs/swarm/master/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/swarm/master/README.md b/docs/swarm/master/README.md index c09f1dd3..2a2a021a 100644 --- a/docs/swarm/master/README.md +++ b/docs/swarm/master/README.md @@ -56,12 +56,12 @@ core@coreos-01 ~ $ sudo umount /mnt/local/ ``` -### Networking mode +## Networking mode On this example, we are using: - the mesh routing mode (default mode). With this mode, each service is given a virtual IP adress and docker manages the routing between this virtual IP and the container(s) providing this service. - the default ingress mode. -## Allow authentification with the mesh routing +### Allow authentification with the mesh routing In order to allow every (front & webmail) container to access the other services, we will use the variable POD_ADDRESS_RANGE. Let's create the mailu_default network: @@ -73,7 +73,7 @@ core@coreos-01 ~ $ docker network inspect mailu_default | grep Subnet In the docker-compose.yml file, we will then use POD_ADDRESS_RANGE = 10.0.1.0/24 In fact, imap & smtp logs doesn't show the IPs from the front(s) container(s), but the IP of "mailu_default-endpoint". So it is sufficient to set POD_ADDRESS_RANGE to this specific ip (which can be found by inspecting mailu_default network). The issue is that this endpoint is created while the stack is created, I did'nt figure a way to determine this IP before the stack creation... -## Limitation with the ingress mode +### Limitation with the ingress mode With the default ingress mode, the front(s) container(s) will see origin IP(s) all being 10.255.0.x (which is the ingress-endpoint, can be found by inspecting the ingress network) This issue is known and discussed here: @@ -84,22 +84,22 @@ A workaround (using network host mode and global deployment) is discussed here: https://github.com/moby/moby/issues/25526#issuecomment-336363408 -## Don't create an open relay ! +### Don't create an open relay ! As a side effect of this ingress mode "feature", make sure that the ingress subnet is not in your RELAYHOST, otherwise you would create an smtp open relay :-( -### Scalability +## Scalability - smtp and imap are scalable - front and webmail are scalable (pending POD_ADDRESS_RANGE is used), although the let's encrypt magic might not like it (race condidtion ? or risk to be banned by let's encrypt server if too many front containers attemps to renew the certs at the same time) - redis, antispam, antivirus, fetchmail, admin, webdav have not been tested (hence replicas=1 in the following docker-compose.yml file) -### Variable substitution and docker-compose.yml +## Variable substitution and docker-compose.yml The docker stack deploy command doesn't support variable substitution in the .yml file itself (but we still can use .env file to pass variables to the services). As a consequence we need to adjust the docker-compose file in order to : - remove all variables : $VERSION , $BIND_ADDRESS4 , $BIND_ADDRESS6 , $ANTIVIRUS , $WEBMAIL , etc - change the way we define the volumes (nfs share in our case) - add a deploy section for every service -### Docker compose +## Docker compose An example of docker-compose-stack.yml file is available here: ```yaml @@ -340,7 +340,7 @@ volumes: device: ":/mnt/Pool1/pv/mailu/redis" ``` -### Deploy Mailu on the docker swarm +## Deploy Mailu on the docker swarm Run the following command: ```bash docker stack deploy -c docker-compose-stack.yml mailu @@ -359,7 +359,7 @@ ID NAME IMAGE NODE tbu8ppgsdffj mailu_fetchmail.1 mailu/fetchmail:1.5 coreos-01 Running Running 11 days ago ``` -### Remove the stack +## Remove the stack Run the follwoing command: ```bash core@coreos-01 ~ $ docker stack rm mailu From ada09f7922dd50656bbaa99f0c624ad2f90eb1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Tue, 9 Oct 2018 12:35:08 +0300 Subject: [PATCH 10/93] Unbound: Use alpine:3.8 --- core/unbound/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/unbound/Dockerfile b/core/unbound/Dockerfile index 6ae8a6ee..3c7f0e7a 100644 --- a/core/unbound/Dockerfile +++ b/core/unbound/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:edge +FROM alpine:3.8 RUN apk add --no-cache unbound curl \ && curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache \ From 013d02d7264c182db459a7d67acc7d941eb68f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Tue, 9 Oct 2018 14:11:59 +0300 Subject: [PATCH 11/93] Add unbound to the build directive --- tests/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/build.yml b/tests/build.yml index 0b6858a0..e0123ca7 100644 --- a/tests/build.yml +++ b/tests/build.yml @@ -6,6 +6,10 @@ services: image: $DOCKER_ORG/nginx:$VERSION build: ../core/nginx + unbound: + image: $DOCKER_ORG/unbound:$VERSION + build: ../core/unbound + imap: image: $DOCKER_ORG/dovecot:$VERSION build: ../core/dovecot From cde22be4c9f4dec9889c75ba1dc7f234b586ba0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Tue, 9 Oct 2018 14:50:09 +0300 Subject: [PATCH 12/93] Some cleanup and changes: - Don't upgrade the docker-compose file. (Not in the scope of this feature) - No need to use aliases. Docker already resolves to service names - Use a fixed IP range, which stays clear of the network ranges used by Docker. (172.xx.0.0/16) --- docs/compose/.env | 3 -- docs/compose/docker-compose.yml | 72 +++++++-------------------------- 2 files changed, 15 insertions(+), 60 deletions(-) diff --git a/docs/compose/.env b/docs/compose/.env index 5378d37e..721aaf22 100644 --- a/docs/compose/.env +++ b/docs/compose/.env @@ -21,9 +21,6 @@ SECRET_KEY=ChangeMeChangeMe BIND_ADDRESS4=127.0.0.1 BIND_ADDRESS6=::1 -# Internal Docker network -IPV4_NETWORK=172.22.1 - # Main mail domain DOMAIN=mailu.io diff --git a/docs/compose/docker-compose.yml b/docs/compose/docker-compose.yml index dc674a2b..8038a0bf 100644 --- a/docs/compose/docker-compose.yml +++ b/docs/compose/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2.1' +version: '2' services: @@ -30,20 +30,14 @@ services: depends_on: - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - front + - 10.177.20.254 unbound: image: mailu/unbound:$VERSION restart: always networks: - backend: - ipv4_address: ${IPV4_NETWORK:-172.22.1}.254 - aliases: - - unbound + default: + ipv4_address: 10.177.20.254 redis: image: redis:alpine @@ -51,13 +45,9 @@ services: volumes: - "$ROOT/redis:/data" dns: - - ${IPV4_NETWORK:-172.22.1}.254 + - 10.177.20.254 depends_on: - unbound - networks: - backend: - aliases: - - redis imap: image: mailu/dovecot:$VERSION @@ -71,11 +61,7 @@ services: - front - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - imap + - 10.177.20.254 smtp: image: mailu/postfix:$VERSION @@ -88,11 +74,7 @@ services: - front - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - smtp + - 10.177.20.254 antispam: image: mailu/rspamd:$VERSION @@ -106,11 +88,7 @@ services: - front - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - antispam + - 10.177.20.254 antivirus: image: mailu/$ANTIVIRUS:$VERSION @@ -121,11 +99,7 @@ services: depends_on: - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - antivirus + - 10.177.20.254 webdav: image: mailu/$WEBDAV:$VERSION @@ -136,11 +110,7 @@ services: depends_on: - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - webdav + - 10.177.20.254 admin: image: mailu/admin:$VERSION @@ -154,11 +124,7 @@ services: - redis - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - admin + - 10.177.20.254 webmail: image: "mailu/$WEBMAIL:$VERSION" @@ -170,11 +136,7 @@ services: - imap - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - webmail + - 10.177.20.254 fetchmail: image: mailu/fetchmail:$VERSION @@ -185,16 +147,12 @@ services: depends_on: - unbound dns: - - ${IPV4_NETWORK:-172.22.1}.254 - networks: - backend: - aliases: - - fetchmail + - 10.177.20.254 networks: - backend: + default: driver: bridge ipam: driver: default config: - - subnet: ${IPV4_NETWORK:-172.22.1}.0/24 + - subnet: 10.177.20.0/24 From f4ef0eed09a31a5ee609414046a99c8cf0d02be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Fri, 12 Oct 2018 20:48:44 +0300 Subject: [PATCH 13/93] Wrote informational section of the FAQ --- docs/faq.rst | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 1 + 2 files changed, 98 insertions(+) create mode 100644 docs/faq.rst diff --git a/docs/faq.rst b/docs/faq.rst new file mode 100644 index 00000000..8c5b5598 --- /dev/null +++ b/docs/faq.rst @@ -0,0 +1,97 @@ +Frequently asked questions +========================== + +Informational +------------- + +Where to ask questions? +``````````````````````` + +First, please read this FAQ to check if your question is listed here. +Simple questions best fit in our `Matrix`_ room. +For more complex questions, you can always open a `new issue`_ on GitHub. +We actively monitor the issues list. + + +My installation is broken! +`````````````````````````` + +We're sorry to hear that. Please check for common mistakes and troubleshooting +advice in the `Technical issues`_ section of this page. + +I think I found a bug! +`````````````````````` + +If you did not manage to solve the issue using this FAQ and there is not any +`open issues`_ describing the same problem, you can continue to open a +`new issue`_ on GitHub. + +I want a new feature or enhancement! +```````````````````````````````````` + +Great! We are always open for suggestions. We currently maintain two tags: + +- `Enhancement issues`_: Typically used for optimization of features in the project. +- `Feature request issues`_: For implementing new functionality, + plugins and applications. + +Please check if your idea (or something similar) is already mentioned there. +If there is one open, you can choose to vote with a thumbs up, so we can +estimate the popular demand. Please refrain from writing comments like +*"me too"* as it clobbers the actual discussion. + +If you can't find anything similar, you can open a `new issue`_. +Please also share (where applicable): + +- Use case: how does this improve the project? +- Any research done on the subject. Perhaps some links to upstream website, + reference implementations etc. + +Why does my feature/bug take so long to solve? +`````````````````````````````````````````````` + +You should be aware that creating, maintaining and expanding a mail server +distribution requires a lot of effort. Mail servers are highly exposed to hacking attempts, +open relay scanners, spam and malware distributors etc. We need to work in a safe way and +have to prevent pushing out something quickly. + +We currently maintain a strict work flow: + +#. Someone writes a solution and sends a pull request; +#. We use Travis-CI fore some very basic building and testing; +#. The pull request needs to be code-reviewed and tested by at least two members + from the contributors team. + +Please consider that this project is mostly developed in people their free time. +We thank you for your understanding and patience. + +I would to donate (for a feature) +````````````````````````````````` + +Donations are welcome at the `patreon`_ account of the project lead. It will be used to pay +for infra structure and project related costs. If there are leftovers, it will be distributed +among the developers. + +It is not yet possible to pay for a specific feature. We don't have +any bounty system implemented. Feel free to come with suggestions in +our ongoing `project management`_ discussion issue. + + +.. _`Matrix`: https://matrix.to/#/#mailu:tedomum.net +.. _`open issues`: https://github.com/Mailu/Mailu/issues +.. _`new issue`: https://github.com/Mailu/Mailu/issues/new +.. _`Enhancement issues`: https://github.com/Mailu/Mailu/issues?q=is%3Aissue+is%3Aopen+label%3Atype%2Fenhancement +.. _`Feature request issues`: https://github.com/Mailu/Mailu/issues?q=is%3Aopen+is%3Aissue+label%3Atype%2Ffeature +.. _`patreon`: https://patreon.com/kaiyou +.. _`project management`: https://github.com/Mailu/Mailu/issues/508 + +Deployment related +------------------ + + +Technical issues +---------------- + +WIP: Link to `troubleshooting`_ related issues will be in the bottom of this section. + +.. _`troubleshooting`: https://github.com/Mailu/Mailu/issues?utf8=%E2%9C%93&q=label%3Afaq%2Ftroubleshooting diff --git a/docs/index.rst b/docs/index.rst index 5219145f..0a4aadff 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -44,6 +44,7 @@ the version of Mailu that you are running. general features + faq releases demo From b5693edc63ce11979459c204793a525b4dc57b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Sat, 13 Oct 2018 20:59:14 +0300 Subject: [PATCH 14/93] Include a doc section for external certbot --- docs/maintain.rst | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/maintain.rst b/docs/maintain.rst index d570690e..ffb51a50 100644 --- a/docs/maintain.rst +++ b/docs/maintain.rst @@ -28,6 +28,33 @@ Logs are managed by Docker directly. You can easily read your logs using: Docker is able to forward logs to multiple log engines. Read the following documentation for details: https://docs.docker.com/engine/admin/logging/overview/. +.. _external_certs: + +Managing of external Let's encrypt certificates +----------------------------------------------- + +When you are not using the embedded ``letsencrypt`` option from Mailu, +you cannot make use of it's symlink functionality in the ``letsencrypt/live`` directory. +You should take care that after every renewal new certificates are copied to ``/mailu/certs`` and +the *nginx* process in the ``front`` container is reloaded. + +In the case of *certbot* you could write a script to be executed as `deploy hook`_. Example: + +.. code-block:: bash + + #!/bin/sh + cp /etc/letsencrypt/live/domain.com/privkey.pem /mailu/certs/key.pem || exit 1 + cp /etc/letsencrypt/live/domain.com/fullchain.pem /mailu/certs/cert.pem || exit 1 + docker exec mailu_front_1 nginx -s reload + +And the certbot command you will use in crontab would look something like: + +.. code-block:: bash + + 52 0,12 * * * root /usr/bin/certbot renew --deploy-hook /path/to/script.sh + +.. _`deploy hook`: https://certbot.eff.org/docs/using.html#renewing-certificates + Migrating an instance --------------------- From 13949554479383e09a184bac695e7e6e085350ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Sat, 13 Oct 2018 21:13:09 +0300 Subject: [PATCH 15/93] FAQ about TLS issues --- docs/faq.rst | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 8c5b5598..81d51b86 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -55,6 +55,7 @@ distribution requires a lot of effort. Mail servers are highly exposed to hackin open relay scanners, spam and malware distributors etc. We need to work in a safe way and have to prevent pushing out something quickly. +**TODO: Move the next section into the contributors part of docs** We currently maintain a strict work flow: #. Someone writes a solution and sends a pull request; @@ -65,8 +66,8 @@ We currently maintain a strict work flow: Please consider that this project is mostly developed in people their free time. We thank you for your understanding and patience. -I would to donate (for a feature) -````````````````````````````````` +I would like to donate (for a feature) +`````````````````````````````````````` Donations are welcome at the `patreon`_ account of the project lead. It will be used to pay for infra structure and project related costs. If there are leftovers, it will be distributed @@ -88,10 +89,90 @@ our ongoing `project management`_ discussion issue. Deployment related ------------------ - Technical issues ---------------- +Changes in .env don't propagate +``````````````````````````````` + +Variables are sent to the containers at creation time. This means you need to take the project +down and up again. A container restart is not sufficient. + +.. code-block:: bash + + docker-compose down && \ + docker-compose up -d + +*Issue reference:* `615`_, + +TLS certificate issues +`````````````````````` + +When there are issues with the TLS/SSL certificates, Mailu denies service on secure ports. +This is a security precaution. Symptoms are: + +- 403 browser errors; + +These issues are typically caused by four scenarios: + +#. ``TLS_FLAVOR=notls`` in ``.env``; +#. Certificates expired; +#. When ``TLS_FLAVOR=letsencrypt``, it might be that the *certbot* script is not capable of + obtaining the certificates for your domain. See `letsencrypt issues`_ +#. When ``TLS_FLAVOR=certs``, certificates are supposed to be copied to ``/mailu/certs``. + Using an external ``letsencrypt`` program, it tends to happen people copy the whole + ``letsencrypt/live`` directory containing symlinks. Symlinks do not resolve inside the + container and therefore it breaks the TLS implementation. + +letsencrypt issues +.................. + +In order to determine the exact problem on TLS / Let's encrypt issues, it might be helpful +to check the logs. + +.. code-block:: bash + + docker-compose logs front | less -R + docker-compose exec front less /var/log/letsencrypt/letsencrypt.log + +Common problems: + +- Port 80 not reachable from outside. +- Faulty DNS records: make sure that all ``HOSTNAMES`` have **A** (IPv4) and **AAAA** (IPv6) + records, pointing the the ``BIND_ADDRESS4`` and ``BIND_ADDRESS6``. +- DNS cache not yet expired. It might be that old / faulty DNS records are stuck in a cache + en-route to letsencrypt's server. The time this takes is set by the ``TTL`` field in the + records. You'll have to wait at least this time after changing the DNS entries. + Don't keep trying, as you might hit `rate-limits`_. + +.. _`rate-limits`: https://letsencrypt.org/docs/rate-limits/ + +Copying certificates +.................... + +As mentioned above, care must be taken not to copy symlinks to the ``/mailu/certs`` location. + +**The wrong way!:** + +.. code-block:: bash + + cp -r /etc/letsencrypt/live/domain.com /mailu/certs + +**The right way!:** + +.. code-block:: bash + + mkdir -p /mailu/certs + cp /etc/letsencrypt/live/domain.com/privkey.pem /mailu/certs/key.pem + cp /etc/letsencrypt/live/domain.com/fullchain.pem /mailu/certs/cert.pem + +See also :ref:`external_certs`. + +*Issue reference:* `426`_, `615`_. + + WIP: Link to `troubleshooting`_ related issues will be in the bottom of this section. +.. _`426`: https://github.com/Mailu/Mailu/issues/426 +.. _`615`: https://github.com/Mailu/Mailu/issues/615 .. _`troubleshooting`: https://github.com/Mailu/Mailu/issues?utf8=%E2%9C%93&q=label%3Afaq%2Ftroubleshooting From 11a8e49f059c4eb71a8f931edcbfa238d90873a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Tue, 16 Oct 2018 11:09:42 +0300 Subject: [PATCH 16/93] Compose file upgrade and define more variables for setup --- setup/flavors/compose/docker-compose.yml | 38 ++++++++++++------------ setup/flavors/compose/mailu.env | 16 +++++----- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index fcf0c092..a82817af 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -2,7 +2,7 @@ # This file is auto-generated by the Mailu configuration wizard. # Please read the documentation before attempting any change. -version: '2' +version: '3.7' services: @@ -11,7 +11,7 @@ services: image: redis:alpine restart: always volumes: - - "$ROOT/redis:/data" + - "{{ root }}/redis:/data" # Core services front: @@ -24,15 +24,15 @@ services: 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" + - "{{ root }}/certs:/certs" {% endif %} admin: @@ -44,8 +44,8 @@ services: - 127.0.0.1:8080:80 {% endif %} volumes: - - "$ROOT/data:/data" - - "$ROOT/dkim:/dkim" + - "{{ root }}/data:/data" + - "{{ root }}/dkim:/dkim" depends_on: - redis @@ -54,9 +54,9 @@ services: restart: always env_file: {{ env }} volumes: - - "$ROOT/data:/data" - - "$ROOT/mail:/mail" - - "$ROOT/overrides:/overrides" + - "{{ root }}/data:/data" + - "{{ root }}/mail:/mail" + - "{{ root }}/overrides:/overrides" depends_on: - front @@ -65,8 +65,8 @@ services: restart: always env_file: {{ env }} volumes: - - "$ROOT/data:/data" - - "$ROOT/overrides:/overrides" + - "{{ root }}/data:/data" + - "{{ root }}/overrides:/overrides" depends_on: - front @@ -77,9 +77,9 @@ services: 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 %} @@ -90,7 +90,7 @@ services: restart: always env_file: {{ env }} volumes: - - "$ROOT/filter:/data" + - "{{ root }}/filter:/data" {% endif %} {% if enable_webdav %} @@ -99,7 +99,7 @@ services: restart: always env_file: {{ env }} volumes: - - "$ROOT/dav:/data" + - "{{ root }}/dav:/data" {% endif %} {% if enable_fetchmail %} @@ -108,7 +108,7 @@ services: restart: always env_file: {{ env }} volumes: - - "$ROOT/data:/data" + - "{{ root }}/data:/data" {% endif %} # Webmail @@ -118,7 +118,7 @@ services: restart: always env_file: {{ env }} volumes: - - "$ROOT/webmail:/data" + - "{{ root }}/webmail:/data" depends_on: - imap {% endif %} diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 24d7b247..2de771f3 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -9,14 +9,16 @@ ################################### # Set this to the path where Mailu data and configuration is stored -ROOT=/mailu +# This variable is now set directly in `docker-compose.yml by the setup utility +# ROOT=/mailu # Set to a randomly generated 16 bytes string SECRET_KEY={{ secret(16) }} # Address where listening ports should bind -{% if bind4 %}PUBLIC_IPV4={{ bind4 }}{% endif %} -{% if bind6 %}PUBLIC_IPV6={{ bind6 }}{% endif %} +# This variables are now set directly in `docker-compose.yml by the setup utility +# PUBLIC_IPV4=127.0.0.1 +# PUBLIC_IPV6=::1 # Mail address of the postmaster POSTMASTER={{ postmaster }} @@ -75,16 +77,16 @@ DOMAIN_REGISTRATION=true ################################### # Path to the admin interface if enabled -WEB_ADMIN=/admin +WEB_ADMIN={{ admin_path }} # Path to the webmail if enabled -WEB_WEBMAIL=/webmail +WEB_WEBMAIL={{ webmail_path }} # Website name -SITENAME=Mailu +SITENAME={{ site_name }{ # Linked Website URL -WEBSITE=https://mailu.io +WEBSITE={{ website }} {% if recaptcha_public_key and recaptcha_private_key %} # Registration reCaptcha settings (warning, this has some privacy impact) From 0d164486b45b194de81905089b37a4557a828a8f Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 16 Oct 2018 12:34:55 +0300 Subject: [PATCH 17/93] docker-compose variables and setup --- setup/Dockerfile | 4 +++- setup/docker-compose.yml | 1 + setup/flavors/compose/docker-compose.yml | 2 +- setup/flavors/compose/mailu.env | 8 ++++---- setup/flavors/compose/setup.html | 6 +++--- setup/server.py | 6 ++++-- setup/templates/steps/expose.html | 4 ++-- setup/templates/steps/root.html | 8 ++++++++ setup/templates/wizard.html | 1 + 9 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 setup/templates/steps/root.html diff --git a/setup/Dockerfile b/setup/Dockerfile index 1fc808f1..c970e57d 100644 --- a/setup/Dockerfile +++ b/setup/Dockerfile @@ -10,8 +10,10 @@ RUN apk add --no-cache git \ COPY server.py ./server.py COPY setup.py ./setup.py COPY main.py ./main.py +COPY flavors /data/master/flavors +COPY templates /data/master/templates -RUN python setup.py https://github.com/mailu/mailu /data +#RUN python setup.py https://github.com/mailu/mailu /data EXPOSE 80/tcp diff --git a/setup/docker-compose.yml b/setup/docker-compose.yml index 9288bb7e..30966167 100644 --- a/setup/docker-compose.yml +++ b/setup/docker-compose.yml @@ -10,4 +10,5 @@ services: image: mailu/setup ports: - "80:80" + build: . diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index a82817af..3dcfa5a2 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -24,7 +24,7 @@ services: ports: {% for port in (80, 443, 25, 465, 587, 110, 995, 143, 993) %} {% if bind4 %} - - "{{ bind4}}:{{ port }}:{{ port }}" + - "{{ bind4 }}:{{ port }}:{{ port }}" {% endif %} {% if bind6 %} - "{{ bind6 }}:{{ port }}:{{ port }}" diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 2de771f3..1512e75b 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -10,15 +10,15 @@ # Set this to the path where Mailu data and configuration is stored # This variable is now set directly in `docker-compose.yml by the setup utility -# ROOT=/mailu +# ROOT= {{ root }} # Set to a randomly generated 16 bytes string SECRET_KEY={{ secret(16) }} # Address where listening ports should bind # This variables are now set directly in `docker-compose.yml by the setup utility -# PUBLIC_IPV4=127.0.0.1 -# PUBLIC_IPV6=::1 +# PUBLIC_IPV4= {{ bind4 }} (default: 127.0.0.1) +# PUBLIC_IPV6= {{ bind6 }} (default: ::1) # Mail address of the postmaster POSTMASTER={{ postmaster }} @@ -83,7 +83,7 @@ WEB_ADMIN={{ admin_path }} WEB_WEBMAIL={{ webmail_path }} # Website name -SITENAME={{ site_name }{ +SITENAME={{ site_name }} # Linked Website URL WEBSITE={{ website }} diff --git a/setup/flavors/compose/setup.html b/setup/flavors/compose/setup.html index e4506e6d..3c190c9c 100644 --- a/setup/flavors/compose/setup.html +++ b/setup/flavors/compose/setup.html @@ -4,13 +4,13 @@

Docker Compose expects a project file, named docker-compose.yml in a project directory. First create your project directory.

-
mkdir /mailu
+
mkdir {{ root }}
 

Then download the project file. A side configuration file makes it easier to read and check the configuration variables generated by the wizard.

-
cd /mailu
+
cd {{ root }}
 wget {{ url_for('.file', uid=uid, filepath='docker-compose.yml', _external=True) }}
 wget {{ url_for('.file', uid=uid, filepath='mailu.env', _external=True) }}
 
@@ -30,7 +30,7 @@ files before going any further.

To start your compose project, simply run the Docker Compose up command.

-
cd /mailu
+
cd {{ root }}
 docker-compose up -d
 
{% endcall %} diff --git a/setup/server.py b/setup/server.py index 108f5043..ddeafd90 100644 --- a/setup/server.py +++ b/setup/server.py @@ -32,9 +32,11 @@ def secret(length=16): def build_app(path): + #Hardcoded master as the only version for test purposes versions = [ - version for version in os.listdir(path) - if os.path.isdir(os.path.join(path, version)) + # version for version in os.listdir(path) + # if os.path.isdir(os.path.join(path, version)) + "master" ] app.jinja_env.trim_blocks = True diff --git a/setup/templates/steps/expose.html b/setup/templates/steps/expose.html index 665b08a2..372ebddc 100644 --- a/setup/templates/steps/expose.html +++ b/setup/templates/steps/expose.html @@ -14,12 +14,12 @@ avoid generic all-interfaces addresses like 0.0.0.0 or :: - +
- +

You server will be available under a main hostname but may expose multiple public diff --git a/setup/templates/steps/root.html b/setup/templates/steps/root.html new file mode 100644 index 00000000..f32c2250 --- /dev/null +++ b/setup/templates/steps/root.html @@ -0,0 +1,8 @@ +{% call macros.panel("info", "Step 0 - Set root path") %} +

Before starting root path must be set

+ +
+ + +
+{% endcall %} diff --git a/setup/templates/wizard.html b/setup/templates/wizard.html index da9d5134..bbebe569 100644 --- a/setup/templates/wizard.html +++ b/setup/templates/wizard.html @@ -9,6 +9,7 @@ {% endcall %}
+ {% include "steps/root.html" %} {% include "steps/flavor.html" %} {% include "steps/expose.html" %} {% include "steps/services.html" %} From e8dee22ecfc8836f7d0a9ec56b3d68fba582b718 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 16 Oct 2018 16:12:42 +0300 Subject: [PATCH 18/93] Added vars and fixed naming use --- setup/flavors/compose/docker-compose.yml | 10 ++-- setup/flavors/compose/mailu.env | 32 +++++++++++-- setup/templates/steps/initial-config.html | 58 +++++++++++++++++++++++ setup/templates/steps/root.html | 8 ---- setup/templates/steps/services.html | 15 ++++-- setup/templates/wizard.html | 4 +- 6 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 setup/templates/steps/initial-config.html delete mode 100644 setup/templates/steps/root.html diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 3dcfa5a2..bf6c2db8 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -71,7 +71,7 @@ services: - front # Optional services - {% if enable_antispam %} + {% if antispam_enabled %} antispam: image: mailu/rspamd:{{ version }} restart: always @@ -84,7 +84,7 @@ services: - front {% endif %} - {% if enable_antivirus %} + {% if antivirus_enabled %} antivirus: image: mailu/clamav:{{ version }} restart: always @@ -93,9 +93,9 @@ services: - "{{ root }}/filter:/data" {% endif %} - {% if enable_webdav %} + {% if webdav_enabled %} webdav: - image: mailu/radivale:{{ version }} + image: mailu/radicale:{{ version }} restart: always env_file: {{ env }} volumes: @@ -112,7 +112,7 @@ services: {% endif %} # Webmail - {% if enable_webmail %} + {% if webmail_enabled %} webmail: image: mailu/{{ webmail }}:{{ version }} restart: always diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 1512e75b..4f470533 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -10,7 +10,7 @@ # Set this to the path where Mailu data and configuration is stored # This variable is now set directly in `docker-compose.yml by the setup utility -# ROOT= {{ root }} +# ROOT={{ root }} # Set to a randomly generated 16 bytes string SECRET_KEY={{ secret(16) }} @@ -20,8 +20,14 @@ SECRET_KEY={{ secret(16) }} # PUBLIC_IPV4= {{ bind4 }} (default: 127.0.0.1) # PUBLIC_IPV6= {{ bind6 }} (default: ::1) +# Main mail domain +# DOMAIN={{ domain }} + # Mail address of the postmaster -POSTMASTER={{ postmaster }} +POSTMASTER={{ postmaster or 'admin'}} + +#Chose how secure connections will behave: +#TLS_FLAVOR={{ tls_flavor }} # Hostnames for this server, separated with comas HOSTNAMES={{ hostnames }} @@ -30,7 +36,27 @@ HOSTNAMES={{ hostnames }} AUTH_RATELIMIT={{ auth_ratelimit }} # Opt-out of statistics, replace with "True" to opt out -DISABLE_STATISTICS={{ disable_statistics }} +DISABLE_STATISTICS={{ disable_statistics or 'False' }} + +################################### +# Optional features +################################### + +#Expose the admin interface +ADMIN={{ admin_enabled or 'false' }} + +#Chose which webmail to run if any +#WEBMAIL_ENABLED={{ webmail_enabled or 'false' }} +WEBMAIL={{ webmail_type or 'none' }} + +#Antivirus solution +ANTIVIRUS={{ antivirus_enabled or 'none' }} + +#Antispam solution +#ANTISPAM={{ antispam_enabled or 'none'}} + +#Dav server implementation +WEBDAV={{ webdav_enabled or 'none' }} ################################### # Server behavior diff --git a/setup/templates/steps/initial-config.html b/setup/templates/steps/initial-config.html new file mode 100644 index 00000000..d71d2971 --- /dev/null +++ b/setup/templates/steps/initial-config.html @@ -0,0 +1,58 @@ +{% call macros.panel("info", "Step 0 - Initial configuration") %} +

Before starting some variables must be st

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +{% endcall %} diff --git a/setup/templates/steps/root.html b/setup/templates/steps/root.html deleted file mode 100644 index f32c2250..00000000 --- a/setup/templates/steps/root.html +++ /dev/null @@ -1,8 +0,0 @@ -{% call macros.panel("info", "Step 0 - Set root path") %} -

Before starting root path must be set

- -
- - -
-{% endcall %} diff --git a/setup/templates/steps/services.html b/setup/templates/steps/services.html index e80b4ff4..e6ee88aa 100644 --- a/setup/templates/steps/services.html +++ b/setup/templates/steps/services.html @@ -9,7 +9,7 @@ manage your email domains, users, etc.

-
+
@@ -21,7 +21,7 @@ accessing messages for beginner users.

-
+

@@ -38,15 +38,22 @@ also disable the antivirus if required (it does use aroung 1GB of ram).

+
+ +
+ {% endcall %} diff --git a/setup/templates/wizard.html b/setup/templates/wizard.html index bbebe569..5a15af6f 100644 --- a/setup/templates/wizard.html +++ b/setup/templates/wizard.html @@ -9,11 +9,11 @@ {% endcall %} - {% include "steps/root.html" %} + {% include "steps/initial-config.html" %} {% include "steps/flavor.html" %} {% include "steps/expose.html" %} {% include "steps/services.html" %} - {% include "steps/optional.html" %} + From b9ecc0ccc6380c51dfd032397524e8c0d9ab4073 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 16 Oct 2018 18:03:59 +0300 Subject: [PATCH 19/93] Added minor changes --- setup/flavors/compose/docker-compose.yml | 10 ++++----- setup/flavors/compose/mailu.env | 11 +++++----- setup/templates/steps/initial-config.html | 25 ++++++++++++----------- setup/templates/steps/services.html | 11 ++++++++-- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index bf6c2db8..83a46169 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -19,8 +19,8 @@ services: restart: always env_file: {{ env }} env: - - TLS_FLAVOR={{ tls_flavor or 'letsencrypt' }} - - ADMIN={{ expose_admin or 'no' }} + - TLS_FLAVOR={{ tls_flavor }} + - ADMIN={{ admin_enabled or 'no' }} ports: {% for port in (80, 443, 25, 465, 587, 110, 995, 143, 993) %} {% if bind4 %} @@ -39,7 +39,7 @@ services: 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 %} @@ -102,7 +102,7 @@ services: - "{{ root }}/dav:/data" {% endif %} - {% if enable_fetchmail %} + {% if fetchmail_enabled %} fetchmail: image: mailu/fetchmail:{{ version }} restart: always @@ -114,7 +114,7 @@ services: # Webmail {% if webmail_enabled %} webmail: - image: mailu/{{ webmail }}:{{ version }} + image: mailu/{{ webmail_type }}:{{ version }} restart: always env_file: {{ env }} volumes: diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 4f470533..b1cded1c 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -33,7 +33,8 @@ POSTMASTER={{ postmaster or 'admin'}} HOSTNAMES={{ hostnames }} # Authentication rate limit (per source IP address) -AUTH_RATELIMIT={{ auth_ratelimit }} +AUTH_RATELIMIT={% if auth_ratelimit_pm %}{{ auth_ratelimit_pm }}/minute;{% endif %} +{% if auth_ratelimit_ph %}{{ auth_ratelimit_ph }}/hour{% endif %} # Opt-out of statistics, replace with "True" to opt out DISABLE_STATISTICS={{ disable_statistics or 'False' }} @@ -43,20 +44,20 @@ DISABLE_STATISTICS={{ disable_statistics or 'False' }} ################################### #Expose the admin interface -ADMIN={{ admin_enabled or 'false' }} +#ADMIN={{ admin_enabled or 'false' }} #Chose which webmail to run if any #WEBMAIL_ENABLED={{ webmail_enabled or 'false' }} -WEBMAIL={{ webmail_type or 'none' }} +#WEBMAIL={{ webmail_type or 'none' }} #Antivirus solution -ANTIVIRUS={{ antivirus_enabled or 'none' }} +#ANTIVIRUS={{ antivirus_enabled or 'none' }} #Antispam solution #ANTISPAM={{ antispam_enabled or 'none'}} #Dav server implementation -WEBDAV={{ webdav_enabled or 'none' }} +#WEBDAV={{ webdav_enabled or 'none' }} ################################### # Server behavior diff --git a/setup/templates/steps/initial-config.html b/setup/templates/steps/initial-config.html index d71d2971..c16d4c13 100644 --- a/setup/templates/steps/initial-config.html +++ b/setup/templates/steps/initial-config.html @@ -3,7 +3,7 @@
- +
@@ -11,9 +11,16 @@
+
+ +
+
- +
@@ -28,7 +35,8 @@
- +

/minute; + /hour

@@ -40,19 +48,12 @@
- +
- -
- -
- +
{% endcall %} diff --git a/setup/templates/steps/services.html b/setup/templates/steps/services.html index e6ee88aa..ed529c83 100644 --- a/setup/templates/steps/services.html +++ b/setup/templates/steps/services.html @@ -38,8 +38,8 @@ also disable the antivirus if required (it does use aroung 1GB of ram).

@@ -56,4 +56,11 @@ also disable the antivirus if required (it does use aroung 1GB of ram).

+
+ +
+ {% endcall %} From 5ada669f43b26b35c7f8ca2eab89fd8d2d5e3611 Mon Sep 17 00:00:00 2001 From: kaiyou Date: Tue, 16 Oct 2018 20:38:18 +0200 Subject: [PATCH 20/93] Rebase reply startdate on master --- core/admin/mailu/internal/templates/default.sieve | 2 +- core/admin/mailu/models.py | 2 +- core/admin/migrations/versions/3b281286c7bd_.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/admin/mailu/internal/templates/default.sieve b/core/admin/mailu/internal/templates/default.sieve index 214b8125..d771ee99 100644 --- a/core/admin/mailu/internal/templates/default.sieve +++ b/core/admin/mailu/internal/templates/default.sieve @@ -32,6 +32,6 @@ if exists "X-Virus" { stop; } -{% if user.reply_active and %} +{% if user.reply_active %} vacation :days 1 :subject "{{ user.reply_subject }}" "{{ user.reply_body }}"; {% endif %} diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index bb8cdc94..f7c3349d 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -280,7 +280,7 @@ class User(Base, Email): @property def reply_active(self): - now = datetime.datetime.now() + now = date.today() return ( self.reply_enabled and self.reply_startdate < now and diff --git a/core/admin/migrations/versions/3b281286c7bd_.py b/core/admin/migrations/versions/3b281286c7bd_.py index 78e44a4c..57b5c327 100644 --- a/core/admin/migrations/versions/3b281286c7bd_.py +++ b/core/admin/migrations/versions/3b281286c7bd_.py @@ -1,13 +1,13 @@ """ Add a start day for vacations Revision ID: 3b281286c7bd -Revises: 049fed905da7 +Revises: 25fd6c7bcb4a Create Date: 2018-09-27 22:20:08.158553 """ revision = '3b281286c7bd' -down_revision = '049fed905da7' +down_revision = '25fd6c7bcb4a' from alembic import op import sqlalchemy as sa From 39272ab05c35d05366c35a8ebfd25e87ea7f41de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Tue, 16 Oct 2018 21:38:12 +0200 Subject: [PATCH 21/93] add healthcheck for http services --- core/admin/Dockerfile | 4 +++- core/nginx/Dockerfile | 4 +++- docs/Dockerfile | 8 ++++++-- optional/radicale/Dockerfile | 4 +++- services/rspamd/Dockerfile | 4 +++- setup/Dockerfile | 4 +++- webmails/rainloop/Dockerfile | 4 +++- webmails/roundcube/Dockerfile | 4 +++- 8 files changed, 27 insertions(+), 9 deletions(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 2e637206..083bec80 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -4,7 +4,7 @@ RUN mkdir -p /app WORKDIR /app COPY requirements-prod.txt requirements.txt -RUN apk add --no-cache openssl \ +RUN apk add --no-cache openssl curl \ && apk add --no-cache --virtual build-dep openssl-dev libffi-dev python-dev build-base \ && pip install -r requirements.txt \ && apk del --no-cache build-dep @@ -20,3 +20,5 @@ EXPOSE 80/tcp VOLUME ["/data"] CMD ["/start.sh"] + +HEALTHCHECK CMD curl -f -L http://localhost/ui || exit 1 diff --git a/core/nginx/Dockerfile b/core/nginx/Dockerfile index 1b61447a..87951c03 100644 --- a/core/nginx/Dockerfile +++ b/core/nginx/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.8 -RUN apk add --no-cache certbot nginx nginx-mod-mail openssl \ +RUN apk add --no-cache certbot nginx nginx-mod-mail openssl curl \ python py-jinja2 py-requests-toolbelt py-pip \ && pip install --upgrade pip \ && pip install idna @@ -12,3 +12,5 @@ EXPOSE 80/tcp 443/tcp 110/tcp 143/tcp 465/tcp 587/tcp 993/tcp 995/tcp 25/tcp 100 VOLUME ["/certs"] CMD /start.py + +HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1 diff --git a/docs/Dockerfile b/docs/Dockerfile index af481a27..b058e0e2 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -3,7 +3,7 @@ FROM python:3-alpine COPY requirements.txt /requirements.txt RUN pip install -r /requirements.txt \ - && apk add --no-cache nginx \ + && apk add --no-cache nginx curl \ && mkdir /run/nginx COPY ./nginx.conf /etc/nginx/conf.d/default.conf @@ -11,4 +11,8 @@ COPY . /docs RUN sphinx-build /docs /build -CMD nginx -g "daemon off;" \ No newline at end of file +EXPOSE 80/tcp + +CMD nginx -g "daemon off;" + +HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1 diff --git a/optional/radicale/Dockerfile b/optional/radicale/Dockerfile index b82a0804..4616d53d 100644 --- a/optional/radicale/Dockerfile +++ b/optional/radicale/Dockerfile @@ -1,7 +1,7 @@ FROM alpine:edge RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ - && apk add --no-cache radicale@testing py-dulwich@testing + && apk add --no-cache radicale@testing py-dulwich@testing curl COPY radicale.conf /radicale.conf @@ -9,3 +9,5 @@ EXPOSE 5232/tcp VOLUME ["/data"] CMD radicale -f -S -C /radicale.conf + +HEALTHCHECK CMD curl -f -L http://localhost:5232/ || exit 1 diff --git a/services/rspamd/Dockerfile b/services/rspamd/Dockerfile index 7239ddaf..d87a64f5 100644 --- a/services/rspamd/Dockerfile +++ b/services/rspamd/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.8 -RUN apk add --no-cache python py-jinja2 rspamd rspamd-controller rspamd-proxy ca-certificates py-pip \ +RUN apk add --no-cache python py-jinja2 rspamd rspamd-controller rspamd-proxy ca-certificates py-pip curl \ && pip install --upgrade pip \ && pip install tenacity @@ -17,3 +17,5 @@ EXPOSE 11332/tcp 11334/tcp VOLUME ["/var/lib/rspamd"] CMD /start.py + +HEALTHCHECK CMD curl -f -L http://localhost:11334/ || exit 1 diff --git a/setup/Dockerfile b/setup/Dockerfile index 1fc808f1..0da1eb7b 100644 --- a/setup/Dockerfile +++ b/setup/Dockerfile @@ -4,7 +4,7 @@ RUN mkdir -p /app WORKDIR /app COPY requirements.txt requirements.txt -RUN apk add --no-cache git \ +RUN apk add --no-cache git curl \ && pip install -r requirements.txt COPY server.py ./server.py @@ -16,3 +16,5 @@ RUN python setup.py https://github.com/mailu/mailu /data EXPOSE 80/tcp CMD gunicorn -w 4 -b :80 --access-logfile - --error-logfile - --preload main:app + +HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1 diff --git a/webmails/rainloop/Dockerfile b/webmails/rainloop/Dockerfile index 889c8486..5d751716 100644 --- a/webmails/rainloop/Dockerfile +++ b/webmails/rainloop/Dockerfile @@ -3,7 +3,7 @@ FROM php:7.2-apache ENV RAINLOOP_URL https://github.com/RainLoop/rainloop-webmail/releases/download/v1.12.1/rainloop-community-1.12.1.zip RUN apt-get update && apt-get install -y \ - unzip python3 python3-jinja2 \ + unzip python3 python3-jinja2 curl \ && rm -rf /var/www/html/ \ && mkdir /var/www/html \ && cd /var/www/html \ @@ -29,3 +29,5 @@ EXPOSE 80/tcp VOLUME ["/data"] CMD /start.py + +HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1 diff --git a/webmails/roundcube/Dockerfile b/webmails/roundcube/Dockerfile index 50a58a4f..6250e6df 100644 --- a/webmails/roundcube/Dockerfile +++ b/webmails/roundcube/Dockerfile @@ -3,7 +3,7 @@ FROM php:7.2-apache ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.3.7/roundcubemail-1.3.7-complete.tar.gz RUN apt-get update && apt-get install -y \ - zlib1g-dev \ + zlib1g-dev curl \ && docker-php-ext-install zip \ && echo date.timezone=UTC > /usr/local/etc/php/conf.d/timezone.ini \ && rm -rf /var/www/html/ \ @@ -28,3 +28,5 @@ EXPOSE 80/tcp VOLUME ["/data"] CMD ["/start.sh"] + +HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1 From 040c1e529ac293b26bccd5d1be86e52a9561bb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Tue, 16 Oct 2018 22:20:16 +0200 Subject: [PATCH 22/93] add healthcheck for antivirus --- optional/clamav/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/optional/clamav/Dockerfile b/optional/clamav/Dockerfile index a27c0eb2..fd5de38b 100644 --- a/optional/clamav/Dockerfile +++ b/optional/clamav/Dockerfile @@ -9,3 +9,5 @@ EXPOSE 3310/tcp VOLUME ["/data"] CMD ["/start.sh"] + +HEALTHCHECK CMD [ "$(echo PING | nc localhost 3310)" = "PONG" ] From f0f5cea5d1dba49d966d4e61d88e5dfae889c09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Tue, 16 Oct 2018 22:30:15 +0200 Subject: [PATCH 23/93] make antivirus-healthcheck more understandable --- optional/clamav/Dockerfile | 3 ++- optional/clamav/health.sh | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 optional/clamav/health.sh diff --git a/optional/clamav/Dockerfile b/optional/clamav/Dockerfile index fd5de38b..3a9bf4aa 100644 --- a/optional/clamav/Dockerfile +++ b/optional/clamav/Dockerfile @@ -4,10 +4,11 @@ RUN apk add --no-cache clamav rsyslog wget clamav-libunrar COPY conf /etc/clamav COPY start.sh /start.sh +COPY health.sh /health.sh EXPOSE 3310/tcp VOLUME ["/data"] CMD ["/start.sh"] -HEALTHCHECK CMD [ "$(echo PING | nc localhost 3310)" = "PONG" ] +HEALTHCHECK CMD /health.sh diff --git a/optional/clamav/health.sh b/optional/clamav/health.sh new file mode 100755 index 00000000..c4c55044 --- /dev/null +++ b/optional/clamav/health.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "$(echo PING | nc localhost 3310)" = "PONG" ]; then + echo "ping successful" +else + echo "ping failed" + exit 1 +fi From 8fa80c15894da57131cea00f8274737d37d8054f Mon Sep 17 00:00:00 2001 From: kaiyou Date: Tue, 16 Oct 2018 22:52:21 +0200 Subject: [PATCH 24/93] Support multiple docs versions --- docs/Dockerfile | 6 +++++- docs/_templates/page.html | 4 ---- docs/_templates/versions.html | 16 ++++++++++++++++ docs/conf.py | 8 +++++++- docs/docker-compose.yml | 21 +++++++++++++++++++++ 5 files changed, 49 insertions(+), 6 deletions(-) delete mode 100644 docs/_templates/page.html create mode 100644 docs/_templates/versions.html create mode 100644 docs/docker-compose.yml diff --git a/docs/Dockerfile b/docs/Dockerfile index af481a27..c1992f32 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -2,6 +2,9 @@ FROM python:3-alpine COPY requirements.txt /requirements.txt +ARG version=master +ENV VERSION=$version + RUN pip install -r /requirements.txt \ && apk add --no-cache nginx \ && mkdir /run/nginx @@ -9,6 +12,7 @@ RUN pip install -r /requirements.txt \ COPY ./nginx.conf /etc/nginx/conf.d/default.conf COPY . /docs -RUN sphinx-build /docs /build +RUN mkdir -p /build/$VERSION \ + && sphinx-build /docs /build/$VERSION CMD nginx -g "daemon off;" \ No newline at end of file diff --git a/docs/_templates/page.html b/docs/_templates/page.html deleted file mode 100644 index 97296793..00000000 --- a/docs/_templates/page.html +++ /dev/null @@ -1,4 +0,0 @@ -{%- extends "layout.html" %} -{% block body %} - {{ body|replace("VERSION_TAG", version) }} -{% endblock %} diff --git a/docs/_templates/versions.html b/docs/_templates/versions.html new file mode 100644 index 00000000..db4d332d --- /dev/null +++ b/docs/_templates/versions.html @@ -0,0 +1,16 @@ +
+ + Versions + v: {{ version }} + + +
+
+
{{ _('Versions') }}
+ {% for slug, url in versions %} +
{{ slug }}
+ {% endfor %} +
+
+
+ diff --git a/docs/conf.py b/docs/conf.py index f89b39fd..e86a7b9e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,6 +2,8 @@ # -*- coding: utf-8 -*- # +import os + extensions = ['sphinx.ext.imgmath', 'sphinx.ext.viewcode'] templates_path = ['_templates'] source_suffix = '.rst' @@ -33,6 +35,10 @@ html_context = { 'display_github': True, 'github_user': 'mailu', 'github_repo': 'mailu', - 'github_version': 'master', + 'github_version': os.environ.get('VERSION', 'master'), + 'versions': [ + ('1.5', '/1.5/'), + ('master', '/master/') + ], 'conf_py_path': '/docs/' } diff --git a/docs/docker-compose.yml b/docs/docker-compose.yml new file mode 100644 index 00000000..0caaa7a4 --- /dev/null +++ b/docs/docker-compose.yml @@ -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/ + From 13e3862ca701f5ec5d5e2f3cbb1fff196f0220ca Mon Sep 17 00:00:00 2001 From: kaiyou Date: Tue, 16 Oct 2018 22:55:05 +0200 Subject: [PATCH 25/93] Simplify the docs configuration --- docs/_templates/layout.html | 2 -- docs/conf.py | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) delete mode 100644 docs/_templates/layout.html diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html deleted file mode 100644 index 3f424a0a..00000000 --- a/docs/_templates/layout.html +++ /dev/null @@ -1,2 +0,0 @@ -{% set version=github_version %} -{% extends "!layout.html" %} diff --git a/docs/conf.py b/docs/conf.py index e86a7b9e..4ac9de3d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,9 +11,9 @@ master_doc = 'index' project = 'Mailu' copyright = '2018, Mailu authors' author = 'Mailu authors' -version = release = 'latest' +version = release = os.environ.get('VERSION', 'master') language = None -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'Dockerfile', 'docker-compose.yml'] pygments_style = 'sphinx' todo_include_todos = False html_theme = 'sphinx_rtd_theme' @@ -35,7 +35,7 @@ html_context = { 'display_github': True, 'github_user': 'mailu', 'github_repo': 'mailu', - 'github_version': os.environ.get('VERSION', 'master'), + 'github_version': version, 'versions': [ ('1.5', '/1.5/'), ('master', '/master/') From 1fc40bf93220e1c1b66343b1ea254d49585b59df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Tue, 16 Oct 2018 22:57:25 +0200 Subject: [PATCH 26/93] add healthcheck for postfix --- core/postfix/Dockerfile | 3 +++ core/postfix/health.sh | 8 ++++++++ 2 files changed, 11 insertions(+) create mode 100755 core/postfix/health.sh diff --git a/core/postfix/Dockerfile b/core/postfix/Dockerfile index ea58ce1d..4208714a 100644 --- a/core/postfix/Dockerfile +++ b/core/postfix/Dockerfile @@ -7,8 +7,11 @@ RUN apk add --no-cache postfix postfix-pcre rsyslog \ COPY conf /conf COPY start.py /start.py +COPY health.sh /health.sh EXPOSE 25/tcp 10025/tcp VOLUME ["/data"] CMD /start.py + +HEALTHCHECK CMD /health.sh diff --git a/core/postfix/health.sh b/core/postfix/health.sh new file mode 100755 index 00000000..192eac25 --- /dev/null +++ b/core/postfix/health.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "$(echo QUIT|nc localhost 25|tail -n1|cut -f1 -d ' ')" = "221" ]; then + echo "ping successful" +else + echo "ping failed" + exit 1 +fi From 0bc901a722f957faab0af81a3d71aff6510cf442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Tue, 16 Oct 2018 23:11:20 +0200 Subject: [PATCH 27/93] add healthcheck for dovecot --- core/dovecot/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/dovecot/Dockerfile b/core/dovecot/Dockerfile index d8d4c55b..c0d3e3cd 100644 --- a/core/dovecot/Dockerfile +++ b/core/dovecot/Dockerfile @@ -13,3 +13,5 @@ EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp VOLUME ["/data", "/mail"] CMD /start.py + +HEALTHCHECK CMD echo QUIT|nc localhost 110|grep "Dovecot ready." From a412951a308c7c1e9a15d7790835f164d0e04814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Tue, 16 Oct 2018 23:12:02 +0200 Subject: [PATCH 28/93] simpler healthcheck for postfix --- core/postfix/Dockerfile | 3 +-- core/postfix/health.sh | 8 -------- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100755 core/postfix/health.sh diff --git a/core/postfix/Dockerfile b/core/postfix/Dockerfile index 4208714a..5533499e 100644 --- a/core/postfix/Dockerfile +++ b/core/postfix/Dockerfile @@ -7,11 +7,10 @@ RUN apk add --no-cache postfix postfix-pcre rsyslog \ COPY conf /conf COPY start.py /start.py -COPY health.sh /health.sh EXPOSE 25/tcp 10025/tcp VOLUME ["/data"] CMD /start.py -HEALTHCHECK CMD /health.sh +HEALTHCHECK CMD echo QUIT|nc localhost 25|grep "220 .* ESMTP Postfix" diff --git a/core/postfix/health.sh b/core/postfix/health.sh deleted file mode 100755 index 192eac25..00000000 --- a/core/postfix/health.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -if [ "$(echo QUIT|nc localhost 25|tail -n1|cut -f1 -d ' ')" = "221" ]; then - echo "ping successful" -else - echo "ping failed" - exit 1 -fi From 53b9c031c99ccb6c2530cacc8c54a57f92f82a58 Mon Sep 17 00:00:00 2001 From: kaiyou Date: Tue, 16 Oct 2018 23:19:48 +0200 Subject: [PATCH 29/93] Add a warning banner when not reading the stable docs --- docs/_templates/layout.html | 9 +++++++++ docs/conf.py | 1 + 2 files changed, 10 insertions(+) create mode 100644 docs/_templates/layout.html diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 00000000..63db07e2 --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,9 @@ +{% extends "!layout.html" %} +{% block document %} +{% if version != stable_version %} +
+

You are currently browsing documentation for the {{ version }} branch. Documentation for the stable {{ stable_version }} branch can be found here.

+
+{% endif %} +{{ super() }} +{% endblock %} diff --git a/docs/conf.py b/docs/conf.py index 4ac9de3d..64997eb1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,6 +36,7 @@ html_context = { 'github_user': 'mailu', 'github_repo': 'mailu', 'github_version': version, + 'stable_version': '1.5', 'versions': [ ('1.5', '/1.5/'), ('master', '/master/') From 4ea12deae792081d86372698dba8a4288bd68302 Mon Sep 17 00:00:00 2001 From: hacor Date: Wed, 17 Oct 2018 07:22:55 +0200 Subject: [PATCH 30/93] Added kubernetes to Mailu --- core/dovecot/Dockerfile | 4 +- core/nginx/Dockerfile | 4 +- core/nginx/conf/nginx.conf | 3 + core/postfix/Dockerfile | 2 +- core/postfix/conf/main.cf | 2 +- docs/compose/.env | 3 + docs/index.rst | 2 +- docs/kubernetes/index.rst | 26 -- docs/kubernetes/kubernetes-mailu.yaml | 419 ------------------ .../kubernetes-nginx-ingress-controller.yaml | 84 ---- docs/kubernetes/mailu/admin-ingress.yaml | 86 ++++ docs/kubernetes/mailu/admin.yaml | 63 +++ docs/kubernetes/mailu/configmap.yaml | 172 +++++++ docs/kubernetes/mailu/fetchmail.yaml | 39 ++ docs/kubernetes/mailu/front.yaml | 135 ++++++ docs/kubernetes/mailu/imap.yaml | 80 ++++ docs/kubernetes/mailu/index.rst | 193 ++++++++ docs/kubernetes/mailu/pvc.yaml | 27 ++ docs/kubernetes/mailu/rbac.yaml | 4 + docs/kubernetes/mailu/redis.yaml | 56 +++ docs/kubernetes/mailu/security-ingress.yaml | 30 ++ docs/kubernetes/mailu/security.yaml | 116 +++++ docs/kubernetes/mailu/smtp.yaml | 80 ++++ docs/kubernetes/mailu/webdav-ingress.yaml | 46 ++ docs/kubernetes/mailu/webdav.yaml | 63 +++ docs/kubernetes/mailu/webmail-ingress.yaml | 31 ++ docs/kubernetes/mailu/webmail.yaml | 59 +++ .../nginx/default-http-backend.yaml | 55 +++ docs/kubernetes/nginx/nginx-ingress.yaml | 127 ++++++ docs/kubernetes/nginx/rbac.yaml | 129 ++++++ services/rspamd/conf/worker-controller.inc | 4 + webmails/roundcube/Dockerfile | 6 +- 32 files changed, 1611 insertions(+), 539 deletions(-) delete mode 100644 docs/kubernetes/index.rst delete mode 100644 docs/kubernetes/kubernetes-mailu.yaml delete mode 100644 docs/kubernetes/kubernetes-nginx-ingress-controller.yaml create mode 100644 docs/kubernetes/mailu/admin-ingress.yaml create mode 100644 docs/kubernetes/mailu/admin.yaml create mode 100644 docs/kubernetes/mailu/configmap.yaml create mode 100644 docs/kubernetes/mailu/fetchmail.yaml create mode 100644 docs/kubernetes/mailu/front.yaml create mode 100644 docs/kubernetes/mailu/imap.yaml create mode 100644 docs/kubernetes/mailu/index.rst create mode 100644 docs/kubernetes/mailu/pvc.yaml create mode 100644 docs/kubernetes/mailu/rbac.yaml create mode 100644 docs/kubernetes/mailu/redis.yaml create mode 100644 docs/kubernetes/mailu/security-ingress.yaml create mode 100644 docs/kubernetes/mailu/security.yaml create mode 100644 docs/kubernetes/mailu/smtp.yaml create mode 100644 docs/kubernetes/mailu/webdav-ingress.yaml create mode 100644 docs/kubernetes/mailu/webdav.yaml create mode 100644 docs/kubernetes/mailu/webmail-ingress.yaml create mode 100644 docs/kubernetes/mailu/webmail.yaml create mode 100644 docs/kubernetes/nginx/default-http-backend.yaml create mode 100644 docs/kubernetes/nginx/nginx-ingress.yaml create mode 100644 docs/kubernetes/nginx/rbac.yaml diff --git a/core/dovecot/Dockerfile b/core/dovecot/Dockerfile index cacfe354..29957921 100644 --- a/core/dovecot/Dockerfile +++ b/core/dovecot/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:edge +FROM alpine:3.7 RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ && apk add --no-cache \ @@ -11,4 +11,4 @@ COPY start.py /start.py EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp -CMD /start.py +CMD /start.py \ No newline at end of file diff --git a/core/nginx/Dockerfile b/core/nginx/Dockerfile index 3be4b50f..49627fb7 100644 --- a/core/nginx/Dockerfile +++ b/core/nginx/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:edge +FROM alpine:3.7 RUN apk add --no-cache nginx nginx-mod-mail python py-jinja2 certbot openssl @@ -7,4 +7,4 @@ COPY *.py / EXPOSE 80/tcp 443/tcp 110/tcp 143/tcp 465/tcp 587/tcp 993/tcp 995/tcp 25/tcp 10025/tcp 10143/tcp -CMD /start.py +CMD /start.py \ No newline at end of file diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index 8fcda1c3..b6e0fbd3 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -34,6 +34,8 @@ http { '' $scheme; } + # Disable the main http server when on kubernetes (port 80 and 443) + {% if KUBERNETES_INGRESS != 'true' %} # Main HTTP server server { # Variables for proxifying @@ -147,6 +149,7 @@ http { proxy_set_header Content-Length ""; } } + {% endif %} # Forwarding authentication server server { diff --git a/core/postfix/Dockerfile b/core/postfix/Dockerfile index bb5831a2..168f3c60 100644 --- a/core/postfix/Dockerfile +++ b/core/postfix/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine +FROM alpine:3.7 RUN apk add --no-cache postfix postfix-sqlite postfix-pcre rsyslog python py-jinja2 diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index 2f2c6990..c1d5e4b2 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -32,7 +32,7 @@ relayhost = {{ RELAYHOST }} recipient_delimiter = {{ RECIPIENT_DELIMITER }} # Only the front server is allowed to perform xclient -smtpd_authorized_xclient_hosts={{ FRONT_ADDRESS }} +smtpd_authorized_xclient_hosts={{ RELAYNETS }} ############### # TLS diff --git a/docs/compose/.env b/docs/compose/.env index 06038bc8..e7a1f55d 100644 --- a/docs/compose/.env +++ b/docs/compose/.env @@ -55,6 +55,9 @@ WEBDAV=none # Antivirus solution (value: clamav, none) ANTIVIRUS=none +# The password for the rspamd web interface +RSPAMD_PASSWORD=Secr3tPassWord + ################################### # Mail settings ################################### diff --git a/docs/index.rst b/docs/index.rst index 0920bb96..ebfbd7a7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -55,7 +55,7 @@ the version of Mailu that you are running. configuration compose/requirements compose/setup - kubernetes/index + kubernetes/mailu/index dns reverse diff --git a/docs/kubernetes/index.rst b/docs/kubernetes/index.rst deleted file mode 100644 index efd1ab7c..00000000 --- a/docs/kubernetes/index.rst +++ /dev/null @@ -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..tld/admin`` (note that visiting just ``mail..tld`` will likely result in a 404 error). diff --git a/docs/kubernetes/kubernetes-mailu.yaml b/docs/kubernetes/kubernetes-mailu.yaml deleted file mode 100644 index a7bafccd..00000000 --- a/docs/kubernetes/kubernetes-mailu.yaml +++ /dev/null @@ -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 diff --git a/docs/kubernetes/kubernetes-nginx-ingress-controller.yaml b/docs/kubernetes/kubernetes-nginx-ingress-controller.yaml deleted file mode 100644 index 5ea9790a..00000000 --- a/docs/kubernetes/kubernetes-nginx-ingress-controller.yaml +++ /dev/null @@ -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 diff --git a/docs/kubernetes/mailu/admin-ingress.yaml b/docs/kubernetes/mailu/admin-ingress.yaml new file mode 100644 index 00000000..72aafa68 --- /dev/null +++ b/docs/kubernetes/mailu/admin-ingress.yaml @@ -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 \ No newline at end of file diff --git a/docs/kubernetes/mailu/admin.yaml b/docs/kubernetes/mailu/admin.yaml new file mode 100644 index 00000000..435b7975 --- /dev/null +++ b/docs/kubernetes/mailu/admin.yaml @@ -0,0 +1,63 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-admin + namespace: mailu-mailserver +spec: + replicas: 1 + template: + metadata: + labels: + app: mailu-admin + role: mail + tier: backend + spec: + containers: + - name: admin + image: mailu/admin:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + volumeMounts: + - name: maildata + mountPath: /data + subPath: maildata + - name: maildata + mountPath: /dkim + subPath: dkim + ports: + - name: http + containerPort: 80 + protocol: TCP + resources: + requests: + memory: 500Mi + cpu: 500m + limits: + memory: 500Mi + cpu: 500m + volumes: + - name: maildata + persistentVolumeClaim: + claimName: mail-storage +--- + +apiVersion: v1 +kind: Service +metadata: + name: admin + namespace: mailu-mailserver + labels: + app: mailu-admin + role: mail + tier: backend +spec: + selector: + app: mailu-admin + role: mail + tier: backend + ports: + - name: http + port: 80 + protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/mailu/configmap.yaml b/docs/kubernetes/mailu/configmap.yaml new file mode 100644 index 00000000..be39fcc9 --- /dev/null +++ b/docs/kubernetes/mailu/configmap.yaml @@ -0,0 +1,172 @@ + apiVersion: v1 + kind: ConfigMap + metadata: + name: mailu-config + namespace: mailu-mailserver + data: + # Mailu main configuration file + # + # Most configuration variables can be modified through the Web interface, + # these few settings must however be configured before starting the mail + # server and require a restart upon change. + + ################################### + # Common configuration variables + ################################### + + # Set this to the path where Mailu data and configuration is stored + ROOT: "/mailu" + + # Mailu version to run (1.0, 1.1, etc. or master) + VERSION: "master" + + # Set to a randomly generated 16 bytes string + SECRET_KEY: "MySup3rS3cr3tPas" + + # Address where listening ports should bind + BIND_ADDRESS4: "127.0.0.1" + #BIND_ADDRESS6: "::1" + + # Main mail domain + DOMAIN: "example.com" + + # Hostnames for this server, separated with comas + HOSTNAMES: "mail.example.com" + + # Postmaster local part (will append the main mail domain) + POSTMASTER: "admin" + + # Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt) + TLS_FLAVOR: "cert" + + # Authentication rate limit (per source IP address) + AUTH_RATELIMIT: "100/minute;10000/hour" + + # Opt-out of statistics, replace with "True" to opt out + 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" + POD_ADDRESS_RANGE: "10.2.0.0/16" + + ################################### + # Optional features + ################################### + + # Expose the admin interface (value: true, false) + ADMIN: "true" + # Run the admin interface in debug mode + #DEBUG: "True" + + # Choose which webmail to run if any (values: roundcube, rainloop, none) + WEBMAIL: "roundcube" + + # Dav server implementation (value: radicale, none) + WEBDAV: "radicale" + + # Antivirus solution (value: clamav, none) + ANTIVIRUS: "clamav" + + # The password for the rspamd web interface + RSPAMD_PASSWORD: "Secr3tPassWord" + + ################################### + # Mail settings + ################################### + + # Message size limit in bytes + # Default: accept messages up to 50MB + 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" + + # Will relay all outgoing mails if configured + #RELAYHOST= + + # 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" + + # 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: "600" + + # Recipient delimiter, character used to delimiter localpart from custom address part + # e.g. localpart+custom@domain;tld + RECIPIENT_DELIMITER: "+" + + # DMARC rua and ruf email + DMARC_RUA: "root" + DMARC_RUF: "root" + + # Welcome email, enable and set a topic and body if you wish to send welcome + # emails to all users. + WELCOME: "false" + WELCOME_SUBJECT: "Welcome to your new email account" + WELCOME_BODY: "Welcome to your new email account, if you can read this, then it is configured properly!" + + ################################### + # Web settings + ################################### + + # 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" + + # 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" + + # Website name + SITENAME: "Mailu" + + # Linked Website URL + WEBSITE: "https://example.com" + + # Registration reCaptcha settings (warning, this has some privacy impact) + # RECAPTCHA_PUBLIC_KEY= + # RECAPTCHA_PRIVATE_KEY= + + # Domain registration, uncomment to enable + # DOMAIN_REGISTRATION=true + + ################################### + # Advanced settings + ################################### + + # Docker-compose project name, this will prepended to containers names. + COMPOSE_PROJECT_NAME: "mailu" + + # Default password scheme used for newly created accounts and changed passwords + # (value: SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT) + PASSWORD_SCHEME: "SHA512-CRYPT" + + # Header to take the real ip from + #REAL_IP_HEADER: + + # IPs for nginx set_real_ip_from (CIDR list separated by commas) + #REAL_IP_FROM: + + # Host settings + HOST_IMAP: "imap.mailu-mailserver.svc.cluster.local" + HOST_POP3: "imap.mailu-mailserver.svc.cluster.local" + HOST_SMTP: "smtp.mailu-mailserver.svc.cluster.local" + HOST_AUTHSMTP: "smtp.mailu-mailserver.svc.cluster.local" + HOST_WEBMAIL: "webmail.mailu-mailserver.svc.cluster.local" + HOST_ADMIN: "admin.mailu-mailserver.svc.cluster.local" + HOST_WEBDAV: "webdav.mailu-mailserver.svc.cluster.local:5232" + HOST_ANTISPAM: "antispam.mailu-mailserver.svc.cluster.local:11332" + HOST_REDIS: "redis.mailu-mailserver.svc.cluster.local" diff --git a/docs/kubernetes/mailu/fetchmail.yaml b/docs/kubernetes/mailu/fetchmail.yaml new file mode 100644 index 00000000..cf3271e7 --- /dev/null +++ b/docs/kubernetes/mailu/fetchmail.yaml @@ -0,0 +1,39 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-fetchmail + namespace: mailu-mailserver +spec: + replicas: 1 + template: + metadata: + labels: + app: mailu-fetchmail + role: mail + tier: backend + spec: + containers: + - name: fetchmail + image: mailu/fetchmail:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + volumeMounts: + - name: maildata + mountPath: /data + subPath: maildata + ports: + - containerPort: 5232 + - containerPort: 80 + resources: + requests: + memory: 100Mi + cpu: 100m + limits: + memory: 100Mi + cpu: 100m + volumes: + - name: maildata + persistentVolumeClaim: + claimName: mail-storage \ No newline at end of file diff --git a/docs/kubernetes/mailu/front.yaml b/docs/kubernetes/mailu/front.yaml new file mode 100644 index 00000000..c13ecd9d --- /dev/null +++ b/docs/kubernetes/mailu/front.yaml @@ -0,0 +1,135 @@ +apiVersion: apps/v1beta2 +kind: DaemonSet +metadata: + name: mailu-front + namespace: mailu-mailserver + labels: + k8s-app: mail-loadbalancer + component: ingress-controller + type: nginx +spec: + selector: + matchLabels: + k8s-app: mail-loadbalancer + component: ingress-controller + type: nginx + template: + metadata: + labels: + k8s-app: mail-loadbalancer + component: ingress-controller + type: nginx + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + hostNetwork: true + nodeSelector: + node-role.kubernetes.io/node: "" + dnsPolicy: ClusterFirstWithHostNet + restartPolicy: Always + terminationGracePeriodSeconds: 60 + containers: + - name: front + image: mailu/nginx:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + volumeMounts: + - name: certs + mountPath: /certs + ports: + - name: pop3 + containerPort: 110 + protocol: TCP + - name: pop3s + containerPort: 995 + protocol: TCP + - name: imap + containerPort: 143 + protocol: TCP + - name: imaps + containerPort: 993 + protocol: TCP + - name: smtp + containerPort: 25 + protocol: TCP + - name: smtp-auth + containerPort: 10025 + protocol: TCP + - name: imap-auth + containerPort: 10143 + protocol: TCP + - name: smtps + containerPort: 465 + protocol: TCP + - name: smtpd + containerPort: 587 + protocol: TCP + - name: auth + containerPort: 8000 + protocol: TCP + resources: + requests: + memory: 100Mi + cpu: 100m + limits: + memory: 200Mi + cpu: 200m + volumes: + - 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: front + namespace: mailu-mailserver + labels: + k8s-app: mail-loadbalancer + component: ingress-controller + type: nginx +spec: + selector: + k8s-app: mail-loadbalancer + component: ingress-controller + type: nginx + ports: + - name: pop3 + port: 110 + protocol: TCP + - name: pop3s + port: 995 + protocol: TCP + - name: imap + port: 143 + protocol: TCP + - name: imaps + port: 993 + protocol: TCP + - name: smtp + port: 25 + protocol: TCP + - name: smtps + port: 465 + protocol: TCP + - name: smtpd + port: 587 + protocol: TCP + - name: smtp-auth + port: 10025 + protocol: TCP + - name: imap-auth + port: 10143 + protocol: TCP diff --git a/docs/kubernetes/mailu/imap.yaml b/docs/kubernetes/mailu/imap.yaml new file mode 100644 index 00000000..37f4899e --- /dev/null +++ b/docs/kubernetes/mailu/imap.yaml @@ -0,0 +1,80 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-imap + namespace: mailu-mailserver +spec: + replicas: 1 + template: + metadata: + labels: + app: mailu-imap + role: mail + tier: backend + spec: + containers: + - name: imap + image: mailu/dovecot:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + volumeMounts: + - mountPath: /data + name: maildata + subPath: maildata + - mountPath: /mail + name: maildata + subPath: mailstate + - mountPath: /overrides + name: maildata + subPath: overrides + ports: + - containerPort: 2102 + - containerPort: 2525 + - containerPort: 143 + - containerPort: 993 + - containerPort: 4190 + resources: + requests: + memory: 1Gi + cpu: 1000m + limits: + memory: 1Gi + cpu: 1000m + volumes: + - name: maildata + persistentVolumeClaim: + claimName: mail-storage +--- +apiVersion: v1 +kind: Service +metadata: + name: imap + namespace: mailu-mailserver + 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 \ No newline at end of file diff --git a/docs/kubernetes/mailu/index.rst b/docs/kubernetes/mailu/index.rst new file mode 100644 index 00000000..ef12eb58 --- /dev/null +++ b/docs/kubernetes/mailu/index.rst @@ -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 diff --git a/docs/kubernetes/mailu/pvc.yaml b/docs/kubernetes/mailu/pvc.yaml new file mode 100644 index 00000000..0ec2852f --- /dev/null +++ b/docs/kubernetes/mailu/pvc.yaml @@ -0,0 +1,27 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: redis-hdd + namespace: mailu-mailserver + annotations: + volume.beta.kubernetes.io/storage-class: "glusterblock-hdd" +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: mail-storage + namespace: mailu-mailserver + annotations: + volume.beta.kubernetes.io/storage-class: "gluster-heketi-hdd" +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 100Gi diff --git a/docs/kubernetes/mailu/rbac.yaml b/docs/kubernetes/mailu/rbac.yaml new file mode 100644 index 00000000..33255130 --- /dev/null +++ b/docs/kubernetes/mailu/rbac.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: mailu-mailserver \ No newline at end of file diff --git a/docs/kubernetes/mailu/redis.yaml b/docs/kubernetes/mailu/redis.yaml new file mode 100644 index 00000000..d6bb1eb8 --- /dev/null +++ b/docs/kubernetes/mailu/redis.yaml @@ -0,0 +1,56 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-redis + namespace: mailu-mailserver +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 + resources: + requests: + memory: 200Mi + cpu: 100m + limits: + memory: 300Mi + cpu: 200m + volumes: + - name: redisdata + persistentVolumeClaim: + claimName: redis-hdd +--- + +apiVersion: v1 +kind: Service +metadata: + name: redis + namespace: mailu-mailserver + labels: + app: mailu-redis + role: mail + tier: backend +spec: + selector: + app: mailu-redis + role: mail + tier: backend + ports: + - name: redis + port: 6379 + protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/mailu/security-ingress.yaml b/docs/kubernetes/mailu/security-ingress.yaml new file mode 100644 index 00000000..74ced47e --- /dev/null +++ b/docs/kubernetes/mailu/security-ingress.yaml @@ -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 \ No newline at end of file diff --git a/docs/kubernetes/mailu/security.yaml b/docs/kubernetes/mailu/security.yaml new file mode 100644 index 00000000..80fde812 --- /dev/null +++ b/docs/kubernetes/mailu/security.yaml @@ -0,0 +1,116 @@ + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-security + namespace: mailu-mailserver +spec: + replicas: 1 + template: + metadata: + labels: + app: mailu-security + role: mail + tier: backend + spec: + containers: + - name: antispam + image: mailu/rspamd:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + resources: + requests: + memory: 100Mi + cpu: 100m + limits: + memory: 200Mi + cpu: 200m + ports: + - name: antispam + containerPort: 11332 + protocol: TCP + - name: antispam-http + containerPort: 11334 + protocol: TCP + volumeMounts: + - name: filter + subPath: filter + mountPath: /var/lib/rspamd + - name: filter + mountPath: /dkim + subPath: dkim + - name: filter + mountPath: /etc/rspamd/override.d + subPath: rspamd-overrides + - name: antivirus + image: mailu/clamav:master + imagePullPolicy: Always + resources: + requests: + memory: 1Gi + cpu: 1000m + limits: + memory: 2Gi + cpu: 1000m + envFrom: + - configMapRef: + name: mailu-config + ports: + - name: antivirus + containerPort: 3310 + protocol: TCP + volumeMounts: + - name: filter + subPath: filter + mountPath: /data + volumes: + - name: filter + persistentVolumeClaim: + claimName: mail-storage + +--- + +apiVersion: v1 +kind: Service +metadata: + name: antispam + namespace: mailu-mailserver + labels: + app: mailu-antispam + role: mail + tier: backend +spec: + selector: + app: mailu-security + role: mail + tier: backend + ports: + - name: antispam + port: 11332 + protocol: TCP + - name: antispam-http + protocol: TCP + port: 11334 + +--- + +apiVersion: v1 +kind: Service +metadata: + name: antivirus + namespace: mailu-mailserver + labels: + app: mailu-antivirus + role: mail + tier: backend +spec: + selector: + app: mailu-security + role: mail + tier: backend + ports: + - name: antivirus + port: 3310 + protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/mailu/smtp.yaml b/docs/kubernetes/mailu/smtp.yaml new file mode 100644 index 00000000..926a2b7c --- /dev/null +++ b/docs/kubernetes/mailu/smtp.yaml @@ -0,0 +1,80 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-smtp + namespace: mailu-mailserver +spec: + replicas: 1 + template: + metadata: + labels: + app: mailu-smtp + role: mail + tier: backend + spec: + containers: + - name: smtp + image: mailu/postfix:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + resources: + requests: + memory: 2Gi + cpu: 500m + limits: + memory: 2Gi + cpu: 500m + volumeMounts: + - mountPath: /data + name: maildata + subPath: maildata + - mountPath: /overrides + name: maildata + subPath: overrides + ports: + - name: smtp + containerPort: 25 + protocol: TCP + - name: smtp-ssl + containerPort: 465 + protocol: TCP + - name: smtp-starttls + containerPort: 587 + protocol: TCP + - name: smtp-auth + containerPort: 10025 + protocol: TCP + volumes: + - name: maildata + persistentVolumeClaim: + claimName: mail-storage +--- +apiVersion: v1 +kind: Service +metadata: + name: smtp + namespace: mailu-mailserver + 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 + - name: smtp-auth + port: 10025 + protocol: TCP diff --git a/docs/kubernetes/mailu/webdav-ingress.yaml b/docs/kubernetes/mailu/webdav-ingress.yaml new file mode 100644 index 00000000..3498eb02 --- /dev/null +++ b/docs/kubernetes/mailu/webdav-ingress.yaml @@ -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 \ No newline at end of file diff --git a/docs/kubernetes/mailu/webdav.yaml b/docs/kubernetes/mailu/webdav.yaml new file mode 100644 index 00000000..07b7733c --- /dev/null +++ b/docs/kubernetes/mailu/webdav.yaml @@ -0,0 +1,63 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-webdav + namespace: mailu-mailserver +spec: + replicas: 1 + template: + metadata: + labels: + app: mailu-webdav + role: mail + tier: backend + spec: + containers: + - name: radicale + image: mailu/radicale:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + volumeMounts: + - mountPath: /data + name: maildata + subPath: dav + ports: + - containerPort: 5232 + - containerPort: 80 + resources: + requests: + memory: 100Mi + cpu: 100m + limits: + memory: 100Mi + cpu: 100m + volumes: + - name: maildata + persistentVolumeClaim: + claimName: mail-storage +--- + +apiVersion: v1 +kind: Service +metadata: + name: webdav + namespace: mailu-mailserver + labels: + app: mailu-webdav + role: mail + tier: backend +spec: + selector: + app: mailu-webdav + role: mail + tier: backend + ports: + ports: + - name: http + port: 80 + protocol: TCP + - name: http-ui + port: 5232 + protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/mailu/webmail-ingress.yaml b/docs/kubernetes/mailu/webmail-ingress.yaml new file mode 100644 index 00000000..40655ca2 --- /dev/null +++ b/docs/kubernetes/mailu/webmail-ingress.yaml @@ -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 \ No newline at end of file diff --git a/docs/kubernetes/mailu/webmail.yaml b/docs/kubernetes/mailu/webmail.yaml new file mode 100644 index 00000000..bbbeb09d --- /dev/null +++ b/docs/kubernetes/mailu/webmail.yaml @@ -0,0 +1,59 @@ + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mailu-roundcube + namespace: mailu-mailserver +spec: + replicas: 1 + template: + metadata: + labels: + app: mailu-roundcube + role: mail + tier: frontend + spec: + containers: + - name: roundcube + image: mailu/roundcube:master + imagePullPolicy: Always + envFrom: + - configMapRef: + name: mailu-config + resources: + requests: + memory: 100Mi + cpu: 100m + limits: + memory: 200Mi + cpu: 200m + volumeMounts: + - mountPath: /data + name: maildata + subPath: webmail + ports: + - containerPort: 80 + volumes: + - name: maildata + persistentVolumeClaim: + claimName: mail-storage +--- +apiVersion: v1 +kind: Service +metadata: + name: webmail + namespace: mailu-mailserver + labels: + app: mailu-roundcube + role: mail + tier: frontend +spec: + selector: + app: mailu-roundcube + role: mail + tier: frontend + ports: + ports: + - name: http + port: 80 + protocol: TCP diff --git a/docs/kubernetes/nginx/default-http-backend.yaml b/docs/kubernetes/nginx/default-http-backend.yaml new file mode 100644 index 00000000..097fe7c5 --- /dev/null +++ b/docs/kubernetes/nginx/default-http-backend.yaml @@ -0,0 +1,55 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: default-http-backend + labels: + app: default-http-backend + namespace: kube-ingress +spec: + replicas: 1 + selector: + matchLabels: + app: default-http-backend + template: + metadata: + labels: + app: default-http-backend + spec: + terminationGracePeriodSeconds: 60 + containers: + - name: default-http-backend + # Any image is permissible as long as: + # 1. It serves a 404 page at / + # 2. It serves 200 on a /healthz endpoint + image: gcr.io/google_containers/defaultbackend:1.4 + livenessProbe: + httpGet: + path: /healthz + port: 8080 + scheme: HTTP + initialDelaySeconds: 30 + timeoutSeconds: 5 + ports: + - containerPort: 8080 + resources: + limits: + cpu: 10m + memory: 20Mi + requests: + cpu: 10m + memory: 20Mi +--- + +apiVersion: v1 +kind: Service +metadata: + name: default-http-backend + namespace: kube-ingress + labels: + app: default-http-backend +spec: + ports: + - port: 80 + targetPort: 8080 + selector: + app: default-http-backend \ No newline at end of file diff --git a/docs/kubernetes/nginx/nginx-ingress.yaml b/docs/kubernetes/nginx/nginx-ingress.yaml new file mode 100644 index 00000000..d8b71e21 --- /dev/null +++ b/docs/kubernetes/nginx/nginx-ingress.yaml @@ -0,0 +1,127 @@ +apiVersion: v1 +kind: Service +metadata: + # keep it under 24 chars + name: ingress-lb + namespace: kube-ingress + labels: + k8s-app: ingress-lb + component: ingress-controller +spec: + type: ClusterIP + selector: + k8s-app: ingress-lb + component: ingress-controller + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 80 + - name: https + protocol: TCP + port: 443 + targetPort: 443 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: udp-services + namespace: kube-ingress + +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: tcp-services + namespace: kube-ingress +data: + +--- +apiVersion: v1 +data: + enable-vts-status: "true" +kind: ConfigMap +metadata: + name: nginx-ingress-lb-conf + namespace: kube-ingress +--- +apiVersion: apps/v1beta2 +kind: DaemonSet +metadata: + name: ingress-controller + namespace: kube-ingress + annotations: + prometheus.io/port: "10254" + prometheus.io/scrape: "true" + labels: + k8s-app: ingress-lb + component: ingress-controller + type: nginx +spec: + updateStrategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + k8s-app: ingress-lb + component: ingress-controller + type: nginx + template: + metadata: + labels: + k8s-app: ingress-lb + component: ingress-controller + type: nginx + spec: + serviceAccount: kube-nginx-ingress + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/master + operator: DoesNotExist + containers: + - name: nginx-ingress-lb + image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.2 + args: + - /nginx-ingress-controller + - --default-backend-service=$(POD_NAMESPACE)/default-http-backend + - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services + - --udp-services-configmap=$(POD_NAMESPACE)/udp-services + - --annotations-prefix=ingress.kubernetes.io + - --enable-ssl-passthrough + # use downward API + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + ports: + - name: http + containerPort: 80 + - name: https + containerPort: 443 + readinessProbe: + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + livenessProbe: + initialDelaySeconds: 10 + timeoutSeconds: 1 + httpGet: + path: /healthz + port: 10254 + scheme: HTTP + hostNetwork: true + nodeSelector: + node-role.kubernetes.io/node: "" + dnsPolicy: ClusterFirstWithHostNet + restartPolicy: Always + terminationGracePeriodSeconds: 60 diff --git a/docs/kubernetes/nginx/rbac.yaml b/docs/kubernetes/nginx/rbac.yaml new file mode 100644 index 00000000..d3c01384 --- /dev/null +++ b/docs/kubernetes/nginx/rbac.yaml @@ -0,0 +1,129 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: kube-ingress +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kube-nginx-ingress + namespace: kube-ingress +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: kube-nginx-ingress +rules: + - apiGroups: + - "" + resources: + - configmaps + - endpoints + - nodes + - pods + - secrets + verbs: + - list + - watch + - update + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch + - apiGroups: + - "extensions" + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "extensions" + resources: + - ingresses/status + verbs: + - update +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: Role +metadata: + name: kube-nginx-ingress + namespace: kube-ingress +rules: + - apiGroups: + - "" + resources: + - configmaps + - pods + - secrets + - namespaces + verbs: + - get + - apiGroups: + - "" + resources: + - configmaps + resourceNames: + - "ingress-controller-leader-nginx" + verbs: + - get + - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - apiGroups: + - "" + resources: + - endpoints + verbs: + - get + - create + - update +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: kube-nginx-ingress + namespace: kube-ingress +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kube-nginx-ingress +subjects: + - kind: ServiceAccount + name: kube-nginx-ingress + namespace: kube-ingress +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: kube-nginx-ingress +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kube-nginx-ingress +subjects: + - kind: ServiceAccount + name: kube-nginx-ingress + namespace: kube-ingress \ No newline at end of file diff --git a/services/rspamd/conf/worker-controller.inc b/services/rspamd/conf/worker-controller.inc index 6a020672..d3ab55f4 100644 --- a/services/rspamd/conf/worker-controller.inc +++ b/services/rspamd/conf/worker-controller.inc @@ -1,3 +1,7 @@ bind_socket = "*:11334"; +{% if RSPAMD_PASSWORD %} +password = "{{ RSPAMD_PASSWORD }}"; +{% else %} password = "mailu"; +{% endif %} secure_ip = "{{ FRONT_ADDRESS }}"; diff --git a/webmails/roundcube/Dockerfile b/webmails/roundcube/Dockerfile index c779e71a..e8a1aeaf 100644 --- a/webmails/roundcube/Dockerfile +++ b/webmails/roundcube/Dockerfile @@ -4,10 +4,10 @@ RUN apt-get update && apt-get install -y \ libfreetype6-dev \ libjpeg62-turbo-dev \ libmcrypt-dev \ - libpng12-dev \ + libpng-dev \ && docker-php-ext-install pdo_mysql mcrypt zip -ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.3.6/roundcubemail-1.3.6-complete.tar.gz +ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.3.7/roundcubemail-1.3.7-complete.tar.gz RUN echo date.timezone=UTC > /usr/local/etc/php/conf.d/timezone.ini @@ -28,4 +28,4 @@ COPY config.inc.php /var/www/html/config/ COPY start.sh /start.sh -CMD ["/start.sh"] +CMD ["/start.sh"] \ No newline at end of file From e67a0d464b16fb339710e61b90c91798db7e30d8 Mon Sep 17 00:00:00 2001 From: Hans Cornelis Date: Wed, 17 Oct 2018 07:44:21 +0200 Subject: [PATCH 31/93] Deleted old folder --- core/dovecot/Dockerfile_BACKUP_7007 | 19 +++ core/dovecot/Dockerfile_BASE_7007 | 14 ++ core/dovecot/Dockerfile_LOCAL_7007 | 14 ++ core/dovecot/Dockerfile_REMOTE_7007 | 15 ++ docs/kubernetes/1.6/README.md | 157 ------------------ docs/kubernetes/1.6/mailu/admin.yaml | 64 ------- docs/kubernetes/1.6/mailu/configmap.yaml | 153 ----------------- docs/kubernetes/1.6/mailu/fetchmail.yaml | 39 ----- docs/kubernetes/1.6/mailu/front.yaml | 129 -------------- docs/kubernetes/1.6/mailu/imap.yaml | 80 --------- docs/kubernetes/1.6/mailu/ingress-ssl.yaml | 32 ---- docs/kubernetes/1.6/mailu/pvc.yaml | 27 --- docs/kubernetes/1.6/mailu/rbac.yaml | 4 - docs/kubernetes/1.6/mailu/redis.yaml | 56 ------- docs/kubernetes/1.6/mailu/security.yaml | 110 ------------ docs/kubernetes/1.6/mailu/smtp.yaml | 80 --------- docs/kubernetes/1.6/mailu/static-ips.yaml | 0 docs/kubernetes/1.6/mailu/webdav.yaml | 63 ------- docs/kubernetes/1.6/mailu/webmail.yaml | 59 ------- .../1.6/nginx/default-http-backend.yaml | 55 ------ docs/kubernetes/1.6/nginx/nginx-ingress.yaml | 139 ---------------- docs/kubernetes/1.6/nginx/rbac.yaml | 129 -------------- 22 files changed, 62 insertions(+), 1376 deletions(-) create mode 100644 core/dovecot/Dockerfile_BACKUP_7007 create mode 100644 core/dovecot/Dockerfile_BASE_7007 create mode 100644 core/dovecot/Dockerfile_LOCAL_7007 create mode 100644 core/dovecot/Dockerfile_REMOTE_7007 delete mode 100644 docs/kubernetes/1.6/README.md delete mode 100644 docs/kubernetes/1.6/mailu/admin.yaml delete mode 100644 docs/kubernetes/1.6/mailu/configmap.yaml delete mode 100644 docs/kubernetes/1.6/mailu/fetchmail.yaml delete mode 100644 docs/kubernetes/1.6/mailu/front.yaml delete mode 100644 docs/kubernetes/1.6/mailu/imap.yaml delete mode 100644 docs/kubernetes/1.6/mailu/ingress-ssl.yaml delete mode 100644 docs/kubernetes/1.6/mailu/pvc.yaml delete mode 100644 docs/kubernetes/1.6/mailu/rbac.yaml delete mode 100644 docs/kubernetes/1.6/mailu/redis.yaml delete mode 100644 docs/kubernetes/1.6/mailu/security.yaml delete mode 100644 docs/kubernetes/1.6/mailu/smtp.yaml delete mode 100644 docs/kubernetes/1.6/mailu/static-ips.yaml delete mode 100644 docs/kubernetes/1.6/mailu/webdav.yaml delete mode 100644 docs/kubernetes/1.6/mailu/webmail.yaml delete mode 100644 docs/kubernetes/1.6/nginx/default-http-backend.yaml delete mode 100644 docs/kubernetes/1.6/nginx/nginx-ingress.yaml delete mode 100644 docs/kubernetes/1.6/nginx/rbac.yaml diff --git a/core/dovecot/Dockerfile_BACKUP_7007 b/core/dovecot/Dockerfile_BACKUP_7007 new file mode 100644 index 00000000..b5590a73 --- /dev/null +++ b/core/dovecot/Dockerfile_BACKUP_7007 @@ -0,0 +1,19 @@ +<<<<<<< HEAD +FROM alpine:3.7 +======= +FROM alpine:3.8 +>>>>>>> upstream/master + +RUN apk add --no-cache \ + dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client \ + python3 py3-pip \ + && pip3 install --upgrade pip \ + && pip3 install jinja2 podop tenacity + +COPY conf /conf +COPY start.py /start.py + +EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp +VOLUME ["/data", "/mail"] + +CMD /start.py \ No newline at end of file diff --git a/core/dovecot/Dockerfile_BASE_7007 b/core/dovecot/Dockerfile_BASE_7007 new file mode 100644 index 00000000..cacfe354 --- /dev/null +++ b/core/dovecot/Dockerfile_BASE_7007 @@ -0,0 +1,14 @@ +FROM alpine:edge + +RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ + && apk add --no-cache \ + dovecot dovecot-sqlite dovecot-pigeonhole-plugin dovecot-pigeonhole-plugin-extdata \ + rspamd-client@testing python py-jinja2 + +COPY conf /conf +COPY sieve /var/lib/dovecot +COPY start.py /start.py + +EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp + +CMD /start.py diff --git a/core/dovecot/Dockerfile_LOCAL_7007 b/core/dovecot/Dockerfile_LOCAL_7007 new file mode 100644 index 00000000..29957921 --- /dev/null +++ b/core/dovecot/Dockerfile_LOCAL_7007 @@ -0,0 +1,14 @@ +FROM alpine:3.7 + +RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ + && apk add --no-cache \ + dovecot dovecot-sqlite dovecot-pigeonhole-plugin dovecot-pigeonhole-plugin-extdata \ + rspamd-client@testing python py-jinja2 + +COPY conf /conf +COPY sieve /var/lib/dovecot +COPY start.py /start.py + +EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp + +CMD /start.py \ No newline at end of file diff --git a/core/dovecot/Dockerfile_REMOTE_7007 b/core/dovecot/Dockerfile_REMOTE_7007 new file mode 100644 index 00000000..d8d4c55b --- /dev/null +++ b/core/dovecot/Dockerfile_REMOTE_7007 @@ -0,0 +1,15 @@ +FROM alpine:3.8 + +RUN apk add --no-cache \ + dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client \ + python3 py3-pip \ + && pip3 install --upgrade pip \ + && pip3 install jinja2 podop tenacity + +COPY conf /conf +COPY start.py /start.py + +EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp +VOLUME ["/data", "/mail"] + +CMD /start.py diff --git a/docs/kubernetes/1.6/README.md b/docs/kubernetes/1.6/README.md deleted file mode 100644 index c0dd935b..00000000 --- a/docs/kubernetes/1.6/README.md +++ /dev/null @@ -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! \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/admin.yaml b/docs/kubernetes/1.6/mailu/admin.yaml deleted file mode 100644 index b36760a2..00000000 --- a/docs/kubernetes/1.6/mailu/admin.yaml +++ /dev/null @@ -1,64 +0,0 @@ - -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-admin - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-admin - role: mail - tier: backend - spec: - containers: - - name: admin - image: mailu/admin:master - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - volumeMounts: - - name: maildata - mountPath: /data - subPath: maildata - - name: maildata - mountPath: /dkim - subPath: dkim - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: - requests: - memory: 500Mi - cpu: 500m - limits: - memory: 500Mi - cpu: 500m - volumes: - - name: maildata - persistentVolumeClaim: - claimName: mail-storage ---- - -apiVersion: v1 -kind: Service -metadata: - name: admin - namespace: mailu-mailserver - labels: - app: mailu-admin - role: mail - tier: backend -spec: - selector: - app: mailu-admin - role: mail - tier: backend - ports: - - name: http - port: 80 - protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/configmap.yaml b/docs/kubernetes/1.6/mailu/configmap.yaml deleted file mode 100644 index 9ebce8b1..00000000 --- a/docs/kubernetes/1.6/mailu/configmap.yaml +++ /dev/null @@ -1,153 +0,0 @@ - apiVersion: v1 - kind: ConfigMap - metadata: - name: mailu-config - namespace: mailu-mailserver - data: - # Mailu main configuration file - # - # Most configuration variables can be modified through the Web interface, - # these few settings must however be configured before starting the mail - # server and require a restart upon change. - - ################################### - # Common configuration variables - ################################### - - # Set this to the path where Mailu data and configuration is stored - ROOT: "/mailu" - - # Mailu version to run (1.0, 1.1, etc. or master) - VERSION: "master" - - # Set to a randomly generated 16 bytes string - SECRET_KEY: "YourKeyHere" - - # Address where listening ports should bind - BIND_ADDRESS4: "127.0.0.1" - #BIND_ADDRESS6: "::1" - - # Main mail domain - DOMAIN: "example.com" - - # Hostnames for this server, separated with comas - HOSTNAMES: "mail.example.com" - - # Postmaster local part (will append the main mail domain) - POSTMASTER: "admin" - - # Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt) - TLS_FLAVOR: "cert" - - # Authentication rate limit (per source IP address) - AUTH_RATELIMIT: "10/minute;1000/hour" - - # Opt-out of statistics, replace with "True" to opt out - DISABLE_STATISTICS: "False" - - ################################### - # Optional features - ################################### - - # Expose the admin interface (value: true, false) - ADMIN: "true" - # Run the admin interface in debug mode - #DEBUG: "True" - - # Choose which webmail to run if any (values: roundcube, rainloop, none) - WEBMAIL: "roundcube" - - # Dav server implementation (value: radicale, none) - WEBDAV: "radicale" - - # Antivirus solution (value: clamav, none) - ANTIVIRUS: "clamav" - - ################################### - # Mail settings - ################################### - - # Message size limit in bytes - # Default: accept messages up to 50MB - 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 - #RELAYHOST= - - # 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" - - # Fetchmail delay - FETCHMAIL_DELAY: "600" - - # Recipient delimiter, character used to delimiter localpart from custom address part - # e.g. localpart+custom@domain;tld - RECIPIENT_DELIMITER: "+" - - # DMARC rua and ruf email - DMARC_RUA: "root" - DMARC_RUF: "root" - - # Welcome email, enable and set a topic and body if you wish to send welcome - # emails to all users. - WELCOME: "false" - WELCOME_SUBJECT: "Welcome to your new email account" - WELCOME_BODY: "Welcome to your new email account, if you can read this, then it is configured properly!" - - ################################### - # Web settings - ################################### - - # Path to the admin interface if enabled - WEB_ADMIN: "/admin" - - # Path to the webmail if enabled - WEB_WEBMAIL: "/webmail" - - # Website name - SITENAME: "AppSynth" - - # Linked Website URL - WEBSITE: "https://example.com" - - # Registration reCaptcha settings (warning, this has some privacy impact) - # RECAPTCHA_PUBLIC_KEY= - # RECAPTCHA_PRIVATE_KEY= - - # Domain registration, uncomment to enable - # DOMAIN_REGISTRATION=true - - ################################### - # Advanced settings - ################################### - - # Docker-compose project name, this will prepended to containers names. - COMPOSE_PROJECT_NAME: "mailu" - - # Default password scheme used for newly created accounts and changed passwords - # (value: SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT) - PASSWORD_SCHEME: "SHA512-CRYPT" - - # Header to take the real ip from - #REAL_IP_HEADER: - - # IPs for nginx set_real_ip_from (CIDR list separated by commas) - #REAL_IP_FROM: - - # Host settings - HOST_IMAP: "imap.mailu-mailserver.svc.cluster.local" - HOST_POP3: "imap.mailu-mailserver.svc.cluster.local" - HOST_SMTP: "smtp.mailu-mailserver.svc.cluster.local" - HOST_AUTHSMTP: "smtp.mailu-mailserver.svc.cluster.local" - HOST_WEBMAIL: "webmail.mailu-mailserver.svc.cluster.local" - HOST_ADMIN: "admin.mailu-mailserver.svc.cluster.local" - HOST_WEBDAV: "webdav.mailu-mailserver.svc.cluster.local:5232" - HOST_ANTISPAM: "antispam.mailu-mailserver.svc.cluster.local:11332" - HOST_REDIS: "redis.mailu-mailserver.svc.cluster.local" diff --git a/docs/kubernetes/1.6/mailu/fetchmail.yaml b/docs/kubernetes/1.6/mailu/fetchmail.yaml deleted file mode 100644 index cf3271e7..00000000 --- a/docs/kubernetes/1.6/mailu/fetchmail.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-fetchmail - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-fetchmail - role: mail - tier: backend - spec: - containers: - - name: fetchmail - image: mailu/fetchmail:master - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - volumeMounts: - - name: maildata - mountPath: /data - subPath: maildata - ports: - - containerPort: 5232 - - containerPort: 80 - resources: - requests: - memory: 100Mi - cpu: 100m - limits: - memory: 100Mi - cpu: 100m - volumes: - - name: maildata - persistentVolumeClaim: - claimName: mail-storage \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/front.yaml b/docs/kubernetes/1.6/mailu/front.yaml deleted file mode 100644 index e25ac828..00000000 --- a/docs/kubernetes/1.6/mailu/front.yaml +++ /dev/null @@ -1,129 +0,0 @@ - -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-front - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-front - role: mail - tier: backend - spec: - restartPolicy: Always - terminationGracePeriodSeconds: 60 - containers: - - name: front - image: mailu/nginx:latest - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - volumeMounts: - - name: certs - mountPath: /certs - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: https - containerPort: 443 - protocol: TCP - - name: pop3 - containerPort: 110 - protocol: TCP - - name: pop3s - containerPort: 995 - protocol: TCP - - name: imap - containerPort: 143 - protocol: TCP - - name: imaps - containerPort: 993 - protocol: TCP - - name: smtp - containerPort: 25 - protocol: TCP - - name: smtp-auth - containerPort: 10025 - protocol: TCP - - name: imap-auth - containerPort: 10143 - protocol: TCP - - name: smtps - containerPort: 465 - protocol: TCP - - name: smtpd - containerPort: 587 - protocol: TCP - - name: auth - containerPort: 8000 - protocol: TCP - resources: - requests: - memory: 100Mi - cpu: 100m - limits: - memory: 200Mi - cpu: 200m - volumes: - - 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: front - namespace: mailu-mailserver - labels: - app: mailu-admin - role: mail - tier: backend -spec: - selector: - app: mailu-front - role: mail - tier: backend - ports: - - name: http - port: 80 - protocol: TCP - - name: https - port: 443 - protocol: TCP - - name: pop3 - port: 110 - protocol: TCP - - name: pop3s - port: 995 - protocol: TCP - - name: imap - port: 143 - protocol: TCP - - name: imaps - port: 993 - protocol: TCP - - name: smtp - port: 25 - protocol: TCP - - name: smtps - port: 465 - protocol: TCP - - name: smtpd - port: 587 - protocol: TCP - - name: smtp-auth - port: 10025 - protocol: TCP - - name: imap-auth - port: 10143 - protocol: TCP diff --git a/docs/kubernetes/1.6/mailu/imap.yaml b/docs/kubernetes/1.6/mailu/imap.yaml deleted file mode 100644 index 069b7730..00000000 --- a/docs/kubernetes/1.6/mailu/imap.yaml +++ /dev/null @@ -1,80 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-imap - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-imap - role: mail - tier: backend - spec: - containers: - - name: imap - image: mailu/dovecot:master - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - volumeMounts: - - mountPath: /data - name: maildata - subPath: maildata - - mountPath: /mail - name: maildata - subPath: mailstate - - mountPath: /overrides - name: maildata - subPath: overrides - ports: - - containerPort: 2102 - - containerPort: 2525 - - containerPort: 143 - - containerPort: 993 - - containerPort: 4190 - resources: - requests: - memory: 500Mi - cpu: 500m - limits: - memory: 1Gi - cpu: 1000m - volumes: - - name: maildata - persistentVolumeClaim: - claimName: mail-storage ---- -apiVersion: v1 -kind: Service -metadata: - name: imap - namespace: mailu-mailserver - 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 \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/ingress-ssl.yaml b/docs/kubernetes/1.6/mailu/ingress-ssl.yaml deleted file mode 100644 index 61ae3cf7..00000000 --- a/docs/kubernetes/1.6/mailu/ingress-ssl.yaml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/pvc.yaml b/docs/kubernetes/1.6/mailu/pvc.yaml deleted file mode 100644 index 0ec2852f..00000000 --- a/docs/kubernetes/1.6/mailu/pvc.yaml +++ /dev/null @@ -1,27 +0,0 @@ -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: redis-hdd - namespace: mailu-mailserver - annotations: - volume.beta.kubernetes.io/storage-class: "glusterblock-hdd" -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: mail-storage - namespace: mailu-mailserver - annotations: - volume.beta.kubernetes.io/storage-class: "gluster-heketi-hdd" -spec: - accessModes: - - ReadWriteMany - resources: - requests: - storage: 100Gi diff --git a/docs/kubernetes/1.6/mailu/rbac.yaml b/docs/kubernetes/1.6/mailu/rbac.yaml deleted file mode 100644 index 33255130..00000000 --- a/docs/kubernetes/1.6/mailu/rbac.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: mailu-mailserver \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/redis.yaml b/docs/kubernetes/1.6/mailu/redis.yaml deleted file mode 100644 index d6bb1eb8..00000000 --- a/docs/kubernetes/1.6/mailu/redis.yaml +++ /dev/null @@ -1,56 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-redis - namespace: mailu-mailserver -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 - resources: - requests: - memory: 200Mi - cpu: 100m - limits: - memory: 300Mi - cpu: 200m - volumes: - - name: redisdata - persistentVolumeClaim: - claimName: redis-hdd ---- - -apiVersion: v1 -kind: Service -metadata: - name: redis - namespace: mailu-mailserver - labels: - app: mailu-redis - role: mail - tier: backend -spec: - selector: - app: mailu-redis - role: mail - tier: backend - ports: - - name: redis - port: 6379 - protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/security.yaml b/docs/kubernetes/1.6/mailu/security.yaml deleted file mode 100644 index c1c1ac0b..00000000 --- a/docs/kubernetes/1.6/mailu/security.yaml +++ /dev/null @@ -1,110 +0,0 @@ - -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-security - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-security - role: mail - tier: backend - spec: - containers: - - name: antispam - image: mailu/rspamd:master - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - resources: - requests: - memory: 100Mi - cpu: 100m - limits: - memory: 200Mi - cpu: 200m - ports: - - name: antispam - containerPort: 11332 - protocol: TCP - volumeMounts: - - name: filter - subPath: filter - mountPath: /var/lib/rspamd - - name: filter - mountPath: /dkim - subPath: dkim - - name: filter - mountPath: /etc/rspamd/override.d - subPath: rspamd-overrides - - name: antivirus - image: mailu/clamav:master - imagePullPolicy: Always - resources: - requests: - memory: 1Gi - cpu: 1000m - limits: - memory: 2Gi - cpu: 1000m - envFrom: - - configMapRef: - name: mailu-config - ports: - - name: antivirus - containerPort: 3310 - protocol: TCP - volumeMounts: - - name: filter - subPath: filter - mountPath: /data - volumes: - - name: filter - persistentVolumeClaim: - claimName: mail-storage - ---- - -apiVersion: v1 -kind: Service -metadata: - name: antispam - namespace: mailu-mailserver - labels: - app: mailu-antispam - role: mail - tier: backend -spec: - selector: - app: mailu-security - role: mail - tier: backend - ports: - - name: antispam - port: 11332 - protocol: TCP - ---- - -apiVersion: v1 -kind: Service -metadata: - name: antivirus - namespace: mailu-mailserver - labels: - app: mailu-antivirus - role: mail - tier: backend -spec: - selector: - app: mailu-security - role: mail - tier: backend - ports: - - name: antivirus - port: 3310 - protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/smtp.yaml b/docs/kubernetes/1.6/mailu/smtp.yaml deleted file mode 100644 index 454b8ed7..00000000 --- a/docs/kubernetes/1.6/mailu/smtp.yaml +++ /dev/null @@ -1,80 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-smtp - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-smtp - role: mail - tier: backend - spec: - containers: - - name: smtp - image: mailu/postfix:master - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - resources: - requests: - memory: 500Mi - cpu: 200m - limits: - memory: 1Gi - cpu: 500m - volumeMounts: - - mountPath: /data - name: maildata - subPath: maildata - - mountPath: /overrides - name: maildata - subPath: overrides - ports: - - name: smtp - containerPort: 25 - protocol: TCP - - name: smtp-ssl - containerPort: 465 - protocol: TCP - - name: smtp-starttls - containerPort: 587 - protocol: TCP - - name: smtp-auth - containerPort: 10025 - protocol: TCP - volumes: - - name: maildata - persistentVolumeClaim: - claimName: mail-storage ---- -apiVersion: v1 -kind: Service -metadata: - name: smtp - namespace: mailu-mailserver - 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 - - name: smtp-auth - port: 10025 - protocol: TCP diff --git a/docs/kubernetes/1.6/mailu/static-ips.yaml b/docs/kubernetes/1.6/mailu/static-ips.yaml deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/kubernetes/1.6/mailu/webdav.yaml b/docs/kubernetes/1.6/mailu/webdav.yaml deleted file mode 100644 index 07b7733c..00000000 --- a/docs/kubernetes/1.6/mailu/webdav.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-webdav - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-webdav - role: mail - tier: backend - spec: - containers: - - name: radicale - image: mailu/radicale:master - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - volumeMounts: - - mountPath: /data - name: maildata - subPath: dav - ports: - - containerPort: 5232 - - containerPort: 80 - resources: - requests: - memory: 100Mi - cpu: 100m - limits: - memory: 100Mi - cpu: 100m - volumes: - - name: maildata - persistentVolumeClaim: - claimName: mail-storage ---- - -apiVersion: v1 -kind: Service -metadata: - name: webdav - namespace: mailu-mailserver - labels: - app: mailu-webdav - role: mail - tier: backend -spec: - selector: - app: mailu-webdav - role: mail - tier: backend - ports: - ports: - - name: http - port: 80 - protocol: TCP - - name: http-ui - port: 5232 - protocol: TCP \ No newline at end of file diff --git a/docs/kubernetes/1.6/mailu/webmail.yaml b/docs/kubernetes/1.6/mailu/webmail.yaml deleted file mode 100644 index 81798782..00000000 --- a/docs/kubernetes/1.6/mailu/webmail.yaml +++ /dev/null @@ -1,59 +0,0 @@ - -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: mailu-roundcube - namespace: mailu-mailserver -spec: - replicas: 1 - template: - metadata: - labels: - app: mailu-roundcube - role: mail - tier: frontend - spec: - containers: - - name: roundcube - image: mailu/roundcube:1.5 - imagePullPolicy: Always - envFrom: - - configMapRef: - name: mailu-config - resources: - requests: - memory: 100Mi - cpu: 100m - limits: - memory: 200Mi - cpu: 200m - volumeMounts: - - mountPath: /data - name: maildata - subPath: webmail - ports: - - containerPort: 80 - volumes: - - name: maildata - persistentVolumeClaim: - claimName: mail-storage ---- -apiVersion: v1 -kind: Service -metadata: - name: webmail - namespace: mailu-mailserver - labels: - app: mailu-roundcube - role: mail - tier: frontend -spec: - selector: - app: mailu-roundcube - role: mail - tier: frontend - ports: - ports: - - name: http - port: 80 - protocol: TCP diff --git a/docs/kubernetes/1.6/nginx/default-http-backend.yaml b/docs/kubernetes/1.6/nginx/default-http-backend.yaml deleted file mode 100644 index 097fe7c5..00000000 --- a/docs/kubernetes/1.6/nginx/default-http-backend.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: default-http-backend - labels: - app: default-http-backend - namespace: kube-ingress -spec: - replicas: 1 - selector: - matchLabels: - app: default-http-backend - template: - metadata: - labels: - app: default-http-backend - spec: - terminationGracePeriodSeconds: 60 - containers: - - name: default-http-backend - # Any image is permissible as long as: - # 1. It serves a 404 page at / - # 2. It serves 200 on a /healthz endpoint - image: gcr.io/google_containers/defaultbackend:1.4 - livenessProbe: - httpGet: - path: /healthz - port: 8080 - scheme: HTTP - initialDelaySeconds: 30 - timeoutSeconds: 5 - ports: - - containerPort: 8080 - resources: - limits: - cpu: 10m - memory: 20Mi - requests: - cpu: 10m - memory: 20Mi ---- - -apiVersion: v1 -kind: Service -metadata: - name: default-http-backend - namespace: kube-ingress - labels: - app: default-http-backend -spec: - ports: - - port: 80 - targetPort: 8080 - selector: - app: default-http-backend \ No newline at end of file diff --git a/docs/kubernetes/1.6/nginx/nginx-ingress.yaml b/docs/kubernetes/1.6/nginx/nginx-ingress.yaml deleted file mode 100644 index 90b24f24..00000000 --- a/docs/kubernetes/1.6/nginx/nginx-ingress.yaml +++ /dev/null @@ -1,139 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - # keep it under 24 chars - name: appsynth-lb - namespace: kube-ingress - labels: - k8s-app: appsynth-lb - component: ingress-controller -spec: - type: ClusterIP - selector: - k8s-app: appsynth-lb - component: ingress-controller - ports: - - name: http - protocol: TCP - port: 80 - targetPort: 80 - - name: https - protocol: TCP - port: 443 - targetPort: 443 ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: udp-services - namespace: kube-ingress - ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: tcp-services - namespace: kube-ingress -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 -data: - enable-vts-status: "true" -kind: ConfigMap -metadata: - name: nginx-ingress-lb-conf - namespace: kube-ingress ---- -apiVersion: apps/v1beta2 -kind: DaemonSet -metadata: - name: ingress-controller - namespace: kube-ingress - annotations: - prometheus.io/port: "10254" - prometheus.io/scrape: "true" - labels: - k8s-app: appsynth-lb - component: ingress-controller - type: nginx -spec: - updateStrategy: - rollingUpdate: - maxUnavailable: 1 - type: RollingUpdate - selector: - matchLabels: - k8s-app: appsynth-lb - component: ingress-controller - type: nginx - template: - metadata: - labels: - k8s-app: appsynth-lb - component: ingress-controller - type: nginx - spec: - serviceAccount: kube-nginx-ingress - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: node-role.kubernetes.io/master - operator: DoesNotExist - containers: - - name: nginx-ingress-lb - image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.2 - args: - - /nginx-ingress-controller - - --configmap=$(POD_NAMESPACE)/tectonic-custom-error - - --default-backend-service=$(POD_NAMESPACE)/default-http-backend - #- --default-ssl-certificate=tectonic-system/tectonic-ingress-tls-secret - - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - - --annotations-prefix=ingress.kubernetes.io - - --enable-ssl-passthrough - - --ingress-class=tectonic - # use downward API - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - ports: - - name: http - containerPort: 80 - hostPort: 80 - - name: https - containerPort: 443 - hostPort: 443 - readinessProbe: - httpGet: - path: /healthz - port: 10254 - scheme: HTTP - livenessProbe: - initialDelaySeconds: 10 - timeoutSeconds: 1 - httpGet: - path: /healthz - port: 10254 - scheme: HTTP - hostNetwork: true - nodeSelector: - node-role.kubernetes.io/node: "" - dnsPolicy: ClusterFirst - restartPolicy: Always - terminationGracePeriodSeconds: 60 diff --git a/docs/kubernetes/1.6/nginx/rbac.yaml b/docs/kubernetes/1.6/nginx/rbac.yaml deleted file mode 100644 index d3c01384..00000000 --- a/docs/kubernetes/1.6/nginx/rbac.yaml +++ /dev/null @@ -1,129 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: kube-ingress ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kube-nginx-ingress - namespace: kube-ingress ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRole -metadata: - name: kube-nginx-ingress -rules: - - apiGroups: - - "" - resources: - - configmaps - - endpoints - - nodes - - pods - - secrets - verbs: - - list - - watch - - update - - apiGroups: - - "" - resources: - - nodes - verbs: - - get - - apiGroups: - - "" - resources: - - services - verbs: - - get - - list - - watch - - apiGroups: - - "extensions" - resources: - - ingresses - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - - apiGroups: - - "extensions" - resources: - - ingresses/status - verbs: - - update ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: Role -metadata: - name: kube-nginx-ingress - namespace: kube-ingress -rules: - - apiGroups: - - "" - resources: - - configmaps - - pods - - secrets - - namespaces - verbs: - - get - - apiGroups: - - "" - resources: - - configmaps - resourceNames: - - "ingress-controller-leader-nginx" - verbs: - - get - - update - - apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - apiGroups: - - "" - resources: - - endpoints - verbs: - - get - - create - - update ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: kube-nginx-ingress - namespace: kube-ingress -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: kube-nginx-ingress -subjects: - - kind: ServiceAccount - name: kube-nginx-ingress - namespace: kube-ingress ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding -metadata: - name: kube-nginx-ingress -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kube-nginx-ingress -subjects: - - kind: ServiceAccount - name: kube-nginx-ingress - namespace: kube-ingress \ No newline at end of file From ef55ca525c1286006c5090f4c653d133557851bb Mon Sep 17 00:00:00 2001 From: Hans Cornelis Date: Wed, 17 Oct 2018 07:48:52 +0200 Subject: [PATCH 32/93] Deleted conflicting merge files Signed-off-by: Hans Cornelis --- core/dovecot/Dockerfile_BACKUP_7007 | 19 ------------------- core/dovecot/Dockerfile_BASE_7007 | 14 -------------- core/dovecot/Dockerfile_LOCAL_7007 | 14 -------------- core/dovecot/Dockerfile_REMOTE_7007 | 15 --------------- 4 files changed, 62 deletions(-) delete mode 100644 core/dovecot/Dockerfile_BACKUP_7007 delete mode 100644 core/dovecot/Dockerfile_BASE_7007 delete mode 100644 core/dovecot/Dockerfile_LOCAL_7007 delete mode 100644 core/dovecot/Dockerfile_REMOTE_7007 diff --git a/core/dovecot/Dockerfile_BACKUP_7007 b/core/dovecot/Dockerfile_BACKUP_7007 deleted file mode 100644 index b5590a73..00000000 --- a/core/dovecot/Dockerfile_BACKUP_7007 +++ /dev/null @@ -1,19 +0,0 @@ -<<<<<<< HEAD -FROM alpine:3.7 -======= -FROM alpine:3.8 ->>>>>>> upstream/master - -RUN apk add --no-cache \ - dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client \ - python3 py3-pip \ - && pip3 install --upgrade pip \ - && pip3 install jinja2 podop tenacity - -COPY conf /conf -COPY start.py /start.py - -EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp -VOLUME ["/data", "/mail"] - -CMD /start.py \ No newline at end of file diff --git a/core/dovecot/Dockerfile_BASE_7007 b/core/dovecot/Dockerfile_BASE_7007 deleted file mode 100644 index cacfe354..00000000 --- a/core/dovecot/Dockerfile_BASE_7007 +++ /dev/null @@ -1,14 +0,0 @@ -FROM alpine:edge - -RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ - && apk add --no-cache \ - dovecot dovecot-sqlite dovecot-pigeonhole-plugin dovecot-pigeonhole-plugin-extdata \ - rspamd-client@testing python py-jinja2 - -COPY conf /conf -COPY sieve /var/lib/dovecot -COPY start.py /start.py - -EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp - -CMD /start.py diff --git a/core/dovecot/Dockerfile_LOCAL_7007 b/core/dovecot/Dockerfile_LOCAL_7007 deleted file mode 100644 index 29957921..00000000 --- a/core/dovecot/Dockerfile_LOCAL_7007 +++ /dev/null @@ -1,14 +0,0 @@ -FROM alpine:3.7 - -RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ - && apk add --no-cache \ - dovecot dovecot-sqlite dovecot-pigeonhole-plugin dovecot-pigeonhole-plugin-extdata \ - rspamd-client@testing python py-jinja2 - -COPY conf /conf -COPY sieve /var/lib/dovecot -COPY start.py /start.py - -EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp - -CMD /start.py \ No newline at end of file diff --git a/core/dovecot/Dockerfile_REMOTE_7007 b/core/dovecot/Dockerfile_REMOTE_7007 deleted file mode 100644 index d8d4c55b..00000000 --- a/core/dovecot/Dockerfile_REMOTE_7007 +++ /dev/null @@ -1,15 +0,0 @@ -FROM alpine:3.8 - -RUN apk add --no-cache \ - dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client \ - python3 py3-pip \ - && pip3 install --upgrade pip \ - && pip3 install jinja2 podop tenacity - -COPY conf /conf -COPY start.py /start.py - -EXPOSE 110/tcp 143/tcp 993/tcp 4190/tcp 2525/tcp -VOLUME ["/data", "/mail"] - -CMD /start.py From b3c7c45140f4c8d1e019ecff9db5c5f623b6f8ff Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Wed, 17 Oct 2018 15:11:55 +0300 Subject: [PATCH 33/93] Added input form constraints --- setup/flavors/compose/docker-compose.yml | 4 ++-- setup/flavors/compose/mailu.env | 6 ++--- .../config.html} | 22 +++++++++++++------ .../templates/steps/{ => compose}/expose.html | 12 +++++++--- .../templates/steps/{ => compose}/flavor.html | 0 .../steps/{ => compose}/optional.html | 0 .../steps/{ => compose}/services.html | 21 ++++++++++++------ setup/templates/wizard.html | 10 ++++----- 8 files changed, 48 insertions(+), 27 deletions(-) rename setup/templates/steps/{initial-config.html => compose/config.html} (71%) rename setup/templates/steps/{ => compose}/expose.html (67%) rename setup/templates/steps/{ => compose}/flavor.html (100%) rename setup/templates/steps/{ => compose}/optional.html (100%) rename setup/templates/steps/{ => compose}/services.html (77%) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 83a46169..8316e681 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -20,7 +20,7 @@ services: env_file: {{ env }} env: - TLS_FLAVOR={{ tls_flavor }} - - ADMIN={{ admin_enabled or 'no' }} + - ADMIN={{ admin_enabled or 'false' }} ports: {% for port in (80, 443, 25, 465, 587, 110, 995, 143, 993) %} {% if bind4 %} @@ -112,7 +112,7 @@ services: {% endif %} # Webmail - {% if webmail_enabled %} + {% if webmail_type != 'none' %} webmail: image: mailu/{{ webmail_type }}:{{ version }} restart: always diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index b1cded1c..77da5670 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -33,8 +33,9 @@ POSTMASTER={{ postmaster or 'admin'}} HOSTNAMES={{ hostnames }} # Authentication rate limit (per source IP address) -AUTH_RATELIMIT={% if auth_ratelimit_pm %}{{ auth_ratelimit_pm }}/minute;{% endif %} -{% if auth_ratelimit_ph %}{{ auth_ratelimit_ph }}/hour{% endif %} +{% if auth_ratelimit_pm > '0' and auth_ratelimit_ph > '0' %} +AUTH_RATELIMIT={{ auth_ratelimit_pm }}/minute;{{ auth_ratelimit_ph }}/hour +{% endif %} # Opt-out of statistics, replace with "True" to opt out DISABLE_STATISTICS={{ disable_statistics or 'False' }} @@ -47,7 +48,6 @@ DISABLE_STATISTICS={{ disable_statistics or 'False' }} #ADMIN={{ admin_enabled or 'false' }} #Chose which webmail to run if any -#WEBMAIL_ENABLED={{ webmail_enabled or 'false' }} #WEBMAIL={{ webmail_type or 'none' }} #Antivirus solution diff --git a/setup/templates/steps/initial-config.html b/setup/templates/steps/compose/config.html similarity index 71% rename from setup/templates/steps/initial-config.html rename to setup/templates/steps/compose/config.html index c16d4c13..f5a39a5a 100644 --- a/setup/templates/steps/initial-config.html +++ b/setup/templates/steps/compose/config.html @@ -3,12 +3,15 @@
- + +
- + +
@@ -20,7 +23,7 @@
- +
@@ -35,8 +38,11 @@
-

/minute; - /hour

+ +

/minute; + /hour

@@ -48,12 +54,14 @@
- +
- + +
{% endcall %} diff --git a/setup/templates/steps/expose.html b/setup/templates/steps/compose/expose.html similarity index 67% rename from setup/templates/steps/expose.html rename to setup/templates/steps/compose/expose.html index 372ebddc..e0aa8fee 100644 --- a/setup/templates/steps/expose.html +++ b/setup/templates/steps/compose/expose.html @@ -14,12 +14,16 @@ avoid generic all-interfaces addresses like 0.0.0.0 or :: - + +
- + +

You server will be available under a main hostname but may expose multiple public @@ -28,6 +32,8 @@ hostnames in its MX record. Hostnames must be coma-separated.

- + +
{% endcall %} diff --git a/setup/templates/steps/flavor.html b/setup/templates/steps/compose/flavor.html similarity index 100% rename from setup/templates/steps/flavor.html rename to setup/templates/steps/compose/flavor.html diff --git a/setup/templates/steps/optional.html b/setup/templates/steps/compose/optional.html similarity index 100% rename from setup/templates/steps/optional.html rename to setup/templates/steps/compose/optional.html diff --git a/setup/templates/steps/services.html b/setup/templates/steps/compose/services.html similarity index 77% rename from setup/templates/steps/services.html rename to setup/templates/steps/compose/services.html index ed529c83..d8ec8106 100644 --- a/setup/templates/steps/services.html +++ b/setup/templates/steps/compose/services.html @@ -18,16 +18,23 @@ manage your email domains, users, etc.

email client. These do add some complexity but provide an easier way of accessing messages for beginner users.

+
-
-
- -
+ + + + +
+

-
- {{ 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") }} +
+ +
diff --git a/setup/templates/wizard.html b/setup/templates/wizard.html index 5a15af6f..1c85a0ad 100644 --- a/setup/templates/wizard.html +++ b/setup/templates/wizard.html @@ -9,11 +9,11 @@ {% endcall %}
- {% include "steps/initial-config.html" %} - {% include "steps/flavor.html" %} - {% include "steps/expose.html" %} - {% include "steps/services.html" %} - + {% include "steps/compose/flavor.html" %} + {% include "steps/compose/config.html" %} + {% include "steps/compose/services.html" %} + {% include "steps/compose/expose.html" %} +
From 6b6cbcf977002f768827389f035ab45fde1c4c15 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Wed, 17 Oct 2018 15:38:51 +0300 Subject: [PATCH 34/93] Modified variables in .env file --- setup/flavors/compose/mailu.env | 27 ++++++++++++++--------- setup/templates/steps/compose/config.html | 2 +- setup/templates/steps/compose/expose.html | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 77da5670..a577f979 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -65,26 +65,24 @@ DISABLE_STATISTICS={{ disable_statistics or 'False' }} # Message size limit in bytes # Default: accept messages up to 50MB -MESSAGE_SIZE_LIMIT={{ message_size_limit }} +MESSAGE_SIZE_LIMIT={{ message_size_limit or '50000000' }} # Networks granted relay permissions, make sure that you include your Docker # internal network (default to 172.17.0.0/16) -RELAYNETS={{ relaynets }} +RELAYNETS={{ relaynets or '172.17.0.0/16'}} # Will relay all outgoing mails if configured RELAYHOST={{ relayhost }} # Fetchmail delay -FETCHMAIL_DELAY={{ fetchmail_delay }} +FETCHMAIL_DELAY={{ fetchmail_delay or '600' }} # Recipient delimiter, character used to delimiter localpart from custom address part -RECIPIENT_DELIMITER={{ recipient_delimiter }} +RECIPIENT_DELIMITER={{ recipient_delimiter or '+' }} -{% if dmarc_rua or dmarc_ruf %} # DMARC rua and ruf email -{% if dmarc_rua %}DMARC_RUA={{ dmarc_rua }}{% endif %} -{% if dmarc_ruf %}DMARC_RUF={{ dmarc_ruf }}{% endif %} -{% endif %} +DMARC_RUA={{ dmarc_rua or 'admin' }} +DMARC_RUF={{ dmarc_ruf or 'admin' }} {% if welcome_enabled %} # Welcome email, enable and set a topic and body if you wish to send welcome @@ -94,6 +92,12 @@ WELCOME_SUBJECT={{ welcome_subject }} WELCOME_BODY={{ welcome_body }} {% endif %} +# Maildir Compression +# choose compression-method, default: none (value: bz2, gz) +COMPRESSION={{ compression }} +# change compression-level, default: 6 (value: 1-9) +COMPRESSION_LEVEL={{ compression_level }} + {% if domain_registration %} # Domain registration (remove to disable) DOMAIN_REGISTRATION=true @@ -125,13 +129,14 @@ WEBSITE={{ website }} # Advanced settings ################################### -{% if password_scheme %} # Specific password storage scheme -PASSWORD_SCHEME={{ password_scheme }} -{% endif %} +PASSWORD_SCHEME={{ password_scheme or 'SHA512-CRYPT'}} # Header to take the real ip from REAL_IP_HEADER={{ real_ip_header }} # IPs for nginx set_real_ip_from (CIDR list separated by commas) REAL_IP_FROM={{ real_ip_from }} + +# choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no) +REJECT_UNLISTED_RECIPIENT={{ reject_unlisted_recipient }} diff --git a/setup/templates/steps/compose/config.html b/setup/templates/steps/compose/config.html index f5a39a5a..8d613d08 100644 --- a/setup/templates/steps/compose/config.html +++ b/setup/templates/steps/compose/config.html @@ -1,4 +1,4 @@ -{% call macros.panel("info", "Step 0 - Initial configuration") %} +{% call macros.panel("info", "Step 2 - Initial configuration") %}

Before starting some variables must be st

diff --git a/setup/templates/steps/compose/expose.html b/setup/templates/steps/compose/expose.html index e0aa8fee..6bc2f528 100644 --- a/setup/templates/steps/compose/expose.html +++ b/setup/templates/steps/compose/expose.html @@ -1,4 +1,4 @@ -{% call macros.panel("info", "Step 2 - expose Mailu to the world") %} +{% call macros.panel("info", "Step 4 - expose Mailu to the world") %}

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.

From cb1ed349bf15f13690416583816ff0f6a8b8c117 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Wed, 17 Oct 2018 16:46:20 +0300 Subject: [PATCH 35/93] Bug fixes --- setup/flavors/compose/docker-compose.yml | 10 ++-------- setup/flavors/compose/mailu.env | 8 ++++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 8316e681..3d84e595 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -2,7 +2,7 @@ # This file is auto-generated by the Mailu configuration wizard. # Please read the documentation before attempting any change. -version: '3.7' +version: '3.6' services: @@ -18,7 +18,7 @@ services: image: mailu/nginx:{{ version }} restart: always env_file: {{ env }} - env: + environment: - TLS_FLAVOR={{ tls_flavor }} - ADMIN={{ admin_enabled or 'false' }} ports: @@ -30,10 +30,8 @@ services: - "{{ bind6 }}:{{ port }}:{{ port }}" {% endif %} {% endfor %} - {% if flavor in ('cert', 'mail') %} volumes: - "{{ root }}/certs:/certs" - {% endif %} admin: image: mailu/admin:{{ version }} @@ -54,7 +52,6 @@ services: restart: always env_file: {{ env }} volumes: - - "{{ root }}/data:/data" - "{{ root }}/mail:/mail" - "{{ root }}/overrides:/overrides" depends_on: @@ -65,7 +62,6 @@ services: restart: always env_file: {{ env }} volumes: - - "{{ root }}/data:/data" - "{{ root }}/overrides:/overrides" depends_on: - front @@ -107,8 +103,6 @@ services: image: mailu/fetchmail:{{ version }} restart: always env_file: {{ env }} - volumes: - - "{{ root }}/data:/data" {% endif %} # Webmail diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index a577f979..55def163 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -21,7 +21,7 @@ SECRET_KEY={{ secret(16) }} # PUBLIC_IPV6= {{ bind6 }} (default: ::1) # Main mail domain -# DOMAIN={{ domain }} +DOMAIN={{ domain }} # Mail address of the postmaster POSTMASTER={{ postmaster or 'admin'}} @@ -48,16 +48,16 @@ DISABLE_STATISTICS={{ disable_statistics or 'False' }} #ADMIN={{ admin_enabled or 'false' }} #Chose which webmail to run if any -#WEBMAIL={{ webmail_type or 'none' }} +WEBMAIL={{ webmail_type }} #Antivirus solution #ANTIVIRUS={{ antivirus_enabled or 'none' }} #Antispam solution -#ANTISPAM={{ antispam_enabled or 'none'}} +ANTISPAM={{ antispam_enabled or 'none'}} #Dav server implementation -#WEBDAV={{ webdav_enabled or 'none' }} +WEBDAV={{ webdav_enabled or 'none' }} ################################### # Server behavior From 7c0f5b20d6e196f71cda5d4d38773810a15cdaf1 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Wed, 17 Oct 2018 17:54:37 +0300 Subject: [PATCH 36/93] Bug fixes --- setup/templates/steps/compose/expose.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/templates/steps/compose/expose.html b/setup/templates/steps/compose/expose.html index 6bc2f528..df121c7d 100644 --- a/setup/templates/steps/compose/expose.html +++ b/setup/templates/steps/compose/expose.html @@ -15,7 +15,7 @@ avoid generic all-interfaces addresses like 0.0.0.0 or :: -
@@ -23,7 +23,7 @@ avoid generic all-interfaces addresses like 0.0.0.0 or ::IPv6 listen address + 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]))?$">

You server will be available under a main hostname but may expose multiple public From ed53d655d3977c8e7794ec66eeac38881c541cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 17 Oct 2018 18:38:10 +0300 Subject: [PATCH 37/93] Extend documentation in download page. Small cleanup in env. --- setup/flavors/compose/mailu.env | 2 +- setup/flavors/compose/setup.html | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 55def163..fba5bee8 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -24,7 +24,7 @@ SECRET_KEY={{ secret(16) }} DOMAIN={{ domain }} # Mail address of the postmaster -POSTMASTER={{ postmaster or 'admin'}} +POSTMASTER={{ postmaster }} #Chose how secure connections will behave: #TLS_FLAVOR={{ tls_flavor }} diff --git a/setup/flavors/compose/setup.html b/setup/flavors/compose/setup.html index 3c190c9c..d5f7abc5 100644 --- a/setup/flavors/compose/setup.html +++ b/setup/flavors/compose/setup.html @@ -11,8 +11,8 @@ in a project directory. First create your project directory.

to read and check the configuration variables generated by the wizard.

cd {{ root }}
-wget {{ url_for('.file', uid=uid, filepath='docker-compose.yml', _external=True) }}
-wget {{ url_for('.file', uid=uid, filepath='mailu.env', _external=True) }}
+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
 
{% endcall %} @@ -33,4 +33,17 @@ command.

cd {{ root }}
 docker-compose up -d
 
+ +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: + +
docker-compose exec admin python manage.py admin {{ postmaster }} {{ domain }} PASSWORD
+
+ +Login the the admin interface to change the password for a safe one, at +{% if admin_enabled %} +one of the hostnames ({{ hostnames }}){{ admin_path }}. +{% else %} +http://127.0.0.1:8080 (only directly from the host running docker). +{% endif %} +And choose the "Update password" option in the left menu. {% endcall %} From 0a5dbf6230d9749dbf1a1129b606abe6f4dad0fc Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 17:41:21 +0200 Subject: [PATCH 38/93] Re-enable local dovecot sieve scripts --- core/dovecot/conf/dovecot.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/dovecot/conf/dovecot.conf b/core/dovecot/conf/dovecot.conf index d6c4eb21..a9ec2676 100644 --- a/core/dovecot/conf/dovecot.conf +++ b/core/dovecot/conf/dovecot.conf @@ -136,7 +136,8 @@ service managesieve { } plugin { - sieve = dict:proxy:/tmp/podop.socket:sieve + sieve = file:~/sieve;active=~/.dovecot.sieve + sieve_before = dict:proxy:/tmp/podop.socket:sieve sieve_plugins = sieve_imapsieve sieve_extprograms sieve_extensions = +spamtest +spamtestplus +editheader sieve_global_extensions = +vnd.dovecot.execute From 5679d355aafa14cdce652e5dc50a3e053f1e1a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 17 Oct 2018 18:45:09 +0300 Subject: [PATCH 39/93] Avoid binding conflicts on production servers --- setup/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/docker-compose.yml b/setup/docker-compose.yml index 30966167..e91332e1 100644 --- a/setup/docker-compose.yml +++ b/setup/docker-compose.yml @@ -9,6 +9,6 @@ services: setup: image: mailu/setup ports: - - "80:80" + - "8000:80" build: . From b9b4a8cd77c4a483d7dbf70314db777f021f0443 Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 18:47:55 +0200 Subject: [PATCH 40/93] Explicitely specify the fuzzy worker listen address --- services/rspamd/conf/worker-fuzzy.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/services/rspamd/conf/worker-fuzzy.inc b/services/rspamd/conf/worker-fuzzy.inc index a0021a03..0f71ba32 100644 --- a/services/rspamd/conf/worker-fuzzy.inc +++ b/services/rspamd/conf/worker-fuzzy.inc @@ -1,4 +1,5 @@ type = "fuzzy"; +bind_socket = "*:11335"; count = 1; backend = "redis"; expire = 90d; From ce0bf3366d2193b01e34c04ede5f870c94d250c3 Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 18:48:28 +0200 Subject: [PATCH 41/93] Learn fuzzy hashes automatically --- core/dovecot/Dockerfile | 2 +- core/dovecot/conf/bin/ham | 4 ++++ core/dovecot/conf/bin/mailtrain | 3 --- core/dovecot/conf/bin/spam | 4 ++++ core/dovecot/conf/report-ham.sieve | 2 +- core/dovecot/conf/report-spam.sieve | 2 +- 6 files changed, 11 insertions(+), 6 deletions(-) create mode 100755 core/dovecot/conf/bin/ham delete mode 100755 core/dovecot/conf/bin/mailtrain create mode 100755 core/dovecot/conf/bin/spam diff --git a/core/dovecot/Dockerfile b/core/dovecot/Dockerfile index d8d4c55b..41437e23 100644 --- a/core/dovecot/Dockerfile +++ b/core/dovecot/Dockerfile @@ -2,7 +2,7 @@ FROM alpine:3.8 RUN apk add --no-cache \ dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client \ - python3 py3-pip \ + bash python3 py3-pip \ && pip3 install --upgrade pip \ && pip3 install jinja2 podop tenacity diff --git a/core/dovecot/conf/bin/ham b/core/dovecot/conf/bin/ham new file mode 100755 index 00000000..c74a97bd --- /dev/null +++ b/core/dovecot/conf/bin/ham @@ -0,0 +1,4 @@ +#!/bin/bash + +tee >(rspamc -h antispam:11334 -P mailu learn_ham /dev/stdin) \ + | rspamc -h antispam:11334 -P mailu -f 13 fuzzy_add /dev/stdin \ No newline at end of file diff --git a/core/dovecot/conf/bin/mailtrain b/core/dovecot/conf/bin/mailtrain deleted file mode 100755 index cfa36398..00000000 --- a/core/dovecot/conf/bin/mailtrain +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -rspamc -h antispam:11334 -P mailu "learn_$1" /dev/stdin <&0 diff --git a/core/dovecot/conf/bin/spam b/core/dovecot/conf/bin/spam new file mode 100755 index 00000000..e6a66f89 --- /dev/null +++ b/core/dovecot/conf/bin/spam @@ -0,0 +1,4 @@ +#!/bin/bash + +tee >(rspamc -h antispam:11334 -P mailu learn_spam /dev/stdin) \ + >(rspamc -h antispam:11334 -P mailu -f 11 fuzzy_add /dev/stdin) \ No newline at end of file diff --git a/core/dovecot/conf/report-ham.sieve b/core/dovecot/conf/report-ham.sieve index 1ad8abdf..0c69d67b 100644 --- a/core/dovecot/conf/report-ham.sieve +++ b/core/dovecot/conf/report-ham.sieve @@ -8,4 +8,4 @@ if string "${mailbox}" "Trash" { stop; } -execute :pipe "mailtrain" "ham"; +execute :pipe "ham"; diff --git a/core/dovecot/conf/report-spam.sieve b/core/dovecot/conf/report-spam.sieve index b2a544a6..108d6210 100644 --- a/core/dovecot/conf/report-spam.sieve +++ b/core/dovecot/conf/report-spam.sieve @@ -1,3 +1,3 @@ require "vnd.dovecot.execute"; -execute :pipe "mailtrain" "spam"; +execute :pipe "spam"; From d5162328eca5e2344c4ca1e432ec8f31bc5b7e1f Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 18:48:59 +0200 Subject: [PATCH 42/93] Allow dovecot to write the source configuration directory for compiling sieve scripts --- core/dovecot/start.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dovecot/start.py b/core/dovecot/start.py index afd0513e..b65b4db9 100755 --- a/core/dovecot/start.py +++ b/core/dovecot/start.py @@ -36,5 +36,5 @@ for dovecot_file in glob.glob("/conf/*.conf"): # Run Podop, then postfix multiprocessing.Process(target=start_podop).start() -os.system("chown -R mail:mail /mail /var/lib/dovecot") +os.system("chown -R mail:mail /mail /var/lib/dovecot /conf") os.execv("/usr/sbin/dovecot", ["dovecot", "-c", "/etc/dovecot/dovecot.conf", "-F"]) From 86bdce840774f7c7170d4eccfc7dc9e9d3d9ea5e Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Wed, 17 Oct 2018 18:49:19 +0000 Subject: [PATCH 43/93] Explicitely specify the fuzzy worker listen address --- services/rspamd/conf/worker-fuzzy.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/services/rspamd/conf/worker-fuzzy.inc b/services/rspamd/conf/worker-fuzzy.inc index a0021a03..0f71ba32 100644 --- a/services/rspamd/conf/worker-fuzzy.inc +++ b/services/rspamd/conf/worker-fuzzy.inc @@ -1,4 +1,5 @@ type = "fuzzy"; +bind_socket = "*:11335"; count = 1; backend = "redis"; expire = 90d; From dba8f1810d3d9271ff9ca9dcc21521d3bef7327c Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 21:21:00 +0200 Subject: [PATCH 44/93] Do not check the password another time in Dovecot --- core/admin/mailu/internal/views/dovecot.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/internal/views/dovecot.py b/core/admin/mailu/internal/views/dovecot.py index c2f53794..036140f0 100644 --- a/core/admin/mailu/internal/views/dovecot.py +++ b/core/admin/mailu/internal/views/dovecot.py @@ -1,14 +1,24 @@ -from mailu import db, models +from mailu import db, models, app from mailu.internal import internal import flask +import socket @internal.route("/dovecot/passdb/") def dovecot_passdb_dict(user_email): user = models.User.query.get(user_email) or flask.abort(404) + allow_nets = [] + allow_nets.append( + app.config.get("POD_ADDRESS_RANGE") or + socket.gethostbyname(app.config["HOST_FRONT"]) + ) + allow_nets.append(socket.gethostbyname(app.config["HOST_WEBMAIL"])) + print(allow_nets) return flask.jsonify({ - "password": user.password, + "password": None, + "nopassword": "Y", + "allow_nets": ",".join(allow_nets) }) From 988e09e65eecab6daae5f090556826b0310a434a Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 21:21:24 +0200 Subject: [PATCH 45/93] Add a profiler in debug mode for improving performance --- core/admin/mailu/__init__.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index 167f04ae..a73e6ab9 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -12,7 +12,7 @@ import docker import socket import uuid -from werkzeug.contrib import fixers +from werkzeug.contrib import fixers, profiler # Create application app = flask.Flask(__name__) @@ -62,7 +62,10 @@ default_config = { 'HOST_IMAP': 'imap', 'HOST_POP3': 'imap', 'HOST_SMTP': 'smtp', + 'HOST_WEBMAIL': 'webmail', + 'HOST_FRONT': 'front', 'HOST_AUTHSMTP': os.environ.get('HOST_SMTP', 'smtp'), + 'POD_ADDRESS_RANGE': None } # Load configuration from the environment if available @@ -80,6 +83,10 @@ if app.config.get("DEBUG"): import flask_debugtoolbar toolbar = flask_debugtoolbar.DebugToolbarExtension(app) +# Profiler +if app.config.get("DEBUG"): + app.wsgi_app = profiler.ProfilerMiddleware(app.wsgi_app, restrictions=[30]) + # Manager commnad manager = flask_script.Manager(app) manager.add_command('db', flask_migrate.MigrateCommand) @@ -129,4 +136,5 @@ class PrefixMiddleware(object): environ['SCRIPT_NAME'] = prefix return self.app(environ, start_response) + app.wsgi_app = PrefixMiddleware(fixers.ProxyFix(app.wsgi_app)) From 01fa1797674e2badeaa42292172807107338c41a Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 21:21:35 +0200 Subject: [PATCH 46/93] Update the user password in database when needed --- core/admin/mailu/models.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 0c80fd4f..51d07f24 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -276,7 +276,8 @@ class User(Base, Email): else: return self.email - scheme_dict = {'BLF-CRYPT': "bcrypt", + scheme_dict = {'PBKDF2': "pbkdf2_sha512", + 'BLF-CRYPT': "bcrypt", 'SHA512-CRYPT': "sha512_crypt", 'SHA256-CRYPT': "sha256_crypt", 'MD5-CRYPT': "md5_crypt", @@ -287,8 +288,14 @@ class User(Base, Email): ) def check_password(self, password): + context = User.pw_context reference = re.match('({[^}]+})?(.*)', self.password).group(2) - return User.pw_context.verify(password, reference) + result = context.verify(password, reference) + if result and context.identify(reference) != context.default_scheme(): + self.set_password(password) + db.session.add(self) + db.session.commit() + return result def set_password(self, password, hash_scheme=app.config['PASSWORD_SCHEME'], raw=False): """Set password for user with specified encryption scheme From 828d96f8f01da044611950b3df57137ef1797c11 Mon Sep 17 00:00:00 2001 From: kaiyou Date: Wed, 17 Oct 2018 21:26:44 +0200 Subject: [PATCH 47/93] Switch the default password scheme to PBKDF2 --- docs/compose/.env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/compose/.env b/docs/compose/.env index 7823bc3e..ce8e9eb9 100644 --- a/docs/compose/.env +++ b/docs/compose/.env @@ -130,8 +130,8 @@ LOG_DRIVER=json-file COMPOSE_PROJECT_NAME=mailu # Default password scheme used for newly created accounts and changed passwords -# (value: BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT) -PASSWORD_SCHEME=BLF-CRYPT +# (value: PBKDF2, BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT) +PASSWORD_SCHEME=PBKDF2 # Header to take the real ip from REAL_IP_HEADER= From adfadab4cf4d749d6bf95f0b9bd420fa3bc93094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Thu, 18 Oct 2018 12:56:16 +0300 Subject: [PATCH 48/93] Load steps after setting flavor --- setup/server.py | 5 +++++ setup/templates/macros.html | 4 ++-- setup/templates/steps/{compose => }/flavor.html | 8 ++++---- setup/templates/wizard.html | 17 +++++++++++------ 4 files changed, 22 insertions(+), 12 deletions(-) rename setup/templates/steps/{compose => }/flavor.html (81%) diff --git a/setup/server.py b/setup/server.py index ddeafd90..4e29fe9e 100644 --- a/setup/server.py +++ b/setup/server.py @@ -65,6 +65,11 @@ def build_app(path): def wizard(): return flask.render_template('wizard.html') + @bp.route("/submit_flavor", methods=["POST"]) + def submit_flavor(): + data = flask.request.form.copy() + return flask.render_template('wizard.html', flavor=data["flavor"]) + @bp.route("/submit", methods=["POST"]) def submit(): data = flask.request.form.copy() diff --git a/setup/templates/macros.html b/setup/templates/macros.html index 579800d2..4af20c4e 100644 --- a/setup/templates/macros.html +++ b/setup/templates/macros.html @@ -9,10 +9,10 @@
{% endmacro %} -{% macro radio(name, value, emph, text) %} +{% macro radio(name, value, emph, text, current) %}
+
+ +
+ +
+ + +
+

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 MX record. Hostnames must be coma-separated.

diff --git a/setup/templates/steps/stack/03_expose.html b/setup/templates/steps/stack/03_expose.html index a9cffc1c..1cd0cde5 100644 --- a/setup/templates/steps/stack/03_expose.html +++ b/setup/templates/steps/stack/03_expose.html @@ -5,7 +5,8 @@ you expose it to the world.

- +

You server will be available under a main hostname but may expose multiple public From da37555a3c6af23a28237bf8ba9da7ff34ed5529 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 23 Oct 2018 15:46:53 +0300 Subject: [PATCH 78/93] Fixed naming error --- setup/flavors/compose/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 4fef7468..630531fe 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -31,7 +31,7 @@ services: {% if resolver_enabled %} resolver: - image: mailu/resolver:{{ version }} + image: mailu/unbound:{{ version }} restart: always networks: default: From 12d8872a0950173fed22050eb1baad3786f0e3f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Tue, 23 Oct 2018 16:09:59 +0300 Subject: [PATCH 79/93] Fix unbound build path --- tests/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/build.yml b/tests/build.yml index 8a5cd540..ed5b75fe 100644 --- a/tests/build.yml +++ b/tests/build.yml @@ -8,7 +8,7 @@ services: resolver: image: ${DOCKER_ORG:-mailu}/unbound:${VERSION:-local} - build: ../core/unbound + build: ../services/unbound imap: image: ${DOCKER_ORG:-mailu}/dovecot:${VERSION:-local} From 6c12e2fffb9990dec70fdbc650245d78796b282c Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 23 Oct 2018 16:39:22 +0300 Subject: [PATCH 80/93] Fixed subnet variable in unbound --- setup/flavors/compose/docker-compose.yml | 1 + setup/flavors/compose/mailu.env | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 630531fe..e6b64077 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -32,6 +32,7 @@ services: {% if resolver_enabled %} resolver: image: mailu/unbound:{{ version }} + env_file: {{ env }} restart: always networks: default: diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 425f4cad..4a14de63 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -26,7 +26,7 @@ SECRET_KEY={{ secret(16) }} # PUBLIC_IPV6= {{ bind6 }} (default: ::1) # Subnet -# SUBNET={{ subnet }} +SUBNET={{ subnet }} # Main mail domain DOMAIN={{ domain }} From 120c29eff603850d8bb9573df1ddbc8edc4a56b5 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 23 Oct 2018 17:46:06 +0300 Subject: [PATCH 81/93] Added unbound for stack flavor --- setup/flavors/compose/docker-compose.yml | 4 ++-- setup/flavors/stack/docker-compose.yml | 25 ++++++++++++++++++++++ setup/templates/steps/stack/03_expose.html | 7 ++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index e6b64077..50fd1705 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -29,7 +29,7 @@ services: volumes: - "{{ root }}/certs:/certs" - {% if resolver_enabled %} + {% if resolver_enabled %} resolver: image: mailu/unbound:{{ version }} env_file: {{ env }} @@ -68,7 +68,7 @@ services: - "{{ root }}/overrides:/overrides" depends_on: - front - {% if resolver_enabled %} + {% if resolver_enabled %} - resolver dns: - {{ dns }} diff --git a/setup/flavors/stack/docker-compose.yml b/setup/flavors/stack/docker-compose.yml index f27b661f..b9537e94 100644 --- a/setup/flavors/stack/docker-compose.yml +++ b/setup/flavors/stack/docker-compose.yml @@ -28,6 +28,15 @@ services: - "{{ root }}/certs:/certs" deploy: replicas: 1 + + {% if resolver_enabled %} + resolver: + image: mailu/unbound:{{ version }} + env_file: {{ env }} + networks: + default: + ipv4_address: {{ dns }} + {% endif %} admin: image: mailu/admin:{{ version }} @@ -63,6 +72,10 @@ services: - "{{ root }}/overrides:/overrides" deploy: replicas: 1 + {% if resolver_enabled %} + dns: + - {{ dns }} + {% endif %} # Optional services {% if antispam_enabled %} @@ -77,6 +90,10 @@ services: - "{{ root }}/overrides/rspamd:/etc/rspamd/override.d" deploy: replicas: 1 + {% if resolver_enabled %} + dns: + - {{ dns }} + {% endif %} {% endif %} {% if antivirus_enabled %} @@ -87,6 +104,10 @@ services: - "{{ root }}/filter:/data" deploy: replicas: 1 + {% if resolver_enabled %} + dns: + - {{ dns }} + {% endif %} {% endif %} {% if webdav_enabled %} @@ -107,6 +128,10 @@ services: - "{{ root }}/data:/data" deploy: replicas: 1 + {% if resolver_enabled %} + dns: + - {{ dns }} + {% endif %} {% endif %} {% if webmail_type != 'none' %} diff --git a/setup/templates/steps/stack/03_expose.html b/setup/templates/steps/stack/03_expose.html index 1cd0cde5..d47390be 100644 --- a/setup/templates/steps/stack/03_expose.html +++ b/setup/templates/steps/stack/03_expose.html @@ -3,6 +3,13 @@ and let users access their mailboxes. Mailu has some flexibility in the way you expose it to the world.

+
+ +
+
Date: Tue, 23 Oct 2018 10:47:31 -0500 Subject: [PATCH 82/93] Fix typo (duplicate self). Fixes #683 --- core/admin/mailu/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 3653011f..62c25c81 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -271,7 +271,7 @@ class User(Base, Email): @property def destination(self): if self.forward_enabled: - result = self.self.forward_destination + result = self.forward_destination if self.forward_keep: result += ',' + self.email return result From b8783b670aa6a299047f280c0c272b68905cbb62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 24 Oct 2018 12:18:03 +0300 Subject: [PATCH 83/93] Take out DNS entry for webmail --- setup/flavors/compose/docker-compose.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 50fd1705..81b6bcb2 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -135,9 +135,6 @@ services: - "{{ root }}/webmail:/data" depends_on: - imap - - resolver - dns: - - {{ dns }} {% endif %} {% if resolver_enabled %} From fd3a9448500bf6aea4686583d104473e3f96911e Mon Sep 17 00:00:00 2001 From: hoellen Date: Thu, 25 Oct 2018 13:04:40 +0200 Subject: [PATCH 84/93] fix typo in doc --- docs/cli.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli.rst b/docs/cli.rst index 4a5250a2..038f1247 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -39,7 +39,7 @@ primary difference with simple `user` command is that password is being imported .. code-block:: bash - docker-compose run --rm admin python manage.py user --hash_scheme='SHA512-CRYPT' myuser example.net '$6$51ebe0cb9f1dab48effa2a0ad8660cb489b445936b9ffd812a0b8f46bca66dd549fea530ce' + docker-compose run --rm admin python manage.py user_import --hash_scheme='SHA512-CRYPT' myuser example.net '$6$51ebe0cb9f1dab48effa2a0ad8660cb489b445936b9ffd812a0b8f46bca66dd549fea530ce' user_delete ------------ From 2237e641b04726c1482fc87becd260ed4c374e77 Mon Sep 17 00:00:00 2001 From: Daniel Huber Date: Sun, 28 Oct 2018 12:26:14 +0100 Subject: [PATCH 85/93] Fix Typo in K8s Docs --- docs/kubernetes/mailu/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/kubernetes/mailu/index.rst b/docs/kubernetes/mailu/index.rst index ef12eb58..99abd8b1 100644 --- a/docs/kubernetes/mailu/index.rst +++ b/docs/kubernetes/mailu/index.rst @@ -189,5 +189,5 @@ This problem can be easily fixed by running following commands: .. code:: bash - kubectl -n mailu-mailserver exec -it maolu-imap-... /bin/sh + kubectl -n mailu-mailserver exec -it mailu-imap-... /bin/sh chmod 777 /data/main.db From 7125077dec76cd5a9e3f1d4d1d03e2100c96cd1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Mon, 29 Oct 2018 01:41:04 +0100 Subject: [PATCH 86/93] Update roundcube --- webmails/roundcube/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webmails/roundcube/Dockerfile b/webmails/roundcube/Dockerfile index 6250e6df..69e0f334 100644 --- a/webmails/roundcube/Dockerfile +++ b/webmails/roundcube/Dockerfile @@ -1,6 +1,6 @@ FROM php:7.2-apache -ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.3.7/roundcubemail-1.3.7-complete.tar.gz +ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.3.8/roundcubemail-1.3.8-complete.tar.gz RUN apt-get update && apt-get install -y \ zlib1g-dev curl \ From 9ba086fcffad3ec469df910920013757255b3e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Tue, 30 Oct 2018 23:28:25 +0100 Subject: [PATCH 87/93] store rspamd history in redis --- services/rspamd/conf/history_redis.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 services/rspamd/conf/history_redis.conf diff --git a/services/rspamd/conf/history_redis.conf b/services/rspamd/conf/history_redis.conf new file mode 100644 index 00000000..fee07024 --- /dev/null +++ b/services/rspamd/conf/history_redis.conf @@ -0,0 +1 @@ +servers = "{{ HOST_REDIS }}"; From 5fa2aac56945ddaf72323ffff49ae5bbea2c0f83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 31 Oct 2018 17:47:05 +0200 Subject: [PATCH 88/93] Fix imap login when no webmail selected --- core/admin/mailu/internal/views/dovecot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/internal/views/dovecot.py b/core/admin/mailu/internal/views/dovecot.py index 036140f0..e6e4c10f 100644 --- a/core/admin/mailu/internal/views/dovecot.py +++ b/core/admin/mailu/internal/views/dovecot.py @@ -3,7 +3,7 @@ from mailu.internal import internal import flask import socket - +import os @internal.route("/dovecot/passdb/") def dovecot_passdb_dict(user_email): @@ -13,7 +13,8 @@ def dovecot_passdb_dict(user_email): app.config.get("POD_ADDRESS_RANGE") or socket.gethostbyname(app.config["HOST_FRONT"]) ) - allow_nets.append(socket.gethostbyname(app.config["HOST_WEBMAIL"])) + if os.environ["WEBMAIL"] != "none": + allow_nets.append(socket.gethostbyname(app.config["HOST_WEBMAIL"])) print(allow_nets) return flask.jsonify({ "password": None, From 42e2dbe35d97dbdea05d60bb8443058d5c7d6b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 31 Oct 2018 19:17:23 +0200 Subject: [PATCH 89/93] Standarize image by using shared / similair layers --- core/admin/Dockerfile | 12 ++++++++---- core/admin/start.py | 8 ++++---- core/dovecot/Dockerfile | 16 +++++++++++----- core/nginx/Dockerfile | 12 ++++++++---- core/nginx/config.py | 2 +- core/nginx/letsencrypt.py | 2 +- core/nginx/start.py | 2 +- core/postfix/Dockerfile | 13 ++++++++++--- optional/clamav/Dockerfile | 8 ++++++-- optional/clamav/start.py | 4 ++-- services/fetchmail/Dockerfile | 10 +++++++--- services/fetchmail/fetchmail.py | 2 +- services/rspamd/Dockerfile | 14 ++++++++++---- services/rspamd/start.py | 2 +- services/unbound/Dockerfile | 11 ++++++++--- services/unbound/start.py | 2 +- webmails/rainloop/Dockerfile | 6 +++++- webmails/roundcube/Dockerfile | 6 +++++- 18 files changed, 90 insertions(+), 42 deletions(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 3d08984f..315b2e39 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -1,12 +1,16 @@ -FROM python:3-alpine - +FROM alpine:3.8 +# python3 shared with most images +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install --upgrade pip +# Image specific layers under this line RUN mkdir -p /app WORKDIR /app COPY requirements-prod.txt requirements.txt RUN apk add --no-cache openssl curl \ - && apk add --no-cache --virtual build-dep openssl-dev libffi-dev python-dev build-base \ - && pip install -r requirements.txt \ + && apk add --no-cache --virtual build-dep openssl-dev libffi-dev python3-dev build-base \ + && pip3 install -r requirements.txt \ && apk del --no-cache build-dep COPY mailu ./mailu diff --git a/core/admin/start.py b/core/admin/start.py index e8b59ff4..59c97686 100755 --- a/core/admin/start.py +++ b/core/admin/start.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python3 +#!/usr/bin/python3 import os -os.system("python manage.py advertise") -os.system("python manage.py db upgrade") -os.system("gunicorn -w 4 -b :80 --access-logfile - --error-logfile - --preload mailu:app") \ No newline at end of file +os.system("python3 manage.py advertise") +os.system("python3 manage.py db upgrade") +os.system("gunicorn -w 4 -b :80 --access-logfile - --error-logfile - --preload mailu:app") diff --git a/core/dovecot/Dockerfile b/core/dovecot/Dockerfile index da29756f..1d4f7b91 100644 --- a/core/dovecot/Dockerfile +++ b/core/dovecot/Dockerfile @@ -1,10 +1,16 @@ FROM alpine:3.8 - +# python3 shared with most images RUN apk add --no-cache \ - dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client \ - bash python3 py3-pip \ - && pip3 install --upgrade pip \ - && pip3 install jinja2 podop tenacity + python3 py3-pip \ + && pip3 install --upgrade pip +# Shared layer between rspamd, postfix, dovecot, unbound and nginx +RUN pip3 install jinja2 +# Shared layer between rspamd, postfix, dovecot +RUN pip3 install tenacity +# Image specific layers under this line +RUN apk add --no-cache \ + dovecot dovecot-pigeonhole-plugin dovecot-fts-lucene rspamd-client bash \ + && pip3 install podop COPY conf /conf COPY start.py /start.py diff --git a/core/nginx/Dockerfile b/core/nginx/Dockerfile index 00ecf84e..7181487e 100644 --- a/core/nginx/Dockerfile +++ b/core/nginx/Dockerfile @@ -1,9 +1,13 @@ FROM alpine:3.8 - +# python3 shared with most images +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install --upgrade pip +# Shared layer between rspamd, postfix, dovecot, unbound and nginx +RUN pip3 install jinja2 +# Image specific layers under this line RUN apk add --no-cache certbot nginx nginx-mod-mail openssl curl \ - python py-jinja2 py-requests-toolbelt py-pip \ - && pip install --upgrade pip \ - && pip install idna + && pip3 install idna requests COPY conf /conf COPY *.py / diff --git a/core/nginx/config.py b/core/nginx/config.py index 33071d01..07b7ea32 100755 --- a/core/nginx/config.py +++ b/core/nginx/config.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import jinja2 import os diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index b6044eca..3fe8ea92 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import os import time diff --git a/core/nginx/start.py b/core/nginx/start.py index b63b64a2..7c5fa71e 100755 --- a/core/nginx/start.py +++ b/core/nginx/start.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import os import subprocess diff --git a/core/postfix/Dockerfile b/core/postfix/Dockerfile index e0529e01..ac9c8159 100644 --- a/core/postfix/Dockerfile +++ b/core/postfix/Dockerfile @@ -1,9 +1,16 @@ FROM alpine:3.8 +# python3 shared with most images +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install --upgrade pip +# Shared layer between rspamd, postfix, dovecot, unbound and nginx +RUN pip3 install jinja2 +# Shared layer between rspamd, postfix, dovecot +RUN pip3 install tenacity +# Image specific layers under this line RUN apk add --no-cache postfix postfix-pcre rsyslog \ - python3 py3-pip \ - && pip3 install --upgrade pip \ - && pip3 install jinja2 podop tenacity + && pip3 install podop COPY conf /conf COPY start.py /start.py diff --git a/optional/clamav/Dockerfile b/optional/clamav/Dockerfile index fa5f0016..b3df2d45 100644 --- a/optional/clamav/Dockerfile +++ b/optional/clamav/Dockerfile @@ -1,5 +1,9 @@ -FROM python:3-alpine - +FROM alpine:3.8 +# python3 shared with most images +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install --upgrade pip +# Image specific layers under this line RUN apk add --no-cache clamav rsyslog wget clamav-libunrar COPY conf /etc/clamav diff --git a/optional/clamav/start.py b/optional/clamav/start.py index e9df3f6e..d4701d2d 100755 --- a/optional/clamav/start.py +++ b/optional/clamav/start.py @@ -1,4 +1,4 @@ -#!/usr/local/bin/python3 +#!/usr/bin/python3 import os @@ -9,4 +9,4 @@ os.system("[ -f /data/main.cvd ] || freshclam") os.system("freshclam -d -c 6") # Run clamav -os.system("clamd") \ No newline at end of file +os.system("clamd") diff --git a/services/fetchmail/Dockerfile b/services/fetchmail/Dockerfile index 33f8a7de..52f794d5 100644 --- a/services/fetchmail/Dockerfile +++ b/services/fetchmail/Dockerfile @@ -1,7 +1,11 @@ -FROM python:3-alpine - +FROM alpine:3.8 +# python3 shared with most images +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install --upgrade pip +# Image specific layers under this line RUN apk add --no-cache fetchmail ca-certificates \ - && pip install requests + && pip3 install requests COPY fetchmail.py /fetchmail.py USER fetchmail diff --git a/services/fetchmail/fetchmail.py b/services/fetchmail/fetchmail.py index 8e006f84..9b1bcc4f 100755 --- a/services/fetchmail/fetchmail.py +++ b/services/fetchmail/fetchmail.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 import time import os diff --git a/services/rspamd/Dockerfile b/services/rspamd/Dockerfile index 76731c9a..6d0cb5d0 100644 --- a/services/rspamd/Dockerfile +++ b/services/rspamd/Dockerfile @@ -1,8 +1,14 @@ FROM alpine:3.8 - -RUN apk add --no-cache python py-jinja2 rspamd rspamd-controller rspamd-proxy rspamd-fuzzy ca-certificates py-pip curl\ - && pip install --upgrade pip \ - && pip install tenacity +# python3 shared with most images +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install --upgrade pip +# Shared layer between rspamd, postfix, dovecot, unbound and nginx +RUN pip3 install jinja2 +# Shared layer between rspamd, postfix, dovecot +RUN pip3 install tenacity +# Image specific layers under this line +RUN apk add --no-cache rspamd rspamd-controller rspamd-proxy rspamd-fuzzy ca-certificates curl RUN mkdir /run/rspamd diff --git a/services/rspamd/start.py b/services/rspamd/start.py index 015f3063..0b3c48a8 100755 --- a/services/rspamd/start.py +++ b/services/rspamd/start.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import jinja2 import os diff --git a/services/unbound/Dockerfile b/services/unbound/Dockerfile index 1b84855c..dbf8a3a9 100644 --- a/services/unbound/Dockerfile +++ b/services/unbound/Dockerfile @@ -1,7 +1,12 @@ -FROM python:3-alpine - +FROM alpine:3.8 +# python3 shared with most images +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install --upgrade pip +# Shared layer between rspamd, postfix, dovecot, unbound and nginx +RUN pip3 install jinja2 +# Image specific layers under this line RUN apk add --no-cache unbound curl bind-tools \ - && pip3 install jinja2 \ && curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache \ && chown root:unbound /etc/unbound \ && chmod 775 /etc/unbound \ diff --git a/services/unbound/start.py b/services/unbound/start.py index 82e017f7..6f494762 100755 --- a/services/unbound/start.py +++ b/services/unbound/start.py @@ -1,4 +1,4 @@ -#!/usr/local/bin/python3 +#!/usr/bin/python3 import jinja2 import os diff --git a/webmails/rainloop/Dockerfile b/webmails/rainloop/Dockerfile index 5d751716..db7403f5 100644 --- a/webmails/rainloop/Dockerfile +++ b/webmails/rainloop/Dockerfile @@ -1,9 +1,13 @@ FROM php:7.2-apache +#Shared layer between rainloop and roundcube +RUN apt-get update && apt-get install -y \ + python3 curl \ + && rm -rf /var/lib/apt/lists ENV RAINLOOP_URL https://github.com/RainLoop/rainloop-webmail/releases/download/v1.12.1/rainloop-community-1.12.1.zip RUN apt-get update && apt-get install -y \ - unzip python3 python3-jinja2 curl \ + unzip python3-jinja2 \ && rm -rf /var/www/html/ \ && mkdir /var/www/html \ && cd /var/www/html \ diff --git a/webmails/roundcube/Dockerfile b/webmails/roundcube/Dockerfile index 0c3a0a55..14bee56e 100644 --- a/webmails/roundcube/Dockerfile +++ b/webmails/roundcube/Dockerfile @@ -1,9 +1,13 @@ FROM php:7.2-apache +#Shared layer between rainloop and roundcube +RUN apt-get update && apt-get install -y \ + python3 curl \ + && rm -rf /var/lib/apt/lists ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.3.8/roundcubemail-1.3.8-complete.tar.gz RUN apt-get update && apt-get install -y \ - zlib1g-dev curl python3 \ + zlib1g-dev \ && docker-php-ext-install zip \ && echo date.timezone=UTC > /usr/local/etc/php/conf.d/timezone.ini \ && rm -rf /var/www/html/ \ From 13bc6261e4c15685d264c8eea0dd8f8dc527111e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A4nger?= Date: Wed, 31 Oct 2018 20:30:16 +0100 Subject: [PATCH 90/93] allow DKIM-signing if From-Header and Auth-User mismatch --- services/rspamd/conf/dkim_signing.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/services/rspamd/conf/dkim_signing.conf b/services/rspamd/conf/dkim_signing.conf index 70f7e9b4..e00e8d67 100644 --- a/services/rspamd/conf/dkim_signing.conf +++ b/services/rspamd/conf/dkim_signing.conf @@ -1,3 +1,4 @@ try_fallback = true; path = "/dkim/$domain.$selector.key"; use_esld = false; +allow_username_mismatch = true; From 6dcc33e390003c1f1ea0955ec260ae2f9c776d2a Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Fri, 2 Nov 2018 12:14:23 +0200 Subject: [PATCH 91/93] Fixed admin_1 errors in the logs Fixed errors when trying to log in with an account without domain. This closes #585 --- core/admin/mailu/models.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 62c25c81..cd37f76c 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -35,11 +35,14 @@ class IdnaEmail(db.TypeDecorator): impl = db.String(255, collation="NOCASE") def process_bind_param(self, value, dialect): - localpart, domain_name = value.split('@') - return "{0}@{1}".format( - localpart, - idna.encode(domain_name).decode('ascii'), - ) + try: + localpart, domain_name = value.split('@') + return "{0}@{1}".format( + localpart, + idna.encode(domain_name).decode('ascii'), + ) + except: + pass def process_result_value(self, value, dialect): localpart, domain_name = value.split('@') From 2576379df556e5eecd8fd2dd9f5138fc3c8aeefb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Fri, 2 Nov 2018 15:10:18 +0200 Subject: [PATCH 92/93] Dev. docs.: Add git workflows for branching, PR and reviewing --- docs/contributors/environment.rst | 199 ++++++++++++++++++++++++++++-- docs/contributors/guide.rst | 2 + 2 files changed, 194 insertions(+), 7 deletions(-) diff --git a/docs/contributors/environment.rst b/docs/contributors/environment.rst index a79f6bb9..b539293b 100644 --- a/docs/contributors/environment.rst +++ b/docs/contributors/environment.rst @@ -1,20 +1,117 @@ Development environment ======================= +Git +--- + +Before any partaking in development, you will need to fork the Mailu repository on GitHub. +For this you will need a `GitHub`_ account. GitHub has excellent documentation on: + +#. How to `fork a repo`_ and set upstream (Mailu); +#. Keeping your fork `synced`_; +#. Sending a `pull request`_. + +Working on Mailu usually requires you to clone (download) your fork to your work station and +create a branch. From here you can work on Mailu. When done, create a commit and push the +branch to your GitHub repository. Then, on GitHub you can create a "pull request". +Please make sure you have read the :ref:`git_workflow` section of the *Development guidelines* +before submitting any pull requests. + +.. note:: It is strongly advised to **never** modify the ``master`` branch of your fork. + This will make it impossible to sync your fork with upstream and creating new (and clean) + branches! This includes never merging other branches from yourself or other users into your + ``master``. If you want to do that, create a separate branch for it. + +Short work flow example +``````````````````````` + +.. code-block:: bash + + git clone https://github.com//Mailu.git + cd Mailu + git add remote upstream https://github.com/Mailu/Mailu.git + git checkout -b fix-something master + +Work on the code as desired. Before doing a commit, you should at least build +and run the containers. Keep reading this guide for more information. After this, +continue to commit and send a PR. + +.. code-block:: bash + + git commit -a + #Enter commit message in editor, save and close. + git push --set-upstream origin fix-something + +Now you can go to your GitHub page, select the new branch and "send pull request". + +Updating your fork +`````````````````` + +The Mailu ``master`` branch is an ever evolving target. It is important that newly +created branches originate from the latest ``upstream/master``. In order to do so, you will +need to `sync your fork`__: + +.. code-block:: bash + + git fetch --all + git checkout master + git merge upstream/master + +If you kept your master branch clean, this should fast-forward it to the latest upstream version. +Likewise, if you worked on your branch for a longer amount of time, it is advised to merge the +latest ``upstream/master`` into the branch. + +.. code-block:: bash + + git checkout my-old-branch + git merge upstream/master + +Now, git won't fast forward but write a merge commit. Typically you can accept the commit message +presented. Read the output if there are any merge conflicts. In ``git status`` you can find the files +that need editing to have the desired contents. Also, it will tell you how to mark them as resolved. + +Optionally, you can ``git push`` after any of above merges to propagate them to GitHub. + +__ `synced`_ + +Bad habits +``````````` + +Some bad habits from users that we are sometimes confronted with. Please refrain yourself from: + +- ``git reset REF`` and ``git push --force`` after submitting a PR. +- Merge a branch (other then master) into yours and submitting a PR before that other branch got + merged into master. It will cause you to submit commits someone else wrote and are probably outside + the subject of your PR. (There are valid cases however, but take care!) +- ``git reset REF`` after merging ``upstream/master`` into your branch. It will unstage **all** + changed files that where updated in the merge. Your will have to clean up all of them + (don't delete!) using ``git checkout -- ``. And take care not to do that to the files you + have modified. However, it can be that the merge modified some other lines then yours. You'll have + to make sure there will be no conflicts when you are submitting this messed up branch to Mailu! You + get the point, I hope. +- ``git rebase`` on a branch that is pull-requested. Others will not be able to see you modified the + branch and it messes with the order of commits, compared to a merge. It might break things after we + have conducted tests. + +.. _`GitHub`: https://github.com/ +.. _`fork a repo`: https://help.github.com/articles/fork-a-repo/ +.. _`synced`: https://help.github.com/articles/syncing-a-fork/ +.. _`pull request`: https://help.github.com/articles/about-pull-requests/ + Docker containers ----------------- -The development environment is quite similar to the production one. You should always use -the ``master`` version when developing. +The development environment is quite similar to the production one. Building images ``````````````` -We supply a separate ``test/build.yml`` file for -convenience. To build all Mailu containers: +We supply a separate ``test/build.yml`` file for convenience. +After cloning the git repository to your workstation, you can build the images: .. code-block:: bash + cd Mailu docker-compose -f tests/build.yml build The ``build.yml`` file has two variables: @@ -73,10 +170,96 @@ Finally, if you need to install packages inside the containers for debugging: docker-compose exec admin apk add --no-cache package-name +Reviewing +--------- + +System requirements +``````````````````` + +Reviewing pull requests requires some additional git setup. First, for 90% of the review jobs, +you will need a PC or server that can expose all Mailu ports to the outside world. Also, a valid +domain name would be required. This can be a simple free DynDNS account. Do not use a production +server, as there are cases where data corruption occurs and you need to delete the ``/mailu`` +directory structure. + +If you do no posses the resources, but want to become an involved tester/reviewer. +Please contact `muhlemmer on Matrix`_. +He can provide access to a testing server, if a thrust relation can be established. + +.. _`muhlemmer on Matrix`: https://matrix.to/#/@muhlemmer:matrix.org + +Preparations +```````````` + +#. Setup `Git`_ the same way as on a development PC. It is advised to keep ``origin`` as your + own repository and ``upstream`` as the one from Mailu. This will avoid confusion; +#. You will need a ``docker-compose.yml`` and ``.env``, set up for the test server; +#. Make sure that the build ``$VERSION`` corresponds with those files. + +Add the sender +`````````````` + +Replace ```` with the repository name the PR is sent from. + +.. code-block:: bash + + git remote add https://github.com//Mailu.git + +Merge conflicts +``````````````` + +Before proceeding, check the PR page in the bottom. It should not indicate a merge conflict. +If there are merge conflicts, you have 2 options: + +#. Do a review "request changes" and ask the author to resolve the merge conflict. +#. Solve the merge conflict yourself on Github, using the web editor. + +If it can't be done in the web editor, go for option 1. Unless you want to go through the trouble of +importing the branch into your fork, do the merge and send a PR to the repository of the *sender*. + +Merge the PR locally +``````````````````````` + +When someone sends a PR, you need merge his PR into master locally. This example will put you in a +"detached head" state and do the merge in that state. Any commits done in this state will be lost +forever when you checkout a "normal" branch. This is exactly what we want, as we do not want to mess +with our repositories. This is just a test run. + +The following must be done on every PR or after every new commit to an existing PR: +1. Fetch the latest status of all the remotes. +2. List all local and remote available branches (this is not needed, but very helpful at times) +3. Checkout ``upstream/master`` +4. Merge ``upstream/master`` with ``SENDER/branch`` + +.. code-block:: bash + + git fetch --all + git checkout upstream/master + # ...You are in 'detached HEAD' state.... (bla bla bla) + git branch -a + # Hit `q` to exit the viewer, if it was opened. Uses arrows up/down for scrolling. + git merge kaiyou/fix-sender-checks + +If git opens a editor for a commit message just save and exit as-is. If you have a merge conflict, +see above and do the complete procedure from ``git fetch`` onward again. + +Test +```` + +You can now build and run the containers for testing. See the "`Docker containers`_" section for +instructions. Play around. See if (external) mails work. Check for whatever functionality the PR is +trying to fix. When happy, you can approve the PR. When running into failures, mark the review as +"request changes" and try to provide as much as possible details on the failure. +(Logs, error codes form clients etc). + +.. note:: Github marks positive reviews as obsolete when a new commit is added to a PR. + This requires a new review from your side. + Web administration ------------------ -The administration Web interface requires a proper dev environment that can easily be setup using ``virtualenv`` (make sure you are using Python 3) : +The administration Web interface requires a proper dev environment that can easily be setup using +``virtualenv`` (make sure you are using Python 3) : .. code-block:: bash @@ -105,7 +288,8 @@ of the screen, that you can open to access query details, internal variables, et Documentation ------------- -Documentation is maintained in the ``docs`` directory and are maintained as `reStructuredText`_ files. It is possible to run a local documentation server for reviewing purposes, using Docker: +Documentation is maintained in the ``docs`` directory and are maintained as `reStructuredText`_ +files. It is possible to run a local documentation server for reviewing purposes, using Docker: .. code-block:: bash @@ -116,6 +300,7 @@ Documentation is maintained in the ``docs`` directory and are maintained as `reS In a local build Docker always assumes the version to be master. You can read the local documentation by navigating to http://localhost:8080/master. -.. note:: After modifying the documentation, the image needs to be rebuild and the container restarted for the changes to become visible. +.. note:: After modifying the documentation, the image needs to be rebuild and the container + restarted for the changes to become visible. .. _`reStructuredText`: http://docutils.sourceforge.net/rst.html diff --git a/docs/contributors/guide.rst b/docs/contributors/guide.rst index 705af469..865fca94 100644 --- a/docs/contributors/guide.rst +++ b/docs/contributors/guide.rst @@ -13,6 +13,8 @@ Docker best practices and be as generic as possible : - interesting settings should be available as environment variables - base images should be well-trusted (officiel Alpine or Debian for instance). +.. _git_workflow: + Git workflow ------------ From 680ad4b67a33243ecb6535c24c7d2c8bba0bf306 Mon Sep 17 00:00:00 2001 From: hoellen Date: Mon, 5 Nov 2018 19:36:28 +0200 Subject: [PATCH 93/93] Catching only ValueError Co-Authored-By: ionutfilip --- core/admin/mailu/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index cd37f76c..9a19730f 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -41,7 +41,7 @@ class IdnaEmail(db.TypeDecorator): localpart, idna.encode(domain_name).decode('ascii'), ) - except: + except ValueError: pass def process_result_value(self, value, dialect):