diff --git a/pillar/id/mailman3_infra_opensuse_org.sls b/pillar/id/mailman3_infra_opensuse_org.sls
new file mode 100644
index 0000000..993ac20
--- /dev/null
+++ b/pillar/id/mailman3_infra_opensuse_org.sls
@@ -0,0 +1,20 @@
+grains:
+ city: nuremberg
+ country: de
+ hostusage:
+ - lists.o.o
+ roles:
+ - mailman3
+ reboot_safe: yes
+ salt_cluster: opensuse
+ virt_cluster: atreju
+
+ aliases: []
+ description: Mailman 3 setup for the openSUSE Mailing Lists
+ documentation:
+ - https://www.list.org
+ responsible:
+ - hellcp
+ partners: []
+ weburls:
+ - https://lists.opensuse.org
diff --git a/pillar/role/mailman3.sls b/pillar/role/mailman3.sls
new file mode 100644
index 0000000..eb100a7
--- /dev/null
+++ b/pillar/role/mailman3.sls
@@ -0,0 +1,17 @@
+# Special config for mailman in the postfix relay
+profile:
+ postfix:
+ maincf:
+ recipient_delimiter: '+'
+ unknown_local_recipient_reject_code: '550'
+ owner_request_special: 'no'
+ transport_maps: 'hash://var/lib/mailman/data/postfix_lmtp'
+ local_recipient_maps: 'hash://var/lib/mailman/data/postfix_lmtp'
+ relay_domains: 'hash://var/lib/mailman/data/postfix_domains'
+ mailman3:
+ admin_user: mailman
+ database_user: mailman
+ database_host: postgres.infra.opensuse.org
+ server_list:
+ - lists.opensuse.org
+ - mailman3.infra.opensuse.org
diff --git a/pillar/secrets/role/mailman3.sls b/pillar/secrets/role/mailman3.sls
new file mode 100644
index 0000000..9a923bf
--- /dev/null
+++ b/pillar/secrets/role/mailman3.sls
@@ -0,0 +1,368 @@
+#!yaml|gpg
+
+profile:
+ mailman3:
+ secret_key: |
+ -----BEGIN PGP MESSAGE-----
+
+ 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
+ ByL2zg==
+ =NVn3
+ -----END PGP MESSAGE-----
+ admin_pass: |
+ -----BEGIN PGP MESSAGE-----
+
+ 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
+ dvlPmA==
+ =CQkD
+ -----END PGP MESSAGE-----
+ archiver_key: |
+ -----BEGIN PGP MESSAGE-----
+
+ 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
+ mr/gcg==
+ =R22r
+ -----END PGP MESSAGE-----
+
+postgres:
+ users:
+ mailman3:
+ password: |
+ -----BEGIN PGP MESSAGE-----
+
+ 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
+ 9g3BqQ==
+ =L9cL
+ -----END PGP MESSAGE-----
diff --git a/salt/profile/mailman3/config.sls b/salt/profile/mailman3/config.sls
new file mode 100644
index 0000000..3eaae78
--- /dev/null
+++ b/salt/profile/mailman3/config.sls
@@ -0,0 +1,118 @@
+mailman_conf_dir:
+ file.directory:
+ - name: /etc/mailman/
+
+mailman_var_dir:
+ file.directory:
+ - name: /var/lib/mailman/
+
+# Preparation for when we have a set of templates for mailman core
+
+mailman_template_dir:
+ file.directory:
+ - name: /var/lib/mailman/templates/
+
+mailman_webui_dir:
+ file.directory:
+ - name: /var/lib/mailman_webui/
+
+# Preparation for when we have a theme for hyperkitty
+
+mailman_webui_template_dir:
+ file.directory:
+ - name: /var/lib/mailman_webui/templates/
+
+mailman_webui_static_dir:
+ file.directory:
+ - name: /var/lib/mailman_webui/static-openSUSE/
+
+mailman_conf_file:
+ file.managed:
+ - name: /etc/mailman/mailman.cfg
+ - source: salt://profile/lists/files/mailman.cfg
+ - template: jinja
+ - require:
+ - file: mailman_conf_dir
+ - require_in:
+ - service: mailman_service
+ - watch_in:
+ - module: mailman_restart
+
+mailman_webui_manage_file:
+ file.managed:
+ - name: /var/lib/mailman_webui/manage.py
+ - source: salt://profile/lists/files/manage.py
+ - template: jinja
+ - require:
+ - file: mailman_webui_dir
+ - require_in:
+ - service: mailman_service
+ - watch_in:
+ - module: mailman_restart
+
+mailman_webui_settings_file:
+ file.managed:
+ - name: /var/lib/mailman_webui/settings.py
+ - source: salt://profile/lists/files/settings.py
+ - template: jinja
+ - require:
+ - file: mailman_webui_dir
+ - require_in:
+ - service: mailman_service
+ - watch_in:
+ - module: mailman_restart
+
+mailman_webui_urls_file:
+ file.managed:
+ - name: /var/lib/mailman/urls.py
+ - source: salt://profile/lists/files/urls.py
+ - template: jinja
+ - require:
+ - file: mailman_webui_dir
+ - require_in:
+ - service: mailman_service
+ - watch_in:
+ - module: mailman_restart
+
+mailman_webui_wsgi_file:
+ file.managed:
+ - name: /var/lib/mailman_webui/wsgi.py
+ - source: salt://profile/lists/files/wsgi.py
+ - template: jinja
+ - require:
+ - file: mailman_webui_dir
+ - require_in:
+ - service: mailman_service
+ - watch_in:
+ - module: mailman_restart
+
+mailman_disable_signup:
+ file.managed:
+ - name: /var/lib/mailman_webui/django_fedora_nosignup.py
+ - source: salt://profile/lists/files/django_fedora_nosignup.py
+ - require:
+ - file: mailman_webui_dir
+
+mailman_uwsgi_conf:
+ file.managed:
+ - name: /etc/mailman/uwsgi.ini
+ - source: salt://profile/lists/files/uwsgi.ini
+ - template: jinja
+ - require:
+ - file: mailman_conf_dir
+ - require_in:
+ - service: mailman_service
+ - watch_in:
+ - module: mailman_restart
+
+mailman_hyperkitty_conf:
+ file.managed:
+ - name: /etc/mailman/hyperkitty.cfg
+ - source: salt://profile/lists/files/hyperkitty.cfg
+ - template: jinja
+ - require:
+ - file: mailman_conf_dir
+ - require_in:
+ - service: mailman_service
+ - watch_in:
+ - module: mailman_restart
diff --git a/salt/profile/mailman3/files/django_fedora_nosignup.py b/salt/profile/mailman3/files/django_fedora_nosignup.py
new file mode 100644
index 0000000..22a2df0
--- /dev/null
+++ b/salt/profile/mailman3/files/django_fedora_nosignup.py
@@ -0,0 +1,14 @@
+# Disable local signup
+
+from allauth.account.adapter import DefaultAccountAdapter
+from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
+
+class NoLocalSignUpAdapter(DefaultAccountAdapter):
+
+ def is_open_for_signup(self, request):
+ return False
+
+class SignUpEnabledSocialAdapter(DefaultSocialAccountAdapter):
+
+ def is_open_for_signup(self, request, sociallogin):
+ return True
diff --git a/salt/profile/mailman3/files/hyperkitty.cfg b/salt/profile/mailman3/files/hyperkitty.cfg
new file mode 100644
index 0000000..49a1c94
--- /dev/null
+++ b/salt/profile/mailman3/files/hyperkitty.cfg
@@ -0,0 +1,20 @@
+# This is the mailman extension configuration file to enable HyperKitty as an
+# archiver. Remember to add the following lines in the mailman.cfg file:
+#
+# [archiver.hyperkitty]
+# class: mailman_hyperkitty.Archiver
+# enable: yes
+# configuration: /path/to/here/hyperkitty.cfg
+#
+
+[general]
+
+# This is your HyperKitty installation, preferably on the localhost. This
+# address will be used by Mailman to forward incoming emails to HyperKitty
+# for archiving. It does not need to be publicly available, in fact it's
+# better if it is not.
+base_url: http://localhost/archives/
+
+# Shared API key, must be the identical to the value in HyperKitty's
+# settings.
+api_key: {{ pillar['profile']['mailman3']['archiver_key'] }}
diff --git a/salt/profile/mailman3/files/mailman.cfg b/salt/profile/mailman3/files/mailman.cfg
new file mode 100644
index 0000000..b06ea6f
--- /dev/null
+++ b/salt/profile/mailman3/files/mailman.cfg
@@ -0,0 +1,175 @@
+# AUTOMATICALLY GENERATED BY MAILMAN ON 2019-09-05 04:35:36 UTC
+#
+# This is your GNU Mailman 3 configuration file. You can edit this file to
+# configure Mailman to your needs, and Mailman will never overwrite it.
+# Additional configuration information is available here:
+#
+# https://mailman.readthedocs.io/en/latest/src/mailman/config/docs/config.html
+#
+# For example, uncomment the following lines to run Mailman in developer mode.
+#
+# [devmode]
+# enabled: yes
+# recipient: your.address@your.domain
+
+[mailman]
+layout: fhs
+
+[mta]
+incoming: mailman.mta.postfix.LMTP
+outgoing: mailman.mta.deliver.deliver
+lmtp_host: localhost
+lmtp_port: 8024
+smtp_host: localhost
+smtp_port: 25
+remove_dkim_headers: yes
+
+# Remember, this should NOT be accessible from the outside of infra.o.o
+[webservice]
+hostname: localhost
+port: 8001
+use_https: no
+admin_user: {{ pillar['profile']['mailman3']['admin_user'] }}
+admin_pass: {{ pillar['profile']['mailman3']['admin_pass'] }}
+api_version: 3.1
+
+[archiver.hyperkitty]
+class: mailman_hyperkitty.Archiver
+enable: yes
+configuration: /etc/mailman/hyperkitty.cfg
+
+[database]
+class: mailman.database.postgresql.PostgreSQLDatabase
+url: postgres://{{ pillar['profile']['mailman3']['database_user'] }}:{{ pillar['postgres']['users']['mailman3']['password'] }}@{{ pillar['profile']['mailman3']['database_host'] }}/mailman
+
+[antispam]
+# This section defines basic antispam detection settings.
+
+# This value contains lines which specify RFC 822 headers in the email to
+# check for spamminess. Each line contains a `key: value` pair, where the key
+# is the header to check and the value is a Python regular expression to match
+# against the header's value. E.g.:
+#
+# X-Spam: (yes|maybe)
+#
+# The header value and regular expression are always matched
+# case-insensitively.
+header_checks:
+ X-Spam: yes
+ X-Spam-Flag: Yes
+ X-Spam-Status: ^Yes,
+
+# The chain to jump to if any of the header patterns matches. This must be
+# the name of an existing chain such as 'discard', 'reject', 'hold', or
+# 'accept', otherwise 'hold' will be used.
+jump_chain: discard
+
+
+[language.en]
+# Change the english language to be UTF-8 (it defaults to ascii).
+description: English (USA)
+charset: utf-8
+enabled: yes
+
+
+# http://www.lingoes.net/en/translator/langcode.htm
+
+[language.pt]
+description: Protuguese
+charset: iso-8859-15
+enabled: yes
+
+[language.cs]
+description: Czech
+charset: utf-8
+enabled: yes
+
+[language.ca]
+description: Catalan
+charset: utf-8
+enabled: yes
+
+[language.ja]
+description: Japanese
+charset: utf-8
+enabled: yes
+
+[language.ar]
+description: Arabic
+charset: utf-8
+enabled: yes
+
+[language.nl]
+description: Dutch
+charset: utf-8
+enabled: yes
+
+[language.pl]
+description: Polish
+charset: utf-8
+enabled: yes
+
+[language.es]
+description: Spanish
+charset: utf-8
+enabled: yes
+
+[language.pt_BR]
+description: Protuguese (Brazil)
+charset: iso-8859-15
+enabled: yes
+
+[language.zh_CN]
+description: Chinese (S)
+charset: utf-8
+enabled: yes
+
+[language.zh_TW]
+description: Chinese (T)
+charset: utf-8
+enabled: yes
+
+[language.ru]
+description: Russian
+charset: utf-8
+enabled: yes
+
+[language.vi]
+description: Vietnamese
+charset: utf-8
+enabled: yes
+
+[language.it]
+description: Italian
+charset: utf-8
+enabled: yes
+
+[language.fr]
+description: French
+charset: utf-8
+enabled: yes
+
+[language.ro]
+description: Romanian
+charset: utf-8
+enabled: yes
+
+[language.de]
+description: German
+charset: utf-8
+enabled: yes
+
+[language.hu]
+description: Hungarian
+charset: utf-8
+enabled: yes
+
+[language.ko]
+description: Korean
+charset: utf-8
+enabled: yes
+
+[language.uk]
+description: Ukrainian
+charset: utf-8
+enabled: yes
diff --git a/salt/profile/mailman3/files/mailman.service b/salt/profile/mailman3/files/mailman.service
new file mode 100644
index 0000000..4d94013
--- /dev/null
+++ b/salt/profile/mailman3/files/mailman.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=GNU Mailman Service
+
+[Service]
+Type=simple
+Restart=on-failure
+RestartSec=3
+
+User=mailman
+Group=mailman
+WorkingDirectory=/var/lib/mailman_webui/
+ExecStart=uwsgi --ini /etc/mailman_webui/uwsgi.ini
+
+[Install]
+WantedBy=multi-user.target
diff --git a/salt/profile/mailman3/files/manage.py b/salt/profile/mailman3/files/manage.py
new file mode 100644
index 0000000..4eb6f34
--- /dev/null
+++ b/salt/profile/mailman3/files/manage.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python3
+import os
+import sys
+
+if __name__ == "__main__":
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
+
+ from django.core.management import execute_from_command_line
+
+ execute_from_command_line(sys.argv)
diff --git a/salt/profile/mailman3/files/settings.py b/salt/profile/mailman3/files/settings.py
new file mode 100644
index 0000000..fdcdf44
--- /dev/null
+++ b/salt/profile/mailman3/files/settings.py
@@ -0,0 +1,505 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 1998-2016 by the Free Software Foundation, Inc.
+#
+# This file is part of Mailman Suite.
+#
+# Mailman Suite is free sofware: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# Mailman Suite is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+
+# You should have received a copy of the GNU General Public License along
+# with Mailman Suite. If not, see .
+"""
+Django Settings for Mailman Suite (hyperkitty + postorius)
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.8/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/1.8/ref/settings/
+"""
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+import os
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = '{{ pillar['profile']['lists']['secret_key'] }}'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = False
+
+ADMINS = (
+ ('openSUSE Mailing Lists Admins', 'admin@opensuse.org'),
+)
+
+SITE_ID = 1
+
+# Hosts/domain names that are valid for this site; required if DEBUG is False
+# See https://docs.djangoproject.com/en/1.8/ref/settings/#allowed-hosts
+ALLOWED_HOSTS = [
+ "localhost", # Archiving API from Mailman, keep it.
+ {%- for server in pillar['profile']['mailman3']['server_list'] %}
+ "{{server}}",
+ {%- endfor %}
+ # Add here all production URLs you may have.
+]
+
+# Mailman API credentials
+MAILMAN_REST_API_URL = 'http://localhost:8001'
+MAILMAN_REST_API_USER = '{{ pillar['profile']['mailman3']['admin_user'] }}'
+MAILMAN_REST_API_PASS = '{{ pillar['profile']['mailman3']['admin_pass'] }}'
+MAILMAN_ARCHIVER_KEY = '{{ pillar['profile']['mailman3']['archiver_key'] }}'
+MAILMAN_ARCHIVER_FROM = ('127.0.0.1', '::1')
+
+# Application definition
+
+INSTALLED_APPS = (
+ 'hyperkitty',
+ 'postorius',
+ 'django_mailman3',
+ # Uncomment the next line to enable the admin:
+ 'django.contrib.admin',
+ # Uncomment the next line to enable admin documentation:
+ # 'django.contrib.admindocs',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+ 'rest_framework',
+ 'django_gravatar',
+ 'compressor',
+ 'haystack',
+ 'django_extensions',
+ 'django_q',
+ 'allauth',
+ 'allauth.account',
+ 'allauth.socialaccount',
+ 'django_mailman3.lib.auth.fedora',
+ 'allauth.socialaccount.providers.openid',
+ 'allauth.socialaccount.providers.github',
+ 'allauth.socialaccount.providers.gitlab',
+ 'allauth.socialaccount.providers.google',
+ # 'allauth.socialaccount.providers.facebook',
+ 'allauth.socialaccount.providers.twitter',
+ 'allauth.socialaccount.providers.stackexchange',
+)
+
+
+MIDDLEWARE = (
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.middleware.locale.LocaleMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ 'django.middleware.security.SecurityMiddleware',
+ 'django_mailman3.middleware.TimezoneMiddleware',
+ 'postorius.middleware.PostoriusMiddleware',
+)
+
+ROOT_URLCONF = 'urls'
+
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [
+ BASE_DIR + '/templates/',
+ ],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'loaders': [
+ # https://docs.djangoproject.com/en/1.8/ref/templates/api/#django.template.loaders.cached.Loader
+ ('django.template.loaders.cached.Loader', [
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+ ]),
+ ],
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.i18n',
+ 'django.template.context_processors.media',
+ 'django.template.context_processors.static',
+ 'django.template.context_processors.tz',
+ 'django.template.context_processors.csrf',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ 'django_mailman3.context_processors.common',
+ 'hyperkitty.context_processors.common',
+ 'postorius.context_processors.postorius',
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = 'wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
+
+DATABASES = {
+ # Example for PostgreSQL (recommanded for production):
+ 'default': {
+ 'ENGINE': 'django.db.backends.postgresql_psycopg2',
+ 'NAME': 'mailman_frontend',
+ 'USER': '{{ pillar['profile']['mailman3']['database_user'] }}',
+ 'PASSWORD': '{{ pillar['postgres']['users']['mailman3']['password'] }}',
+ 'HOST': '{{ pillar['profile']['mailman3']['database_host'] }}',
+ }
+}
+
+
+# If you're behind a proxy, use the X-Forwarded-Host header
+# See https://docs.djangoproject.com/en/1.8/ref/settings/#use-x-forwarded-host
+USE_X_FORWARDED_HOST = True
+
+# And if your proxy does your SSL encoding for you, set SECURE_PROXY_SSL_HEADER
+# https://docs.djangoproject.com/en/1.8/ref/settings/#secure-proxy-ssl-header
+# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
+SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_SCHEME', 'https')
+
+# Other security settings
+# SECURE_SSL_REDIRECT = True
+# If you set SECURE_SSL_REDIRECT to True, make sure the SECURE_REDIRECT_EXEMPT
+# contains at least this line:
+# SECURE_REDIRECT_EXEMPT = [
+# "archives/api/mailman/.*", # Request from Mailman.
+# ]
+SESSION_COOKIE_SECURE = True
+SECURE_CONTENT_TYPE_NOSNIFF = True
+SECURE_BROWSER_XSS_FILTER = True
+CSRF_COOKIE_SECURE = True
+CSRF_COOKIE_HTTPONLY = True
+X_FRAME_OPTIONS = 'DENY'
+
+
+# Password validation
+# https://docs.djangoproject.com/en/1.9/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',
+ },
+]
+
+# Internationalization
+# https://docs.djangoproject.com/en/1.8/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/1.8/howto/static-files/
+
+# Absolute path to the directory static files should be collected to.
+# Don't put anything in this directory yourself; store your static files
+# in apps' "static/" subdirectories and in STATICFILES_DIRS.
+# Example: "/var/www/example.com/static/"
+STATIC_ROOT = os.path.join(BASE_DIR, 'static')
+
+# URL prefix for static files.
+# Example: "http://example.com/static/", "http://static.example.com/"
+STATIC_URL = '/static/'
+
+# Additional locations of static files
+STATICFILES_DIRS = (
+ # Put strings here, like "/home/html/static" or "C:/www/django/static".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ BASE_DIR + '/static-openSUSE/',
+
+)
+
+# List of finder classes that know how to find static files in
+# various locations.
+STATICFILES_FINDERS = (
+ 'django.contrib.staticfiles.finders.FileSystemFinder',
+ 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+ # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
+ 'compressor.finders.CompressorFinder',
+)
+
+# Django 1.6+ defaults to a JSON serializer, but it won't work with
+# django-openid, see
+# https://bugs.launchpad.net/django-openid-auth/+bug/1252826
+SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
+
+
+LOGIN_URL = 'account_login'
+LOGIN_REDIRECT_URL = 'list_index'
+LOGOUT_URL = 'account_logout'
+
+
+# If you enable internal authentication, this is the address that the emails
+# will appear to be coming from. Make sure you set a valid domain name,
+# otherwise the emails may get rejected.
+# https://docs.djangoproject.com/en/1.8/ref/settings/#default-from-email
+# DEFAULT_FROM_EMAIL = "mailing-lists@you-domain.org"
+DEFAULT_FROM_EMAIL = 'mailing-lists@opensuse.org'
+
+# If you enable email reporting for error messages, this is where those emails
+# will appear to be coming from. Make sure you set a valid domain name,
+# otherwise the emails may get rejected.
+# https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-SERVER_EMAIL
+# SERVER_EMAIL = 'root@your-domain.org'
+SERVER_EMAIL = 'admin@opensuse.org'
+
+# Change this when you have a real email backend
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'localhost'
+EMAIL_PORT = 25
+# EMAIL_HOST_USER =
+# EMAIL_HOST_PASSWORD =
+
+# Compatibility with Bootstrap 3
+from django.contrib.messages import constants as messages # flake8: noqa
+MESSAGE_TAGS = {
+ messages.ERROR: 'danger'
+}
+
+
+#
+# Social auth
+#
+AUTHENTICATION_BACKENDS = (
+ 'django.contrib.auth.backends.ModelBackend',
+ 'allauth.account.auth_backends.AuthenticationBackend',
+)
+
+# Django Allauth
+ACCOUNT_AUTHENTICATION_METHOD = "username_email"
+ACCOUNT_EMAIL_REQUIRED = True
+ACCOUNT_EMAIL_VERIFICATION = "mandatory"
+# You probably want https in production, but this is a dev setup file
+ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https"
+ACCOUNT_UNIQUE_EMAIL = True
+# Disable local signup
+ACCOUNT_ADAPTER = "django_fedora_nosignup.NoLocalSignUpAdapter"
+SOCIALACCOUNT_ADAPTER = "django_fedora_nosignup.SignUpEnabledSocialAdapter"
+
+SOCIALACCOUNT_PROVIDERS = {
+ 'openid': {
+ 'SERVERS': [
+ dict(id='yahoo',
+ name='Yahoo',
+ openid_url='http://me.yahoo.com'),
+ ],
+ },
+ 'google': {
+ 'SCOPE': ['profile', 'email'],
+ 'AUTH_PARAMS': {'access_type': 'online'},
+ },
+ 'facebook': {
+ 'METHOD': 'oauth2',
+ 'SCOPE': ['email'],
+ 'FIELDS': [
+ 'email',
+ 'name',
+ 'first_name',
+ 'last_name',
+ 'locale',
+ 'timezone',
+ ],
+ 'VERSION': 'v2.4',
+ },
+}
+
+
+#
+# Gravatar
+# https://github.com/twaddington/django-gravatar
+#
+# Gravatar base url.
+GRAVATAR_URL = 'http://cdn.libravatar.org/'
+# Gravatar base secure https url.
+GRAVATAR_SECURE_URL = 'https://seccdn.libravatar.org/'
+# Gravatar size in pixels.
+GRAVATAR_DEFAULT_SIZE = '80'
+# An image url or one of the following: 'mm', 'identicon', 'monsterid',
+# 'wavatar', 'retro'.
+GRAVATAR_DEFAULT_IMAGE = 'mm'
+# One of the following: 'g', 'pg', 'r', 'x'.
+GRAVATAR_DEFAULT_RATING = 'g'
+# True to use https by default, False for plain http.
+GRAVATAR_DEFAULT_SECURE = True
+
+#
+# django-compressor
+# https://pypi.python.org/pypi/django_compressor
+#
+COMPRESS_PRECOMPILERS = (
+ ('text/less', 'lessc {infile} {outfile}'),
+ ('text/x-scss', 'sassc -t compressed {infile} {outfile}'),
+ ('text/x-sass', 'sassc -t compressed {infile} {outfile}'),
+)
+# On a production setup, setting COMPRESS_OFFLINE to True will bring a
+# significant performance improvement, as CSS files will not need to be
+# recompiled on each requests. It means running an additional "compress"
+# management command after each code upgrade.
+# http://django-compressor.readthedocs.io/en/latest/usage/#offline-compression
+# COMPRESS_OFFLINE = True
+
+# Needed for debug mode
+# INTERNAL_IPS = ('127.0.0.1',)
+
+
+#
+# Full-text search engine
+#
+HAYSTACK_CONNECTIONS = {
+ 'default': {
+ #'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
+ #'PATH': os.path.join(BASE_DIR, "fulltext_index"),
+ # You can also use the Xapian engine, it's faster and more accurate,
+ # but requires another library.
+ # http://django-haystack.readthedocs.io/en/v2.4.1/installing_search_engines.html#xapian
+ # Example configuration for Xapian:
+ 'ENGINE': 'xapian_backend.XapianEngine'
+ },
+}
+
+
+#
+# Asynchronous tasks
+#
+Q_CLUSTER = {
+ 'timeout': 300,
+ 'save_limit': 100,
+ 'orm': 'default',
+}
+
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error when DEBUG=False.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'filters': {
+ 'require_debug_false': {
+ '()': 'django.utils.log.RequireDebugFalse'
+ }
+ },
+ 'handlers': {
+ 'mail_admins': {
+ 'level': 'ERROR',
+ 'filters': ['require_debug_false'],
+ 'class': 'django.utils.log.AdminEmailHandler'
+ },
+ 'file':{
+ 'level': 'INFO',
+ #'class': 'logging.handlers.RotatingFileHandler',
+ 'class': 'logging.handlers.WatchedFileHandler',
+ 'filename': os.path.join(BASE_DIR, 'logs', 'mailmansuite.log'),
+ 'formatter': 'verbose',
+ },
+ 'console': {
+ 'class': 'logging.StreamHandler',
+ 'formatter': 'simple',
+ },
+ },
+ 'loggers': {
+ 'django.request': {
+ 'handlers': ['mail_admins', 'file'],
+ 'level': 'ERROR',
+ 'propagate': True,
+ },
+ 'django': {
+ 'handlers': ['file'],
+ 'level': 'ERROR',
+ 'propagate': True,
+ },
+ 'hyperkitty': {
+ 'handlers': ['file'],
+ 'level': 'DEBUG',
+ 'propagate': True,
+ },
+ 'postorius': {
+ 'handlers': ['console', 'file'],
+ 'level': 'INFO',
+ },
+ },
+ 'formatters': {
+ 'verbose': {
+ 'format': '%(levelname)s %(asctime)s %(process)d %(name)s %(message)s'
+ },
+ 'simple': {
+ 'format': '%(levelname)s %(message)s'
+ },
+ },
+ #'root': {
+ # 'handlers': ['file'],
+ # 'level': 'INFO',
+ #},
+}
+
+
+# Using the cache infrastructure can significantly improve performance on a
+# production setup. This is an example with a local Memcached server.
+CACHES = {
+ 'default': {
+ 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
+ 'LOCATION': '127.0.0.1:11211',
+ }
+}
+
+
+# When DEBUG is True, don't actually send emails to the SMTP server, just store
+# them in a directory. This way you won't accidentally spam your mailing-lists
+# while you're fiddling with the code.
+if DEBUG == True:
+ EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
+ EMAIL_FILE_PATH = os.path.join(BASE_DIR, 'emails')
+
+
+#
+# HyperKitty-specific
+#
+
+# Only display mailing-lists from the same virtual host as the webserver
+FILTER_VHOST = False
+
+
+POSTORIUS_TEMPLATE_BASE_URL = 'http://localhost:80'
+
+
+try:
+ from settings_local import *
+except ImportError:
+ pass
diff --git a/salt/profile/mailman3/files/urls.py b/salt/profile/mailman3/files/urls.py
new file mode 100644
index 0000000..e8bb66c
--- /dev/null
+++ b/salt/profile/mailman3/files/urls.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 1998-2016 by the Free Software Foundation, Inc.
+#
+# This file is part of Postorius.
+#
+# Postorius is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# Postorius is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# Postorius. If not, see .
+
+
+from django.conf.urls import include, url
+from django.contrib import admin
+from django.urls import reverse_lazy
+from django.views.generic import RedirectView
+
+urlpatterns = [
+ url(r'^$', RedirectView.as_view(
+ url=reverse_lazy('list_index'),
+ permanent=True)),
+ url(r'^postorius/', include('postorius.urls')),
+ url(r'^hyperkitty/', include('hyperkitty.urls')),
+ url(r'', include('django_mailman3.urls')),
+ url(r'^accounts/', include('allauth.urls')),
+ # Django admin
+ url(r'^admin/', admin.site.urls),
+]
diff --git a/salt/profile/mailman3/files/uwsgi.ini b/salt/profile/mailman3/files/uwsgi.ini
new file mode 100644
index 0000000..5c1e4b3
--- /dev/null
+++ b/salt/profile/mailman3/files/uwsgi.ini
@@ -0,0 +1,37 @@
+# uwsgi.ini
+#
+[uwsgi]
+# Port on which uwsgi will be listening.
+uwsgi-socket = 0.0.0.0:80
+
+# Move to the directory wher the django files are.
+chdir = /var/lib/mailman_webui
+
+# Use the wsgi file provided with the django project.
+wsgi-file = wsgi.py
+
+# Setup default number of processes and threads per process.
+master = true
+process = 2
+threads = 2
+
+# Drop privielges and don't run as root.
+uid = 4200
+gid = 4200
+
+# Setup the django_q related worker processes.
+attach-daemon = ./manage.py qcluster
+
+# Setup the request log.
+req-logger = file://var/log/mailman/uwsgi.log
+
+# Log cron seperately.
+logger = cron file://var/log/mailman/uwsgi-cron.log
+log-route = cron uwsgi-cron
+
+# Log qcluster commands seperately.
+logger = qcluster file://var/log/mailman/uwsgi-qcluster.log
+log-route = qcluster uwsgi-daemons
+
+# Last log and it logs the rest of the stuff.
+logger = file://var/log/mailman/uwsgi-error.log
diff --git a/salt/profile/mailman3/files/wsgi.py b/salt/profile/mailman3/files/wsgi.py
new file mode 100644
index 0000000..8e59cd8
--- /dev/null
+++ b/salt/profile/mailman3/files/wsgi.py
@@ -0,0 +1,38 @@
+"""
+WSGI config for HyperKitty project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/{{ docs_version }}/howto/deployment/wsgi/
+"""
+
+import os
+
+# import sys
+# import site
+
+# For some unknown reason, sometimes mod_wsgi fails to set the python paths to
+# the virtualenv, with the 'python-path' option. You can do it here too.
+#
+# # Remember original sys.path.
+# prev_sys_path = list(sys.path)
+# # Add here, for the settings module
+# site.addsitedir(os.path.abspath(os.path.dirname(__file__)))
+# # Add the virtualenv
+# venv = os.path.join(os.path.abspath(os.path.dirname(__file__)),
+# '..', 'lib', 'python2.6', 'site-packages')
+# site.addsitedir(venv)
+# # Reorder sys.path so new directories at the front.
+# new_sys_path = []
+# for item in list(sys.path):
+# if item not in prev_sys_path:
+# new_sys_path.append(item)
+# sys.path.remove(item)
+# sys.path[:0] = new_sys_path
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
+
+application = get_wsgi_application()
diff --git a/salt/profile/mailman3/init.sls b/salt/profile/mailman3/init.sls
new file mode 100644
index 0000000..0e2c57d
--- /dev/null
+++ b/salt/profile/mailman3/init.sls
@@ -0,0 +1,11 @@
+mailman_service:
+ service.running:
+ - name: mailman
+ - enable: True
+
+mailman_restart:
+ module.wait:
+ - name: service.restart
+ - m_name: mailman
+ - require:
+ - service: mailman_service
diff --git a/salt/profile/mailman3/mailman.sls b/salt/profile/mailman3/mailman.sls
new file mode 100644
index 0000000..ec16853
--- /dev/null
+++ b/salt/profile/mailman3/mailman.sls
@@ -0,0 +1,78 @@
+mailman_pgks:
+ pkg.installed:
+ - pkgs:
+ - python3-xapian
+ - python3-psycopg2
+ - python3-mailman
+ - python3-mailmanclient
+ - python3-postorius
+ - python3-mailman-web
+ - python3-HyperKitty
+ - python3-mailman-hyperkitty
+ # html => text for mailman
+ - lynx
+ - memcached
+
+mailman:
+ user.present:
+ - home: /var/lib/mailman
+ - uid: 4200
+ group.present:
+ - system: True
+ - gid: 4200
+ - members:
+ - mailman
+
+/usr/bin/mailman digests --periodic:
+ cron.present:
+ - user: mailman
+ - minute: 0
+ - hour: 0
+
+/path/to/mailman notify:
+ cron.present:
+ - user: mailman
+ - minute: 0
+ - hour: 8
+
+django-admin runjobs hourly --pythonpath /var/lib/mailman --settings settings:
+ cron.present:
+ - user: mailman
+ - minute: 0
+
+django-admin runjobs daily --pythonpath /var/lib/mailman --settings settings:
+ cron.present:
+ - user: mailman
+ - minute: 0
+ - hour: 0
+
+django-admin runjobs weekly --pythonpath /var/lib/mailman --settings settings:
+ cron.present:
+ - user: mailman
+ - minute: 0
+ - hour: 0
+ - dayweek: 0
+
+django-admin runjobs monthly --pythonpath /var/lib/mailman --settings settings:
+ cron.present:
+ - user: mailman
+ - minute: 0
+ - hour: 0
+ - daymonth: 0
+
+django-admin runjobs yearly --pythonpath /var/lib/mailman --settings settings:
+ cron.present:
+ - user: mailman
+ - minute: 0
+ - hour: 0
+ - daymonth: 0
+ - month: 0
+
+django-admin runjobs minutely --pythonpath /var/lib/mailman --settings settings:
+ cron.present:
+ - user: mailman
+
+django-admin runjobs quarter_hourly --pythonpath /var/lib/mailman --settings settings:
+ cron.present:
+ - user: mailman
+ - minute: '0,15,30,45'
diff --git a/salt/role/mailman3.sls b/salt/role/mailman3.sls
new file mode 100644
index 0000000..47b3963
--- /dev/null
+++ b/salt/role/mailman3.sls
@@ -0,0 +1,4 @@
+include:
+ - profile.mailman3.mailman
+ - profile.mailman3.config
+ - profile.mailman3.init