You've already forked Mailu
							
							
				mirror of
				https://github.com/Mailu/Mailu.git
				synced 2025-10-30 23:37:43 +02:00 
			
		
		
		
	Merge branch 'master' into fix-swarm-start
This commit is contained in:
		
							
								
								
									
										10
									
								
								.mergify.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.mergify.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| rules: | ||||
|   default: null | ||||
|   branches: | ||||
|     master: | ||||
|       protection: | ||||
|         required_status_checks: | ||||
|           contexts: | ||||
|             - continuous-integration/travis-ci  | ||||
|         required_pull_request_reviews: | ||||
|           required_approving_review_count: 2 | ||||
							
								
								
									
										17
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,8 +1,11 @@ | ||||
| language: python | ||||
| python: | ||||
|   - "3.6" | ||||
| install: | ||||
|   - pip install -r docs/requirements.txt | ||||
| sudo: required | ||||
| services: docker | ||||
| addons: | ||||
|   apt: | ||||
|     packages: | ||||
|       - docker-ce | ||||
| env: | ||||
|   - VERSION=$TRAVIS_BRANCH | ||||
|  | ||||
| script: | ||||
|   - sphinx-versioning build -b -B 1.5 -r 1.5 -w '^[0-9.]*$' -w master -W '^$' docs/ build/ | ||||
|   - python "docs/conf.py" "build" "$DEPLOY_HOST" "$DEPLOY_USERNAME" "$DEPLOY_PASSWORD" "$DEPLOY_REMOTEDIR" | ||||
| - docker-compose -f tests/build.yml -p Mailu build | ||||
|   | ||||
| @@ -17,5 +17,6 @@ COPY start.sh /start.sh | ||||
| RUN pybabel compile -d mailu/translations | ||||
|  | ||||
| EXPOSE 80/tcp | ||||
| VOLUME ["/data"] | ||||
|  | ||||
| CMD ["/start.sh"] | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| from flask_limiter import RateLimitExceeded | ||||
|  | ||||
| from mailu import limiter | ||||
|  | ||||
| import socket | ||||
| @@ -6,6 +8,14 @@ import flask | ||||
|  | ||||
| internal = flask.Blueprint('internal', __name__) | ||||
|  | ||||
| @internal.app_errorhandler(RateLimitExceeded) | ||||
| def rate_limit_handler(e): | ||||
|     response = flask.Response() | ||||
|     response.headers['Auth-Status'] = 'Authentication rate limit from one source exceeded' | ||||
|     response.headers['Auth-Error-Code'] = '451 4.3.2' | ||||
|     if int(flask.request.headers['Auth-Login-Attempt']) < 10: | ||||
|         response.headers['Auth-Wait'] = '3' | ||||
|     return response | ||||
|  | ||||
| @limiter.request_filter | ||||
| def whitelist_webmail(): | ||||
|   | ||||
| @@ -2,4 +2,4 @@ | ||||
|  | ||||
| python manage.py advertise | ||||
| python manage.py db upgrade | ||||
| gunicorn -w 4 -b 0.0.0.0:80 -b [::]:80 --access-logfile - --error-logfile - --preload mailu:app | ||||
| gunicorn -w 4 -b :80 --access-logfile - --error-logfile - --preload mailu:app | ||||
|   | ||||
| @@ -3,12 +3,13 @@ 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 | ||||
|      dovecot-fts-lucene 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 | ||||
| VOLUME ["/data", "/mail"] | ||||
|  | ||||
| CMD /start.py | ||||
|   | ||||
| @@ -18,6 +18,20 @@ dict { | ||||
|   sieve = sqlite:/etc/dovecot/pigeonhole-sieve.dict | ||||
| } | ||||
|  | ||||
| ############### | ||||
| # Full-text search | ||||
| ############### | ||||
| mail_plugins =  $mail_plugins fts fts_lucene | ||||
|  | ||||
| plugin { | ||||
|   fts = lucene | ||||
|  | ||||
|   fts_autoindex = yes | ||||
|   fts_autoindex_exclude = \Junk | ||||
|  | ||||
|   fts_lucene = whitespace_chars=@. | ||||
| } | ||||
|  | ||||
| ############### | ||||
| # Mailboxes | ||||
| ############### | ||||
| @@ -32,7 +46,7 @@ mail_access_groups = mail | ||||
| maildir_stat_dirs = yes | ||||
| mailbox_list_index = yes | ||||
| mail_vsize_bg_after_count = 100 | ||||
| mail_plugins = $mail_plugins quota quota_clone | ||||
| mail_plugins = $mail_plugins quota quota_clone zlib | ||||
|  | ||||
| namespace inbox { | ||||
|   inbox = yes | ||||
| @@ -58,6 +72,14 @@ plugin { | ||||
|   quota = count:User quota | ||||
|   quota_vsizes = yes | ||||
|   quota_clone_dict = redis:host={{ REDIS_ADDRESS }}:port=6379:db=1 | ||||
|  | ||||
|   {% if COMPRESSION in [ 'gz', 'bz2' ] %} | ||||
|   zlib_save = {{ COMPRESSION }} | ||||
|   {% endif %} | ||||
|  | ||||
|   {% if COMPRESSION_LEVEL %} | ||||
|   zlib_save_level = {{ COMPRESSION_LEVEL }} | ||||
|   {% endif %} | ||||
| } | ||||
|  | ||||
| ############### | ||||
|   | ||||
| @@ -1,3 +1,11 @@ | ||||
| require "vnd.dovecot.execute"; | ||||
| require ["vnd.dovecot.execute", "copy", "imapsieve", "environment", "variables"]; | ||||
|  | ||||
| if environment :matches "imap.mailbox" "*" { | ||||
|   set "mailbox" "${1}"; | ||||
| } | ||||
|  | ||||
| if string "${mailbox}" "Trash" { | ||||
|   stop; | ||||
| } | ||||
|  | ||||
| execute :pipe "mailtrain" "ham"; | ||||
|   | ||||
| @@ -6,5 +6,6 @@ COPY conf /conf | ||||
| 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 | ||||
| VOLUME ["/certs"] | ||||
|  | ||||
| CMD /start.py | ||||
|   | ||||
| @@ -6,5 +6,6 @@ COPY conf /conf | ||||
| COPY start.py /start.py | ||||
|  | ||||
| EXPOSE 25/tcp 10025/tcp | ||||
| VOLUME ["/data"] | ||||
|  | ||||
| CMD /start.py | ||||
|   | ||||
| @@ -8,6 +8,7 @@ smtp      inet  n       -       n       -       -       smtpd | ||||
| 10025     inet  n       -       n       -       -       smtpd | ||||
|   -o smtpd_sasl_auth_enable=yes | ||||
|   -o smtpd_recipient_restrictions=reject_unlisted_sender,reject_authenticated_sender_login_mismatch,permit | ||||
|   -o smtpd_reject_unlisted_recipient={% if REJECT_UNLISTED_RECIPIENT %}{{ REJECT_UNLISTED_RECIPIENT }}{% else %}no{% endif %} | ||||
|   -o cleanup_service_name=outclean | ||||
| outclean  unix n       -       n       -       0       cleanup | ||||
|   -o header_checks=pcre:/etc/postfix/outclean_header_filter.cf | ||||
|   | ||||
							
								
								
									
										14
									
								
								docs/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								docs/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| FROM python:3-alpine | ||||
|  | ||||
| COPY requirements.txt /requirements.txt | ||||
|  | ||||
| RUN pip install -r /requirements.txt \ | ||||
|  && apk add --no-cache nginx \ | ||||
|  && mkdir /run/nginx | ||||
|  | ||||
| COPY ./nginx.conf /etc/nginx/conf.d/default.conf | ||||
| COPY . /docs | ||||
|  | ||||
| RUN sphinx-build /docs /build | ||||
|  | ||||
| CMD nginx -g "daemon off;" | ||||
| @@ -87,6 +87,12 @@ 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! | ||||
|  | ||||
| # Maildir Compression | ||||
| # choose compression-method, default: none (value: bz2, gz) | ||||
| COMPRESSION= | ||||
| # change compression-level, default: 6 (value: 1-9) | ||||
| COMPRESSION_LEVEL= | ||||
|  | ||||
| ################################### | ||||
| # Web settings | ||||
| ################################### | ||||
| @@ -126,3 +132,6 @@ REAL_IP_HEADER= | ||||
|  | ||||
| # IPs for nginx set_real_ip_from (CIDR list separated by commas) | ||||
| REAL_IP_FROM= | ||||
|  | ||||
| # choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no) | ||||
| REJECT_UNLISTED_RECIPIENT= | ||||
|   | ||||
							
								
								
									
										25
									
								
								docs/conf.py
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								docs/conf.py
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ templates_path = ['_templates'] | ||||
| source_suffix = '.rst' | ||||
| master_doc = 'index' | ||||
| project = 'Mailu' | ||||
| copyright = '2017, Mailu authors' | ||||
| copyright = '2018, Mailu authors' | ||||
| author = 'Mailu authors' | ||||
| version = release = 'latest' | ||||
| language = None | ||||
| @@ -23,7 +23,7 @@ htmlhelp_basename = 'Mailudoc' | ||||
| # to template names. | ||||
| html_sidebars = { | ||||
|     '**': [ | ||||
|         'relations.html',  # needs 'show_related': True theme option to display | ||||
|         'relations.html',  | ||||
|         'searchbox.html', | ||||
|     ] | ||||
| } | ||||
| @@ -36,24 +36,3 @@ html_context = { | ||||
|     'github_version': 'master', | ||||
|     'conf_py_path': '/docs/' | ||||
| } | ||||
|  | ||||
|  | ||||
| # Upload function when the script is called directly | ||||
| if __name__ == "__main__": | ||||
|     import os, sys, paramiko | ||||
|     build_dir, hostname, username, password, dest_dir = sys.argv[1:] | ||||
|     transport = paramiko.Transport((hostname, 22)) | ||||
|     transport.connect(username=username, password=password) | ||||
|     sftp = paramiko.SFTPClient.from_transport(transport) | ||||
|     os.chdir(build_dir) | ||||
|     for dirpath, dirnames, filenames in os.walk("."): | ||||
|         remote_path = os.path.join(dest_dir, dirpath) | ||||
|         try: | ||||
|             sftp.mkdir(remote_path) | ||||
|         except: | ||||
|             pass | ||||
|         for filename in filenames: | ||||
|             sftp.put( | ||||
|                 os.path.join(dirpath, filename), | ||||
|                 os.path.join(remote_path, filename) | ||||
|             ) | ||||
|   | ||||
| @@ -89,3 +89,20 @@ Any change to the files will automatically restart the Web server and reload the | ||||
|  | ||||
| When using the development environment, a debugging toolbar is displayed on the right side | ||||
| of the screen, that you can open to access query details, internal variables, etc. | ||||
|  | ||||
| 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: | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|   cd <Mailu repo> | ||||
|   docker build -t docs docs | ||||
|   docker run -p 127.0.0.1:8080:80 docs | ||||
|  | ||||
| You can now read the local documentation by navigating to http://localhost:8080. | ||||
|  | ||||
| .. 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 | ||||
|   | ||||
							
								
								
									
										5
									
								
								docs/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								docs/nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| server { | ||||
|     listen 80; | ||||
|     listen [::]:80; | ||||
|     root /build; | ||||
| } | ||||
| @@ -2,5 +2,3 @@ recommonmark | ||||
| Sphinx | ||||
| sphinx-autobuild | ||||
| sphinx-rtd-theme | ||||
| sphinxcontrib-versioning | ||||
| paramiko | ||||
|   | ||||
							
								
								
									
										364
									
								
								docs/swarm/1.5/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								docs/swarm/1.5/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,364 @@ | ||||
| # 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 <IP_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) provinding this service. | ||||
| With this default networking mode, I cannot get login working properly... As found in https://github.com/Mailu/Mailu/issues/375 ,  a workaround is to use the dnsrr networking mode at least for the front services. | ||||
|  | ||||
| The main consequence/limitation will be that the front services will *not* be available on every node, but only on the node where it will be deployed. In my case, I have only one manager and I choose to deploy the front service to the manager node, so I know on wich IP the front service will be available (aka the IP adress of my manager node). | ||||
|  | ||||
| ### 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:1.5 | ||||
|     env_file: .env | ||||
|     ports: | ||||
|       - target: 80 | ||||
|         published: 80 | ||||
|         mode: host | ||||
|       - target: 443 | ||||
|         published: 443 | ||||
|         mode: host | ||||
|       - target: 110 | ||||
|         published: 110 | ||||
|         mode: host | ||||
|       - target: 143 | ||||
|         published: 143 | ||||
|         mode: host | ||||
|       - target: 993 | ||||
|         published: 993 | ||||
|         mode: host | ||||
|       - target: 995 | ||||
|         published: 995 | ||||
|         mode: host | ||||
|       - target: 25 | ||||
|         published: 25 | ||||
|         mode: host | ||||
|       - target: 465 | ||||
|         published: 465 | ||||
|         mode: host | ||||
|       - target: 587 | ||||
|         published: 587 | ||||
|         mode: host | ||||
|     volumes: | ||||
| #      - "$ROOT/certs:/certs" | ||||
|       - type: volume | ||||
|         source: mailu_certs | ||||
|         target: /certs | ||||
|     deploy: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   redis: | ||||
|     image: redis:alpine | ||||
|     restart: always | ||||
|     volumes: | ||||
| #      - "$ROOT/redis:/data" | ||||
|       - type: volume | ||||
|         source: mailu_redis | ||||
|         target: /data | ||||
|     deploy: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   imap: | ||||
|     image: mailu/dovecot:1.5 | ||||
|     restart: always | ||||
|     env_file: .env | ||||
|     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: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   smtp: | ||||
|     image: mailu/postfix:1.5 | ||||
|     restart: always | ||||
|     env_file: .env | ||||
|     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: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   antispam: | ||||
|     image: mailu/rspamd:1.5 | ||||
|     restart: always | ||||
|     env_file: .env | ||||
|     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: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   antivirus: | ||||
|     image: mailu/none:1.5 | ||||
|     restart: always | ||||
|     env_file: .env | ||||
|     volumes: | ||||
| #      - "$ROOT/filter:/data" | ||||
|       - type: volume | ||||
|         source: mailu_filter | ||||
|         target: /data | ||||
|     deploy: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   webdav: | ||||
|     image: mailu/none:1.5 | ||||
|     restart: always | ||||
|     env_file: .env | ||||
|     volumes: | ||||
| #      - "$ROOT/dav:/data" | ||||
|       - type: volume | ||||
|         source: mailu_dav | ||||
|         target: /data | ||||
|     deploy: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   admin: | ||||
|     image: mailu/admin:1.5 | ||||
|     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: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   webmail: | ||||
|     image: "mailu/roundcube:1.5" | ||||
|     restart: always | ||||
|     env_file: .env | ||||
|     volumes: | ||||
| #      - "$ROOT/webmail:/data" | ||||
|       - type: volume | ||||
|         source: mailu_data | ||||
|         target: /data | ||||
|     depends_on: | ||||
|       - imap | ||||
|     deploy: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
|   fetchmail: | ||||
|     image: mailu/fetchmail:1.5 | ||||
|     restart: always | ||||
|     env_file: .env | ||||
|     volumes: | ||||
| #      - "$ROOT/data:/data" | ||||
|       - type: volume | ||||
|         source: mailu_data | ||||
|         target: /data | ||||
|     logging: | ||||
|       driver: none | ||||
|     deploy: | ||||
|       endpoint_mode: dnsrr | ||||
|       replicas: 1 | ||||
|       placement: | ||||
|         constraints: [node.role == manager] | ||||
|  | ||||
| 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 | ||||
| ``` | ||||
| @@ -6,5 +6,6 @@ COPY conf /etc/clamav | ||||
| COPY start.sh /start.sh | ||||
|  | ||||
| EXPOSE 3310/tcp | ||||
| VOLUME ["/data"] | ||||
|  | ||||
| CMD ["/start.sh"] | ||||
|   | ||||
| @@ -6,5 +6,6 @@ RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/re | ||||
| COPY radicale.conf /radicale.conf | ||||
|  | ||||
| EXPOSE 5232/tcp | ||||
| VOLUME ["/data"] | ||||
|  | ||||
| CMD radicale -f -S -C /radicale.conf | ||||
|   | ||||
| @@ -12,4 +12,6 @@ RUN sed -i '/fuzzy/,$d' /etc/rspamd/rspamd.conf | ||||
|  | ||||
| EXPOSE 11332/tcp 11334/tcp | ||||
|  | ||||
| VOLUME ["/var/lib/rspamd"] | ||||
|  | ||||
| CMD /start.py | ||||
|   | ||||
							
								
								
									
										4
									
								
								services/rspamd/conf/arc.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								services/rspamd/conf/arc.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| try_fallback = true; | ||||
| path = "/dkim/$domain.$selector.key"; | ||||
| selector = "dkim" | ||||
| use_esld = false; | ||||
| @@ -15,4 +15,4 @@ RUN python setup.py https://github.com/mailu/mailu /data | ||||
|  | ||||
| EXPOSE 80/tcp | ||||
|  | ||||
| CMD gunicorn -w 4 -b 0.0.0.0:80 -b [::]:80 --access-logfile - --error-logfile - --preload main:app | ||||
| CMD gunicorn -w 4 -b :80 --access-logfile - --error-logfile - --preload main:app | ||||
|   | ||||
							
								
								
									
										13
									
								
								setup/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								setup/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| # This file is used to run the mailu/setup utility | ||||
|  | ||||
| version: '2' | ||||
|  | ||||
| services: | ||||
|   redis: | ||||
|     image: redis:alpine | ||||
|  | ||||
|   setup: | ||||
|     image: mailu/setup | ||||
|     ports: | ||||
|       - "80:80" | ||||
|  | ||||
							
								
								
									
										51
									
								
								tests/build.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tests/build.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|  | ||||
|   front: | ||||
|     image: mailu/nginx:$VERSION | ||||
|     build: ../core/nginx | ||||
|  | ||||
|   imap: | ||||
|     image: mailu/dovecot:$VERSION | ||||
|     build: ../core/dovecot | ||||
|  | ||||
|   smtp: | ||||
|     image: mailu/postfix:$VERSION | ||||
|     build: ../core/postfix | ||||
|  | ||||
|   antispam: | ||||
|     image: mailu/rspamd:$VERSION | ||||
|     build: ../services/rspamd | ||||
|  | ||||
|   antivirus: | ||||
|     image: mailu/clamav:$VERSION | ||||
|     build: ../optional/clamav | ||||
|  | ||||
|   webdav: | ||||
|     image: mailu/radicale:$VERSION | ||||
|     build: ../optional/radicale | ||||
|  | ||||
|   admin: | ||||
|     image: mailu/admin:$VERSION | ||||
|     build: ../core/admin | ||||
|  | ||||
|   roundcube: | ||||
|     image: mailu/roundcube:$VERSION | ||||
|     build: ../webmails/roundcube | ||||
|  | ||||
|   rainloop: | ||||
|     image: mailu/rainloop:$VERSION | ||||
|     build: ../webmails/rainloop | ||||
|  | ||||
|   fetchmail: | ||||
|     image: mailu/fetchmail:$VERSION | ||||
|     build: ../services/fetchmail | ||||
|  | ||||
|   none: | ||||
|     image: mailu/none:$VERSION | ||||
|     build: ../core/none | ||||
|  | ||||
|   docs: | ||||
|     image: mailu/docs:$VERSION | ||||
|     build: ../docs | ||||
| @@ -24,4 +24,7 @@ COPY default.ini /default.ini | ||||
|  | ||||
| COPY start.py /start.py | ||||
|  | ||||
| EXPOSE 80/tcp | ||||
| VOLUME ["/data"] | ||||
|  | ||||
| CMD /start.py | ||||
|   | ||||
| @@ -1,11 +1,8 @@ | ||||
| FROM php:7.0-apache | ||||
| FROM php:7.2-apache | ||||
|  | ||||
| RUN apt-get update && apt-get install -y \ | ||||
|       libfreetype6-dev \ | ||||
|       libjpeg62-turbo-dev \ | ||||
|       libmcrypt-dev \ | ||||
|       libpng-dev \ | ||||
|  && docker-php-ext-install pdo_mysql mcrypt zip | ||||
|       zlib1g-dev \ | ||||
|  && docker-php-ext-install zip | ||||
|  | ||||
| ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.3.7/roundcubemail-1.3.7-complete.tar.gz | ||||
|  | ||||
| @@ -28,4 +25,7 @@ COPY config.inc.php /var/www/html/config/ | ||||
|  | ||||
| COPY start.sh /start.sh | ||||
|  | ||||
| EXPOSE 80/tcp | ||||
| VOLUME ["/data"] | ||||
|  | ||||
| CMD ["/start.sh"] | ||||
|   | ||||
| @@ -6,6 +6,7 @@ $config = array(); | ||||
| $config['db_dsnw'] = 'sqlite:////data/roundcube.db'; | ||||
| $config['temp_dir'] = '/tmp/'; | ||||
| $config['des_key'] = getenv('SECRET_KEY'); | ||||
| $config['cipher_method'] = 'AES-256-CBC'; | ||||
| $config['identities_level'] = 3; | ||||
| $config['reply_all_mode'] = 1; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user