Merge pull request #668 from usrpro/feat-setup

Feat setup
master
mergify[bot] 6 years ago committed by GitHub
commit d167c8ca7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,8 +10,10 @@ RUN apk add --no-cache git \
COPY server.py ./server.py
COPY setup.py ./setup.py
COPY main.py ./main.py
COPY flavors /data/master/flavors
COPY templates /data/master/templates
RUN python setup.py https://github.com/mailu/mailu /data
#RUN python setup.py https://github.com/mailu/mailu /data
EXPOSE 80/tcp

@ -9,5 +9,6 @@ services:
setup:
image: mailu/setup
ports:
- "80:80"
- "8000:80"
build: .

@ -1,124 +1,106 @@
{% set env='mailu.env' %}
# This file is auto-generated by the Mailu configuration wizard.
# Please read the documentation before attempting any change.
# Generated for {{ flavor }} flavor
version: '2'
version: '3.6'
services:
# External dependencies
redis:
image: redis:alpine
restart: always
volumes:
- "$ROOT/redis:/data"
- "{{ root }}/redis:/data"
# Core services
front:
image: mailu/nginx:{{ version }}
restart: always
env_file: {{ env }}
env:
- TLS_FLAVOR={{ tls_flavor or 'letsencrypt' }}
- ADMIN={{ expose_admin or 'no' }}
ports:
{% for port in (80, 443, 25, 465, 587, 110, 995, 143, 993) %}
{% if bind4 %}
- "$PUBLIC_IPV4:{{ port }}:{{ port }}"
- "{{ bind4 }}:{{ port }}:{{ port }}"
{% endif %}
{% if bind6 %}
- "$PUBLIC_IPV6:{{ port }}:{{ port }}"
- "{{ bind6 }}:{{ port }}:{{ port }}"
{% endif %}
{% endfor %}
{% if flavor in ('cert', 'mail') %}
volumes:
- "$ROOT/certs:/certs"
{% endif %}
- "{{ root }}/certs:/certs"
admin:
image: mailu/admin:{{ version }}
restart: always
env_file: {{ env }}
{% if not expose_admin %}
{% if not admin_enabled %}
ports:
- 127.0.0.1:8080:80
{% endif %}
volumes:
- "$ROOT/data:/data"
- "$ROOT/dkim:/dkim"
- "{{ root }}/data:/data"
- "{{ root }}/dkim:/dkim"
depends_on:
- redis
imap:
image: mailu/dovecot:{{ version }}
restart: always
env_file: {{ env }}
volumes:
- "$ROOT/data:/data"
- "$ROOT/mail:/mail"
- "$ROOT/overrides:/overrides"
- "{{ root }}/mail:/mail"
- "{{ root }}/overrides:/overrides"
depends_on:
- front
smtp:
image: mailu/postfix:{{ version }}
restart: always
env_file: {{ env }}
volumes:
- "$ROOT/data:/data"
- "$ROOT/overrides:/overrides"
- "{{ root }}/overrides:/overrides"
depends_on:
- front
# Optional services
{% if enable_antispam %}
{% if antispam_enabled %}
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"
- "{{ root }}/filter:/var/lib/rspamd"
- "{{ root }}/dkim:/dkim"
- "{{ root }}/overrides/rspamd:/etc/rspamd/override.d"
depends_on:
- front
{% endif %}
{% if enable_antivirus %}
{% if antivirus_enabled %}
antivirus:
image: mailu/clamav:{{ version }}
restart: always
env_file: {{ env }}
volumes:
- "$ROOT/filter:/data"
- "{{ root }}/filter:/data"
{% endif %}
{% if enable_webdav %}
{% if webdav_enabled %}
webdav:
image: mailu/radivale:{{ version }}
restart: always
image: mailu/radicale:{{ version }}
env_file: {{ env }}
volumes:
- "$ROOT/dav:/data"
- "{{ root }}/dav:/data"
{% endif %}
{% if enable_fetchmail %}
{% if fetchmail_enabled %}
fetchmail:
image: mailu/fetchmail:{{ version }}
restart: always
env_file: {{ env }}
volumes:
- "$ROOT/data:/data"
{% endif %}
# Webmail
{% if enable_webmail %}
{% if webmail_type != 'none' %}
webmail:
image: mailu/{{ webmail }}:{{ version }}
restart: always
image: mailu/{{ webmail_type }}:{{ version }}
env_file: {{ env }}
volumes:
- "$ROOT/webmail:/data"
- "{{ root }}/webmail:/data"
depends_on:
- imap
{% endif %}

