From 66df7a31b0572324600bfd3e43ab0c0941aa38b0 Mon Sep 17 00:00:00 2001 From: Dario Ernst Date: Sun, 13 Jan 2019 10:17:38 +0100 Subject: [PATCH 01/13] Unify and coerce booleans from env used in admin At some places, the string that DOMAIN_REGISTRATION is got used like a boolean (an easy misassumption to make while in python and dealing with the config dict), making `DOMAIN_REGISTRATION=False` act as a truthy value. To stop such future problems from happening, coerce environment config strings to real bools. closes #830 --- CHANGELOG.md | 1 + core/admin/mailu/configuration.py | 14 +++++++++++--- core/admin/mailu/manage.py | 2 +- core/admin/mailu/models.py | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07b5b164..2b068547 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,6 +116,7 @@ v1.6.0 - unreleased - Bug: Don't recursivly chown on mailboxes ([#776](https://github.com/Mailu/Mailu/issues/776)) - Bug: Fix forced password input for user edit ([#745](https://github.com/Mailu/Mailu/issues/745)) - Bug: Fetched accounts: Password field is of type "text" ([#789](https://github.com/Mailu/Mailu/issues/789)) +- Bug: DOMAIN_REGISTRATION=False in .env was not treated correctly ([#830](https://github.com/Mailu/Mailu/issues/830)) v1.5.1 - 2017-11-21 ------------------- diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 95004017..a8cd3e25 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -30,11 +30,11 @@ DEFAULT_CONFIG = { 'POSTMASTER': 'postmaster', 'TLS_FLAVOR': 'cert', 'AUTH_RATELIMIT': '10/minute;1000/hour', - 'DISABLE_STATISTICS': 'False', + 'DISABLE_STATISTICS': False, # Mail settings 'DMARC_RUA': None, 'DMARC_RUF': None, - 'WELCOME': 'False', + 'WELCOME': False, 'WELCOME_SUBJECT': 'Dummy welcome topic', 'WELCOME_BODY': 'Dummy welcome body', 'DKIM_SELECTOR': 'dkim', @@ -74,13 +74,21 @@ class ConfigManager(dict): def __init__(self): self.config = dict() + def __coerce_value(self, value): + if isinstance(value, str) and value.lower() in ('true','yes'): + return True + elif isinstance(value, str) and value.lower() in ('false', 'no'): + return False + return value + def init_app(self, app): self.config.update(app.config) # get environment variables self.config.update({ - key: os.environ.get(key, value) + key: self.__coerce_value(os.environ.get(key, value)) for key, value in DEFAULT_CONFIG.items() }) + # automatically set the sqlalchemy string if self.config['DB_FLAVOR']: template = self.DB_TEMPLATES[self.config['DB_FLAVOR']] diff --git a/core/admin/mailu/manage.py b/core/admin/mailu/manage.py index 4846c2d6..e11644e7 100644 --- a/core/admin/mailu/manage.py +++ b/core/admin/mailu/manage.py @@ -31,7 +31,7 @@ def advertise(): instance_id = str(uuid.uuid4()) with open(app.config["INSTANCE_ID_PATH"], "w") as handle: handle.write(instance_id) - if app.config["DISABLE_STATISTICS"].lower() != "true": + if not app.config["DISABLE_STATISTICS"]: try: socket.gethostbyname(app.config["STATS_ENDPOINT"].format(instance_id)) except: diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 37823f02..15685abd 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -410,7 +410,7 @@ class User(Base, Email): return emails def send_welcome(self): - if app.config["WELCOME"].lower() == "true": + if app.config["WELCOME"]: self.sendmail(app.config["WELCOME_SUBJECT"], app.config["WELCOME_BODY"]) From 2d34f0ee5236b1ec7f5ce14ecf12e8c6479bd996 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 15 Jan 2019 14:03:09 +0200 Subject: [PATCH 02/13] Fixed auto-forward email validation --- core/admin/mailu/ui/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/ui/forms.py b/core/admin/mailu/ui/forms.py index e8302199..48355748 100644 --- a/core/admin/mailu/ui/forms.py +++ b/core/admin/mailu/ui/forms.py @@ -37,7 +37,7 @@ class MultipleEmailAddressesVerify(object): self.message = message def __call__(self, form, field): - pattern = re.compile(r'^([_a-z0-9\-]+)(\.[_a-z0-9\-]+)*@([a-z0-9\-]{2,}\.)*([a-z]{2,4})(,([_a-z0-9\-]+)(\.[_a-z0-9\-]+)*@([a-z0-9\-]{2,}\.)*([a-z]{2,4}))*$') + pattern = re.compile(r'^([_a-z0-9\-]+)(\.[_a-z0-9\-]+)*@([a-z0-9\-]{2,}\.)*([a-z]{2,})(,([_a-z0-9\-]+)(\.[_a-z0-9\-]+)*@([a-z0-9\-]{2,}\.)*([a-z]{2,}))*$') if not pattern.match(field.data.replace(" ", "")): raise validators.ValidationError(self.message) From d24b4b37abdd9d9c363b84d74475ffb7e6b72650 Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Tue, 15 Jan 2019 14:27:21 +0200 Subject: [PATCH 03/13] Add entry in changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07b5b164..6fd0bad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,6 +116,7 @@ v1.6.0 - unreleased - Bug: Don't recursivly chown on mailboxes ([#776](https://github.com/Mailu/Mailu/issues/776)) - Bug: Fix forced password input for user edit ([#745](https://github.com/Mailu/Mailu/issues/745)) - Bug: Fetched accounts: Password field is of type "text" ([#789](https://github.com/Mailu/Mailu/issues/789)) +- Bug: Auto-forward destination not accepting top level domains ([#818](https://github.com/Mailu/Mailu/issues/818)) v1.5.1 - 2017-11-21 ------------------- From f1e1c96c3ba996f217fe4212e9b3bf6fc02cf573 Mon Sep 17 00:00:00 2001 From: hoellen Date: Tue, 15 Jan 2019 15:02:56 +0100 Subject: [PATCH 04/13] create migration file for changing quota to big integer --- .../migrations/versions/2335c80a6bc3_.py | 2 +- .../migrations/versions/25fd6c7bcb4a_.py | 2 +- .../migrations/versions/3b7eee912b41_.py | 30 +++++++++++++++++++ .../migrations/versions/ff0417f4318f_.py | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 core/admin/migrations/versions/3b7eee912b41_.py diff --git a/core/admin/migrations/versions/2335c80a6bc3_.py b/core/admin/migrations/versions/2335c80a6bc3_.py index 43d03547..ac5c1e83 100644 --- a/core/admin/migrations/versions/2335c80a6bc3_.py +++ b/core/admin/migrations/versions/2335c80a6bc3_.py @@ -15,7 +15,7 @@ import sqlalchemy as sa def upgrade(): - op.add_column('domain', sa.Column('max_quota_bytes', sa.BigInteger(), nullable=False, server_default='0')) + op.add_column('domain', sa.Column('max_quota_bytes', sa.Integer(), nullable=False, server_default='0')) def downgrade(): diff --git a/core/admin/migrations/versions/25fd6c7bcb4a_.py b/core/admin/migrations/versions/25fd6c7bcb4a_.py index 6e89d2c3..cf9a0fc7 100644 --- a/core/admin/migrations/versions/25fd6c7bcb4a_.py +++ b/core/admin/migrations/versions/25fd6c7bcb4a_.py @@ -20,7 +20,7 @@ import sqlalchemy as sa def upgrade(): with op.batch_alter_table('user') as batch: - batch.add_column(sa.Column('quota_bytes_used', sa.BigInteger(), nullable=False, server_default='0')) + batch.add_column(sa.Column('quota_bytes_used', sa.Integer(), nullable=False, server_default='0')) def downgrade(): diff --git a/core/admin/migrations/versions/3b7eee912b41_.py b/core/admin/migrations/versions/3b7eee912b41_.py new file mode 100644 index 00000000..17f1e0ef --- /dev/null +++ b/core/admin/migrations/versions/3b7eee912b41_.py @@ -0,0 +1,30 @@ +"""change quota type to bigint + +Revision ID: 3b7eee912b41 +Revises: fc099bd15cbe +Create Date: 2019-01-15 08:51:05.346257 + +""" + +# revision identifiers, used by Alembic. +revision = '3b7eee912b41' +down_revision = 'fc099bd15cbe' + +from alembic import op +import sqlalchemy as sa + +def upgrade(): + with op.batch_alter_table('domain') as batch: + batch.alter_column('max_quota_bytes', type_=sa.BigInteger(), nullable=False, server_default='0') + + with op.batch_alter_table('user') as batch: + batch.alter_column('quota_bytes', type_=sa.BigInteger(), nullable=False) + batch.alter_column('quota_bytes_used', type_=sa.BigInteger(), nullable=False, server_default='0') + +def downgrade(): + with op.batch_alter_table('domain') as batch: + batch.alter_column('max_quota_bytes', type_=sa.Integer(), nullable=False, server_default='0') + + with op.batch_alter_table('user') as batch: + batch.alter_column('quota_bytes', type_=sa.Integer(), nullable=False) + batch.alter_column('quota_bytes_used', type_=sa.Integer(), nullable=False, server_default='0') diff --git a/core/admin/migrations/versions/ff0417f4318f_.py b/core/admin/migrations/versions/ff0417f4318f_.py index 99411087..7c92f241 100644 --- a/core/admin/migrations/versions/ff0417f4318f_.py +++ b/core/admin/migrations/versions/ff0417f4318f_.py @@ -41,7 +41,7 @@ def upgrade(): sa.Column('comment', sa.String(length=255), nullable=True), sa.Column('localpart', sa.String(length=80), nullable=False), sa.Column('password', sa.String(length=255), nullable=False), - sa.Column('quota_bytes', sa.BigInteger(), nullable=False), + sa.Column('quota_bytes', sa.Integer(), nullable=False), sa.Column('global_admin', sa.Boolean(), nullable=False), sa.Column('enable_imap', sa.Boolean(), nullable=False), sa.Column('enable_pop', sa.Boolean(), nullable=False), From 9721df0bc598d93467f9be9904388a5273a0fbed Mon Sep 17 00:00:00 2001 From: hoellen Date: Tue, 15 Jan 2019 16:41:58 +0100 Subject: [PATCH 05/13] fix default value for created_at and updated_at Use date instead of datetime for created_at and updated_at. --- core/admin/mailu/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 15685abd..9c3786b9 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -101,8 +101,8 @@ class Base(db.Model): } ) - created_at = db.Column(db.Date, nullable=False, default=datetime.now) - updated_at = db.Column(db.Date, nullable=True, onupdate=datetime.now) + created_at = db.Column(db.Date, nullable=False, default=date.today) + updated_at = db.Column(db.Date, nullable=True, onupdate=date.today) comment = db.Column(db.String(255), nullable=True) From 1975534125f50fcb22fab05da82b511a3e6346b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 16 Jan 2019 20:50:52 +0200 Subject: [PATCH 06/13] Make docker-compose.yml for setup and docs development friendly This enables easy local running. Actual deployment files are moved to github.com/mailu/infra. --- docs/docker-compose.yml | 32 ++++++---------------------- setup/docker-compose.yml | 46 ++++++---------------------------------- setup/server.py | 2 +- 3 files changed, 14 insertions(+), 66 deletions(-) diff --git a/docs/docker-compose.yml b/docs/docker-compose.yml index b7026564..9c5d2473 100644 --- a/docs/docker-compose.yml +++ b/docs/docker-compose.yml @@ -1,28 +1,10 @@ +# This file is used to test the mailu/docs website +# Deployment files can be found on github.com/mailu/infra + version: '3' - services: - docs_master: - image: mailu/docs:master - networks: - - web - labels: - - traefik.enable=true - - traefik.port=80 - - traefik.main.frontend.rule=Host:${ADDRESS};PathPrefix:/master/ - - docs_15: - image: mailu/docs:1.5 - networks: - - web - labels: - - traefik.enable=true - - traefik.port=80 - - traefik.root.frontend.redirect.regex=.* - - traefik.root.frontend.redirect.replacement=/1.5/ - - traefik.root.frontend.rule=Host:${ADDRESS};PathPrefix:/ - - traefik.main.frontend.rule=Host:${ADDRESS};PathPrefix:/1.5/ - -networks: - web: - external: true + docs: + image: ${DOCKER_ORG:-mailu}/docs:${MAILU_VERSION:-master} + ports: + - 127.0.0.1:8000:80 diff --git a/setup/docker-compose.yml b/setup/docker-compose.yml index 6d14153a..9c93fd6f 100644 --- a/setup/docker-compose.yml +++ b/setup/docker-compose.yml @@ -1,50 +1,16 @@ -# This file is used to run the mailu/setup utility +# This file is used to test the mailu/setup utility +# Deployment files can be found on github.com/mailu/infra version: '3.6' services: redis: image: redis:alpine - networks: - - default - setup_master: - image: mailu/setup:master - networks: - - web - - default + setup: + image: ${DOCKER_ORG:-mailu}/setup:${MAILU_VERSION:-master} env_file: .env - environment: - this_version: "master" - labels: - - traefik.enable=true - - traefik.port=80 - - traefik.docker.network=web - - traefik.main.frontend.rule=Host:${ADDRESS};PathPrefix:/master/ depends_on: - redis - - setup_release: - image: mailu/setup:${RELEASE} - networks: - - web - - default - env_file: .env - environment: - this_version: ${RELEASE} - labels: - - traefik.enable=true - - traefik.port=80 - - traefik.docker.network=web - - traefik.root.frontend.redirect.regex=.* - - traefik.root.frontend.redirect.replacement=/${RELEASE}/ - - traefik.root.frontend.rule=Host:${ADDRESS};PathPrefix:/ - - traefik.main.frontend.rule=Host:${ADDRESS};PathPrefix:/${RELEASE}/ - depends_on: - - redis - -networks: - web: - external: true - default: - external: false + ports: + - 127.0.0.1:8001:80 diff --git a/setup/server.py b/setup/server.py index fea27ead..556d4b3a 100644 --- a/setup/server.py +++ b/setup/server.py @@ -11,7 +11,7 @@ import ipaddress import hashlib -version = os.getenv("this_version") +version = os.getenv("this_version", "master") static_url_path = "/" + version + "/static" app = flask.Flask(__name__, static_url_path=static_url_path) flask_bootstrap.Bootstrap(app) From 38e754be6d29d8d18c7794de25d37bd08ddc75e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 16 Jan 2019 21:01:09 +0200 Subject: [PATCH 07/13] Make docs refer to the setup utility --- docs/compose/.env | 2 + docs/compose/docker-compose.yml | 2 + docs/compose/setup.rst | 83 ++++--------------- docs/configuration.rst | 11 ++- docs/index.rst | 2 +- .../templates/steps/compose/02_services.html | 24 +++--- setup/templates/steps/compose/03_expose.html | 6 +- setup/templates/steps/config.html | 13 ++- setup/templates/steps/flavor.html | 3 - setup/templates/steps/stack/02_services.html | 28 +++---- 10 files changed, 73 insertions(+), 101 deletions(-) diff --git a/docs/compose/.env b/docs/compose/.env index cf906b58..218b94d2 100644 --- a/docs/compose/.env +++ b/docs/compose/.env @@ -1,3 +1,5 @@ +# WARNING: this file is being deprecated over the new setup utility, found at https://setup.mailu.io + # 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 diff --git a/docs/compose/docker-compose.yml b/docs/compose/docker-compose.yml index 2cff9608..2686ee27 100644 --- a/docs/compose/docker-compose.yml +++ b/docs/compose/docker-compose.yml @@ -1,3 +1,5 @@ +# WARNING: this file is being deprecated over the new setup utility, found at https://setup.mailu.io + version: '2' services: diff --git a/docs/compose/setup.rst b/docs/compose/setup.rst index 3ff1f678..c1a620e6 100644 --- a/docs/compose/setup.rst +++ b/docs/compose/setup.rst @@ -12,34 +12,22 @@ Mailu will store all of its persistent data in a path of your choice mkdir /mailu cd /mailu -Download the initial configuration file ---------------------------------------- +Create the configuration files +------------------------------ -Docker Compose configuration is stored in a file named -:download:`docker-compose.yml`. Additionally, Mailu -relies on a :download:`.env` file for various settings. Download -the proper template files from the git repository. To download the configuration -for the ``VERSION_TAG`` branch, use: +Docker Compose configuration is stored in a file named ``docker-compose.yml``. +Additionally, Mailu relies on a ``mailu.env`` file for various settings. +Both files can be generated by the `mailu setup utility`_. The setup utility +is mostly self-explanatory, with some more additional information in this section. -.. code-block:: bash +.. _`mailu setup utility`: https://setup.mailu.io - wget https://mailu.io/VERSION_TAG/_downloads/docker-compose.yml - wget https://mailu.io/VERSION_TAG/_downloads/.env - -Important configuration variables ---------------------------------- - -Open the ``.env`` file and review the following variable settings: - -- Change ``ROOT`` if you have your setup directory in a different location then ``/mailu``. -- Check ``VERSION`` to reflect the version you picked. (``master`` or ``1.5``). - -Make sure to read the comments in the file and instructions from the :ref:`common_cfg` section. +.. _tls_flavor: TLS certificates ```````````````` -Set the ``TLS_FLAVOR`` to one of the following +Sets the ``TLS_FLAVOR`` to one of the following values: - ``cert`` is the default and requires certificates to be setup manually; @@ -59,7 +47,7 @@ values: Bind address ```````````` -Modify ``BIND_ADDRESS4`` and ``BIND_ADDRESS6`` to match the public IP addresses assigned to your server. For IPv6 you will need the ```` scope address. +The bind addresses need to match the public IP addresses assigned to your server. For IPv6 you will need the ```` scope address. You can find those addresses by running the following: @@ -81,56 +69,17 @@ you would simply like the server to listen on all interfaces, use ``0.0.0.0`` an .. _issues: https://github.com/Mailu/Mailu/issues/641 -Enable optional features ------------------------- +Review configuration variables +------------------------------ -Some of Mailu features are not used by every user and are thus not enabled in a -default configuration. - -A Webmail is a Web interface exposing an email client. Mailu webmails are -bound to the internal IMAP and SMTP server for users to access their mailbox through -the Web. By exposing a complex application such as a Webmail, you should be aware of -the security implications caused by such an increase of attack surface. The ``WEBMAIL`` -configuration option must be one of the following: - -- ``none`` is the default value, no Webmail service will be exposed; -- ``roundcube`` will run the popular Roundcube Webmail; -- ``rainloop`` will run the popular Rainloop Webmail. - -The administration interface is not exposed on the public address by default, -you will need to set the ``ADMIN`` variable accordingly: - -- ``true`` will expose the admin interface in ``/admin``; -- ``false`` (or any other value) will disable this behaviour. - -A Webdav server exposes a Dav interface over HTTP so that clients can store -contacts or calendars using the mail account. This can be enabled using the `WEBDAV` -setting. The configuration option must be one of the following: - -- ``none`` is the default value, no webdav service will be exposed; -- ``radicale`` exposes the radicale Webdav service. - -An antivirus server helps fighting large scale virus spreading campaigns -that leverage e-mail for initial infection. This can be setup using the ``ANTIVIRUS`` -setting. The configuration option must be one of the following: - -- ``none`` disables antivirus checks; -- ``clamav`` is the default values, the popular ClamAV antivirus is enabled. - -Make sure that you have at least 1GB of memory for ClamAV to load its signature -database. - -If you run Mailu behind a reverse proxy you can use ``REAL_IP_HEADER`` and -``REAL_IP_FROM`` to set the values of respective the Nginx directives -``real_ip_header`` and ``set_real_ip_from``. The ``REAL_IP_FROM`` configuration -option is a comma-separated list of IPs (or CIDRs) of which for each a -``set_real_ip_from`` directive is added in the Nginx configuration file. +After downloading the files, open ``mailu.env`` and review the variable settings. +Make sure to read the comments in the file and instructions from the :ref:`common_cfg` page. Finish setting up TLS --------------------- Mailu relies heavily on TLS and must have a key pair and a certificate -available, at least for the hostname configured in the ``.env`` file. +available, at least for the hostname configured in the ``mailu.env`` file. If you set ``TLS_FLAVOR`` to ``cert`` or ``mail`` then you must create a ``certs`` directory in your root path and setup a key-certificate pair there: @@ -155,4 +104,4 @@ Finally, you must create the initial admin user account: This will create a user named ``me@example.net`` with password ``password`` and administration privileges. Connect to the Web admin interface and change the password to a strong one. - .. note:: It is vitally important that either a user with the same email as ``POSTMASTER`` in your ``.env`` exists, or you remember to create an alias with this name after you log in. All kinds of strange errors will occur as a result of not doing so! + .. note:: It is vitally important that either a user with the same email as ``POSTMASTER`` in your ``mailu.env`` exists, or you remember to create an alias with this name after you log in. All kinds of strange errors will occur as a result of not doing so! diff --git a/docs/configuration.rst b/docs/configuration.rst index ec114c97..0bea04b9 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -1,5 +1,9 @@ -Mailu configuration settings -============================ +Configuration reference +======================= + +This page explains the variables found in ``mailu.env``. +In most cases ``mailu.env`` is setup correctly by the setup utility and can be left as-is. +However, some advanced settings or modifications can be done by modifying this file. .. _common_cfg: @@ -37,6 +41,9 @@ The ``AUTH_RATELIMIT`` holds a security setting for fighting attackers that try to guess user passwords. The value is the limit of requests that a single IP address can perform against IMAP, POP and SMTP authentication endpoints. +The ``TLS_FLAVOR`` sets how Mailu handles TLS connections. Setting this value to +``notl`` will cause Mailu not to server any web content! More on :ref:`tls_flavor`. + Mail settings ------------- diff --git a/docs/index.rst b/docs/index.rst index 98825ab6..0808010c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -53,10 +53,10 @@ the version of Mailu that you are running. :caption: Setup setup - configuration compose/requirements compose/setup kubernetes/mailu/index + configuration dns reverse database diff --git a/setup/templates/steps/compose/02_services.html b/setup/templates/steps/compose/02_services.html index 11e7a14e..a78a3f62 100644 --- a/setup/templates/steps/compose/02_services.html +++ b/setup/templates/steps/compose/02_services.html @@ -1,13 +1,13 @@ {% call macros.panel("info", "Step 3 - pick some features") %}

