Merge branch 'feat-setup-ipv6' of github.com:usrpro/Mailu into feat-setup-ipv6

master
Ionut Filip 6 years ago
commit bdb0821e6e

@ -29,7 +29,6 @@ v1.6.0 - unreleased
- Feature: Automated Releases ([#487](https://github.com/Mailu/Mailu/issues/487)) - Feature: Automated Releases ([#487](https://github.com/Mailu/Mailu/issues/487))
- Feature: Support for ARC ([#495](https://github.com/Mailu/Mailu/issues/495)) - Feature: Support for ARC ([#495](https://github.com/Mailu/Mailu/issues/495))
- Feature: Add posibilty to run webmail on root ([#501](https://github.com/Mailu/Mailu/issues/501)) - Feature: Add posibilty to run webmail on root ([#501](https://github.com/Mailu/Mailu/issues/501))
- Feature: Upgrade docker-compose.yml to version 3 ([#539](https://github.com/Mailu/Mailu/issues/539))
- Feature: Documentation to deploy mailu on a docker swarm ([#551](https://github.com/Mailu/Mailu/issues/551)) - Feature: Documentation to deploy mailu on a docker swarm ([#551](https://github.com/Mailu/Mailu/issues/551))
- Feature: Add optional Maildir-Compression ([#553](https://github.com/Mailu/Mailu/issues/553)) - Feature: Add optional Maildir-Compression ([#553](https://github.com/Mailu/Mailu/issues/553))
- Feature: Preserve rspamd history on container restart ([#561](https://github.com/Mailu/Mailu/issues/561)) - Feature: Preserve rspamd history on container restart ([#561](https://github.com/Mailu/Mailu/issues/561))
@ -80,6 +79,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: 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: 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: 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 Roundcube
- Upstream: Update Rainloop - Upstream: Update Rainloop
- Bug: Rainloop fails with "domain not allowed" ([#93](https://github.com/Mailu/Mailu/issues/93)) - Bug: Rainloop fails with "domain not allowed" ([#93](https://github.com/Mailu/Mailu/issues/93))
@ -116,6 +116,8 @@ v1.6.0 - unreleased
- Bug: Don't recursivly chown on mailboxes ([#776](https://github.com/Mailu/Mailu/issues/776)) - 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: 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: 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))
- Bug: DOMAIN_REGISTRATION=False in .env was not treated correctly ([#830](https://github.com/Mailu/Mailu/issues/830))
v1.5.1 - 2017-11-21 v1.5.1 - 2017-11-21
------------------- -------------------

@ -30,11 +30,11 @@ DEFAULT_CONFIG = {
'POSTMASTER': 'postmaster', 'POSTMASTER': 'postmaster',
'TLS_FLAVOR': 'cert', 'TLS_FLAVOR': 'cert',
'AUTH_RATELIMIT': '10/minute;1000/hour', 'AUTH_RATELIMIT': '10/minute;1000/hour',
'DISABLE_STATISTICS': 'False', 'DISABLE_STATISTICS': False,
# Mail settings # Mail settings
'DMARC_RUA': None, 'DMARC_RUA': None,
'DMARC_RUF': None, 'DMARC_RUF': None,
'WELCOME': 'False', 'WELCOME': False,
'WELCOME_SUBJECT': 'Dummy welcome topic', 'WELCOME_SUBJECT': 'Dummy welcome topic',
'WELCOME_BODY': 'Dummy welcome body', 'WELCOME_BODY': 'Dummy welcome body',
'DKIM_SELECTOR': 'dkim', 'DKIM_SELECTOR': 'dkim',
@ -74,13 +74,21 @@ class ConfigManager(dict):
def __init__(self): def __init__(self):
self.config = dict() 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): def init_app(self, app):
self.config.update(app.config) self.config.update(app.config)
# get environment variables # get environment variables
self.config.update({ 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() for key, value in DEFAULT_CONFIG.items()
}) })
# automatically set the sqlalchemy string # automatically set the sqlalchemy string
if self.config['DB_FLAVOR']: if self.config['DB_FLAVOR']:
template = self.DB_TEMPLATES[self.config['DB_FLAVOR']] template = self.DB_TEMPLATES[self.config['DB_FLAVOR']]

@ -31,7 +31,7 @@ def advertise():
instance_id = str(uuid.uuid4()) instance_id = str(uuid.uuid4())
with open(app.config["INSTANCE_ID_PATH"], "w") as handle: with open(app.config["INSTANCE_ID_PATH"], "w") as handle:
handle.write(instance_id) handle.write(instance_id)
if app.config["DISABLE_STATISTICS"].lower() != "true": if not app.config["DISABLE_STATISTICS"]:
try: try:
socket.gethostbyname(app.config["STATS_ENDPOINT"].format(instance_id)) socket.gethostbyname(app.config["STATS_ENDPOINT"].format(instance_id))
except: except:

@ -101,8 +101,8 @@ class Base(db.Model):
} }
) )
created_at = db.Column(db.Date, nullable=False, default=datetime.now) created_at = db.Column(db.Date, nullable=False, default=date.today)
updated_at = db.Column(db.Date, nullable=True, onupdate=datetime.now) updated_at = db.Column(db.Date, nullable=True, onupdate=date.today)
comment = db.Column(db.String(255), nullable=True) comment = db.Column(db.String(255), nullable=True)
@ -131,7 +131,7 @@ class Domain(Base):
backref=db.backref('manager_of'), lazy='dynamic') backref=db.backref('manager_of'), lazy='dynamic')
max_users = db.Column(db.Integer, nullable=False, default=-1) max_users = db.Column(db.Integer, nullable=False, default=-1)
max_aliases = db.Column(db.Integer, nullable=False, default=-1) max_aliases = db.Column(db.Integer, nullable=False, default=-1)
max_quota_bytes = db.Column(db.Integer(), nullable=False, default=0) max_quota_bytes = db.Column(db.BigInteger(), nullable=False, default=0)
signup_enabled = db.Column(db.Boolean(), nullable=False, default=False) signup_enabled = db.Column(db.Boolean(), nullable=False, default=False)
@property @property
@ -307,8 +307,8 @@ class User(Base, Email):
domain = db.relationship(Domain, domain = db.relationship(Domain,
backref=db.backref('users', cascade='all, delete-orphan')) backref=db.backref('users', cascade='all, delete-orphan'))
password = db.Column(db.String(255), nullable=False) password = db.Column(db.String(255), nullable=False)
quota_bytes = db.Column(db.Integer(), nullable=False, default=10**9) quota_bytes = db.Column(db.BigInteger(), nullable=False, default=10**9)
quota_bytes_used = db.Column(db.Integer(), nullable=False, default=0) quota_bytes_used = db.Column(db.BigInteger(), nullable=False, default=0)
global_admin = db.Column(db.Boolean(), nullable=False, default=False) global_admin = db.Column(db.Boolean(), nullable=False, default=False)
enabled = db.Column(db.Boolean(), nullable=False, default=True) enabled = db.Column(db.Boolean(), nullable=False, default=True)
@ -410,7 +410,7 @@ class User(Base, Email):
return emails return emails
def send_welcome(self): def send_welcome(self):
if app.config["WELCOME"].lower() == "true": if app.config["WELCOME"]:
self.sendmail(app.config["WELCOME_SUBJECT"], self.sendmail(app.config["WELCOME_SUBJECT"],
app.config["WELCOME_BODY"]) app.config["WELCOME_BODY"])

@ -37,7 +37,7 @@ class MultipleEmailAddressesVerify(object):
self.message = message self.message = message
def __call__(self, form, field): 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(" ", "")): if not pattern.match(field.data.replace(" ", "")):
raise validators.ValidationError(self.message) raise validators.ValidationError(self.message)

@ -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')

@ -16,10 +16,11 @@ log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING"))
def start_podop(): def start_podop():
os.setuid(8) os.setuid(8)
url = "http://" + os.environ["ADMIN_ADDRESS"] + "/internal/dovecot/§"
run_server(0, "dovecot", "/tmp/podop.socket", [ run_server(0, "dovecot", "/tmp/podop.socket", [
("quota", "url", "http://admin/internal/dovecot/§"), ("quota", "url", url ),
("auth", "url", "http://admin/internal/dovecot/§"), ("auth", "url", url),
("sieve", "url", "http://admin/internal/dovecot/§"), ("sieve", "url", url),
]) ])
def convert(src, dst): def convert(src, dst):
@ -42,6 +43,7 @@ def resolve(hostname):
# Actual startup script # Actual startup script
os.environ["FRONT_ADDRESS"] = resolve(os.environ.get("FRONT_ADDRESS", "front")) os.environ["FRONT_ADDRESS"] = resolve(os.environ.get("FRONT_ADDRESS", "front"))
os.environ["REDIS_ADDRESS"] = resolve(os.environ.get("REDIS_ADDRESS", "redis")) 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": if os.environ["WEBMAIL"] != "none":
os.environ["WEBMAIL_ADDRESS"] = resolve(os.environ.get("WEBMAIL_ADDRESS", "webmail")) os.environ["WEBMAIL_ADDRESS"] = resolve(os.environ.get("WEBMAIL_ADDRESS", "webmail"))

@ -17,14 +17,15 @@ log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING"))
def start_podop(): def start_podop():
os.setuid(100) os.setuid(100)
url = "http://" + os.environ["ADMIN_ADDRESS"] + "/internal/postfix/"
# TODO: Remove verbosity setting from Podop? # TODO: Remove verbosity setting from Podop?
run_server(0, "postfix", "/tmp/podop.socket", [ run_server(0, "postfix", "/tmp/podop.socket", [
("transport", "url", "http://admin/internal/postfix/transport/§"), ("transport", "url", url + "transport/§"),
("alias", "url", "http://admin/internal/postfix/alias/§"), ("alias", "url", url + "alias/§"),
("domain", "url", "http://admin/internal/postfix/domain/§"), ("domain", "url", url + "domain/§"),
("mailbox", "url", "http://admin/internal/postfix/mailbox/§"), ("mailbox", "url", url + "mailbox/§"),
("senderaccess", "url", "http://admin/internal/postfix/sender/access/§"), ("senderaccess", "url", url + "sender/access/§"),
("senderlogin", "url", "http://admin/internal/postfix/sender/login/§") ("senderlogin", "url", url + "sender/login/§")
]) ])
def convert(src, dst): def convert(src, dst):
@ -46,6 +47,7 @@ def resolve(hostname):
# Actual startup script # Actual startup script
os.environ["FRONT_ADDRESS"] = resolve(os.environ.get("FRONT_ADDRESS", "front")) 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_ANTISPAM"] = os.environ.get("HOST_ANTISPAM", "antispam:11332")
os.environ["HOST_LMTP"] = os.environ.get("HOST_LMTP", "imap:2525") os.environ["HOST_LMTP"] = os.environ.get("HOST_LMTP", "imap:2525")

@ -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 # Mailu main configuration file
## Most configuration variables can be modified through the Web interface, ## Most configuration variables can be modified through the Web interface,
# these few settings must however be configured before starting the mail # these few settings must however be configured before starting the mail

@ -1,3 +1,5 @@
# WARNING: this file is being deprecated over the new setup utility, found at https://setup.mailu.io
version: '2' version: '2'
services: services:

@ -12,34 +12,22 @@ Mailu will store all of its persistent data in a path of your choice
mkdir /mailu mkdir /mailu
cd /mailu cd /mailu
Download the initial configuration file Create the configuration files
--------------------------------------- ------------------------------
Docker Compose configuration is stored in a file named Docker Compose configuration is stored in a file named ``docker-compose.yml``.
:download:`docker-compose.yml`. Additionally, Mailu Additionally, Mailu relies on a ``mailu.env`` file for various settings.
relies on a :download:`.env` file for various settings. Download Both files can be generated by the `mailu setup utility`_. The setup utility
the proper template files from the git repository. To download the configuration is mostly self-explanatory, with some more additional information in this section.
for the ``VERSION_TAG`` branch, use:
.. code-block:: bash .. _`mailu setup utility`: https://setup.mailu.io
wget https://mailu.io/VERSION_TAG/_downloads/docker-compose.yml .. _tls_flavor:
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 certificates TLS certificates
```````````````` ````````````````
Set the ``TLS_FLAVOR`` to one of the following Sets the ``TLS_FLAVOR`` to one of the following
values: values:
- ``cert`` is the default and requires certificates to be setup manually; - ``cert`` is the default and requires certificates to be setup manually;
@ -59,7 +47,7 @@ values:
Bind address Bind address
```````````` ````````````
Modify ``BIND_ADDRESS4`` and ``BIND_ADDRESS6`` to match the public IP addresses assigned to your server. For IPv6 you will need the ``<global>`` scope address. The bind addresses need to match the public IP addresses assigned to your server. For IPv6 you will need the ``<global>`` scope address.
You can find those addresses by running the following: 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 .. _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 After downloading the files, open ``mailu.env`` and review the variable settings.
default configuration. Make sure to read the comments in the file and instructions from the :ref:`common_cfg` page.
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.
Finish setting up TLS Finish setting up TLS
--------------------- ---------------------
Mailu relies heavily on TLS and must have a key pair and a certificate 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 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: 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. 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!

@ -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: .. _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 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. IP address can perform against IMAP, POP and SMTP authentication endpoints.
The ``TLS_FLAVOR`` sets how Mailu handles TLS connections. Setting this value to
``notls`` will cause Mailu not to server any web content! More on :ref:`tls_flavor`.
Mail settings Mail settings
------------- -------------

@ -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' version: '3'
services: services:
docs_master: docs:
image: mailu/docs:master image: ${DOCKER_ORG:-mailu}/docs:${MAILU_VERSION:-master}
networks: ports:
- web - 127.0.0.1:8000:80
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

@ -134,6 +134,49 @@ You're mail service will be reachable for IMAP, POP3, SMTP and Webmail at the ad
*Issue reference:* `742`_, `747`_. *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 <https://github.com/docker/docker/issues/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 <https://github.com/docker/docker/issues/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 <https://github.com/docker/docker/issues/14856>`_) and has various issues, like:
- It can use a lot of RAM (`docker/docker#11185 <https://github.com/docker/docker/issues/11185>`_)
- Source IP addresses are rewritten, making it completely unusable for many purposes, e.g. mail servers
(`docker/docker#17666 <https://github.com/docker/docker/issues/17666>`_),
(`docker/libnetwork#1099 <https://github.com/docker/libnetwork/issues/1099>`_).
-- `Robbert Klarenbeek <https://github.com/robbertkl>`_ (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? How does Mailu scale up?
```````````````````````` ````````````````````````

@ -53,10 +53,10 @@ the version of Mailu that you are running.
:caption: Setup :caption: Setup
setup setup
configuration
compose/requirements compose/requirements
compose/setup compose/setup
kubernetes/mailu/index kubernetes/mailu/index
configuration
dns dns
reverse reverse
database database

@ -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' version: '3.6'
services: services:
redis: redis:
image: redis:alpine image: redis:alpine
networks:
- default
setup_master: setup:
image: mailu/setup:master image: ${DOCKER_ORG:-mailu}/setup:${MAILU_VERSION:-master}
networks:
- web
- default
env_file: .env 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: depends_on:
- redis - redis
ports:
setup_release: - 127.0.0.1:8001:80
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

@ -12,7 +12,7 @@ import hashlib
import time import time
version = os.getenv("this_version") version = os.getenv("this_version", "master")
static_url_path = "/" + version + "/static" static_url_path = "/" + version + "/static"
app = flask.Flask(__name__, static_url_path=static_url_path) app = flask.Flask(__name__, static_url_path=static_url_path)
flask_bootstrap.Bootstrap(app) flask_bootstrap.Bootstrap(app)

@ -1,13 +1,13 @@
{% call macros.panel("info", "Step 3 - pick some features") %} {% call macros.panel("info", "Step 3 - pick some features") %}
<p>Mailu comes with multiple base features, including a specific admin <p>Mailu comes with multiple base features, including a specific admin
interface, Web email clients (webmails), antispam, antivirus, etc. If you interface, Web email clients, antispam, antivirus, etc.
wish to disable some of these features, you are free to do so.</p> In this section you can enable the services to you liking.</p>
<p>Emails will be available through IMAP and POP3. You may also enable a Web
email client. These do add some complexity but provide an easier way of
accessing messages for beginner users.</p>
<!-- Switched from radio buttons to dropdown menu in order to remove the checkbox --> <!-- Switched from radio buttons to dropdown menu in order to remove the checkbox -->
<p>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.<p>
<div class="form-group"> <div class="form-group">
<label>Enable Web email client (and path to the Web email client)</label> <label>Enable Web email client (and path to the Web email client)</label>
<!-- <div class="radio"> --> <!-- <div class="radio"> -->
@ -26,10 +26,9 @@ accessing messages for beginner users.</p>
</div> </div>
</div> </div>
<p>Email filtering is a really important features. You can still disable it, which <p>An antivirus server helps fighting large scale virus spreading campaigns that leverage
will prevent Mailu from doing spam filtering, virus filtering, and from applying e-mail for initial infection. Make sure that you have at least 1GB of memory for ClamAV to
white and blacklists that you may configure in the admin interface. You may load its signature database.</p>
also disable the antivirus if required (it does use aroung 1GB of ram).</p>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<label class="form-check-label"> <label class="form-check-label">
@ -38,6 +37,9 @@ also disable the antivirus if required (it does use aroung 1GB of ram).</p>
</label> </label>
</div> </div>
<p>A Webdav server exposes a Dav interface over HTTP so that clients can store
contacts or calendars using the mail account.</p>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<label class="form-check-label"> <label class="form-check-label">
<input class="form-check-input" type="checkbox" name="webdav_enabled" value="radicale"> <input class="form-check-input" type="checkbox" name="webdav_enabled" value="radicale">
@ -45,6 +47,8 @@ also disable the antivirus if required (it does use aroung 1GB of ram).</p>
</label> </label>
</div> </div>
<p>Fetchmail allows to download mails over IMAP/POP3 and uploads it your Mailu mailbox.</p>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<label class="form-check-label"> <label class="form-check-label">
<input class="form-check-input" type="checkbox" name="fetchmail_enabled" value="true"> <input class="form-check-input" type="checkbox" name="fetchmail_enabled" value="true">

@ -10,7 +10,8 @@ IP addresses in order to expose its public services. You must at least setup
an IPv4 or an IPv6 address if you wish to access Mailu.</p> an IPv4 or an IPv6 address if you wish to access Mailu.</p>
<p><span class="label label-warning">Warning</span> You must use specific addresses, please <p><span class="label label-warning">Warning</span> You must use specific addresses, please
avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</code>.</p> avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</code>.
<a href="https://mailu.io/{{ version }}/compose/setup.html#bind-address">How to find these addresses.</a></p>
<div class="form-group"> <div class="form-group">
<label>IPv4 listen address</label> <label>IPv4 listen address</label>
@ -30,8 +31,7 @@ avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</co
</div> </div>
<div class="form-group" id="ipv6" style="display: none"> <div class="form-group" id="ipv6" style="display: none">
<p><span class="label label-warning">Warning</span> You must use specific addresses, please <p><span class="label label-danger">Read this:</span> Docker currently does not expose the IPv6 ports properly, as it does not interface with <code>ip6tables</code>. Be sure to read our <a href="https://mailu.io/{{ version }}/faq.html#how-to-make-ipv6-work">FAQ section</a>!</p>
avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</code>.</p>
<label>IPv6 listen address</label> <label>IPv6 listen address</label>
<!-- Validates IPv6 address --> <!-- Validates IPv6 address -->
<input class="form-control" type="text" name="bind6" value="::1" <input class="form-control" type="text" name="bind6" value="::1"
@ -40,6 +40,7 @@ avoid generic all-interfaces addresses like <code>0.0.0.0</code> or <code>::</co
<input class="form-control" type="text" name="subnet6" required value="{{ subnet6 }}:beef::/64"> <input class="form-control" type="text" name="subnet6" required value="{{ subnet6 }}:beef::/64">
</div> </div>
<p>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.</p>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<label class="form-check-label"> <label class="form-check-label">
<input class="form-check-input" type="checkbox" name="resolver_enabled" value="true"> <input class="form-check-input" type="checkbox" name="resolver_enabled" value="true">

@ -1,8 +1,17 @@
{% if flavor == "stack" %}
{% call macros.panel("danger", "Docker stack / swarm is experimental") %}
Setup is capable of generating a somewhat decent docker-compose.yml,
for the docker stack flavor. However its usage is for advanced users an is experimental.
Expect many challenges is shared mail storage and fail-over scenarios! Some user experiences
have been <a href="https://github.com/Mailu/Mailu/blob/master/docs/swarm/master/README.md">shared on GitHub.</a>
{% endcall %}
{% endif %}
{% call macros.panel("info", "Step 2 - Initial configuration") %} {% call macros.panel("info", "Step 2 - Initial configuration") %}
<p>Before starting some variables must be set</p> <p>Before starting some variables must be set</p>
<div class="form-group"> <div class="form-group">
<label>Root path: </label> <label>Mailu storage path: </label>
<!-- Validates path --> <!-- Validates path -->
<input class="form-control" type="text" name="root" value="/mailu" required pattern="^/[-_A-Za-z0-9]+(/[-_A-Za-z0-9]*)*"> <input class="form-control" type="text" name="root" value="/mailu" required pattern="^/[-_A-Za-z0-9]+(/[-_A-Za-z0-9]*)*">
</div> </div>
@ -27,7 +36,7 @@ Or in plain english: if receivers start to classify your mail as spam, this post
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Choose how you wish to handle security (TLS) certificates</label> <label>Choose how you wish to handle security <a href="https://mailu.io/{{ version }}/compose/setup.html#tls-certificates">TLS certificates</a></label>
<br/> <br/>
<select class="btn btn-primary dropdown-toggle" name="tls_flavor"> <select class="btn btn-primary dropdown-toggle" name="tls_flavor">
{% for tlsflavor in ["letsencrypt", "cert", "notls", "mail", "mail-letsencrypt"] %} {% for tlsflavor in ["letsencrypt", "cert", "notls", "mail", "mail-letsencrypt"] %}
@ -61,7 +70,7 @@ Or in plain english: if receivers start to classify your mail as spam, this post
<label>Linked Website URL</label> <label>Linked Website URL</label>
<!-- Validates url with or without https:// --> <!-- Validates url with or without https:// -->
<input class="form-control" type="url" name="website" value="https://mailu.io" required <input class="form-control" type="url" name="website" value="https://mailu.io" required
pattern="^(https?://)?([a-zA-Z0-9]([a-zA-ZäöüÄÖÜ0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$"> pattern="^(https?://)?([a-zA-Z0-9]([a-zA-ZäöüÄÖÜ0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$">
</div> </div>
<p>The admin interface is the main Mailu-specific bit, it provides tools to <p>The admin interface is the main Mailu-specific bit, it provides tools to

@ -9,8 +9,5 @@ maintained by specific contributors.</p>
<div class="radio"> <div class="radio">
{{ macros.radio("flavor", "compose", "Compose", "simply using Docker Compose manager", flavor) }} {{ macros.radio("flavor", "compose", "Compose", "simply using Docker Compose manager", flavor) }}
{{ macros.radio("flavor", "stack", "Stack", "using stack deployments in a Swarm cluster", flavor) }} {{ macros.radio("flavor", "stack", "Stack", "using stack deployments in a Swarm cluster", flavor) }}
{{ macros.radio("flavor", "rancher", "Rancher", "on top of the Rancher container manager", flavor) }}
{{ macros.radio("flavor", "kubernetes", "Kubernetes", "on top of the Kubernetes container manager", flavor) }}
</div> </div>
{% endcall %} {% endcall %}

@ -1,19 +1,15 @@
{% call macros.panel("info", "Step 3 - pick some features") %} {% call macros.panel("info", "Step 3 - pick some features") %}
<p>Mailu comes with multiple base features, including a specific admin <p>Mailu comes with multiple base features, including a specific admin
interface, Web email clients (webmails), antispam, antivirus, etc. If you interface, Web email clients, antispam, antivirus, etc.
wish to disable some of these features, you are free to do so.</p> In this section you can enable the services to you liking.</p>
<p>Emails will be available through IMAP and POP3. You may also enable a Web
email client. These do add some complexity but provide an easier way of
accessing messages for beginner users.</p>
<!-- Switched from radio buttons to dropdown menu in order to remove the checkbox --> <!-- Switched from radio buttons to dropdown menu in order to remove the checkbox -->
<p>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.<p>
<div class="form-group"> <div class="form-group">
<label>Enable Web email client (and path to the Web email client)</label> <label>Enable Web email client (and path to the Web email client)</label>
<!-- <div class="radio"> -->
<!-- {{ macros.radio("webmail_type", "roundcube", "RoundCube", "popular Webmail running on top of PHP") }} -->
<!-- {{ macros.radio("webmail_type", "rainloop", "Rainloop", "lightweight Webmail based on PHP, no database") }} -->
<!-- </div> -->
<br/> <br/>
<select class="btn btn-primary dropdown-toggle" name="webmail_type" id="webmail"> <select class="btn btn-primary dropdown-toggle" name="webmail_type" id="webmail">
{% for webmailtype in ["none", "roundcube", "rainloop"] %} {% for webmailtype in ["none", "roundcube", "rainloop"] %}
@ -26,10 +22,9 @@ accessing messages for beginner users.</p>
</div> </div>
</div> </div>
<p>Email filtering is a really important features. You can still disable it, which <p>An antivirus server helps fighting large scale virus spreading campaigns that leverage
will prevent Mailu from doing spam filtering, virus filtering, and from applying e-mail for initial infection. Make sure that you have at least 1GB of memory for ClamAV to
white and blacklists that you may configure in the admin interface. You may load its signature database.</p>
also disable the antivirus if required (it does use aroung 1GB of ram).</p>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<label class="form-check-label"> <label class="form-check-label">
@ -38,6 +33,9 @@ also disable the antivirus if required (it does use aroung 1GB of ram).</p>
</label> </label>
</div> </div>
<p>A Webdav server exposes a Dav interface over HTTP so that clients can store
contacts or calendars using the mail account.</p>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<label class="form-check-label"> <label class="form-check-label">
<input class="form-check-input" type="checkbox" name="webdav_enabled" value="radicale"> <input class="form-check-input" type="checkbox" name="webdav_enabled" value="radicale">
@ -45,6 +43,8 @@ also disable the antivirus if required (it does use aroung 1GB of ram).</p>
</label> </label>
</div> </div>
<p>Fetchmail allows to download mails over IMAP/POP3 and uploads it your Mailu mailbox.</p>
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<label class="form-check-label"> <label class="form-check-label">
<input class="form-check-input" type="checkbox" name="fetchmail_enabled" value="true"> <input class="form-check-input" type="checkbox" name="fetchmail_enabled" value="true">

Loading…
Cancel
Save