@ -1,5 +1,7 @@
# Mailu main configuration file
#
# Generated for {{ flavor }} flavor
#
# This file is autogenerated by the configuration management wizard.
# For a detailed list of configuration variables, see the documentation at
# https://mailu.io
@ -9,60 +11,118 @@
###################################
# Set this to the path where Mailu data and configuration is stored
ROOT=/mailu
# This variable is now set directly in `docker-compose.yml by the setup utility
# ROOT={{ root }}
# Mailu version to run (1.0, 1.1, etc. or master)
#VERSION={{ version }}
# Set to a randomly generated 16 bytes string
SECRET_KEY={{ secret(16) }}
# Address where listening ports should bind
{% if bind4 %}PUBLIC_IPV4={{ bind4 }}{% endif %}
{% if bind6 %}PUBLIC_IPV6={{ bind6 }}{% endif %}
# This variables are now set directly in `docker-compose.yml by the setup utility
# PUBLIC_IPV4= {{ bind4 }} (default: 127.0.0.1)
# PUBLIC_IPV6= {{ bind6 }} (default: ::1)
# Mail address of the postmaster
POSTMASTER={{ postmaster }}
# Main mail domain
DOMAIN={{ domain }}
# Hostnames for this server, separated with comas
HOSTNAMES={{ hostnames }}
# Postmaster local part (will append the main mail domain)
POSTMASTER={{ postmaster }}
# Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt)
TLS_FLAVOR={{ tls_flavor }}
# Authentication rate limit (per source IP address)
AUTH_RATELIMIT={{ auth_ratelimit }}
{% if auth_ratelimit_pm > '0' and auth_ratelimit_ph > '0' %}
AUTH_RATELIMIT={{ auth_ratelimit_pm }}/minute;{{ auth_ratelimit_ph }}/hour
{% endif %}
# Opt-out of statistics, replace with "True" to opt out
DISABLE_STATISTICS={{ disable_statistics }}
DISABLE_STATISTICS={{ disable_statistics or 'False' }}
###################################
# Server behavior
# Optional features
###################################
# Expose the admin interface (value: true, false)
ADMIN={{ admin_enabled or 'false' }}
# Choose which webmail to run if any (values: roundcube, rainloop, none)
WEBMAIL={{ webmail_type }}
# Dav server implementation (value: radicale, none)
WEBDAV={{ webdav_enabled or 'none' }}
# Antivirus solution (value: clamav, none)
#ANTIVIRUS={{ antivirus_enabled or 'none' }}
#Antispam solution
ANTISPAM={{ antispam_enabled or 'none'}}
###################################
# Mail settings
###################################
# Message size limit in bytes
# Default: accept messages up to 50MB
MESSAGE_SIZE_LIMIT={{ message_size_limit }}
MESSAGE_SIZE_LIMIT={{ message_size_limit or '50000000' }}
# Networks granted relay permissions, make sure that you include your Docker
# internal network (default to 172.17.0.0/16)
RELAYNETS={{ relaynets }}
RELAYNETS={{ relaynets or '172.17.0.0/16' }}
# Will relay all outgoing mails if configured
RELAYHOST={{ relayhost }}
# Fetchmail delay
FETCHMAIL_DELAY={{ fetchmail_delay }}
FETCHMAIL_DELAY={{ fetchmail_delay or '600' }}
# Recipient delimiter, character used to delimiter localpart from custom address part
RECIPIENT_DELIMITER={{ recipient_delimiter }}
RECIPIENT_DELIMITER={{ recipient_delimiter or '+' }}
{% if dmarc_rua or dmarc_ruf %}
# DMARC rua and ruf email
{% if dmarc_rua %}DMARC_RUA={{ dmarc_rua }}{% endif %}
{% if dmarc_ruf %}DMARC_RUF={{ dmarc_ruf }}{% endif %}
{% endif %}
DMARC_RUA={{ dmarc_rua or 'admin' }}
DMARC_RUF={{ dmarc_ruf or 'admin' }}
{% if welcome_enabled %}
# Welcome email, enable and set a topic and body if you wish to send welcome
# emails to all users.
WELCOME={{ welcome_enable }}
WELCOME_SUBJECT={{ welcome_subject }}
WELCOME_BODY={{ welcome_body }}
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)
COMPRESSION={{ compression }}
# change compression-level, default: 6 (value: 1-9)
COMPRESSION_LEVEL={{ compression_level }}
###################################
# Web settings
###################################
# Path to the admin interface if enabled
WEB_ADMIN={{ admin_path }}
# Path to the webmail if enabled
WEB_WEBMAIL={{ webmail_path }}
# Website name
SITENAME={{ site_name }}
# Linked Website URL
WEBSITE={{ website }}
{% if recaptcha_public_key and recaptcha_private_key %}
# Registration reCaptcha settings (warning, this has some privacy impact)
# RECAPTCHA_PUBLIC_KEY={{ recaptcha_public_key }}
# RECAPTCHA_PRIVATE_KEY={{ recaptcha_private_key }}
{% endif %}
{% if domain_registration %}
@ -70,39 +130,28 @@ WELCOME_BODY={{ welcome_body }}
DOMAIN_REGISTRATION=true
{% endif %}
###################################
# Web settings
###################################
# Path to the admin interface if enabled
WEB_ADMIN=/admin
# Path to the webmail if enabled
WEB_WEBMAIL=/webmail
# Website name
SITENAME=Mailu
# Linked Website URL
WEBSITE=https://mailu.io
{% if recaptcha_public_key and recaptcha_private_key %}
# Registration reCaptcha settings (warning, this has some privacy impact)
# RECAPTCHA_PUBLIC_KEY={{ recaptcha_public_key }}
# RECAPTCHA_PRIVATE_KEY={{ recaptcha_private_key }}
{% endif %}
###################################
# Advanced settings
###################################
{% if password_scheme %}
# Specific password storage scheme
PASSWORD_SCHEME={{ password_scheme }}
{% endif %}
# Log driver for front service. Possible values:
# json-file (default)
# journald (On systemd platforms, useful for Fail2Ban integration)
# syslog (Non systemd platforms, Fail2Ban integration. Disables `docker-compose log` for front!)
LOG_DRIVER={{ log_driver or 'json-file' }}
# Docker-compose project name, this will prepended to containers names.
COMPOSE_PROJECT_NAME={{ compose_project_name or 'mailu' }}
# Default password scheme used for newly created accounts and changed passwords
# (value: BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT)
PASSWORD_SCHEME={{ password_scheme or 'BLF-CRYPT' }}
# Header to take the real ip from
REAL_IP_HEADER={{ real_ip_header }}
# IPs for nginx set_real_ip_from (CIDR list separated by commas)
REAL_IP_FROM={{ real_ip_from }}
# choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no)
REJECT_UNLISTED_RECIPIENT={{ reject_unlisted_recipient }}