Mailu comes with multiple base features, including a specific admin -interface, Web email clients (webmails), antispam, antivirus, etc. If you -wish to disable some of these features, you are free to do so.

- -

Emails will be available through IMAP and POP3. You may also enable a Web -email client. These do add some complexity but provide an easier way of -accessing messages for beginner users.

+interface, Web email clients, antispam, antivirus, etc. +In this section you can enable the services to you liking.

+

A Webmail is a Web interface exposing an email client. Mailu webmails are +bound to the internal IMAP and SMTP server for users to access their mailbox through +the Web. By exposing a complex application such as a Webmail, you should be aware of +the security implications caused by such an increase of attack surface.

@@ -26,10 +26,9 @@ accessing messages for beginner users.

-

Email filtering is a really important features. You can still disable it, which -will prevent Mailu from doing spam filtering, virus filtering, and from applying -white and blacklists that you may configure in the admin interface. You may -also disable the antivirus if required (it does use aroung 1GB of ram).

+

An antivirus server helps fighting large scale virus spreading campaigns that leverage +e-mail for initial infection. Make sure that you have at least 1GB of memory for ClamAV to +load its signature database.

+

A Webdav server exposes a Dav interface over HTTP so that clients can store +contacts or calendars using the mail account.

+
+

Fetchmail allows to download mails over IMAP/POP3 and uploads it your Mailu mailbox.

