diff --git a/dovecot/to-do_put_config_files_here b/dovecot/to-do_put_config_files_here new file mode 100644 index 0000000..e69de29 diff --git a/modoboa/gunicorn.conf.py b/modoboa/gunicorn.conf.py new file mode 100644 index 0000000..061243c --- /dev/null +++ b/modoboa/gunicorn.conf.py @@ -0,0 +1,8 @@ +backlog = 2048 +bind = "unix:/opt/modoboa/gunicorn.sock" +pidfile = "/opt/modoboa/gunicorn.pid" +daemon = False +debug = True +workers = 2 +logfile = "/var/log/modoboa/gunicorn.log" +loglevel = "debug" diff --git a/modoboa/settings.py b/modoboa/settings.py new file mode 100644 index 0000000..3539785 --- /dev/null +++ b/modoboa/settings.py @@ -0,0 +1,356 @@ +""" +Django settings for instance01 project. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.2/ref/settings/ +""" + +from logging.handlers import SysLogHandler +import os + + + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'xxx' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False + +ALLOWED_HOSTS = [ + 'modoboa-theia-local.local', +] + +SITE_ID = 1 + +# A list of all the people who get code error notifications. When DEBUG=False +# and a view raises an exception, Django will email these people with the full +# exception information. +# See https://docs.djangoproject.com/en/dev/ref/settings/#admins +#ADMINS = [('Administrator', 'admin@example.net')] + +# The email address that error messages come from, such as those sent to ADMINS +#SERVER_EMAIL = 'webmaster@example.net' + +# Security settings + +X_FRAME_OPTIONS = "SAMEORIGIN" +CSRF_COOKIE_DOMAIN = "modoboa-theia.local" +CSRF_COOKIE_SECURE = True +SESSION_COOKIE_SECURE = True + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.sites', + 'django.contrib.staticfiles', + 'reversion', + 'ckeditor', + 'ckeditor_uploader', + 'rest_framework', + 'rest_framework.authtoken', + 'phonenumber_field', + 'django_otp', + 'django_otp.plugins.otp_totp', + 'django_otp.plugins.otp_static', + +) + +# A dedicated place to register Modoboa applications +# Do not delete it. +# Do not change the order. +MODOBOA_APPS = ( + 'modoboa', + 'modoboa.core', + 'modoboa.lib', + 'modoboa.admin', + 'modoboa.transport', + 'modoboa.relaydomains', + 'modoboa.limits', + 'modoboa.parameters', + 'modoboa.dnstools', + 'modoboa.policyd', + 'modoboa.maillog', + # Modoboa extensions here. + 'modoboa_dmarc', + 'modoboa_imap_migration', +# 'modoboa_pdfcredentials', + 'modoboa_postfix_autoreply', + 'modoboa_sievefilters', + 'modoboa_webmail', + +) + +INSTALLED_APPS += MODOBOA_APPS + +AUTH_USER_MODEL = 'core.User' + +MIDDLEWARE = ( + 'x_forwarded_for.middleware.XForwardedForMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django_otp.middleware.OTPMiddleware', + 'modoboa.core.middleware.TwoFAMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'modoboa.core.middleware.LocalConfigMiddleware', + 'modoboa.lib.middleware.AjaxLoginRedirect', + 'modoboa.lib.middleware.CommonExceptionCatcher', + 'modoboa.lib.middleware.RequestCatcherMiddleware', +) + +AUTHENTICATION_BACKENDS = ( + # 'modoboa.lib.authbackends.LDAPBackend', + # 'modoboa.lib.authbackends.SMTPBackend', + 'django.contrib.auth.backends.ModelBackend', +) + +# SMTP authentication +# AUTH_SMTP_SERVER_ADDRESS = 'localhost' +# AUTH_SMTP_SERVER_PORT = 25 +# AUTH_SMTP_SECURED_MODE = None # 'ssl' or 'starttls' are accepted + + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + 'modoboa.core.context_processors.top_notifications', + ], + 'debug': False, + }, + }, +] + +ROOT_URLCONF = 'instance01.urls' + +WSGI_APPLICATION = 'instance01.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases + +DATABASES = { + + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': '$db', + 'USER': '$dbuser', + 'PASSWORD': '$dbsec', + 'HOST': '$dbhost', + 'PORT': '', + 'ATOMIC_REQUESTS': True, + 'OPTIONS' : { + "init_command" : 'SET foreign_key_checks = 0;', + }, + }, + +} + +# Internationalization +# https://docs.djangoproject.com/en/2.2/topics/i18n/ + +LANGUAGE_CODE = 'en' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.2/howto/static-files/ + +STATIC_URL = '/sitestatic/' +STATIC_ROOT = os.path.join(BASE_DIR, 'sitestatic') +STATICFILES_DIRS = ( + '/opt/modoboa/modoboa-venv/lib/python3.6/site-packages/modoboa/bower_components', +) + +MEDIA_URL = '/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +# Rest framework settings + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework.authentication.TokenAuthentication', + 'rest_framework.authentication.SessionAuthentication', + ), +} + +# Modoboa settings +# MODOBOA_CUSTOM_LOGO = os.path.join(MEDIA_URL, "custom_logo.png") + +# DOVECOT_LOOKUP_PATH = ('/path/to/dovecot', ) + +MODOBOA_API_URL = 'https://api.modoboa.org/1/' + +DISABLE_DASHBOARD_EXTERNAL_QUERIES = False + +# REDIS + +REDIS_HOST = '$rdbhost' +REDIS_PORT = 6379 +REDIS_QUOTA_DB = 0 +REDIS_URL = 'redis://{}:{}/{}'.format(REDIS_HOST, REDIS_PORT, REDIS_QUOTA_DB) + +# Password validation +# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, + { + 'NAME': 'modoboa.core.password_validation.ComplexityValidator', + 'OPTIONS': { + 'upper': 1, + 'lower': 1, + 'digits': 1, + 'specials': 0 + } + }, +] + +# 2FA + +OTP_TOTP_ISSUER = "3gy.de" + +# CKeditor + +CKEDITOR_UPLOAD_PATH = "uploads/" + +CKEDITOR_IMAGE_BACKEND = "pillow" + +CKEDITOR_RESTRICT_BY_USER = True + +CKEDITOR_BROWSE_SHOW_DIRS = True + +CKEDITOR_ALLOW_NONIMAGE_FILES = False + +CKEDITOR_CONFIGS = { + 'default': { + 'allowedContent': True, + 'toolbar': 'Modoboa', + 'width': None, + 'toolbar_Modoboa': [ + ['Bold', 'Italic', 'Underline'], + ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'], + ['BidiLtr', 'BidiRtl', 'Language'], + ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'], + ['Undo', 'Redo'], + ['Link', 'Unlink', 'Anchor', '-', 'Smiley'], + ['TextColor', 'BGColor', '-', 'Source'], + ['Font', 'FontSize'], + ['Image', ], + ['SpellChecker'] + ], + }, +} + +# Logging configuration + +LOGGING = { + 'version': 1, + 'formatters': { + 'syslog': { + 'format': '%(name)s: %(levelname)s %(message)s' + }, + }, + 'handlers': { + 'mail-admins': { + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler', + 'include_html': True + }, + 'syslog-auth': { + 'class': 'logging.handlers.SysLogHandler', + 'facility': SysLogHandler.LOG_AUTH, + 'formatter': 'syslog' + }, + 'syslog-mail': { + 'class': 'logging.handlers.SysLogHandler', + 'facility': SysLogHandler.LOG_MAIL, + 'formatter': 'syslog' + }, + 'modoboa': { + 'class': 'modoboa.core.loggers.SQLHandler', + } + }, + 'loggers': { + 'django': { + 'handlers': ['mail-admins'], + 'level': 'ERROR', + 'propagate': False + }, + 'modoboa.auth': { + 'handlers': ['syslog-auth', 'modoboa'], + 'level': 'INFO', + 'propagate': False + }, + 'modoboa.admin': { + 'handlers': ['modoboa'], + 'level': 'INFO', + 'propagate': False + }, + 'modoboa.policyd': { + 'handlers': ['syslog-mail'], + 'level': 'INFO', + 'propagate': False + } + } +} + +SILENCED_SYSTEM_CHECKS = [ + "security.W019", # modoboa uses iframes to display e-mails +] + +PHONENUMBER_DB_FORMAT = 'INTERNATIONAL' + +# Load settings from extensions + +try: + from modoboa_imap_migration import settings as modoboa_imap_migration_settings + modoboa_imap_migration_settings.apply(globals()) +except AttributeError: + from modoboa_imap_migration.settings import * # noqa + diff --git a/opendkim/OpenDKIM-Docker/Dockerfile b/opendkim/OpenDKIM-Docker/Dockerfile new file mode 100644 index 0000000..9d48332 --- /dev/null +++ b/opendkim/OpenDKIM-Docker/Dockerfile @@ -0,0 +1,53 @@ +FROM alpine:3.14 + +COPY sources/* /opt/OpenDKIM-Docker/ +COPY opendkim.conf /etc/opendkim/opendkim.conf +ADD syscid-ca.crt /usr/local/share/ca-certificates/syscid.crt + + +RUN apk add --no-cache \ + alpine-sdk \ + ca-certificates \ + curl \ + automake \ + autoconf \ + db-dev \ + libtool \ + mariadb-dev \ + readline-dev \ + gettext \ + && cd /opt/OpenDKIM-Docker \ + && tar xzf opendbx-1.4.6.tar.gz \ + && cd opendbx-1.4.6/ \ + && CPPFLAGS="-I/usr/include/mysql" ./configure --with-backends="mysql" \ + && make -j4 \ + && make install + +RUN apk add --no-cache \ + openssl-dev \ + libmilter-dev \ + && cd /opt/OpenDKIM-Docker/ \ + && tar xzf 2.11.0-Beta2.tar.gz \ + && cd OpenDKIM-2.11.0-Beta2 \ + && autoreconf -vif \ + && CPPFLAGS="-I/usr/include/openssl" ./configure \ + --sysconfdir=/etc/opendkim \ + --with-odbx \ + --with-openssl \ + --with-sql-backend \ + && make -j4 \ + && make install + +RUN mkdir /run/opendkim \ + mkdir /var/lib/opendkim \ + && addgroup -S opendkim && adduser -S opendkim -h /var/lib/opendkim -G opendkim \ + && chown opendkim:opendkim /run/opendkim \ + && chown opendkim:opendkim /var/lib/opendkim \ + && chown opendkim:opendkim /etc/opendkim + +RUN update-ca-certificates + +EXPOSE 8960 + +ENTRYPOINT ["/usr/local/sbin/opendkim"] +CMD ["-f", "-v", "-x", "/etc/opendkim/opendkim.conf"] diff --git a/opendkim/OpenDKIM-Docker/opendkim.conf b/opendkim/OpenDKIM-Docker/opendkim.conf new file mode 100644 index 0000000..f8a7ec2 --- /dev/null +++ b/opendkim/OpenDKIM-Docker/opendkim.conf @@ -0,0 +1,9 @@ +KeyTable dsn:mysql://$dbuser:$dbsec@$dbhost/$db/table=dkim?keycol=id?datacol=domain_name,selector,private_key_path +PidFile /run/opendkim/opendkim.pid +Selector default +SigningTable dsn:mysql://$dbuser:$dbsec@$dbhost/$db/table=dkim?keycol=domain_name?datacol=id +Socket local:/run/opendkim/opendkim.sock +Socket inet:8960@127.0.0.1 +Syslog Yes +UMask 002 +UserID opendkim:opendkim diff --git a/opendkim/OpenDKIM-Docker/sources/2.11.0-Beta2.tar.gz b/opendkim/OpenDKIM-Docker/sources/2.11.0-Beta2.tar.gz new file mode 100644 index 0000000..0575267 Binary files /dev/null and b/opendkim/OpenDKIM-Docker/sources/2.11.0-Beta2.tar.gz differ diff --git a/opendkim/OpenDKIM-Docker/sources/opendbx-1.4.6.tar.gz b/opendkim/OpenDKIM-Docker/sources/opendbx-1.4.6.tar.gz new file mode 100644 index 0000000..ffc4eb4 Binary files /dev/null and b/opendkim/OpenDKIM-Docker/sources/opendbx-1.4.6.tar.gz differ diff --git a/opendkim/OpenDKIM-Docker/syscid-ca.crt b/opendkim/OpenDKIM-Docker/syscid-ca.crt new file mode 100644 index 0000000..3ac52fa --- /dev/null +++ b/opendkim/OpenDKIM-Docker/syscid-ca.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIUUtCa6jguJLt20qzq/MR82JX/6JQwDQYJKoZIhvcNAQEL +BQAwTzEUMBIGA1UECgwLTGliZXJ0YUNhc2ExEzARBgNVBAMMCnN5c2NpZC5jb20x +IjAgBgkqhkiG9w0BCQEWE3N5c3RlbUBseXNlcmdpYy5kZXYwHhcNMjEwODEwMDAy +MjM2WhcNMjIwODEwMDAyMjM2WjBPMRQwEgYDVQQKDAtMaWJlcnRhQ2FzYTETMBEG +A1UEAwwKc3lzY2lkLmNvbTEiMCAGCSqGSIb3DQEJARYTc3lzdGVtQGx5c2VyZ2lj +LmRldjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO0m7lpEZwGB1pxo +24RESADjbnk6iGmH783cuMo7jzio6P5vZk8FRD0/8Gmli/sOe8oZ2hGE5sNx4RKK +4g7kDVnYznHS6k5zpBzU4FP9wVMho/TcfaXlCdSwj6Ih0mLxDYzvX0l12Gi1K9gg +0HxdG2XPfslQbk6py1jQYVkRjwZIj2ya7t7/fNyn6S7flVUIvvcvZd3eNvAlg4ZU +wDV1H5mF3s42Iv5TOEYi88n7yXUex5I9xi5NqG/qOuYuC69yYobI/WjfId7bUDPT +UjZJFD5wHUHwtBmjp2bdyzdl9Z9iJp24jhR3Syi4h/BjYFwUG793PjP8DZBWtrOC +jHoOwkCyYFfOTa8n+Knb8i2FSuX4TgMZeFwcLpSsecBIjknKHPNYW2NTcP7S/Xbl +KpP2fpN7JBlR8WTi9+WQZVHuMfU1rjp3Kjwj9dmjcWsOMuMEqJUZMSsMpUBKULbq +6QFhMPJL+yYDHg1S0E3ymHRU94mlQ57mQwAg0AraCDtdPR3zw+gh2k1hUEkva26G +zHYigssbhCT81Dp4Ez65tKHZoKYKvgywJ6gb7PURS8Ued8PSDEhJd18WN22l4xQP +k08fg+mB5gHXNNGzYVETPalrWmk9IHczQnDITWM1hj14VhIcwa9oMNesIllviL7/ +BRjiz6jHZfc3Htp4NZ/5sBgFDUelAgMBAAGjUzBRMB0GA1UdDgQWBBSU/TIhYSYN +HQ3+7ueHMmkVD8BZRzAfBgNVHSMEGDAWgBSU/TIhYSYNHQ3+7ueHMmkVD8BZRzAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCLf0GU+mrZo4l7qMJz +WfNFxZv3E5GFRgl1NlUfJM2hnpgqrT7ukXcRnY4n9KtLx14QWHpPdX7KyLsSqx6X +UoPsJNywYQNVyAQ0qddY4glGV8u6+QE1zN1yUw6CMbsqWz50T76r1Y1CRZuMyffU +OeVhBM17sWibgDbev0SmG12uYTkq7qmbCKOWUhbaL1jCE1yvu9ZFFXCQ/OaAMyn9 +fYyyn48z7MHsyISuBdAcJkR2JkIgL4oZufw5hcecZ1wcnmYTRm6owuhUsZ2FYXkU +5o2Pn6nce1QEaUKsik8xBNA0/jIBCkiPDb5/eIA8Yys7pb/DeFEE/X0JM9rhoOk7 +tXOvxV2S7Y1xRqVwa3mrlp/0yXHuBb+u3/1+jsxkaeSPQ8FRejPIZzeOGhVHPaub +RdvzSO0TBK54vLA0CrkDRLgFdyuzsvm6VMVqGpcKn/aaju7pLI/knJzITaHHxzqV +wxmA0kf/68+wVvdICZt4R3iqSU9KVmCmh6owTixNTgh1wLmFIyMl2VhOwibFVg4L +600gIb59wEV4tWnYEX3Ugsw8g0ZXoqPDA27CPlpmgaVXwBv1qssRYnUreZEXxEN3 +4A1UOTdjMPn9v1wqmBwTCb9MULX60byX72YPMOnuSAQyptbXx8oMvInK91T5ivZ0 +JpmySX/Gfpgrr7HSI9+cD3eUcQ== +-----END CERTIFICATE----- diff --git a/postfix/to-do_put_config_files_here b/postfix/to-do_put_config_files_here new file mode 100644 index 0000000..e69de29