@ -4,15 +4,15 @@
<p>Docker Compose expects a project file, named <code>docker-compose.yml</code>
in a project directory. First create your project directory.</p>
<pre><code>mkdir /mailu
<pre><code>mkdir {{ root }}
</pre></code>
<p>Then download the project file. A side configuration file makes it easier
to read and check the configuration variables generated by the wizard.</p>
<pre><code>cd /mailu
wget {{ url_for('.file', uid=uid, filepath='docker-compose.yml', _external=True) }}
wget {{ url_for('.file', uid=uid, filepath='mailu.env', _external=True) }}
<pre><code>cd {{ root }}
curl {{ url_for('.file', uid=uid, filepath='docker-compose.yml', _external=True) }} > docker-compose.yml
curl {{ url_for('.file', uid=uid, filepath='mailu.env', _external=True) }} > mailu.env
</pre></code>
{% endcall %}
@ -30,7 +30,22 @@ files before going any further.</p>
<p>To start your compose project, simply run the Docker Compose <code>up</code>
command.</p>
<pre><code>cd /mailu
<pre><code>cd {{ root }}
docker-compose up -d
</pre></code>
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 exec admin python manage.py admin {{ postmaster }} {{ domain }} PASSWORD
</pre></code>
<p>Login to the admin interface to change the password for a safe one, at
{% if admin_enabled %}
one of the hostnames
<a href="https://{{ hostnames.split(',')[0] }}{{ admin_path }}">{{ hostnames.split(',')[0] }}{{ admin_path }}</a>.
{% else %}
<a href="http://127.0.0.1:8080">http://127.0.0.1:8080</a> (only directly from the host running docker).
{% endif %}
And choose the "Update password" option in the left menu.
</p>
{% endcall %}