+
-

Email filtering is a really important features. You can still disable it, which -will prevent Mailu from doing spam filtering, virus filtering, and from applying -white and blacklists that you may configure in the admin interface. You may -also disable the antivirus if required (it does use aroung 1GB of ram).

+

An antivirus server helps fighting large scale virus spreading campaigns that leverage +e-mail for initial infection. Make sure that you have at least 1GB of memory for ClamAV to +load its signature database.

+

A Webdav server exposes a Dav interface over HTTP so that clients can store +contacts or calendars using the mail account.

+
+

Fetchmail allows to download mails over IMAP/POP3 and uploads it your Mailu mailbox.

+

The admin interface is the main Mailu-specific bit, it provides tools to From d9f8510bb6f204bbe58a9241aa6405c4e0c1183e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Thu, 17 Jan 2019 15:17:21 +0200 Subject: [PATCH 09/13] Fix notls typo --- docs/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index 0bea04b9..e7dfa2af 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -42,7 +42,7 @@ try to guess user passwords. The value is the limit of requests that a single IP address can perform against IMAP, POP and SMTP authentication endpoints. The ``TLS_FLAVOR`` sets how Mailu handles TLS connections. Setting this value to -``notl`` will cause Mailu not to server any web content! More on :ref:`tls_flavor`. +``notls`` will cause Mailu not to server any web content! More on :ref:`tls_flavor`. Mail settings ------------- From 3ae1c75c551ba922de5df7503ed4d06867c934fc Mon Sep 17 00:00:00 2001 From: Ionut Filip Date: Thu, 17 Jan 2019 16:24:52 +0200 Subject: [PATCH 10/13] Added IPv6 as optional --- setup/flavors/compose/docker-compose.yml | 8 ++++++- setup/flavors/compose/mailu.env | 3 +++ setup/server.py | 15 ++++++++++++- setup/static/render.js | 13 ++++++++++++ setup/templates/steps/compose/03_expose.html | 22 +++++++++++++------- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 67408bee..a1d985e4 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -3,7 +3,7 @@ # Please read the documentation before attempting any change. # Generated for {{ flavor }} flavor -version: '3.6' +version: '2.2' services: @@ -160,8 +160,14 @@ services: networks: default: + {% if ipv6_enabled %} + enable_ipv6: true + {% endif %} driver: bridge ipam: driver: default config: - subnet: {{ subnet }} + {% if ipv6_enabled %} + - subnet: {{ subnet6 }} + {% endif %} diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index 7d160011..341b7634 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -27,6 +27,9 @@ SECRET_KEY={{ secret(16) }} # Subnet of the docker network. This should not conflict with any networks to which your system is connected. (Internal and external!) SUBNET={{ subnet }} +{% if ipv6_enabled %} +SUBNET6={{ subnet6 }} +{% endif %} # Main mail domain DOMAIN={{ domain }} diff --git a/setup/server.py b/setup/server.py index 556d4b3a..4dfd49ae 100644 --- a/setup/server.py +++ b/setup/server.py @@ -9,6 +9,7 @@ import string import random import ipaddress import hashlib +import time version = os.getenv("this_version", "master") @@ -33,6 +34,17 @@ def secret(length=16): for _ in range(length) ) +#Original copied from https://github.com/andrewlkho/ulagen +def random_ipv6_subnet(): + eui64 = uuid.getnode() >> 24 << 48 | 0xfffe000000 | uuid.getnode() & 0xffffff + eui64_canon = "-".join([format(eui64, "02X")[i:i+2] for i in range(0, 18, 2)]) + + h = hashlib.sha1() + h.update((eui64_canon + str(time.time() - time.mktime((1900, 1, 1, 0, 0, 0, 0, 1, -1)))).encode('utf-8')) + globalid = h.hexdigest()[0:10] + + prefix = ":".join(("fd" + globalid[0:2], globalid[2:6], globalid[6:10])) + return prefix def build_app(path): @@ -69,8 +81,9 @@ def build_app(path): @root_bp.route("/submit_flavor", methods=["POST"]) def submit_flavor(): data = flask.request.form.copy() + subnet6 = random_ipv6_subnet() steps = sorted(os.listdir(os.path.join(path, "templates", "steps", data["flavor"]))) - return flask.render_template('wizard.html', flavor=data["flavor"], steps=steps) + return flask.render_template('wizard.html', flavor=data["flavor"], steps=steps, subnet6=subnet6) @prefix_bp.route("/submit", methods=["POST"]) @root_bp.route("/submit", methods=["POST"]) diff --git a/setup/static/render.js b/setup/static/render.js index 23afcbec..e501fffb 100644 --- a/setup/static/render.js +++ b/setup/static/render.js @@ -86,3 +86,16 @@ $(document).ready(function() { } }); }); + +$(document).ready(function() { + if ($('#enable_ipv6').prop('checked')) { + $("#ipv6").show(); + } + $("#enable_ipv6").change(function() { + if ($(this).is(":checked")) { + $("#ipv6").show(); + } else { + $("#ipv6").hide(); + } + }); +}); diff --git a/setup/templates/steps/compose/03_expose.html b/setup/templates/steps/compose/03_expose.html index 837b7bba..d54985d4 100644 --- a/setup/templates/steps/compose/03_expose.html +++ b/setup/templates/steps/compose/03_expose.html @@ -18,13 +18,27 @@ avoid generic all-interfaces addresses like 0.0.0.0 or :: + + -

