Merge remote-tracking branch 'upstream/master' into fix-setup-filegen

master
Tim Möhlmann 6 years ago
commit cffc7c15f1
No known key found for this signature in database
GPG Key ID: 8677988D8072E8DE

@ -7,7 +7,6 @@ pull_request_rules:
actions:
merge:
method: merge
strict: true
dismiss_reviews:
approved: true
@ -20,6 +19,5 @@ pull_request_rules:
actions:
merge:
method: merge
strict: true
dismiss_reviews:
approved: true

@ -22,3 +22,5 @@ Other contributors:
- "SunMar" - Dutch translation
- "Marty Hou" - Chinese Simple translation
- [Thomas Sänger](https://github.com/HorayNarea) - German translation
- [Tim Mohlmann](https://github.com/muhlemmer) - [Contributions](https://github.com/Mailu/Mailu/commits?author=muhlemmer)
- [Ionut Filip](https://github.com/ionutfilip) - [Contributions](https://github.com/Mailu/Mailu/commits?author=ionutfilip)

@ -5,6 +5,110 @@ Notable changes to this project are documented in the current file. For more
details about individual changes, see the Git log. You should read this before
upgrading Freposte.io as some changes will include useful notes.
v1.6.0 - unreleased
-------------------
- Global: Architecture of the central container ([#56](https://github.com/Mailu/Mailu/issues/56), [#108](https://github.com/Mailu/Mailu/issues/108))
- Global: Serve documentation with docker ([#601](https://github.com/Mailu/Mailu/issues/601), [#608](https://github.com/Mailu/Mailu/issues/608))
- Global: Travis-CI automated test build ([#602](https://github.com/Mailu/Mailu/issues/602))
- Global: Abstract db access from Postfix and Dovecot ([#612](https://github.com/Mailu/Mailu/issues/612))
- Global: Refactor the admin architecture and configuration management ([#670](https://github.com/Mailu/Mailu/issues/670))
- Feature: Used quota in admin interface ([#216](https://github.com/Mailu/Mailu/issues/216))
- Feature: User Signup ([#281](https://github.com/Mailu/Mailu/issues/281), [#340](https://github.com/Mailu/Mailu/issues/340))
- Feature: Client setup page ([#342](https://github.com/Mailu/Mailu/issues/342))
- Feature: Administration setup page ([#343](https://github.com/Mailu/Mailu/issues/343))
- Feature: Visual notice whether the mx record points to mailu server ([#356](https://github.com/Mailu/Mailu/issues/356))
- Feature: Option for vacation start ([#362](https://github.com/Mailu/Mailu/issues/362))
- Feature: Enable enigma in Roundcube ([#391](https://github.com/Mailu/Mailu/issues/391))
- Feature: Allow more charcaters as a valid email address ([#443](https://github.com/Mailu/Mailu/issues/443))
- Feature: IDNA support ([#446](https://github.com/Mailu/Mailu/issues/446))
- Feature: Disable user account ([#449](https://github.com/Mailu/Mailu/issues/449))
- Feature: Use fuzzy hashes in rpamd ([#456](https://github.com/Mailu/Mailu/issues/456), [#527](https://github.com/Mailu/Mailu/issues/527))
- Feature: Enable “doveadm -A” command ([#458](https://github.com/Mailu/Mailu/issues/458))
- Feature: Remove the Service Status page ([#463](https://github.com/Mailu/Mailu/issues/463))
- Feature: Automated Releases ([#487](https://github.com/Mailu/Mailu/issues/487))
- 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: 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: Add full-text search support ([#552](https://github.com/Mailu/Mailu/issues/552))
- 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: FAQ ([#564](https://github.com/Mailu/Mailu/issues/564), [#677](https://github.com/Mailu/Mailu/issues/677))
- Feature: Kubernetes support ([#576](https://github.com/Mailu/Mailu/issues/576))
- Feature: Option to bounce or reject email when recipient is unknown ([#583](https://github.com/Mailu/Mailu/issues/583), [#626](https://github.com/Mailu/Mailu/issues/626))
- Feature: implement healthchecks for all containers ([#631](https://github.com/Mailu/Mailu/issues/631))
- Feature: Option to send front logs to journald or syslog ([#584](https://github.com/Mailu/Mailu/issues/584), [#661](https://github.com/Mailu/Mailu/issues/661))
- Feature: Support bcrypt and PBKDF2 ([#647](https://github.com/Mailu/Mailu/issues/647), [#667](https://github.com/Mailu/Mailu/issues/667))
- Feature: enable http2 ([#674](https://github.com/Mailu/Mailu/issues/674))
- Feature: Unbound DNS as optional service ([#681](https://github.com/Mailu/Mailu/issues/681))
- Feature: Re-write test suite ([#682](https://github.com/Mailu/Mailu/issues/682))
- Feature: Docker image prefixes ([#702](https://github.com/Mailu/Mailu/issues/702))
- Feature: Add authentication method “login” for Outlook ([#704](https://github.com/Mailu/Mailu/issues/704))
- Feature: Allow extending nginx config with overrides ([#713](https://github.com/Mailu/Mailu/issues/713))
- Feature: Dynamic attachment size limit ([#731](https://github.com/Mailu/Mailu/issues/731))
- Feature: Certificate watcher for external certs to reload nginx ([#732](https://github.com/Mailu/Mailu/issues/732))
- Feature: Kubernetes
- Enhancement: Use pre-defined dhparam ([#322](https://github.com/Mailu/Mailu/issues/322))
- Enhancement: Disable ssl_session_tickets ([#329](https://github.com/Mailu/Mailu/issues/329))
- Enhancement: max attachment size in roundcube ([#338](https://github.com/Mailu/Mailu/issues/338))
- Enhancement: Use x-forwarded-proto with redirects ([#347](https://github.com/Mailu/Mailu/issues/347))
- Enhancement: Added adress verification before accepting mails for delivery ([#353](https://github.com/Mailu/Mailu/issues/353))
- Enhancement: Reverse proxy - Real ip header and mail-letsencrypt ([#358](https://github.com/Mailu/Mailu/issues/358))
- Enhancement: Parametrize hosts ([#373](https://github.com/Mailu/Mailu/issues/373))
- Enhancement: Expose ports in dockerfiles ([#392](https://github.com/Mailu/Mailu/issues/392))
- Enhancement: Added webmail-imap dependency in docker-compose ([#403](https://github.com/Mailu/Mailu/issues/403))
- Enhancement: Add environment variables to allow running outside of docker-compose ([#429](https://github.com/Mailu/Mailu/issues/429))
- Enhancement: Add original Delivered-To header to received messages ([#433](https://github.com/Mailu/Mailu/issues/433))
- Enhancement: Use HOST_ADMIN in "Forwarding authentication server" ([#436](https://github.com/Mailu/Mailu/issues/436), [#437](https://github.com/Mailu/Mailu/issues/437))
- Enhancement: Use POD_ADDRESS_RANGE for Dovecot ([#448](https://github.com/Mailu/Mailu/issues/448))
- Enhancement: Using configurable filenames for TLS certs ([#468](https://github.com/Mailu/Mailu/issues/468))
- Enhancement: Don't require BootstrapCDN (GDPR-compliance) ([#477](https://github.com/Mailu/Mailu/issues/477))
- Enhancement: Use dynamic client_max_body_size for webmail ([#502](https://github.com/Mailu/Mailu/issues/502))
- Enhancement: New logo design ([#509](https://github.com/Mailu/Mailu/issues/509))
- Enhancement: New manifests for Kubernetes ([#544](https://github.com/Mailu/Mailu/issues/544))
- Enhancement: Pin Alpine image ([#548](https://github.com/Mailu/Mailu/issues/548), [#557](https://github.com/Mailu/Mailu/issues/557))
- Enhancement: Use safer cipher in roundcube ([#597](https://github.com/Mailu/Mailu/issues/597))
- Enhancement: Improve sender checks ([#633](https://github.com/Mailu/Mailu/issues/633))
- Enhancement: Use PHP 7.2 for rainloop and roundcube ([#606](https://github.com/Mailu/Mailu/issues/606), [#642](https://github.com/Mailu/Mailu/issues/642))
- Enhancement: Multi-version documentation ([#664](https://github.com/Mailu/Mailu/issues/664))
- Enhancement: Contribution documentation ([#700](https://github.com/Mailu/Mailu/issues/700))
- Enhancement: Move Mailu Docker network to a fixed subnet ([#727](https://github.com/Mailu/Mailu/issues/727))
- Enhancement: Added regex validation for alias username ([#764](https://github.com/Mailu/Mailu/issues/764))
- Enhancement: Update documentation
- Upstream: Update Roundcube
- Upstream: Update Rainloop
- Bug: Rainloop fails with "domain not allowed" ([#93](https://github.com/Mailu/Mailu/issues/93))
- Bug: Announces fail ([#309](https://github.com/Mailu/Mailu/issues/309))
- Bug: Authentication issues with rspamd admin ui ([#315](https://github.com/Mailu/Mailu/issues/315))
- Bug: front hangup on restart ([#341](https://github.com/Mailu/Mailu/issues/341))
- Bug: Display the proper user quota when set to 0/infinity ([#345](https://github.com/Mailu/Mailu/issues/345))
- Bug: Domain details button "Regenerate keys" when no keys are generated yet ([#346](https://github.com/Mailu/Mailu/issues/346))
- Bug: Relayed Domains: access denied error ([#351](https://github.com/Mailu/Mailu/issues/351))
- Bug: Do not deny HTTP access upon TLS error when the flavor is mail ([#352](https://github.com/Mailu/Mailu/issues/352))
- Bug: php_zip extension missing in Roundcube webmail ([#364](https://github.com/Mailu/Mailu/issues/364))
- Bug: RoundCube webmail .htaccess assumes PHP 5 ([#366](https://github.com/Mailu/Mailu/issues/366))
- Bug: No quota shows "0 Bytes" in user list ([#368](https://github.com/Mailu/Mailu/issues/368))
- Bug: RELAYNETS not honored when login is different from sender ([#369](https://github.com/Mailu/Mailu/issues/369))
- Bug: Request Entity Too Large ([#371](https://github.com/Mailu/Mailu/issues/371))
- Bug: Pass the full host to the backend ([#372](https://github.com/Mailu/Mailu/issues/372))
- Bug: Can't send from an email account that has forwarding ([#390](https://github.com/Mailu/Mailu/issues/390))
- Bug: SSL protocol error roundcube/imap ([#411](https://github.com/Mailu/Mailu/issues/411), [#414](https://github.com/Mailu/Mailu/issues/414))
- Bug: Unable to send from alternative domains ([#415](https://github.com/Mailu/Mailu/issues/415))
- Bug: Webadmin redirect ignores host port ([#419](https://github.com/Mailu/Mailu/issues/419))
- Bug: Disable esld when signing with dkim ([#435](https://github.com/Mailu/Mailu/issues/435))
- Bug: DKIM missing when using identities ([#462](https://github.com/Mailu/Mailu/issues/462))
- Bug: Moving mails from Junk to Trash flags them as ham ([#474](https://github.com/Mailu/Mailu/issues/474))
- Bug: Cannot set the "keep emails" for fetched accounts ([#479](https://github.com/Mailu/Mailu/issues/479))
- Bug: CVE-2018-8740 ([#482](https://github.com/Mailu/Mailu/issues/482))
- Bug: Hide administration header in sidebar for normal users ([#505](https://github.com/Mailu/Mailu/issues/505))
- Bug: Return correct status codes from auth rate limiter failure ([#513](https://github.com/Mailu/Mailu/issues/513))
- Bug: Domain edit page shows "Create" button ([#523](https://github.com/Mailu/Mailu/issues/523))
- Bug: Hostname resolving in start.py should retry on failure [docker swarm] ([#555](https://github.com/Mailu/Mailu/issues/555))
- Bug: Error when trying to log in with an account without domain ([#585](https://github.com/Mailu/Mailu/issues/585))
- Bug: Fix rainloop permissions ([#637](https://github.com/Mailu/Mailu/issues/637))
- Bug: Fix broken webmail and logo url in admin ([#792](https://github.com/Mailu/Mailu/issues/792))
v1.5.1 - 2017-11-21
-------------------

@ -1,7 +1,7 @@
This project is open source, and your contributions are all welcome. There are mostly three different ways one can contribute to the project:
1. use Mailu, either on test or on production instances, and report meaningful bugs when you find some;
2. contribute code and/or configuration to the repository (see [the development guidelines](https://mailu.io/contributors/guide.html) for details);
3. contribute localization to your native language (see [the localization docs](https://mailu.io/contributors/localization.html) for details);
2. contribute code and/or configuration to the repository (see [the development guidelines](https://mailu.io/master/contributors/guide.html) for details);
3. contribute localization to your native language (see [the localization docs](https://mailu.io/master/contributors/localization.html) for details);
Either way, keep in mind that the code you write or the translation you produce muts be licensed under the same conditions as the project itself. Additionally, all contributors are considered equal co-authors of the project.

@ -20,7 +20,7 @@ COPY start.py /start.py
RUN pybabel compile -d mailu/translations
EXPOSE 80/tcp
VOLUME ["/data"]
VOLUME ["/data","/dkim"]
ENV FLASK_APP mailu
CMD /start.py

@ -33,5 +33,5 @@ if exists "X-Virus" {
}
{% if user.reply_active %}
vacation :days 1 :subject "{{ user.reply_subject }}" "{{ user.reply_body }}";
vacation :days 1 {% if user.displayed_name != "" %}:from "{{ user.displayed_name }} <{{ user.email }}>"{% endif %} :subject "{{ user.reply_subject }}" "{{ user.reply_body }}";
{% endif %}

@ -72,7 +72,7 @@ class CommaSeparatedList(db.TypeDecorator):
return ",".join(value)
def process_result_value(self, value, dialect):
return filter(bool, value.split(",")) if value else []
return list(filter(bool, value.split(","))) if value else []
class JSONEncoded(db.TypeDecorator):

@ -32,6 +32,14 @@ class DestinationField(fields.SelectMultipleField):
if not self.validator.match(item):
raise validators.ValidationError(_('Invalid email address.'))
class MultipleEmailAddressesVerify(object):
def __init__(self,message=_('Invalid email address.')):
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}))*$')
if not pattern.match(field.data.replace(" ", "")):
raise validators.ValidationError(self.message)
class ConfirmationForm(flask_wtf.FlaskForm):
submit = fields.SubmitField(_('Confirm'))
@ -81,6 +89,7 @@ class UserForm(flask_wtf.FlaskForm):
quota_bytes = fields_.IntegerSliderField(_('Quota'), default=1000000000)
enable_imap = fields.BooleanField(_('Allow IMAP access'), default=True)
enable_pop = fields.BooleanField(_('Allow POP3 access'), default=True)
displayed_name = fields.StringField(_('Displayed name'))
comment = fields.StringField(_('Comment'))
enabled = fields.BooleanField(_('Enabled'), default=True)
submit = fields.SubmitField(_('Save'))
@ -101,9 +110,7 @@ class UserSettingsForm(flask_wtf.FlaskForm):
spam_threshold = fields_.IntegerSliderField(_('Spam filter tolerance'))
forward_enabled = fields.BooleanField(_('Enable forwarding'))
forward_keep = fields.BooleanField(_('Keep a copy of the emails'))
forward_destination = fields.StringField(
_('Destination'), [validators.Optional(), validators.Email()]
)
forward_destination = fields.StringField(_('Destination'), [validators.Optional(), MultipleEmailAddressesVerify()])
submit = fields.SubmitField(_('Save settings'))
@ -136,7 +143,7 @@ class TokenForm(flask_wtf.FlaskForm):
class AliasForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('Alias'), [validators.DataRequired()])
localpart = fields.StringField(_('Alias'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)])
wildcard = fields.BooleanField(
_('Use SQL LIKE Syntax (e.g. for catch-all aliases)'))
destination = DestinationField(_('Destination'))

@ -28,7 +28,7 @@ class="hold-transition skin-blue sidebar-mini"
<div class="wrapper">
{% block navbar %}
<header class="main-header">
<a href="/admin/" class="logo">
<a href="{{ config["WEB_ADMIN"] }}" class="logo">
<span class="logo-lg">{{ config["SITENAME"] }}</span>
</a>
</header>

@ -53,7 +53,7 @@ configure your email client
</tr>
<tr>
<th>{% trans %}Username{% endtrans %}</th>
<td><pre>{{ current_user or "******" }}</pre></td>
<td><pre>{{ current_user if current_user.is_authenticated else "******" }}</pre></td>
</tr>
<tr>
<th>{% trans %}Password{% endtrans %}</th>

@ -69,7 +69,7 @@
<li class="header">{% trans %}Go to{% endtrans %}</li>
{% if config["WEBMAIL"] != "none" %}
<li>
<a href="{{ config["WEB_WEBMAIL"] }}/">
<a href="{{ config["WEB_WEBMAIL"] }}">
<i class="fa fa-envelope-o"></i> <span>{% trans %}Webmail{% endtrans %}</span>
</a>
</li>

@ -15,6 +15,7 @@
{% call macros.box(_("General")) %}
{{ macros.form_field(form.localpart, append='<span class="input-group-addon">@'+domain.name+'</span>') }}
{{ macros.form_fields((form.pw, form.pw2)) }}
{{ macros.form_field(form.displayed_name) }}
{{ macros.form_field(form.comment) }}
{{ macros.form_field(form.enabled) }}
{% endcall %}

@ -11,6 +11,10 @@
{% block content %}
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}
{% call macros.box(title=_("Displayed name")) %}
{{ macros.form_field(form.displayed_name) }}
{% endcall %}
{% call macros.box(title=_("Antispam")) %}
{{ macros.form_field(form.spam_enabled) }}

@ -7,7 +7,6 @@ import flask_login
import wtforms
import wtforms_components
@ui.route('/user/list/<domain_name>', methods=['GET'])
@access.domain_admin(models.Domain, 'domain_name')
def user_list(domain_name):
@ -92,9 +91,16 @@ def user_settings(user_email):
user_email_or_current = user_email or flask_login.current_user.email
user = models.User.query.get(user_email_or_current) or flask.abort(404)
form = forms.UserSettingsForm(obj=user)
if isinstance(form.forward_destination.data,str):
data = form.forward_destination.data.replace(" ","").split(",")
else:
data = form.forward_destination.data
form.forward_destination.data = ", ".join(data)
if form.validate_on_submit():
form.forward_destination.data = form.forward_destination.data.replace(" ","").split(",")
form.populate_obj(user)
models.db.session.commit()
form.forward_destination.data = ", ".join(form.forward_destination.data)
flask.flash('Settings updated for %s' % user)
if user_email:
return flask.redirect(

@ -7,6 +7,7 @@ postmaster_address = {{ POSTMASTER }}@{{ DOMAIN }}
hostname = {{ HOSTNAMES.split(",")[0] }}
submission_host = {{ FRONT_ADDRESS }}
{% if DISABLE_FTS_LUCENE != 'true' %}
###############
# Full-text search
###############
@ -20,6 +21,7 @@ plugin {
fts_lucene = whitespace_chars=@.
}
{% endif %}
###############
# Mailboxes
@ -64,6 +66,7 @@ plugin {
###############
# Authentication
###############
auth_username_chars =
auth_mechanisms = plain login
disable_plaintext_auth = no

@ -87,14 +87,15 @@ http {
include /overrides/*.conf;
# Actual logic
{% if WEB_WEBMAIL != '/' %}
location / {
{% if WEBROOT_REDIRECT and WEB_WEBMAIL != '/' %}
{% if WEBROOT_REDIRECT %}
return 301 {{ WEBROOT_REDIRECT }};
{% else %}
return 404;
{% endif %}
}
{% endif %}
{% if WEBMAIL != 'none' %}
location {{ WEB_WEBMAIL }} {

@ -0,0 +1,4 @@
{%- extends "layout.html" %}
{% block body %}
{{ body|replace("VERSION_TAG", version) }}
{% endblock %}

@ -3,6 +3,10 @@
# these few settings must however be configured before starting the mail
# server and require a restart upon change.
# Set this to `true` to disable full text search by lucene (value: true, false)
# This is a workaround for the bug in issue #751 (indexer-worker crashes)
DISABLE_FTS_LUCENE=false
###################################
# Common configuration variables
###################################

@ -88,7 +88,6 @@ services:
volumes:
- "$ROOT/data:/data"
- "$ROOT/dkim:/dkim"
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- redis

@ -0,0 +1,143 @@
version: '2'
services:
# This would normally not be here, but where you define your system services
traefik:
image: traefik:alpine
command: --docker
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/data/traefik/acme.json:/acme.json"
- "/data/traefik/traefik.toml:/traefik.toml"
# This may be needed (plus defining mailu_default external: true) if traefik lives elsewhere
# networks:
# - mailu_default
certdumper:
restart: always
image: mailu/traefik-certdumper:$VERSION
environment:
# Make sure this is the same as the main=-domain in traefik.toml
# !!! Also dont forget to add "TRAEFIK_DOMAIN=[...]" to your .env!
- DOMAIN=$TRAEFIK_DOMAIN
volumes:
- "/data/traefik:/traefik"
- "$ROOT/certs:/output"
front:
image: mailu/nginx:$VERSION
restart: always
env_file: .env
logging:
driver: $LOG_DRIVER
labels: # Traefik labels for simple reverse-proxying
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:$TRAEFIK_DOMAIN"
- "traefik.docker.network=mailu_default"
ports:
- "$BIND_ADDRESS4:110:110"
- "$BIND_ADDRESS4:143:143"
- "$BIND_ADDRESS4:993:993"
- "$BIND_ADDRESS4:995:995"
- "$BIND_ADDRESS4:25:25"
- "$BIND_ADDRESS4:465:465"
- "$BIND_ADDRESS4:587:587"
- "$BIND_ADDRESS6:110:110"
- "$BIND_ADDRESS6:143:143"
- "$BIND_ADDRESS6:993:993"
- "$BIND_ADDRESS6:995:995"
- "$BIND_ADDRESS6:25:25"
- "$BIND_ADDRESS6:465:465"
- "$BIND_ADDRESS6:587:587"
volumes:
- "$ROOT/overrides/nginx:/overrides"
- /data/traefik/ssl/$TRAEFIK_DOMAIN.crt:/certs/cert.pem
- /data/traefik/ssl/$TRAEFIK_DOMAIN.key:/certs/key.pem
redis:
image: redis:alpine
restart: always
volumes:
- "$ROOT/redis:/data"
imap:
image: mailu/dovecot:$VERSION
restart: always
env_file: .env
volumes:
- "$ROOT/mail:/mail"
- "$ROOT/overrides:/overrides"
depends_on:
- front
smtp:
image: mailu/postfix:$VERSION
restart: always
env_file: .env
volumes:
- "$ROOT/overrides:/overrides"
depends_on:
- front
antispam:
image: mailu/rspamd:$VERSION
restart: always
env_file: .env
volumes:
- "$ROOT/filter:/var/lib/rspamd"
- "$ROOT/dkim:/dkim"
- "$ROOT/overrides/rspamd:/etc/rspamd/override.d"
depends_on:
- front
antivirus:
image: mailu/$ANTIVIRUS:$VERSION
restart: always
env_file: .env
volumes:
- "$ROOT/filter:/data"
webdav:
image: mailu/$WEBDAV:$VERSION
restart: always
env_file: .env
volumes:
- "$ROOT/dav:/data"
admin:
image: mailu/admin:$VERSION
restart: always
env_file: .env
volumes:
- "$ROOT/data:/data"
- "$ROOT/dkim:/dkim"
depends_on:
- redis
webmail:
image: "mailu/$WEBMAIL:$VERSION"
restart: always
env_file: .env
volumes:
- "$ROOT/webmail:/data"
depends_on:
- imap
fetchmail:
image: mailu/fetchmail:$VERSION
restart: always
env_file: .env
networks:
default:
driver: bridge
ipam:
driver: default
config:
- subnet: $SUBNET

@ -0,0 +1,33 @@
# This is just boilerplate stuff you probably have in your own config
logLevel = "INFO"
defaultEntryPoints = ["https","http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[docker]
endpoint = "unix:///var/run/docker.sock"
watch = true
exposedByDefault = false
# Make sure we get acme.json saved, and onHostRule enabled
[acme]
email = "your@mail.tld"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
# This should include all of your mail domains, and main= should be your $TRAEFIK_DOMAIN
[[acme.domains]]
main = "mail.your.doma.in"
sans = ["web.mail.your.doma.in", "smtp.mail.doma.in", "imap.mail.doma.in"]

@ -184,7 +184,7 @@ directory structure.
If you do no posses the resources, but want to become an involved tester/reviewer.
Please contact `muhlemmer on Matrix`_.
He can provide access to a testing server, if a thrust relation can be established.
He can provide access to a testing server, if a trust relation can be established.
.. _`muhlemmer on Matrix`: https://matrix.to/#/@muhlemmer:matrix.org

@ -5,21 +5,32 @@ The demo server is for demonstration and test purposes only. Please be
respectful and keep the demo server functional for others to be able to try it
out.
The server is reset every day at 3am, french time. If you find the server is
unusable, you can still ask for someone to reset it manually on our Matrix
chat channel. Please do not open tickets everytime the server is down. Please
do not open tickets if the server is quite slow: it *is* slow because the
machine is a cheap leased server.
If you find the server is unusable, you can ask for someone to reset it manually on our Matrix
chat channel. Please do not open tickets every time the server is down.
Please do not open tickets if the server is quite slow: it *is* slow because the
services have only limited resources available.
Keep in mind that the demo server is also used for some automated tests and runs
the latest unstable version. If you find actual bugs when using the demo
server, please report these!
Keep in mind that the demo server runs the latest unstable (master) version.
If you find actual bugs when using the demo server, please report these!
Functionality
-------------
- The server is reset every day at 3am, UTC.
- You can send mail from any client to the server.
However, the SMTP server is made incapable of relaying the e-mail to the destination server.
As such, the mail will never arrive. This is to prevent abuse of the server.
- The server is capable of receiving mail for any configured domains.
- The server exposes IMAP, POP3 and SMTP as usual for connection with mail clients such as Thunderbird.
- The containers have limited (throttled) CPU, this means it can respond slow during heavy operations.
- The containers have limited memory available and will be killed when exceeded.
This is to prevent people from doing nasty things to the server as a whole.
Connecting to the server
------------------------
* Server name : ``test.mailu.io``
* IP address : ``51.15.169.20``
* IP address : ``173.249.45.89``
* Webmail : https://test.mailu.io/webmail/
* Admin UI : https://test.mailu.io/admin/
* Admin login : ``admin@test.mailu.io``

@ -89,6 +89,51 @@ our ongoing `project management`_ discussion issue.
Deployment related
------------------
What is the difference between DOMAIN and HOSTNAMES?
````````````````````````````````````````````````````
Similar questions:
- Changing domain doesn't work
- Do I need a certificate for ``DOMAIN``?
``DOMAIN`` is the main mail domain. Aka, server identification for outgoing mail. DMARC reports point to ``POSTMASTER`` @ ``DOMAIN``.
These are really the only things it is used for. You don't need a cert for ``DOMAIN``, as it is a mail domain only and not used as host in any sense.
However, it is usual that ``DOMAIN`` gets setup as one of the many mail domains. None of the mail domains ever need a certificate.
TLS certificates work on host connection level only.
``HOSTNAMES`` however, can be used to connect to the server. All host names supplied in this variable will need a certificate. When ``TLS_FLAVOR=letsencrypt`` is set,
a certificate is requested automatically for all those domains.
So when you have something like this:
.. code-block:: bash
DOMAIN=example.com
POSTMASTER=me
HOSTNAMES=mail.example.com,mail.foo.com,bar.com
TLS_FLAVOR=letsencrypt
- You'll end up with a DMARC address to ``me@example.com``.
- Server identifies itself as the SMTP server of ``@example.com`` when sending mail. Make sure your reverse DNS hostname is part of that domain!
- Your server will have certificates for the 3 hostnames. You will need to create ``A`` and ``AAAA`` records for those names,
pointing to the IP addresses of your server.
- The admin interface generates ``MX`` and ``SPF`` examples which point to the first entry of ``HOSTNAMES`` but these are only examples.
You can modify them to use any other ``HOSTNAMES`` entry.
You're mail service will be reachable for IMAP, POP3, SMTP and Webmail at the addresses:
- mail.example.com
- mail.foo.com
- bar.com
.. note::
In this case ``example.com`` is not reachable as a host and will not have a certificate.
It can be used as a mail domain if MX is setup to point to one of the ``HOSTNAMES``. However, it is possible to include ``example.com`` in ``HOSTNAMES``.
*Issue reference:* `742`_, `747`_.
How does Mailu scale up?
````````````````````````
@ -123,6 +168,16 @@ For **service** HA, please see: `How does Mailu scale up?`_
.. _`spam magnet`: https://blog.zensoftware.co.uk/2012/07/02/why-we-tend-to-recommend-not-having-a-secondary-mx-these-days/
Does Mailu run on Rancher?
``````````````````````````
There is a rancher catalog for Mailu in the `Mailu/Rancher`_ repository. The user group for Rancher is small,
so we cannot promise any support on this when you're heading into trouble. See the repository README for more details.
*Issue reference:* `125`_.
.. _`Mailu/Rancher`: https://github.com/Mailu/Rancher
Can I run Mailu without host iptables?
``````````````````````````````````````
@ -138,22 +193,29 @@ For that reason we do **not** support deployment on Docker hosts without iptable
How can I override settings?
````````````````````````````
Postfix, dovecot and Rspamd support overriding configuration files. Override files belong in
Postfix, Dovecot, Nginx and Rspamd support overriding configuration files. Override files belong in
``$ROOT/overrides``. Please refer to the official documentation of those programs for the
correct syntax. The following file names will be taken as override configuration:
- `Postfix`_ - ``postfix.cf``;
- `Dovecot`_ - ``dovecot.conf``;
- `Nginx`_ - All ``*.conf`` files in the ``nginx`` sub-directory.
- `Rspamd`_ - All files in the ``rspamd`` sub-directory.
*Issue reference:* `206`_.
.. _`Postfix`: http://www.postfix.org/postconf.5.html
.. _`Dovecot`: https://wiki.dovecot.org/ConfigFile
.. _`Rspamd`: https://www.rspamd.com/doc/configuration/index.html
.. _`NGINX`: https://nginx.org/en/docs/
.. _`Rspamd`: https://www.rspamd.com/doc/configuration/index.html
.. _`Docker swarm howto`: https://github.com/Mailu/Mailu/tree/master/docs/swarm/master
.. _`125`: https://github.com/Mailu/Mailu/issues/125
.. _`165`: https://github.com/Mailu/Mailu/issues/165
.. _`177`: https://github.com/Mailu/Mailu/issues/177
.. _`332`: https://github.com/Mailu/Mailu/issues/332
.. _`742`: https://github.com/Mailu/Mailu/issues/742
.. _`747`: https://github.com/Mailu/Mailu/issues/747
.. _`520`: https://github.com/Mailu/Mailu/issues/520
.. _`591`: https://github.com/Mailu/Mailu/issues/591
@ -241,8 +303,18 @@ See also :ref:`external_certs`.
*Issue reference:* `426`_, `615`_.
How do I activate DKIM and DMARC?
```````````````````````
Go into the Domain Panel and choose the Domain you want to enable DKIM for.
Click the first icon on the left side (domain details).
Now click on the top right on the *"Regenerate Keys"* Button.
This will generate the DKIM and DMARC entries for you.
*Issue reference:* `102`_.
Do you support Fail2Ban?
````````````````````````
Fail2Ban is not included in Mailu. Fail2Ban needs to modify the host's IP tables in order to
ban the addresses. We consider such a program should be run on the host system and not
inside a container. The ``front`` container does use authentication rate limiting to slow
@ -265,12 +337,50 @@ spam filter weight settings.
*Issue reference:* `503`_.
rspamd: DNS query blocked on multi.uribl.com
````````````````````````````````````````````
This usually relates to the DNS server you are using. Most of the public servers block this query or there is a rate limit.
In order to solve this, you most probably are better off using a root DNS resolver, such as `unbound`_. This can be done in multiple ways:
- Use the *Mailu/unbound* container. This is an optional include when generating the ``docker-compose.yml`` file with the setup utility.
- Setup unbound on the host and make sure the host's ``/etc/resolve.conf`` points to local host.
Docker will then forward all external DNS requests to the local server.
- Set up an external DNS server with root resolving capabilities.
In any case, using a dedicated DNS server will improve the performance of your mail server.
*Issue reference:* `206`_, `554`_, `681`_.
Is there a way to support more (older) ciphers?
```````````````````````````````````````````````
See `How can I override settings?`_ .
You will need to add the protocols you wish to support in an override for the ``front`` container (Nginx).
.. code-block:: bash
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers <list of ciphers>;
We **strongly** advice against downgrading the TLS version and ciphers!
*Issue reference:* `363`_, `698`_.
.. _`troubleshooting tag`: https://github.com/Mailu/Mailu/issues?utf8=%E2%9C%93&q=label%3Afaq%2Ftroubleshooting
.. _`85`: https://github.com/Mailu/Mailu/issues/85
.. _`102`: https://github.com/Mailu/Mailu/issues/102
.. _`116`: https://github.com/Mailu/Mailu/issues/116
.. _`171`: https://github.com/Mailu/Mailu/issues/171
.. _`206`: https://github.com/Mailu/Mailu/issues/206
.. _`363`: https://github.com/Mailu/Mailu/issues/363
.. _`426`: https://github.com/Mailu/Mailu/issues/426
.. _`503`: https://github.com/Mailu/Mailu/issues/503
.. _`554`: https://github.com/Mailu/Mailu/issues/554
.. _`584`: https://github.com/Mailu/Mailu/issues/584
.. _`592`: https://github.com/Mailu/Mailu/issues/592
.. _`615`: https://github.com/Mailu/Mailu/issues/615
.. _`681`: https://github.com/Mailu/Mailu/pull/681
.. _`698`: https://github.com/Mailu/Mailu/issues/698
.. _`unbound`: https://nlnetlabs.nl/projects/unbound/about/

@ -8,6 +8,7 @@ In such a configuration, one would usually run a frontend reverse proxy to serve
There are basically three options, from the most to the least recommended one:
- have Mailu Web frontend listen locally and use your own Web frontend on top of it
- use ``Traefik`` in another container as central system-reverse-proxy
- override Mailu Web frontend configuration
- disable Mailu Web frontend completely and use your own
@ -114,11 +115,87 @@ Depending on how you access the front server, you might want to add a ``proxy_re
This will stop redirects (301 and 302) sent by the Webmail, nginx front and admin interface from sending you to ``localhost``.
Use Traefik in another container as central system-reverse-proxy
--------------------------------------------------------------------
`Traefik`_ is a popular reverse-proxy aimed at containerized systems.
As such, many may wish to integrate Mailu into a system which already uses Traefik as its sole ingress/reverse-proxy.
As the ``mailu/front`` container uses Nginx not only for ``HTTP`` forwarding, but also for the mail-protocols like ``SMTP``, ``IMAP``, etc, we need to keep this
container around even when using another ``HTTP`` reverse-proxy. Furthermore, Traefik is neither able to forward non-HTTP, nor can it easily forward HTTPS-to-HTTPS.
This, however, means 3 things:
- ``mailu/front`` needs to listen internally on ``HTTP`` rather than ``HTTPS``
- ``mailu/front`` is not exposed to the outside world on ``HTTP``
- ``mailu/front`` still needs ``SSL`` certificates (here, we assume ``letsencrypt``) for a well-behaved mail service
This makes the setup with Traefik a bit harder: Traefik saves its certificates in a proprietary *JSON* file, which is not readable by Nginx in the ``front``-container.
To solve this, your ``acme.json`` needs to be exposed to the host or a ``docker-volume``. It will then be read by a script in another container,
which will dump the certificates as ``PEM`` files, readable for Nginx. The ``front`` container will automatically reload Nginx whenever these certificates change.
To set this up, first set ``TLS_FLAVOR=mail`` in your ``.env``. This tells ``mailu/front`` not to try to request certificates using ``letsencrypt``,
but to read provided certificates, and use them only for mail-protocols, not for ``HTTP``.
Next, in your ``docker-compose.yml``, comment out the ``port`` lines of the ``front`` section for port ``…:80`` and ``…:440``.
Add the respective Traefik labels for your domain/configuration, like
.. code-block:: yaml
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:$TRAEFIK_DOMAIN"
.. note:: Please dont forget to add ``TRAEFIK_DOMAIN=[...]`` TO YOUR ``.env``
If your Traefik is configured to automatically request certificates from *letsencrypt*, then youll have a certificate for ``mail.your.doma.in`` now. However,
``mail.your.doma.in`` might only be the location where you want the Mailu web-interfaces to live — your mail should be sent/received from ``your.doma.in``,
and this is the ``DOMAIN`` in your ``.env``?
To support that use-case, Traefik can request ``SANs`` for your domain. Lets add something like
.. code-block:: guess
[acme]
[[acme.domains]]
main = "your.doma.in" # this is the same as $TRAEFIK_DOMAIN!
sans = ["mail.your.doma.in", "webmail.your.doma.in", "smtp.your.doma.in"]
to your ``traefik.toml``. You might need to clear your ``acme.json``, if a certificate for one of these domains already exists.
You will need some solution which dumps the certificates in ``acme.json``, so you can include them in the ``mailu/front`` container.
One such example is ``mailu/traefik-certdumper``, which has been adapted for use in Mailu. You can add it to your ``docker-compose.yml`` like:
.. code-block:: yaml
certdumper:
restart: always
image: mailu/traefik-certdumper:$VERSION
environment:
# Make sure this is the same as the main=-domain in traefik.toml
# !!! Also dont forget to add "TRAEFIK_DOMAIN=[...]" to your .env!
- DOMAIN=$TRAEFIK_DOMAIN
volumes:
- "/data/traefik:/traefik"
- "$ROOT/certs:/output"
Assuming you have ``volume-mounted`` your ``acme.json`` put to ``/data/traefik`` on your host. The dumper will then write out ``/data/traefik/ssl/your.doma.in.crt``
and ``/data/traefik/ssl/your.doma.in.key`` whenever ``acme.json`` is updated. Yay! Now lets mount this to our ``front`` container like:
.. code-block:: yaml
volumes:
- "$ROOT/overrides/nginx:/overrides"
- /data/traefik/ssl/$TRAEFIK_DOMAIN.crt:/certs/cert.pem
- /data/traefik/ssl/$TRAEFIK_DOMAIN.key:/certs/key.pem
.. _`Traefik`: https://traefik.io/
Override Mailu configuration
----------------------------
If you do not have the resources for running a separate reverse proxy, you could override Mailu reverse proxy configuration by using a Docker volume. Simply store your configuration file (Nginx format), in ``/mailu/nginx.conf`` for instance.
If you do not have the resources for running a separate reverse proxy, you could override Mailu reverse proxy configuration by using a Docker volume.
Simply store your configuration file (Nginx format), in ``/mailu/nginx.conf`` for instance.
Then modify your ``docker-compose.yml`` file and change the ``front`` section to add a mount:
@ -135,7 +212,10 @@ Then modify your ``docker-compose.yml`` file and change the ``front`` section to
- "$ROOT/certs:/certs"
- "$ROOT/nginx.conf:/etc/nginx/nginx.conf"
You can use our default configuration file as a sane base for your configuration.
You can also download the example configuration files:
- :download:`compose/traefik/docker-compose.yml`
- :download:`compose/traefik/traefik.toml`
Disable completely Mailu reverse proxy
--------------------------------------

@ -0,0 +1,11 @@
FROM alpine:3.8
RUN apk --no-cache add inotify-tools jq openssl util-linux bash docker
# while not strictly documented, this script seems to always(?) support previous acme.json versions too
RUN wget https://raw.githubusercontent.com/containous/traefik/master/contrib/scripts/dumpcerts.sh -O dumpcerts.sh
VOLUME ["/traefik"]
VOLUME ["/output"]
COPY run.sh /
ENTRYPOINT ["/run.sh"]

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Sven Dowideit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,27 @@
# Single-domain traefik-certdumper for mailu
This is based on the work by Sven Dowideit on https://github.com/SvenDowideit/traefik-certdumper
## Fork?
This is a slight modification that is less flexible, but is adapted to the
usecase in mailu. If you wish to deploy mailu behind a traefik, you face many
problems. One of these is that you need to get the certificates into mailu in a
very defined manner. This will copy the certificate for the **Main:**-domain
given in the DOMAIN-environment onto `output`.
If your output happens to be mailu-front-`/certs`, the certificate-watcher in
the front-container will catch it and reload nginx. This works for mailu
`TLS_FLAVOR=[mail, cert]`
```
certdumper:
restart: always
image: Mailu/traefik-certdumper:$VERSION
environment:
- DOMAIN=$DOMAIN
volumes:
# your traefik data-volume is probably declared outside of the mailu composefile
- /data/traefik:/traefik
- $ROOT/certs/:/output/
```

@ -0,0 +1,30 @@
#!/bin/bash
function dump() {
echo "$(date) Dumping certificates"
bash dumpcerts.sh /traefik/acme.json /tmp/work/ || return
for crt_file in $(ls /tmp/work/certs/*); do
pem_file=$(echo $crt_file | sed 's/certs/pem/g' | sed 's/.crt/-public.pem/g')
echo "openssl x509 -inform PEM -in $crt_file > $pem_file"
openssl x509 -inform PEM -in $crt_file > $pem_file
done
for key_file in $(ls /tmp/work/private/*); do
pem_file=$(echo $key_file | sed 's/private/pem/g' | sed 's/.key/-private.pem/g')
echo "openssl rsa -in $key_file -text > $pem_file"
openssl rsa -in $key_file -text > $pem_file
done
echo "$(date) Copying certificates"
cp -v /tmp/work/pem/${DOMAIN}-private.pem /output/key.pem
cp -v /tmp/work/pem/${DOMAIN}-public.pem /output/cert.pem
}
mkdir -p /tmp/work/pem /tmp/work/certs
# run once on start to make sure we have any old certs
dump
while true; do
inotifywait -e modify /traefik/acme.json && \
dump
done

@ -16,7 +16,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
logging:
@ -36,7 +36,7 @@ services:
{% if resolver_enabled %}
resolver:
image: mailu/unbound:{{ version }}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}unbound:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
restart: always
networks:
@ -45,7 +45,7 @@ services:
{% endif %}
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
{% if not admin_enabled %}
@ -59,7 +59,7 @@ services:
- redis
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
volumes:
@ -69,7 +69,7 @@ services:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
volumes:
@ -83,7 +83,7 @@ services:
{% endif %}
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
volumes:
@ -101,7 +101,7 @@ services:
# Optional services
{% if antivirus_enabled %}
antivirus:
image: ${DOCKER_ORG:-mailu}/clamav:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}clamav:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
volumes:
@ -116,7 +116,7 @@ services:
{% if webdav_enabled %}
webdav:
image: ${DOCKER_ORG:-mailu}/radicale:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}radicale:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
volumes:
@ -125,7 +125,7 @@ services:
{% if fetchmail_enabled %}
fetchmail:
image: ${DOCKER_ORG:-mailu}/fetchmail:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}fetchmail:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
{% if resolver_enabled %}
@ -139,7 +139,7 @@ services:
# Webmail
{% if webmail_type != 'none' %}
webmail:
image: ${DOCKER_ORG:-mailu}/{{ webmail_type }}:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}{{ webmail_type }}:${MAILU_VERSION:-{{ version }}}
restart: always
env_file: {{ env }}
volumes:

@ -93,13 +93,11 @@ RECIPIENT_DELIMITER={{ recipient_delimiter or '+' }}
DMARC_RUA={{ dmarc_rua or 'admin' }}
DMARC_RUF={{ dmarc_ruf or 'admin' }}
{% if welcome_enabled %}
# Welcome email, enable and set a topic and body if you wish to send welcome
# emails to all users.
WELCOME={{ welcome_enable or 'false' }}
WELCOME_SUBJECT={{ welcome_subject or 'Welcome to your new email account' }}
WELCOME_BODY={{ welcome_body or 'Welcome to your new email account, if you can read this, then it is configured properly!' }}
{% endif %}
# Maildir Compression
# choose compression-method, default: none (value: bz2, gz)

@ -36,7 +36,7 @@ docker-compose -p mailu up -d
Before you can use Mailu, you must create the primary administrator user account. This should be {{ postmaster }}@{{ domain }}. Use the following command, changing PASSWORD to your liking:
<pre><code>docker-compose -p mailu exec admin python manage.py admin {{ postmaster }} {{ domain }} PASSWORD
<pre><code>docker-compose -p mailu exec admin flask mailu admin {{ postmaster }} {{ domain }} PASSWORD
</pre></code>
<p>Login to the admin interface to change the password for a safe one, at

@ -15,7 +15,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
logging:
driver: {{ log_driver or 'json-file' }}
@ -33,7 +33,7 @@ services:
{% if resolver_enabled %}
resolver:
image: ${DOCKER_ORG:-mailu}/unbound:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}unbound:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
networks:
default:
@ -41,7 +41,7 @@ services:
{% endif %}
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
{% if not admin_enabled %}
ports:
@ -54,7 +54,7 @@ services:
replicas: {{ admin_replicas }}
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
volumes:
- "{{ root }}/mail:/mail"
@ -63,7 +63,7 @@ services:
replicas: {{ imap_replicas }}
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
volumes:
- "{{ root }}/overrides:/overrides"
@ -75,7 +75,7 @@ services:
{% endif %}
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
volumes:
- "{{ root }}/filter:/var/lib/rspamd"
@ -91,7 +91,7 @@ services:
# Optional services
{% if antivirus_enabled %}
antivirus:
image: ${DOCKER_ORG:-mailu}/clamav:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}clamav:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
volumes:
- "{{ root }}/filter:/data"
@ -105,7 +105,7 @@ services:
{% if webdav_enabled %}
webdav:
image: ${DOCKER_ORG:-mailu}/none:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}radicale:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
volumes:
- "{{ root }}/dav:/data"
@ -115,7 +115,7 @@ services:
{% if fetchmail_enabled %}
fetchmail:
image: ${DOCKER_ORG:-mailu}/fetchmail:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}fetchmail:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
volumes:
- "{{ root }}/data:/data"
@ -129,7 +129,7 @@ services:
{% if webmail_type != 'none' %}
webmail:
image: ${DOCKER_ORG:-mailu}/{{ webmail_type }}:${MAILU_VERSION:-{{ version }}}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}{{ webmail_type }}:${MAILU_VERSION:-{{ version }}}
env_file: {{ env }}
volumes:
- "{{ root }}/webmail:/data"

@ -45,7 +45,7 @@ Command for removing docker stack is
Before you can use Mailu, you must create the primary administrator user account. This should be {{ postmaster }}@{{ domain }}. Use the following command, changing PASSWORD to your liking:
<pre><code>docker exec $(docker ps | grep admin | cut -d ' ' -f1) python manage.py admin {{ postmaster }} {{ domain }} PASSWORD
<pre><code>docker exec $(docker ps | grep admin | cut -d ' ' -f1) flask mailu admin {{ postmaster }} {{ domain }} PASSWORD
</pre></code>
<p>Login to the admin interface to change the password for a safe one, at

@ -3,61 +3,65 @@ version: '3'
services:
front:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}nginx:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-local}
build: ../core/nginx
resolver:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}unbound:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}unbound:${MAILU_VERSION:-local}
build: ../services/unbound
imap:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}dovecot:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-local}
build: ../core/dovecot
smtp:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}postfix:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-local}
build: ../core/postfix
antispam:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}rspamd:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-local}
build: ../services/rspamd
antivirus:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}clamav:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}clamav:${MAILU_VERSION:-local}
build: ../optional/clamav
webdav:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}radicale:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}radicale:${MAILU_VERSION:-local}
build: ../optional/radicale
traefik-certdumper:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}traefik-certdumper:${MAILU_VERSION:-local}
build: ../optional/traefik-certdumper
admin:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}admin:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-local}
build: ../core/admin
roundcube:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}roundcube:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}roundcube:${MAILU_VERSION:-local}
build: ../webmails/roundcube
rainloop:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}rainloop:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rainloop:${MAILU_VERSION:-local}
build: ../webmails/rainloop
fetchmail:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}fetchmail:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}fetchmail:${MAILU_VERSION:-local}
build: ../services/fetchmail
none:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}none:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}none:${MAILU_VERSION:-local}
build: ../core/none
docs:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}docs:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}docs:${MAILU_VERSION:-local}
build:
context: ../docs
args:
version: ${MAILU_VERSION:-local}
setup:
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX}setup:${MAILU_VERSION:-local}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}setup:${MAILU_VERSION:-local}
build: ../setup

@ -15,7 +15,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
logging:
@ -34,7 +34,7 @@ services:
- "/mailu/certs:/certs"
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -44,7 +44,7 @@ services:
- redis
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -54,7 +54,7 @@ services:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -63,7 +63,7 @@ services:
- front
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:

@ -15,7 +15,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
logging:
@ -34,7 +34,7 @@ services:
- "/mailu/certs:/certs"
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -44,7 +44,7 @@ services:
- redis
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -54,7 +54,7 @@ services:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -63,7 +63,7 @@ services:
- front
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -77,7 +77,7 @@ services:
fetchmail:
image: ${DOCKER_ORG:-mailu}/fetchmail:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}fetchmail:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env

@ -15,7 +15,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
logging:
@ -34,7 +34,7 @@ services:
- "/mailu/certs:/certs"
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -44,7 +44,7 @@ services:
- redis
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -54,7 +54,7 @@ services:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -63,7 +63,7 @@ services:
- front
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -75,7 +75,7 @@ services:
# Optional services
antivirus:
image: ${DOCKER_ORG:-mailu}/clamav:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}clamav:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:

@ -15,7 +15,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
logging:
@ -34,7 +34,7 @@ services:
- "/mailu/certs:/certs"
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -44,7 +44,7 @@ services:
- redis
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -54,7 +54,7 @@ services:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -63,7 +63,7 @@ services:
- front
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -79,7 +79,7 @@ services:
# Webmail
webmail:
image: ${DOCKER_ORG:-mailu}/rainloop:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rainloop:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:

@ -15,7 +15,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
logging:
@ -34,7 +34,7 @@ services:
- "/mailu/certs:/certs"
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -44,7 +44,7 @@ services:
- redis
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -54,7 +54,7 @@ services:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -63,7 +63,7 @@ services:
- front
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -79,7 +79,7 @@ services:
# Webmail
webmail:
image: ${DOCKER_ORG:-mailu}/roundcube:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}roundcube:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:

@ -15,7 +15,7 @@ services:
# Core services
front:
image: ${DOCKER_ORG:-mailu}/nginx:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
logging:
@ -34,7 +34,7 @@ services:
- "/mailu/certs:/certs"
admin:
image: ${DOCKER_ORG:-mailu}/admin:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -44,7 +44,7 @@ services:
- redis
imap:
image: ${DOCKER_ORG:-mailu}/dovecot:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -54,7 +54,7 @@ services:
- front
smtp:
image: ${DOCKER_ORG:-mailu}/postfix:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -63,7 +63,7 @@ services:
- front
antispam:
image: ${DOCKER_ORG:-mailu}/rspamd:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:
@ -76,7 +76,7 @@ services:
# Optional services
webdav:
image: ${DOCKER_ORG:-mailu}/radicale:${MAILU_VERSION:-master}
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}radicale:${MAILU_VERSION:-master}
restart: always
env_file: mailu.env
volumes:

Loading…
Cancel
Save