@ -0,0 +1,128 @@
{% set env='mailu.env' %}
# This file is auto-generated by the Mailu configuration wizard.
# Please read the documentation before attempting any change.
# Generated for {{ flavor }} flavor
version: '3.6'
services:
# External dependencies
redis:
image: redis:alpine
restart: always
volumes:
- "{{ root }}/redis:/data"
# Core services
front:
image: mailu/nginx:{{ version }}
env_file: {{ env }}
ports:
{% for port in (80, 443, 25, 465, 587, 110, 995, 143, 993) %}
- target: {{ port }}
published: {{ port }}
mode: overlay
{% endfor %}
volumes:
- "{{ root }}/certs:/certs"
deploy:
replicas: 1
admin:
image: mailu/admin:{{ version }}
env_file: {{ env }}
{% if not admin_enabled %}
ports:
- 127.0.0.1:8080:80
{% endif %}
volumes:
- "{{ root }}/data:/data"
- "{{ root }}/dkim:/dkim"
deploy:
replicas: 1
imap:
image: mailu/dovecot:{{ version }}
env_file: {{ env }}
environment:
# Default to 10.0.1.0/24
- POD_ADDRESS_RANGE={{ subnet }}
volumes:
- "{{ root }}/mail:/mail"
- "{{ root }}/overrides:/overrides"
deploy:
replicas: 1
smtp:
image: mailu/postfix:{{ version }}
env_file: {{ env }}
environment:
- POD_ADDRESS_RANGE={{ subnet }}
volumes:
- "{{ root }}/overrides:/overrides"
deploy:
replicas: 1
# Optional services
{% if antispam_enabled %}
antispam:
image: mailu/rspamd:{{ version }}
env_file: {{ env }}
environment:
- POD_ADDRESS_RANGE={{ subnet }}
volumes:
- "{{ root }}/filter:/var/lib/rspamd"
- "{{ root }}/dkim:/dkim"
- "{{ root }}/overrides/rspamd:/etc/rspamd/override.d"
deploy:
replicas: 1
{% endif %}
{% if antivirus_enabled %}
antivirus:
image: mailu/clamav:{{ version }}
env_file: {{ env }}
volumes:
- "{{ root }}/filter:/data"
deploy:
replicas: 1
{% endif %}
{% if webdav_enabled %}
webdav:
image: mailu/none:{{ version }}
env_file: {{ env }}
volumes:
- "{{ root }}/dav:/data"
deploy:
replicas: 1
{% endif %}
{% if fetchmail_enabled %}
fetchmail:
image: mailu/fetchmail:{{ version }}
env_file: {{ env }}
volumes:
- "{{ root }}/data:/data"
deploy:
replicas: 1
{% endif %}
{% if webmail_type != 'none' %}
webmail:
image: mailu/roundcube:{{ version }}
env_file: {{ env }}
volumes:
- "{{ root }}/webmail:/data"
deploy:
replicas: 1
{% endif %}
networks:
default:
driver: overlay
ipam:
driver: default
config:
- subnet: {{ subnet }}