+
+ +
+ +

The unbound resolver enables Mailu to do DNSsec verification, DNS root lookups and caching. This also helps the antispam service not to get blocked by the public or ISP DNS servers.

@@ -34,12 +48,6 @@ 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 hostnames. Every e-mail domain that points to this server must have one of the From 7a9685bcb93a8a2e5ebd1b8598952be9534a62d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Thu, 17 Jan 2019 16:32:47 +0200 Subject: [PATCH 11/13] Resolve admin during start to work around Docker DNS flaky-ness --- core/dovecot/start.py | 8 +++++--- core/postfix/start.py | 14 ++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/core/dovecot/start.py b/core/dovecot/start.py index 15e370de..bae92260 100755 --- a/core/dovecot/start.py +++ b/core/dovecot/start.py @@ -16,10 +16,11 @@ log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING")) def start_podop(): os.setuid(8) + url = "http://" + os.environ["ADMIN_ADDRESS"] + "/internal/dovecot/§" run_server(0, "dovecot", "/tmp/podop.socket", [ - ("quota", "url", "http://admin/internal/dovecot/§"), - ("auth", "url", "http://admin/internal/dovecot/§"), - ("sieve", "url", "http://admin/internal/dovecot/§"), + ("quota", "url", url ), + ("auth", "url", url), + ("sieve", "url", url), ]) def convert(src, dst): @@ -42,6 +43,7 @@ def resolve(hostname): # Actual startup script os.environ["FRONT_ADDRESS"] = resolve(os.environ.get("FRONT_ADDRESS", "front")) os.environ["REDIS_ADDRESS"] = resolve(os.environ.get("REDIS_ADDRESS", "redis")) +os.environ["ADMIN_ADDRESS"] = resolve(os.environ.get("ADMIN_ADDRESS", "admin")) if os.environ["WEBMAIL"] != "none": os.environ["WEBMAIL_ADDRESS"] = resolve(os.environ.get("WEBMAIL_ADDRESS", "webmail")) diff --git a/core/postfix/start.py b/core/postfix/start.py index a06b3833..e3b3eb40 100755 --- a/core/postfix/start.py +++ b/core/postfix/start.py @@ -17,14 +17,15 @@ log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING")) def start_podop(): os.setuid(100) + url = "http://" + os.environ["ADMIN_ADDRESS"] + "/internal/postfix/" # TODO: Remove verbosity setting from Podop? run_server(0, "postfix", "/tmp/podop.socket", [ - ("transport", "url", "http://admin/internal/postfix/transport/§"), - ("alias", "url", "http://admin/internal/postfix/alias/§"), - ("domain", "url", "http://admin/internal/postfix/domain/§"), - ("mailbox", "url", "http://admin/internal/postfix/mailbox/§"), - ("senderaccess", "url", "http://admin/internal/postfix/sender/access/§"), - ("senderlogin", "url", "http://admin/internal/postfix/sender/login/§") + ("transport", "url", url + "transport/§"), + ("alias", "url", url + "alias/§"), + ("domain", "url", url + "domain/§"), + ("mailbox", "url", url + "mailbox/§"), + ("senderaccess", "url", url + "sender/access/§"), + ("senderlogin", "url", url + "sender/login/§") ]) def convert(src, dst): @@ -46,6 +47,7 @@ def resolve(hostname): # Actual startup script os.environ["FRONT_ADDRESS"] = resolve(os.environ.get("FRONT_ADDRESS", "front")) +os.environ["ADMIN_ADDRESS"] = resolve(os.environ.get("ADMIN_ADDRESS", "admin")) os.environ["HOST_ANTISPAM"] = os.environ.get("HOST_ANTISPAM", "antispam:11332") os.environ["HOST_LMTP"] = os.environ.get("HOST_LMTP", "imap:2525") From 34608727471a24946378a48856118c8567fee45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Thu, 17 Jan 2019 17:56:00 +0200 Subject: [PATCH 12/13] Documentation on IPv6 --- CHANGELOG.md | 1 + docs/faq.rst | 43 ++++++++++++++++++++ setup/templates/steps/compose/03_expose.html | 3 +- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23cbebb0..cf73a463 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,7 @@ v1.6.0 - unreleased - Enhancement: Include favicon package ([#801](https://github.com/Mailu/Mailu/issues/801), ([#802](https://github.com/Mailu/Mailu/issues/802)) - Enhancement: Add logging at critical places in python start.py scripts. Implement LOG_LEVEL to control verbosity ([#588](https://github.com/Mailu/Mailu/issues/588)) - Enhancement: Mark message as seen when reporting as spam +- Enhancement: Better support and document IPv6 ([#827](https://github.com/Mailu/Mailu/issues/827)) - Upstream: Update Roundcube - Upstream: Update Rainloop - Bug: Rainloop fails with "domain not allowed" ([#93](https://github.com/Mailu/Mailu/issues/93)) diff --git a/docs/faq.rst b/docs/faq.rst index 2669d9d1..45f5534b 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -134,6 +134,49 @@ You're mail service will be reachable for IMAP, POP3, SMTP and Webmail at the ad *Issue reference:* `742`_, `747`_. +How to make IPv6 work? +`````````````````````` + +Docker currently does not expose the IPv6 ports properly, as it does not interface with ``ip6tables``. +Lets start with quoting everything that's wrong: + + Unfortunately, initially Docker was not created with IPv6 in mind. + It was added later and, while it has come a long way, is still not as usable as one would want. + Much discussion is still going on as to how IPv6 should be used in a containerized world; + See the various GitHub issues linked below: + + - Giving each container a publicly routable address means all ports (even unexposed / unpublished ports) are suddenly + reachable by everyone, if no additional filtering is done + (`docker/docker#21614 `_) + - By default, each container gets a random IPv6, making it impossible to do properly do DNS; + the alternative is to assign a specific IPv6 address to each container, + still an administrative hassle (`docker/docker#13481 `_) + - Published ports won't work on IPv6, unless you have the userland proxy enabled + (which, for now, is enabled by default in Docker) + - The userland proxy, however, seems to be on its way out + (`docker/docker#14856 `_) and has various issues, like: + + - It can use a lot of RAM (`docker/docker#11185 `_) + - Source IP addresses are rewritten, making it completely unusable for many purposes, e.g. mail servers + (`docker/docker#17666 `_), + (`docker/libnetwork#1099 `_). + + -- `Robbert Klarenbeek `_ (docker-ipv6nat author) + +So, how to make it work? Well, by using `docker-ipv6nat`_! This nifty container will set up ``ip6tables``, +just as Docker would do for IPv4. We know that nat-ing is not advised in IPv6, +however exposing all containers to public network neither. The choice is ultimately yous. + +Mailu `setup utility`_ generates a safe IPv6 ULA subnet by default. So when you run the following command, +Mailu will start to function on IPv6: + +.. code-block:: bash + + docker run -d --restart=always -v /var/run/docker.sock:/var/run/docker.sock:ro --privileged --net=host robbertkl/ipv6nat + +.. _`docker-ipv6nat`: https://github.com/robbertkl/docker-ipv6nat +.. _`setup utility`: https://setup.mailu.io + How does Mailu scale up? ```````````````````````` diff --git a/setup/templates/steps/compose/03_expose.html b/setup/templates/steps/compose/03_expose.html index d54985d4..c909fc9b 100644 --- a/setup/templates/steps/compose/03_expose.html +++ b/setup/templates/steps/compose/03_expose.html @@ -31,8 +31,7 @@ avoid generic all-interfaces addresses like 0.0.0.0 or ::