mirror of
https://github.com/Mailu/Mailu.git
synced 2024-12-14 10:53:30 +02:00
86b4242f82
886: Ipv6 support r=mergify[bot] a=muhlemmer ## What type of PR? (Feature, enhancement, bug-fix, documentation) -> A bit of everything ## What does this PR do? Document how to use ipv6nat. This, however triggers some kind of flaky behavior with the Docker DNS resolver, resulting in lookup failures between containers. So all resolving needs to be done during container startup/configuration. In order not to pollute every single start.py file, we've created a small library called [Mailu/MailuStart](https://github.com/Mailu/MailuStart). As an addition, this library also defines the template generation function, including its logging facility. Note: `docker-compose.yml` downgrade is necessary, as IPv6 settings are not supported by the Docker Compose file format 3 😞 ### Related issue(s) Supersedes PR #844 - Fixes #827 - Hopefully helps with #829 and #834 ## No backport yet This PR directly imports MailuStart from git. This makes it a bit more simple to implement on the short term an do some testing and probably some future improvements. When everything is proved stable, we will create a proper PyPi package with versioning and consider back porting. ## Prerequistes Before we can consider review and merge, please make sure the following list is done and checked. If an entry in not applicable, you can check it or remove it from the list. - [x] In case of feature or enhancement: documentation updated accordingly - [x] Unless it's docs or a minor change: place entry in the [changelog](CHANGELOG.md), under the latest un-released version. Co-authored-by: Ionut Filip <ionut.philip@gmail.com> Co-authored-by: Tim Möhlmann <muhlemmer@gmail.com>
125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
import os
|
|
from mailustart import resolve
|
|
|
|
DEFAULT_CONFIG = {
|
|
# Specific to the admin UI
|
|
'DOCKER_SOCKET': 'unix:///var/run/docker.sock',
|
|
'BABEL_DEFAULT_LOCALE': 'en',
|
|
'BABEL_DEFAULT_TIMEZONE': 'UTC',
|
|
'BOOTSTRAP_SERVE_LOCAL': True,
|
|
'RATELIMIT_STORAGE_URL': 'redis://redis/2',
|
|
'QUOTA_STORAGE_URL': 'redis://redis/1',
|
|
'DEBUG': False,
|
|
'DOMAIN_REGISTRATION': False,
|
|
'TEMPLATES_AUTO_RELOAD': True,
|
|
# Database settings
|
|
'DB_FLAVOR': None,
|
|
'DB_USER': 'mailu',
|
|
'DB_PW': None,
|
|
'DB_HOST': 'database',
|
|
'DB_NAME': 'mailu',
|
|
'SQLITE_DATABASE_FILE':'data/main.db',
|
|
'SQLALCHEMY_DATABASE_URI': 'sqlite:////data/main.db',
|
|
'SQLALCHEMY_TRACK_MODIFICATIONS': False,
|
|
# Statistics management
|
|
'INSTANCE_ID_PATH': '/data/instance',
|
|
'STATS_ENDPOINT': '0.{}.stats.mailu.io',
|
|
# Common configuration variables
|
|
'SECRET_KEY': 'changeMe',
|
|
'DOMAIN': 'mailu.io',
|
|
'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io',
|
|
'POSTMASTER': 'postmaster',
|
|
'TLS_FLAVOR': 'cert',
|
|
'AUTH_RATELIMIT': '10/minute;1000/hour',
|
|
'DISABLE_STATISTICS': False,
|
|
# Mail settings
|
|
'DMARC_RUA': None,
|
|
'DMARC_RUF': None,
|
|
'WELCOME': False,
|
|
'WELCOME_SUBJECT': 'Dummy welcome topic',
|
|
'WELCOME_BODY': 'Dummy welcome body',
|
|
'DKIM_SELECTOR': 'dkim',
|
|
'DKIM_PATH': '/dkim/{domain}.{selector}.key',
|
|
'DEFAULT_QUOTA': 1000000000,
|
|
# Web settings
|
|
'SITENAME': 'Mailu',
|
|
'WEBSITE': 'https://mailu.io',
|
|
'WEB_ADMIN': '/admin',
|
|
'WEB_WEBMAIL': '/webmail',
|
|
'RECAPTCHA_PUBLIC_KEY': '',
|
|
'RECAPTCHA_PRIVATE_KEY': '',
|
|
# Advanced settings
|
|
'PASSWORD_SCHEME': 'BLF-CRYPT',
|
|
# Host settings
|
|
'HOST_IMAP': 'imap',
|
|
'HOST_POP3': 'imap',
|
|
'HOST_SMTP': 'smtp',
|
|
'HOST_WEBMAIL': 'webmail',
|
|
'HOST_FRONT': 'front',
|
|
'HOST_AUTHSMTP': os.environ.get('HOST_SMTP', 'smtp'),
|
|
'SUBNET': '192.168.203.0/24',
|
|
'POD_ADDRESS_RANGE': None
|
|
}
|
|
|
|
class ConfigManager(dict):
|
|
""" Naive configuration manager that uses environment only
|
|
"""
|
|
|
|
DB_TEMPLATES = {
|
|
'sqlite': 'sqlite:////{SQLITE_DATABASE_FILE}',
|
|
'postgresql': 'postgresql://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}',
|
|
'mysql': 'mysql://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}'
|
|
}
|
|
|
|
def __init__(self):
|
|
self.config = dict()
|
|
|
|
def resolve_host(self):
|
|
self.config['HOST_IMAP'] = resolve(self.config['HOST_IMAP'])
|
|
self.config['HOST_POP3'] = resolve(self.config['HOST_POP3'])
|
|
self.config['HOST_AUTHSMTP'] = resolve(self.config['HOST_AUTHSMTP'])
|
|
self.config['HOST_SMTP'] = resolve(self.config['HOST_SMTP'])
|
|
|
|
def __coerce_value(self, value):
|
|
if isinstance(value, str) and value.lower() in ('true','yes'):
|
|
return True
|
|
elif isinstance(value, str) and value.lower() in ('false', 'no'):
|
|
return False
|
|
return value
|
|
|
|
def init_app(self, app):
|
|
self.config.update(app.config)
|
|
# get environment variables
|
|
self.config.update({
|
|
key: self.__coerce_value(os.environ.get(key, value))
|
|
for key, value in DEFAULT_CONFIG.items()
|
|
})
|
|
self.resolve_host()
|
|
|
|
# automatically set the sqlalchemy string
|
|
if self.config['DB_FLAVOR']:
|
|
template = self.DB_TEMPLATES[self.config['DB_FLAVOR']]
|
|
self.config['SQLALCHEMY_DATABASE_URI'] = template.format(**self.config)
|
|
# update the app config itself
|
|
app.config = self
|
|
|
|
def setdefault(self, key, value):
|
|
if key not in self.config:
|
|
self.config[key] = value
|
|
return self.config[key]
|
|
|
|
def get(self, *args):
|
|
return self.config.get(*args)
|
|
|
|
def keys(self):
|
|
return self.config.keys()
|
|
|
|
def __getitem__(self, key):
|
|
return self.config.get(key)
|
|
|
|
def __setitem__(self, key, value):
|
|
self.config[key] = value
|
|
|
|
def __contains__(self, key):
|
|
return key in self.config
|