@ -0,0 +1 @@
../compose/mailu.env

@ -0,0 +1,60 @@
{% import "macros.html" as macros %}
{% call macros.panel("info", "Step 1 - Download your configuration files") %}
<p>Docker Stack expects a project file, named <code>docker-compose.yml</code>
in a project directory. First create your project directory.</p>
<pre><code>mkdir -p /{{ root }}/{redis,certs,data,dkim,mail,overrides/rspamd,filter,dav,webmail}
</pre></code>
<p>Then download the project file. A side configuration file makes it easier
to read and check the configuration variables generated by the wizard.</p>
<pre><code>cd {{ root }}
curl {{ url_for('.file', uid=uid, filepath='docker-compose.yml', _external=True) }} > docker-compose.yml
curl {{ url_for('.file', uid=uid, filepath='mailu.env', _external=True) }} > mailu.env
</pre></code>
{% endcall %}
{% call macros.panel("info", "Step 2 - Review the configuration") %}
<p>We did not insert any malicious code on purpose in the configurations we
distribute, but your download could have been intercepted, or our wizard
website could have been compromised, so make sure you check the configuration
files before going any further.</p>
<p>When you are done checking them, check them one last time.</p>
{% endcall %}
{% call macros.panel("info", "Step 3 - Deploy docker stack") %}
<p>To deploy the docker stack use the following commands. For more information about setting up docker swarm nodes read the
<a href="https://docs.docker.com/get-started">docker documentation</a></p>
<pre><code>cd {{ root }}
docker swarm init
docker stack deploy -c docker-compose.yml mailu
</pre></code>
In the docker stack deploy command, mailu is the app name. Feel free to change it.<br/>
In order to display the running container you can use<br/>
<pre><code>docker ps</code></pre>
or
<pre><code>docker stack ps --no-trunc mailu</code></pre>
Command for removing docker stack is
<pre><code>docker stack rm mailu</code></pre>
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>
<p>Login to the admin interface to change the password for a safe one, at
{% if admin_enabled %}
one of the hostnames
<a href="https://{{ hostnames.split(',')[0] }}{{ admin_path }}">{{ hostnames.split(',')[0] }}{{ admin_path }}</a>.
{% else %}
<a href="http://127.0.0.1:8080">http://127.0.0.1:8080</a> (only directly from the host running docker).
{% endif %}
And choose the "Update password" option in the left menu.
</p>
{% endcall %}

@ -32,9 +32,11 @@ def secret(length=16):
def build_app(path):
#Hardcoded master as the only version for test purposes
versions = [
version for version in os.listdir(path)
if os.path.isdir(os.path.join(path, version))
# version for version in os.listdir(path)
# if os.path.isdir(os.path.join(path, version))
"master"
]
app.jinja_env.trim_blocks = True
@ -63,6 +65,12 @@ def build_app(path):
def wizard():
return flask.render_template('wizard.html')
@bp.route("/submit_flavor", methods=["POST"])
def submit_flavor():
data = flask.request.form.copy()
steps = sorted(os.listdir(path + "/" + version + "/templates/steps/" + data["flavor"]))
return flask.render_template('wizard.html', flavor=data["flavor"], steps=steps)
@bp.route("/submit", methods=["POST"])
def submit():
data = flask.request.form.copy()

@ -8,7 +8,7 @@
<h1>Mailu configuration</h1>
<p>
Version
<select onchange="window.location.href=this.value;">
<select onchange="window.location.href=this.value;" class="btn btn-primary dropdown-toggle">
{% for available in versions %}
<option value="{{ url_for('{}.wizard'.format(available)) }}" {% if available == version %}selected{% endif %}>{{ available }}</option>
{% endfor %}

@ -9,10 +9,10 @@
</div>
{% endmacro %}
{% macro radio(name, value, emph, text) %}
{% macro radio(name, value, emph, text, current) %}
<div class="radio">
<label>
<input type="radio" name="{{ name }}" value="{{ value }}">
<input type="radio" name="{{ name }}" value="{{ value }}"{% if current == value %} checked="checked"{% endif %}>
{% if emph %}
<strong>{{ emph }}</strong>,
{% endif %}

@ -3,31 +3,27 @@
interface, Web email clients (webmails), antispam, antivirus, etc. If you
wish to disable some of these features, you are free to do so.</p>
<p>The admin interface is the main Mailu-specific bit, it provides tools to
manage your email domains, users, etc.</p>
<div class="form-group">
<label>Enable the admin UI (and path to the admin UI)</label>
<div class="input-group">
<div class="input-group-addon"><input type="checkbox" name="admin_enabled" checked></div>
<input class="form-control" type="text" name="admin_path" value="/admin">
</div>
</div>
<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 -->
<div class="form-group">
<label>Enable Web email client (and path to the Web email client)</label>
<div class="input-group">
<div class="input-group-addon"><input type="checkbox" name="webmail_enabled" checked></div>
<input class="form-control" type="text" name="webmail_path" value="/webmail">
</div>
<!-- <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/>
<select class="btn btn-primary dropdown-toggle" name="webmail_type">
{% for webmailtype in ["none", "roundcube", "rainloop"] %}
<option value="{{ webmailtype }}" >{{ webmailtype }}</option>
{% endfor %}
</select>
<p></p>
<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 class="input-group">
<!-- <div class="input-group-addon"><input type="checkbox" name="webmail_enabled" value="true"></div> -->
<input class="form-control" type="text" name="webmail_path" value="/webmail">
</div>
</div>
@ -38,15 +34,29 @@ also disable the antivirus if required (it does use aroung 1GB of ram).</p>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="antispam_enabled" checked>
Enable the filtering service
<input class="form-check-input" type="checkbox" name="antispam_enabled" value="rspamd" checked>
Enable the spam filtering service
</label>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="antivirus_enabled" checked>
<input class="form-check-input" type="checkbox" name="antivirus_enabled" value="clamav">
Enable the antivirus service
</label>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="webdav_enabled" value="radicale">
Enable the webdav service
</label>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="fetchmail_enabled" value="true">
Enable fetchmail
</label>
</div>
{% endcall %}

@ -0,0 +1,39 @@
{% call macros.panel("info", "Step 4 - expose Mailu to the world") %}
<p>A mail server must be exposed to the world to receive emails, send emails,
and let users access their mailboxes. Mailu has some flexibility in the way
you expose it to the world.</p>
<p>Among Mailu services, the <em>front</em> server is the one accepting connections,
be it directly from the outside world, through a reverse proxy or in any
complex configuration that you might want to setup. It needs to listen on some
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>
<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>
<div class="form-group">
<label>IPv4 listen address</label>
<!-- Validates IPv4 address -->
<input class="form-control" type="text" name="bind4" value="127.0.0.1"
pattern="^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$">
</div>
<div class="form-group">
<label>IPv6 listen address</label>
<!-- Validates IPv6 address -->
<input class="form-control" type="text" name="bind6" value="::1"
pattern="^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$">
</div>
<p>You server will be available under a main hostname but may expose multiple public
hostnames. Every e-mail domain that points to this server must have one of the
hostnames in its <code>MX</code> record. Hostnames must be coma-separated.</p>
<div class="form-group">
<label>Public hostnames</label>
<!-- Validates hostname or list of hostnames -->
<input class="form-control" type="text" name="hostnames" placeholder="my.host.name,other.host.name" multiple required
pattern="^(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)*(?:,(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)\s*)*$">
</div>
{% endcall %}

@ -0,0 +1,78 @@
{% call macros.panel("info", "Step 2 - Initial configuration") %}
<p>Before starting some variables must be set</p>
<div class="form-group">
<label>Root path: </label>
<!-- Validates path -->
<input class="form-control" type="text" name="root" value="/mailu" required pattern="^/[-_A-Za-z0-9]+(/[-_A-Za-z0-9]*)*">
</div>
<p>In the next sections we need to set the postmaster address. This is a combination from the <i>postmaster</i> local part and the <i>main mail domain</i>.
The <i>main mail domain</i> is also used as </i>"server display name"</i>. This is the way the SMTP server identifies himself when connecting to others.
The Postmaster will get an e-mail address &lt;postmaster&gt;@&lt;main_domain&gt;. This address will receive the DMARC "rua" and "ruf" reports.
Or in plain english: if receivers start to classify your mail as spam, this postmaster will be informed.</p>
<div class="form-group">
<label>
Main mail domain and server display name.
</label>
<!-- Validates domain name -->
<input class="form-control" type="text" name="domain" placeholder="e.g. mailu.io"
required pattern="^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$">
</div>
<div class="form-group">
<label>Postmaster local part</label>
<input class="form-control" type="text" name="postmaster" value="admin" required>
</div>
<div class="form-group">
<label>Choose how you wish to handle security (TLS) certificates</label>
<br/>
<select class="btn btn-primary dropdown-toggle" name="tls_flavor">
{% for tlsflavor in ["letsencrypt", "cert", "notls", "mail", "mail-letsencrypt"] %}
<option value="{{ tlsflavor }}" >{{ tlsflavor }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label>Authentication rate limit (per source IP address)</label>
<!-- Validates number input only -->
<p><input class="form-control" style="width: 7%; display: inline;" type="number" name="auth_ratelimit_pm"
value="10" required >/minute;
<input class="form-control" style="width: 7%; display: inline;;" type="number" name="auth_ratelimit_ph"
value="1000" required >/hour</p>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="disable_statistics" value="True">
Opt-out of statistics
</label>
</div>
<div class="form-group">
<label>Website name</label>
<input class="form-control" type="text" name="site_name" value="Mailu" required>
</div>
<div class="form-group">
<label>Linked Website URL</label>
<!-- Validates url with or without https:// -->
<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}$">
</div>
<p>The admin interface is the main Mailu-specific bit, it provides tools to
manage your email domains, users, etc.</p>
<div class="form-group">
<label>Enable the admin UI (and path to the admin UI)</label>
<div class="input-group">
<div class="input-group-addon"><input type="checkbox" name="admin_enabled" value="true"></div>
<input class="form-control" type="text" name="admin_path" value="/admin">
</div>
</div>
{% endcall %}

@ -1,33 +0,0 @@
{% call macros.panel("info", "Step 2 - expose Mailu to the world") %}
<p>A mail server must be exposed to the world to receive emails, send emails,
and let users access their mailboxes. Mailu has some flexibility in the way
you expose it to the world.</p>
<p>Among Mailu services, the <em>front</em> server is the one accepting connections,
be it directly from the outside world, through a reverse proxy or in any
complex configuration that you might want to setup. It needs to listen on some
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>
<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>
<div class="form-group">
<label>IPv4 listen address</label>
<input class="form-control" type="text" name="ip4" placeholder="1.2.3.4">
</div>
<div class="form-group">
<label>IPv6 listen address</label>
<input class="form-control" type="text" name="ip6" placeholder="2001:be4:1234::1">
</div>
<p>You server will be available under a main hostname but may expose multiple public
hostnames. Every e-mail domain that points to this server must have one of the
hostnames in its <code>MX</code> record. Hostnames must be coma-separated.</p>
<div class="form-group">
<label>Public hostnames</label>
<input class="form-control" type="text" name="hostnames" placeholder="my.host.name,other.host.name" multiple>
</div>
{% endcall %}

@ -7,10 +7,10 @@ developpers, will mostly cover Compose and Stack, while other flavors are
maintained by specific contributors.</p>
<div class="radio">
{{ macros.radio("flavor", "compose", "Compose", "simply using Docker Compose manager") }}
{{ macros.radio("flavor", "stack", "Stack", "using stack deployments in a Swarm cluster") }}
{{ macros.radio("flavor", "rancher", "Rancher", "on top of the Rancher container manager") }}
{{ macros.radio("flavor", "kubernetes", "Kubernetes", "on top of the Kubernetes container manager") }}
{{ 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", "rancher", "Rancher", "on top of the Rancher container manager", flavor) }}
{{ macros.radio("flavor", "kubernetes", "Kubernetes", "on top of the Kubernetes container manager", flavor) }}
</div>
{% endcall %}

@ -1,16 +0,0 @@
{% call macros.panel("info", "Step 4 - enable optional features") %}
<p>Mailu also comes with less common optional features that you might wish
to enable.</p>
<p>The DAV service enables contacts and calendar storage through Mailu,
it is especially userful when synchronizing your desktop and mobile devices.</p>
<div class="form-group">
<label>Enable the DAV service (and path to the DAV service)</label>
<div class="input-group">
<div class="input-group-addon"><input type="checkbox" name="dav_enabled" checked></div>
<input class="form-control" type="text" name="admin_path" value="/webdav">
</div>
</div>
{% endcall %}

@ -0,0 +1,62 @@
{% call macros.panel("info", "Step 3 - pick some features") %}
<p>Mailu comes with multiple base features, including a specific admin
interface, Web email clients (webmails), antispam, antivirus, etc. If you
wish to disable some of these features, you are free to do so.</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 -->
<div class="form-group">
<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/>
<select class="btn btn-primary dropdown-toggle" name="webmail_type">
{% for webmailtype in ["none", "roundcube", "rainloop"] %}
<option value="{{ webmailtype }}" >{{ webmailtype }}</option>
{% endfor %}
</select>
<p></p>
<div class="input-group">
<!-- <div class="input-group-addon"><input type="checkbox" name="webmail_enabled" value="true"></div> -->
<input class="form-control" type="text" name="webmail_path" value="/webmail">
</div>
</div>
<p>Email filtering is a really important features. You can still disable it, which
will prevent Mailu from doing spam filtering, virus filtering, and from applying
white and blacklists that you may configure in the admin interface. You may
also disable the antivirus if required (it does use aroung 1GB of ram).</p>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="antispam_enabled" value="rspamd" checked>
Enable the spam filtering service
</label>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="antivirus_enabled" value="clamav">
Enable the antivirus service
</label>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="webdav_enabled" value="radicale">
Enable the webdav service
</label>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="fetchmail_enabled" value="true">
Enable fetchmail
</label>
</div>
{% endcall %}

@ -0,0 +1,21 @@
{% call macros.panel("info", "Step 4 - expose Mailu to the world") %}
<p>A mail server must be exposed to the world to receive emails, send emails,
and let users access their mailboxes. Mailu has some flexibility in the way
you expose it to the world.</p>
<div class="form-group">
<label>Subnet</label>
<input class="form-control" type="text" name="subnet" required pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))$">
</div>
<p>You server will be available under a main hostname but may expose multiple public
hostnames. Every e-mail domain that points to this server must have one of the
hostnames in its <code>MX</code> record. Hostnames must be coma-separated.</p>
<div class="form-group">
<label>Public hostnames</label>
<!-- Validates hostname or list of hostnames -->
<input class="form-control" type="text" name="hostnames" placeholder="my.host.name,other.host.name" multiple required
pattern="^(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)*(?:,(?:(?:\w+(?:-+\w+)*\.)+[a-z]+)\s*)*$">
</div>
{% endcall %}

@ -8,12 +8,18 @@
ready when using this wizard.
{% endcall %}
<form method="post" action="{{ url_for(".submit") }}">
<form method="post" action="{{ url_for(".submit_flavor") }}">
{% include "steps/flavor.html" %}
{% include "steps/expose.html" %}
{% include "steps/services.html" %}
{% include "steps/optional.html" %}
<input class="btn btn-primary" type="submit" value="Next >" style="margin-bottom: 15px">
</form>
{% if flavor %}
<form method="post" action="{{ url_for(".submit") }}">
<input type="hidden" name="flavor" value="{{ flavor }}">
{% include "steps/config.html" %}
{%for file in steps %}
{% include "steps/" + flavor + "/" + file %}
{% endfor %}
<input class="btn btn-primary" type="submit" value="Setup Mailu">
{% endif %}
</form>
{% endblock %}

Loading…
Cancel
Save