Merge "Add a mailman3 list server"
This commit is contained in:
commit
b7b2157133
inventory/service
playbooks
testinfra
tools
zuul.d
89
inventory/service/group_vars/mailman3.yaml
Normal file
89
inventory/service/group_vars/mailman3.yaml
Normal file
@ -0,0 +1,89 @@
|
||||
exim_queue_interval: '1m'
|
||||
exim_queue_run_max: '50'
|
||||
exim_smtp_accept_max: '100'
|
||||
exim_smtp_accept_max_per_host: '10'
|
||||
iptables_extra_public_tcp_ports:
|
||||
- 25
|
||||
- 80
|
||||
- 443
|
||||
- 465
|
||||
letsencrypt_certs:
|
||||
lists-opendev-org-main:
|
||||
- "{{ inventory_hostname }}"
|
||||
- lists.opendev.org
|
||||
- lists.airshipit.org
|
||||
- lists.katacontainers.io
|
||||
- lists.openinfra.dev
|
||||
- lists.openstack.org
|
||||
- lists.starlingx.io
|
||||
- lists.zuul-ci.org
|
||||
borg_backup_excludes_extra:
|
||||
# db is backed up in dumps, don't capture live files
|
||||
- /var/lib/mailman/database
|
||||
# backed up by streaming backup
|
||||
- /var/backups/mailman-mariadb
|
||||
# Can regenerate indexes from source email files
|
||||
- /var/lib/mailman/web-data/fulltext_index
|
||||
exim_routers:
|
||||
- mailman_verp_router: |
|
||||
{% raw -%}
|
||||
driver = dnslookup
|
||||
condition = ${if or{{eq{$sender_host_address}{127.0.0.1}}\
|
||||
{eq{$sender_host_address}{::1}}}{yes}{no}}
|
||||
{% endraw %}
|
||||
domains = !+local_domains
|
||||
ignore_target_hosts = <; 0.0.0.0; \
|
||||
127.0.0.0/8; \
|
||||
::1/128;fe80::/10;fe \
|
||||
c0::/10;ff00::/8
|
||||
senders = "*-bounces@*"
|
||||
transport = mailman_verp_smtp
|
||||
- dnslookup: '{{ exim_dnslookup_router }}'
|
||||
- system_aliases: '{{ exim_system_aliases_router }}'
|
||||
- domain_aliases: |
|
||||
driver = redirect
|
||||
allow_fail
|
||||
allow_defer
|
||||
data = ${lookup{$local_part@$domain}lsearch{/etc/aliases.domain}}
|
||||
file_transport = address_file
|
||||
pipe_transport = address_pipe
|
||||
- localuser: '{{ exim_localuser_router }}'
|
||||
- mailman_copy: |
|
||||
driver = accept
|
||||
domains = lists.openstack.org
|
||||
local_parts = openstack-discuss
|
||||
transport = local_copy
|
||||
unseen
|
||||
- mailman_router: |
|
||||
driver = accept
|
||||
domains = {{ mm_domains }}
|
||||
local_part_suffix = -admin : \
|
||||
-bounces : -bounces+* : \
|
||||
-confirm : -confirm+* : \
|
||||
-join : -leave : \
|
||||
-owner : -request : \
|
||||
-subscribe : -unsubscribe
|
||||
local_part_suffix_optional
|
||||
require_files = /var/lib/mailman/core/var/lists/${local_part}.${domain}
|
||||
transport = mailman_transport
|
||||
exim_transports:
|
||||
- local_copy: |
|
||||
driver = appendfile
|
||||
file = /var/mail/$local_part
|
||||
group = mail
|
||||
mode = 0660
|
||||
- mailman_transport: |
|
||||
debug_print = "Email for mailman"
|
||||
driver = smtp
|
||||
protocol = lmtp
|
||||
allow_localhost
|
||||
hosts = localhost
|
||||
port = 8024
|
||||
rcpt_include_affixes = true
|
||||
- mailman_verp_smtp: |
|
||||
driver = smtp
|
||||
headers_add = Errors-To: ${return_path}
|
||||
headers_remove = Errors-To
|
||||
max_rcpt = 1
|
||||
return_path = ${local_part:$return_path}+$local_part=$domain@${domain:$return_path}
|
||||
mailman_multihost: true
|
@ -26,11 +26,13 @@ groups:
|
||||
- kdc03.openstack.org
|
||||
- eavesdrop01.opendev.org
|
||||
- paste01.opendev.org
|
||||
- lists01.opendev.org
|
||||
# These are test specific hosts that we add to the backup
|
||||
# group to mimic as much as possible what their prod version
|
||||
# end up doing.
|
||||
- gitea99.opendev.org
|
||||
- review99.opendev.org
|
||||
- lists99.opendev.org
|
||||
# All these servers are "special-cased" in specifically
|
||||
# as they are puppet and should be replaced "soon"
|
||||
- lists.openstack.org
|
||||
@ -91,6 +93,7 @@ groups:
|
||||
- keycloak[0-9]*.opendev.org
|
||||
- lists.katacontainers.io
|
||||
- lists.openstack.org
|
||||
- lists[0-9]*.opendev.org
|
||||
- meetpad[0-9]*.opendev.org
|
||||
- mirror[0-9]*.opendev.org
|
||||
- nb[0-9]*.opendev.org
|
||||
@ -103,8 +106,10 @@ groups:
|
||||
- translate[0-9]*.open*.org
|
||||
- zuul[0-9]*.opendev.org
|
||||
mailman:
|
||||
- lists*.katacontainers.io
|
||||
- lists*.open*.org
|
||||
- lists.katacontainers.io
|
||||
- lists.openstack.org
|
||||
mailman3:
|
||||
- lists[0-9]*.opendev.org
|
||||
meetpad:
|
||||
- meetpad[0-9]*.opendev.org
|
||||
mirror:
|
||||
|
225
inventory/service/host_vars/lists01.opendev.org.yaml
Normal file
225
inventory/service/host_vars/lists01.opendev.org.yaml
Normal file
@ -0,0 +1,225 @@
|
||||
mm_domains: 'lists.openstack.org:lists.zuul-ci.org:lists.airshipit.org:lists.starlingx.io:lists.opendev.org:lists.openinfra.dev:lists.katacontainers.io'
|
||||
exim_local_domains: "@:{{ mm_domains }}"
|
||||
exim_enable_spf: true
|
||||
exim_aliases:
|
||||
root: "{{ ','.join(listadmins|default([])) }}"
|
||||
interop-wg: openstack-discuss
|
||||
openstack: openstack-discuss
|
||||
openstack-dev: openstack-discuss
|
||||
openstack-infra: openstack-discuss
|
||||
openstack-operators: openstack-discuss
|
||||
openstack-security: openstack-discuss
|
||||
openstack-sigs: openstack-discuss
|
||||
openstack-tc: openstack-discuss
|
||||
user-committee: openstack-discuss
|
||||
airship-discuss-owner: spam
|
||||
community-owner: spam
|
||||
edge-computing-owner: spam
|
||||
foundation-board-confidential-owner: spam
|
||||
foundation-board-owner: spam
|
||||
foundation-owner: spam
|
||||
legal-discuss-owner: spam
|
||||
mailman-owner: spam
|
||||
marketing-owner: spam
|
||||
openstack-announce-owner: spam
|
||||
openstack-docs-owner: spam
|
||||
openstack-fr-owner: spam
|
||||
openstack-i18n-owner: spam
|
||||
openstack-infra-owner: spam
|
||||
openstack-ko-owner: spam
|
||||
openstack-qa-owner: spam
|
||||
product-wg-owner: spam
|
||||
user-committee-owner: spam
|
||||
spam: ':fail: delivery temporarily disabled due to ongoing spam flood'
|
||||
# TODO It would be better to bypass verification for postorius@listdomain
|
||||
# and set a :fail: rule for anyone trying to send email to this addr.
|
||||
# But that requires updating our main exim config so that needs more thought.
|
||||
postorius: ':blackhole: outgoing email only from this address'
|
||||
exim_domain_aliases:
|
||||
community@lists.openstack.org: community@lists.openinfra.dev
|
||||
edge-computing@lists.openstack.org: edge-computing@lists.opendev.org
|
||||
foundation@lists.openstack.org: foundation@lists.openinfra.dev
|
||||
foundation-board@lists.openstack.org: foundation-board@lists.openinfra.dev
|
||||
foundation-board-confidential@lists.openstack.org: foundation-board-confidential@lists.openinfra.dev
|
||||
goldmembers@lists.openstack.org: goldmembers@lists.openinfra.dev
|
||||
marketing@lists.openstack.org: marketing@lists.openinfra.dev
|
||||
staff@lists.openstack.org: staff@lists.openinfra.dev
|
||||
summit-programming-committee@lists.openinfra.dev: summit-track-chairs@lists.openinfra.dev
|
||||
summitsponsors@lists.openstack.org: summitsponsors@lists.openinfra.dev
|
||||
mailman_sites:
|
||||
# First entry in this list is the primary web domain
|
||||
- listdomain: lists.opendev.org
|
||||
install_languages: ['en']
|
||||
lists:
|
||||
- name: computing-force-network
|
||||
description: 'Organizing efforts around Computing Force Network related area'
|
||||
owner: 'niujie@outlook.com'
|
||||
- name: edge-computing
|
||||
description: 'Organizing efforts around the edge-computing focus area.'
|
||||
owner: 'ildiko@openinfra.dev'
|
||||
- name: floss-mooc
|
||||
description: 'Discussions & Coordination around the FLOSS MOOC being collaboratively developed here: https://gitlab.com/mooc-floss/mooc-floss'
|
||||
owner: 'knelson@openinfra.dev'
|
||||
- name: nbmp-discuss
|
||||
description: 'Collaborating on Network Based Media Processing related platform and infrastructure systems usage and development.'
|
||||
owner: 'ildiko@openstack.org'
|
||||
- name: openinfralabs
|
||||
description: 'Discussion of the OpenInfra Labs academic and research resource sharing effort'
|
||||
owner: 'mnaser@vexxhost.com'
|
||||
- name: rust-vmm
|
||||
description: 'Collaborating on Rust-based virtual machine monitors.'
|
||||
owner: 'claire@openstack.org'
|
||||
- name: rustyk8s
|
||||
description: 'Collaborating on Rust-based Kubernetes API.'
|
||||
owner: 'allison@lohutok.net'
|
||||
- name: service-announce
|
||||
description: 'Announcement list for OpenDev services.'
|
||||
owner: 'cboylan@sapwetik.org'
|
||||
- name: service-discuss
|
||||
description: 'Discussion list for OpenDev services.'
|
||||
owner: 'cboylan@sapwetik.org'
|
||||
- name: service-incident
|
||||
description: 'Private list for OpenDev incident coordination.'
|
||||
owner: 'cboylan@sapwetik.org'
|
||||
private: true
|
||||
# The domains and lists below are currently commented out as we intend on
|
||||
# deploying a single domain and its lists at a time starting with
|
||||
# lists.opendev.org. As we deploy other domains we can uncomment these
|
||||
# blocks. Double check no new lists are been added or removed first.
|
||||
#- listdomain: lists.airshipit.org
|
||||
# install_languages: ['en']
|
||||
# lists:
|
||||
# - name: airship-announce
|
||||
# description: 'Announcements of Airship releases and other important information.'
|
||||
# owner: 'jonathan@openstack.org'
|
||||
# - name: airship-discuss
|
||||
# description: 'Discussion of Airship usage and development.'
|
||||
# owner: 'jonathan@openstack.org'
|
||||
# - name: airship-embargo-notice
|
||||
# description: 'Embargoed security vulnerability announcements for Airship consumers.'
|
||||
# owner: 'andrew.walters@att.com'
|
||||
# private: true
|
||||
# - name: airship-job-failures
|
||||
# description: 'Notification messages for failures from CICD jobs.'
|
||||
# owner: 'roman.gorshunov@att.com'
|
||||
# - name: airship-security
|
||||
# description: 'Public Airship security advisories.'
|
||||
# owner: 'andrew.walters@att.com'
|
||||
#- listdomain: lists.katacontainers.io
|
||||
# install_languages: ['en']
|
||||
# lists:
|
||||
# - name: embargo-notice
|
||||
# description: 'Announcements of embargoed notices for the Kata Containers project'
|
||||
# owner: 'jonathan@openstack.org'
|
||||
# private: true
|
||||
# - name: kata-dev
|
||||
# description: 'Kata Containers Development Mailing List (not for usage questions)'
|
||||
# owner: 'jonathan@openstack.org'
|
||||
# - name: kata-hypervisor
|
||||
# description: 'Discussion of security and virtualization targeted at container use cases'
|
||||
# owner: 'jonathan@openstack.org'
|
||||
#- listdomain: lists.openinfra.dev
|
||||
# install_languages: ['en']
|
||||
# lists:
|
||||
# - name: community
|
||||
# description: 'The OpenInfra Community team is the main contact point for anybody running a local OpenInfra Group.'
|
||||
# owner: 'allison@openinfra.dev'
|
||||
# - name: foundation
|
||||
# description: 'General discussion list for activities of the OpenInfra Foundation'
|
||||
# owner: 'jonathan@openinfra.dev'
|
||||
# - name: foundation-board
|
||||
# description: 'OpenInfra Foundation Board of Directors'
|
||||
# owner: 'jonathan@openinfra.dev'
|
||||
# - name: foundation-board-confidential
|
||||
# description: 'OpenInfra Foundation Board of Directors'
|
||||
# owner: 'jonathan@openinfra.dev'
|
||||
# private: true
|
||||
# - name: goldmembers
|
||||
# description: 'The discussion list for Gold Members of the OpenInfra Foundation'
|
||||
# owner: 'jonathan@openinfra.dev'
|
||||
# private: true
|
||||
# - name: marketing
|
||||
# description: 'The OpenInfra Marketing list is the meant to facilitate discussion and best practice sharing among marketers and event organizers in the OpenInfra community.'
|
||||
# owner: 'allison@openinfra.dev'
|
||||
# - name: staff
|
||||
# description: 'Private list for OpenInfra Foundation staff members'
|
||||
# owner: 'mark@openinfra.dev'
|
||||
# private: true
|
||||
# - name: summit-track-chairs
|
||||
# description: 'OpenInfra Summit track chair communications'
|
||||
# owner: 'erin@openinfra.dev'
|
||||
# private: true
|
||||
# - name: summitsponsors
|
||||
# description: 'Coordination among OpenInfra Summit event sponsors'
|
||||
# owner: 'erin@openinfra.dev'
|
||||
# private: true
|
||||
#- listdomain: lists.openstack.org
|
||||
# install_languages: ['de', 'fr', 'it', 'ko', 'ru', 'vi', 'zh_TW']
|
||||
# lists:
|
||||
# - name: embargo-notice
|
||||
# description: 'Announcements to stakeholders for embargoed security vulnerabilities.'
|
||||
# owner: 'fungi@yuggoth.org'
|
||||
# private: true
|
||||
# - name: legal-discuss
|
||||
# description: 'Discussions on legal matters related to the project'
|
||||
# owner: 'thierry@openinfra.dev'
|
||||
# - name: openstack-announce
|
||||
# description: 'Key announcements about OpenStack & Security advisories'
|
||||
# owner: 'fungi@yuggoth.org'
|
||||
# - name: openstack-discuss
|
||||
# description: 'Discussion of OpenStack usage and development.'
|
||||
# owner: 'fungi@yuggoth.org'
|
||||
# - name: openstack-es
|
||||
# description: 'Lista de correo acerca de OpenStack en español'
|
||||
# owner: 'flavio@redhat.com'
|
||||
# - name: openstack-fr
|
||||
# description: 'List of the OpenStack french user group'
|
||||
# owner: 'erwan@erwan.com'
|
||||
# - name: openstack-hpc
|
||||
# description: 'High-Performance Computing OpenStack List'
|
||||
# owner: 'brian.schott@nimbisservices.com'
|
||||
# - name: openstack-i18n
|
||||
# description: 'List of the OpenStack Internationalization team.'
|
||||
# owner: 'guoyingc@cn.ibm.com'
|
||||
# - name: openstack-it
|
||||
# description: 'Discussioni su OpenStack in italiano'
|
||||
# owner: 'stefano@openstack.org'
|
||||
# - name: openstack-ko
|
||||
# description: 'OpenStack Korea Community Discussions in Korean (오픈스택 한국 커뮤니티 메일링리스트)'
|
||||
# owner: 'ianyrchoi@gmail.com'
|
||||
# - name: openstack-mentoring
|
||||
# description: 'List to coordinate interactions between mentors and mentees of the OpenStack mentoring program. Also for questions about the mentoring program (i.e. how to get involved, how it works, etc.'
|
||||
# owner: 'amy@demarco.com'
|
||||
# - name: openstack-stable-maint
|
||||
# description: 'A mailing list for the OpenStack Stable Branch test reports.'
|
||||
# owner: 'tony@bakeyournoodle.com'
|
||||
# - name: openstack-zh
|
||||
# description: 'OpenStack社区中文讨论群组'
|
||||
# owner: 'yeluaiesec@gmail.com'
|
||||
# - name: release-announce
|
||||
# description: 'Announcement of official OpenStack releases.'
|
||||
# owner: 'thierry@openstack.org'
|
||||
# - name: release-job-failures
|
||||
# description: 'Notification messages for failures from release-related build jobs.'
|
||||
# owner: 'doug@doughellmann.com'
|
||||
#- listdomain: lists.starlingx.io
|
||||
# install_languages: ['en']
|
||||
# lists:
|
||||
# - name: starlingx-announce
|
||||
# description: 'Announcements of StarlingX releases and other important information.'
|
||||
# owner: 'jonathan@openstack.org'
|
||||
# - name: starlingx-discuss
|
||||
# description: 'Discussion of StarlingX usage and development.'
|
||||
# owner: 'jonathan@openstack.org'
|
||||
#- listdomain: lists.zuul-ci.org
|
||||
# install_languages: ['en']
|
||||
# lists:
|
||||
# - name: zuul-announce
|
||||
# description: 'Announcements of Zuul releases and other important information.'
|
||||
# owner: 'corvus@inaugust.com'
|
||||
# - name: zuul-discuss
|
||||
# description: 'Discussion of Zuul usage and development.'
|
||||
# owner: 'corvus@inaugust.com'
|
||||
# - name: zuul-jobs-failures
|
||||
# description: 'Gets notifications about zuul-jobs periodic job failures.'
|
||||
# owner: 'ssbarnea@redhat.com'
|
@ -45,6 +45,9 @@
|
||||
- name: letsencrypt updated lists-openstack-org-main
|
||||
include_tasks: roles/letsencrypt-create-certs/handlers/restart_apache.yaml
|
||||
|
||||
- name: letsencrypt updated lists-opendev-org-main
|
||||
include_tasks: roles/letsencrypt-create-certs/handlers/restart_apache.yaml
|
||||
|
||||
# Static
|
||||
- name: letsencrypt updated static-opendev-org-main
|
||||
include_tasks: roles/letsencrypt-create-certs/handlers/restart_apache.yaml
|
||||
|
1
playbooks/roles/mailman3/README.rst
Normal file
1
playbooks/roles/mailman3/README.rst
Normal file
@ -0,0 +1 @@
|
||||
Role to configure mailman3.
|
10
playbooks/roles/mailman3/files/99-max_allowed_packet.cnf
Normal file
10
playbooks/roles/mailman3/files/99-max_allowed_packet.cnf
Normal file
@ -0,0 +1,10 @@
|
||||
[mysqldump]
|
||||
# Default is 24MB which is not large enough for all mailman attachments.
|
||||
# This affects clients including mysqldump. It is larger than the server
|
||||
# side because mysqldump apparently can do larger packets to insert blobs.
|
||||
max_allowed_packet=256M
|
||||
|
||||
[mysqld]
|
||||
# Default is 16MB which is not large enough for all mailman attachments.
|
||||
# This affects the server side.
|
||||
max_allowed_packet=128M
|
429
playbooks/roles/mailman3/files/web-settings.py
Normal file
429
playbooks/roles/mailman3/files/web-settings.py
Normal file
@ -0,0 +1,429 @@
|
||||
# This file has been copied from:
|
||||
# https://github.com/maxking/docker-mailman/blob/2693386453ff3865b7c106c6aa456b683bd3bf08/web/mailman-web/settings.py
|
||||
# In order to override the ALLOWED_HOSTS setting.
|
||||
#
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
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
|
||||
import dj_database_url
|
||||
import sys
|
||||
from socket import gethostbyname
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = os.environ.get('SECRET_KEY')
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
|
||||
ADMINS = (
|
||||
('Mailman Suite Admin', 'root@localhost'),
|
||||
)
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
# Hosts/domain names that are valid for this site; required if DEBUG is False
|
||||
# See https://docs.djangoproject.com/en/3.1/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = [
|
||||
"localhost", # Archiving API from Mailman, keep it.
|
||||
"127.0.0.1", # Archiving API from Mailman, keep it. OpenDev edit
|
||||
# "lists.your-domain.org",
|
||||
# Add here all production URLs you may have.
|
||||
# The next two entries are commented out to prevent name resolution
|
||||
# problems. This is an opendev local edit.
|
||||
# Note we cannot use settings_local.py as this entry is evaluated at
|
||||
# import time.
|
||||
#"mailman-web",
|
||||
#gethostbyname("mailman-web"),
|
||||
os.environ.get('SERVE_FROM_DOMAIN'),
|
||||
#os.environ.get('DJANGO_ALLOWED_HOSTS'),
|
||||
]
|
||||
|
||||
# We have modified handling of DJANGO_ALLOWED_HOSTS here to deserialize a
|
||||
# list of hosts into a python list of strings.
|
||||
django_allowed_hosts = os.environ.get('DJANGO_ALLOWED_HOSTS')
|
||||
if django_allowed_hosts:
|
||||
ALLOWED_HOSTS.extend(django_allowed_hosts.split(':'))
|
||||
|
||||
# Mailman API credentials
|
||||
MAILMAN_REST_API_URL = os.environ.get('MAILMAN_REST_URL', 'http://mailman-core:8001')
|
||||
MAILMAN_REST_API_USER = os.environ.get('MAILMAN_REST_USER', 'restadmin')
|
||||
MAILMAN_REST_API_PASS = os.environ.get('MAILMAN_REST_PASSWORD', 'restpass')
|
||||
MAILMAN_ARCHIVER_KEY = os.environ.get('HYPERKITTY_API_KEY')
|
||||
MAILMAN_ARCHIVER_FROM = (os.environ.get('MAILMAN_HOST_IP', gethostbyname(os.environ.get('MAILMAN_HOSTNAME', 'mailman-core'))),)
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = []
|
||||
DEFAULT_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',
|
||||
]
|
||||
|
||||
MAILMAN_WEB_SOCIAL_AUTH = [
|
||||
'django_mailman3.lib.auth.fedora',
|
||||
'allauth.socialaccount.providers.openid',
|
||||
'allauth.socialaccount.providers.github',
|
||||
'allauth.socialaccount.providers.gitlab',
|
||||
'allauth.socialaccount.providers.google',
|
||||
]
|
||||
|
||||
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': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'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
|
||||
# dj_database_url uses $DATABASE_URL environment variable to create a
|
||||
# django-style-config-dict.
|
||||
# https://github.com/kennethreitz/dj-database-url
|
||||
DATABASES = {
|
||||
'default': dj_database_url.config(conn_max_age=600)
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# 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_ROOT = '/opt/mailman-web-data/static'
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# Additional locations of static files
|
||||
|
||||
|
||||
# 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',
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
|
||||
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
|
||||
|
||||
LOGIN_URL = 'account_login'
|
||||
LOGIN_REDIRECT_URL = 'list_index'
|
||||
LOGOUT_URL = 'account_logout'
|
||||
|
||||
|
||||
# Use SERVE_FROM_DOMAIN as the default domain in the email.
|
||||
hostname = os.environ.get('SERVE_FROM_DOMAIN', 'localhost.local')
|
||||
DEFAULT_FROM_EMAIL = 'postorius@{}'.format(hostname)
|
||||
SERVER_EMAIL = 'root@{}'.format(hostname)
|
||||
|
||||
# Change this when you have a real email backend
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
EMAIL_HOST = os.environ.get('SMTP_HOST', '')
|
||||
EMAIL_PORT = os.environ.get('SMTP_PORT', 25)
|
||||
EMAIL_HOST_USER = os.environ.get('SMTP_HOST_USER', '')
|
||||
EMAIL_HOST_PASSWORD = os.environ.get('SMTP_HOST_PASSWORD', '')
|
||||
EMAIL_USE_TLS = os.environ.get('SMTP_USE_TLS', False)
|
||||
EMAIL_USE_SSL = os.environ.get('SMTP_USE_SSL', False)
|
||||
|
||||
# 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
|
||||
|
||||
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',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
#
|
||||
# Full-text search engine
|
||||
#
|
||||
HAYSTACK_CONNECTIONS = {
|
||||
'default': {
|
||||
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
|
||||
'PATH': "/opt/mailman-web-data/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'
|
||||
},
|
||||
}
|
||||
|
||||
import sys
|
||||
# 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.environ.get('DJANGO_LOG_URL','/opt/mailman-web-data/logs/mailmanweb.log'),
|
||||
'formatter': 'verbose',
|
||||
},
|
||||
'console': {
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simple',
|
||||
'level': 'INFO',
|
||||
'stream': sys.stdout,
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins', 'file'],
|
||||
'level': 'INFO',
|
||||
'propagate': True,
|
||||
},
|
||||
'django': {
|
||||
'handlers': ['file'],
|
||||
'level': 'INFO',
|
||||
'propagate': True,
|
||||
},
|
||||
'hyperkitty': {
|
||||
'handlers': ['file'],
|
||||
'level': 'INFO',
|
||||
'propagate': True,
|
||||
},
|
||||
'postorius': {
|
||||
'handlers': ['file'],
|
||||
'level': 'INFO',
|
||||
'propagate': True
|
||||
},
|
||||
},
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '%(levelname)s %(asctime)s %(process)d %(name)s %(message)s'
|
||||
},
|
||||
'simple': {
|
||||
'format': '%(levelname)s %(message)s'
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
if os.environ.get('LOG_TO_CONSOLE') == 'yes':
|
||||
LOGGING['loggers']['django']['handlers'].append('console')
|
||||
LOGGING['loggers']['django.request']['handlers'].append('console')
|
||||
|
||||
# HyperKitty-specific
|
||||
#
|
||||
# Only display mailing-lists from the same virtual host as the webserver
|
||||
FILTER_VHOST = False
|
||||
|
||||
|
||||
Q_CLUSTER = {
|
||||
'timeout': 300,
|
||||
'retry': 300,
|
||||
'save_limit': 100,
|
||||
'orm': 'default',
|
||||
}
|
||||
|
||||
POSTORIUS_TEMPLATE_BASE_URL = os.environ.get('POSTORIUS_TEMPLATE_BASE_URL', 'http://mailman-web:8000')
|
||||
|
||||
DISKCACHE_PATH = os.environ.get('DISKCACHE_PATH', '/opt/mailman-web-data/diskcache')
|
||||
DISKCACHE_SIZE = os.environ.get('DISKCACHE_SIZE', 2 ** 30) # 1 gigabyte
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'diskcache.DjangoCache',
|
||||
'LOCATION': DISKCACHE_PATH,
|
||||
'OPTIONS': {
|
||||
'size_limit': DISKCACHE_SIZE,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
try:
|
||||
from settings_local import *
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Compatibility for older installs that override INSTALLED_APPS
|
||||
if not INSTALLED_APPS:
|
||||
INSTALLED_APPS = DEFAULT_APPS + MAILMAN_WEB_SOCIAL_AUTH
|
21
playbooks/roles/mailman3/files/web-settings_local.py
Normal file
21
playbooks/roles/mailman3/files/web-settings_local.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Override default index system. Xapian will be the default in the next
|
||||
# major release of mailman3, but is currently recommended.
|
||||
HAYSTACK_CONNECTIONS = {
|
||||
'default': {
|
||||
'ENGINE': 'xapian_backend.XapianEngine',
|
||||
'PATH': "/opt/mailman-web-data/fulltext_index",
|
||||
},
|
||||
}
|
||||
|
||||
# Disable Gravatar integration since it violates privacy expectations
|
||||
HYPERKITTY_ENABLE_GRAVATAR = False
|
||||
|
||||
# This disables web auth using Google, GitHub, Gitlab, Yahoo,
|
||||
# Fedora, and generic OpenID.
|
||||
# TODO: In the future we will want to enable this specifically for
|
||||
# our keycloak server only.
|
||||
MAILMAN_WEB_SOCIAL_AUTH = []
|
||||
|
||||
FILTER_VHOST = True
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
9
playbooks/roles/mailman3/handlers/main.yaml
Normal file
9
playbooks/roles/mailman3/handlers/main.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
- name: mailman restart apache2
|
||||
service:
|
||||
name: apache2
|
||||
state: restarted
|
||||
|
||||
- name: mailman reload apache2
|
||||
service:
|
||||
name: apache2
|
||||
state: reloaded
|
114
playbooks/roles/mailman3/tasks/create_lists.yaml
Normal file
114
playbooks/roles/mailman3/tasks/create_lists.yaml
Normal file
@ -0,0 +1,114 @@
|
||||
- name: Check if domain exists
|
||||
uri:
|
||||
url: 'http://localhost:8001/3.1/domains/{{ mm_site.listdomain }}'
|
||||
url_username: restadmin
|
||||
url_password: "{{ mailman3_rest_password }}"
|
||||
force_basic_auth: yes
|
||||
method: GET
|
||||
body_format: json
|
||||
status_code: [200, 404]
|
||||
register: domain_exists
|
||||
no_log: true
|
||||
|
||||
- name: Create list domain in mm3
|
||||
when: domain_exists.status == 404
|
||||
uri:
|
||||
url: 'http://localhost:8001/3.1/domains'
|
||||
url_username: restadmin
|
||||
url_password: "{{ mailman3_rest_password }}"
|
||||
force_basic_auth: yes
|
||||
method: POST
|
||||
body_format: json
|
||||
body:
|
||||
mail_host: "{{ mm_site.listdomain }}"
|
||||
status_code: [201]
|
||||
no_log: true
|
||||
|
||||
- name: Check if list exists
|
||||
uri:
|
||||
url: 'http://localhost:8001/3.1/lists/{{ mm_list.name }}@{{ mm_site.listdomain }}'
|
||||
url_username: restadmin
|
||||
url_password: "{{ mailman3_rest_password }}"
|
||||
force_basic_auth: yes
|
||||
method: GET
|
||||
body_format: json
|
||||
status_code: [200, 404]
|
||||
register: list_exists
|
||||
loop: "{{ mm_site.lists }}"
|
||||
loop_control:
|
||||
loop_var: mm_list
|
||||
no_log: true
|
||||
|
||||
- name: Create lists in mm3
|
||||
when: list_exists.results[exists_idx].status == 404
|
||||
uri:
|
||||
url: 'http://localhost:8001/3.1/lists'
|
||||
url_username: restadmin
|
||||
url_password: "{{ mailman3_rest_password }}"
|
||||
force_basic_auth: yes
|
||||
method: POST
|
||||
body_format: json
|
||||
body:
|
||||
fqdn_listname: "{{ mm_list.name }}@{{ mm_site.listdomain }}"
|
||||
style_name: "{{ mm_list.private | default('false') | bool | ternary('private-default', 'legacy-default') }}"
|
||||
status_code: [201]
|
||||
loop: "{{ mm_site.lists }}"
|
||||
loop_control:
|
||||
loop_var: mm_list
|
||||
index_var: exists_idx
|
||||
no_log: true
|
||||
|
||||
- name: Set list properties in mm3
|
||||
when: list_exists.results[exists_idx].status == 404
|
||||
uri:
|
||||
url: 'http://localhost:8001/3.1/lists/{{ mm_list.name }}@{{ mm_site.listdomain }}/config'
|
||||
url_username: restadmin
|
||||
url_password: "{{ mailman3_rest_password }}"
|
||||
force_basic_auth: yes
|
||||
method: PATCH
|
||||
body_format: json
|
||||
body:
|
||||
description: "{{ mm_list.description }}"
|
||||
advertised: "{{ mm_list.private | default('false') | bool | ternary('false', 'true') }}"
|
||||
# TODO enable this when lynx is present on the container images
|
||||
# convert_html_to_plaintext: "true"
|
||||
process_bounces: "false"
|
||||
filter_extensions:
|
||||
- "exe"
|
||||
- "bat"
|
||||
- "cmd"
|
||||
- "com"
|
||||
- "pif"
|
||||
- "scr"
|
||||
- "vbs"
|
||||
- "cpl"
|
||||
pass_types:
|
||||
- "multipart/mixed"
|
||||
- "multipart/alternative"
|
||||
- "text/plain"
|
||||
status_code: [204]
|
||||
loop: "{{ mm_site.lists }}"
|
||||
loop_control:
|
||||
loop_var: mm_list
|
||||
index_var: exists_idx
|
||||
no_log: true
|
||||
|
||||
- name: Set list owner in mm3
|
||||
when: list_exists.results[exists_idx].status == 404
|
||||
uri:
|
||||
url: 'http://localhost:8001/3.1/members'
|
||||
url_username: restadmin
|
||||
url_password: "{{ mailman3_rest_password }}"
|
||||
force_basic_auth: yes
|
||||
method: POST
|
||||
body_format: json
|
||||
body:
|
||||
list_id: "{{ mm_list.name }}.{{ mm_site.listdomain }}"
|
||||
subscriber: "{{ mm_list.owner }}"
|
||||
role: "owner"
|
||||
status_code: [201]
|
||||
loop: "{{ mm_site.lists }}"
|
||||
loop_control:
|
||||
loop_var: mm_list
|
||||
index_var: exists_idx
|
||||
no_log: true
|
278
playbooks/roles/mailman3/tasks/main.yaml
Normal file
278
playbooks/roles/mailman3/tasks/main.yaml
Normal file
@ -0,0 +1,278 @@
|
||||
# The old mailman2 exim config refers to this file. Write it out
|
||||
# to make basic testing happy, but we may need to clean it up or
|
||||
# modify it for mailman3.
|
||||
- name: Write /etc/aliases.domain
|
||||
template:
|
||||
src: "domain_aliases.j2"
|
||||
dest: "/etc/aliases.domain"
|
||||
mode: '0444'
|
||||
|
||||
- name: Create Mailman Group
|
||||
group:
|
||||
name: mailman
|
||||
gid: 10010
|
||||
system: yes
|
||||
|
||||
- name: Create Mailman User
|
||||
user:
|
||||
name: mailman
|
||||
uid: 10010
|
||||
comment: Mailman User
|
||||
shell: /bin/bash
|
||||
home: /var/lib/mailman
|
||||
group: mailman
|
||||
create_home: yes
|
||||
system: yes
|
||||
|
||||
#### Install Mailman ####
|
||||
|
||||
- name: Ensure Mailman core volume directory exists
|
||||
file:
|
||||
state: directory
|
||||
path: "/var/lib/mailman/core"
|
||||
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
|
||||
owner: 100
|
||||
group: 65533
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Mailman database volume directory exists
|
||||
file:
|
||||
state: directory
|
||||
path: "/var/lib/mailman/database"
|
||||
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
|
||||
owner: 999
|
||||
group: 999
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Mailman web volume directories exist
|
||||
file:
|
||||
state: directory
|
||||
path: "/var/lib/mailman/{{ item }}"
|
||||
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
|
||||
owner: 100
|
||||
group: 101
|
||||
mode: '0755'
|
||||
loop:
|
||||
- import
|
||||
- web
|
||||
- web-data
|
||||
- web-data/fulltext_index
|
||||
- web-data/mm2archives
|
||||
|
||||
- name: Copy our overridden settings.py for mailman-web
|
||||
copy:
|
||||
src: web-settings.py
|
||||
dest: /var/lib/mailman/web/settings.py
|
||||
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
|
||||
owner: 100
|
||||
group: 101
|
||||
mode: '0644'
|
||||
|
||||
- name: Copy our settings_local.py for mailman-web
|
||||
copy:
|
||||
src: web-settings_local.py
|
||||
dest: /var/lib/mailman/web-data/settings_local.py
|
||||
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
|
||||
owner: 100
|
||||
group: 101
|
||||
mode: '0644'
|
||||
|
||||
- name: Copy our max_allowed_packet override config
|
||||
copy:
|
||||
src: 99-max_allowed_packet.cnf
|
||||
dest: /var/lib/mailman/99-max_allowed_packet.cnf
|
||||
owner: 999
|
||||
group: 999
|
||||
mode: '0644'
|
||||
|
||||
- name: Ensure /etc/mailman-compose directory
|
||||
file:
|
||||
state: directory
|
||||
path: /etc/mailman-compose
|
||||
mode: '0755'
|
||||
|
||||
- name: Put docker-compose file in place
|
||||
template:
|
||||
src: docker-compose.yaml.j2
|
||||
dest: /etc/mailman-compose/docker-compose.yaml
|
||||
mode: '0600'
|
||||
|
||||
- name: Run docker-compose pull
|
||||
shell:
|
||||
cmd: docker-compose pull
|
||||
chdir: /etc/mailman-compose/
|
||||
|
||||
- name: Run docker-compose up
|
||||
shell:
|
||||
cmd: docker-compose up -d
|
||||
chdir: /etc/mailman-compose/
|
||||
|
||||
- name: Run docker prune to cleanup unneeded images
|
||||
shell:
|
||||
cmd: docker image prune -f
|
||||
|
||||
- name: Install apache2
|
||||
package:
|
||||
name:
|
||||
- apache2
|
||||
- apache2-utils
|
||||
state: present
|
||||
|
||||
- name: Apache modules
|
||||
apache2_module:
|
||||
state: present
|
||||
name: "{{ a2_mod }}"
|
||||
loop:
|
||||
- authz_host
|
||||
- proxy
|
||||
- proxy_uwsgi
|
||||
- ssl
|
||||
- rewrite
|
||||
loop_control:
|
||||
loop_var: a2_mod
|
||||
notify: mailman restart apache2
|
||||
|
||||
- name: Make sure packaged default site disabled
|
||||
command: a2dissite 000-default.conf
|
||||
args:
|
||||
removes: /etc/apache2/sites-enabled/000-default.conf
|
||||
|
||||
- name: Create mailman vhost config
|
||||
template:
|
||||
src: mailman.vhost.j2
|
||||
dest: "/etc/apache2/sites-enabled/50-{{ mailman_sites.0.listdomain }}.conf"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: mailman reload apache2
|
||||
|
||||
- name: Enable apache2 server
|
||||
service:
|
||||
name: "apache2"
|
||||
enabled: yes
|
||||
|
||||
#### Configure Mailman Services ####
|
||||
|
||||
- name: Wait for mm3 REST API to be up and running
|
||||
uri:
|
||||
url: 'http://localhost:8001/3.1/domains'
|
||||
url_username: restadmin
|
||||
url_password: "{{ mailman3_rest_password }}"
|
||||
force_basic_auth: yes
|
||||
method: GET
|
||||
register: mm_rest_api_up
|
||||
delay: 1
|
||||
retries: 300
|
||||
until: mm_rest_api_up and mm_rest_api_up.status == 200
|
||||
no_log: true
|
||||
|
||||
# It has been difficult to nail down a reliable mathod for determining
|
||||
# when the database is sufficiently populated that we can create the django
|
||||
# admin user. We apply a number of approaches in response to this. If we
|
||||
# can identify a single method that is reliable this list can be trimmed.
|
||||
- name: Wait for DB to be populated
|
||||
command: >
|
||||
docker exec mailman-compose_database_1 bash -c
|
||||
'mysql -u mailman -p"$MYSQL_PASSWORD" -D mailmandb -e
|
||||
"SHOW TABLES LIKE \"auth_user\";"'
|
||||
register: django_db_exists
|
||||
delay: 1
|
||||
retries: 300
|
||||
until: django_db_exists.stdout_lines | length > 1 and django_db_exists.stdout_lines[1] == "auth_user"
|
||||
|
||||
- name: Wait for DB to be populated second approach
|
||||
command: >
|
||||
docker exec mailman-core alembic -c /usr/lib/python3.9/site-packages/mailman/config/alembic.cfg current
|
||||
register: alembic_version
|
||||
delay: 1
|
||||
retries: 300
|
||||
until: alembic_version.stdout_lines | length > 0 and "(head)" in alembic_version.stdout_lines[0]
|
||||
|
||||
- name: Wait for DB to be populated third approach
|
||||
shell: >
|
||||
docker exec mailman-web bash -c
|
||||
'python3 manage.py showmigrations' |
|
||||
grep -q '^ \[ \] [0-9]\+_.*'
|
||||
register: django_db_migrations
|
||||
delay: 1
|
||||
retries: 300
|
||||
failed_when: false
|
||||
# When grep stops matching the empty '[ ]' that indicates all migrations
|
||||
# are marked with '[X]' and are complete. Grep returns non zero when we
|
||||
# reach this point.
|
||||
until: django_db_migrations.rc != 0
|
||||
|
||||
- name: Check if django admin user exists
|
||||
command: >
|
||||
docker exec mailman-compose_database_1 bash -c
|
||||
'mysql -u mailman -p"$MYSQL_PASSWORD" -D mailmandb -e
|
||||
"SELECT COUNT(id) FROM auth_user WHERE id = 1 AND is_superuser = 1;"'
|
||||
register: django_admin_exists
|
||||
|
||||
- name: Create django admin user
|
||||
when: django_admin_exists.stdout_lines[1] == "0"
|
||||
command: >
|
||||
docker exec mailman-web bash -c
|
||||
"DJANGO_SUPERUSER_PASSWORD={{ mailman3_admin_password }}
|
||||
python3 manage.py createsuperuser --no-input
|
||||
--username {{ mailman3_admin_user }}
|
||||
--email '{{ mailman3_admin_email }}'"
|
||||
no_log: true
|
||||
|
||||
- name: Create lists in mm3
|
||||
include_tasks: create_lists.yaml
|
||||
loop: "{{ mailman_sites }}"
|
||||
loop_control:
|
||||
loop_var: mm_site
|
||||
|
||||
#### Logrotate for service logs ####
|
||||
|
||||
- name: Rotate mailman logs
|
||||
include_role:
|
||||
name: logrotate
|
||||
vars:
|
||||
logrotate_rotate: 90
|
||||
logrotate_file_name: '/var/lib/mailman/web-data/logs/*.log'
|
||||
|
||||
#### Database Backups ####
|
||||
|
||||
- name: Create db backup dest
|
||||
file:
|
||||
state: directory
|
||||
path: /var/backups/mailman-mariadb
|
||||
mode: 0700
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Set up cron job to backup the database
|
||||
cron:
|
||||
name: mailman-db-backup
|
||||
state: present
|
||||
user: root
|
||||
job: >
|
||||
/usr/local/bin/docker-compose -f /etc/mailman-compose/docker-compose.yaml exec -T database
|
||||
bash -c '/usr/bin/mysqldump --opt --databases mailmandb --single-transaction -uroot -p"$MYSQL_ROOT_PASSWORD"' |
|
||||
gzip -9 > /var/backups/mailman-mariadb/mailman-mariadb.sql.gz
|
||||
minute: 14
|
||||
hour: 5
|
||||
|
||||
- name: Rotate db backups
|
||||
include_role:
|
||||
name: logrotate
|
||||
vars:
|
||||
logrotate_file_name: /var/backups/mailman-mariadb/mailman-mariadb.sql.gz
|
||||
logrotate_compress: false
|
||||
|
||||
- name: Setup db backup streaming job
|
||||
block:
|
||||
- name: Create backup streaming config dir
|
||||
file:
|
||||
path: /etc/borg-streams
|
||||
state: directory
|
||||
|
||||
- name: Create db streaming file
|
||||
copy:
|
||||
content: >-
|
||||
/usr/local/bin/docker-compose -f /etc/mailman-compose/docker-compose.yaml exec -T mariadb
|
||||
bash -c '/usr/bin/mysqldump --skip-extended-insert --databases mailmandb --single-transaction -uroot -p"$MYSQL_ROOT_PASSWORD"'
|
||||
dest: /etc/borg-streams/mysql
|
71
playbooks/roles/mailman3/templates/docker-compose.yaml.j2
Normal file
71
playbooks/roles/mailman3/templates/docker-compose.yaml.j2
Normal file
@ -0,0 +1,71 @@
|
||||
# Adapted from https://github.com/maxking/docker-mailman/blob/2693386453ff3865b7c106c6aa456b683bd3bf08/docker-compose-mysql.yaml
|
||||
# which is an MIT licensed repo.
|
||||
|
||||
version: '2'
|
||||
services:
|
||||
mailman-core:
|
||||
image: docker.io/maxking/mailman-core:0.4
|
||||
restart: always
|
||||
container_name: mailman-core
|
||||
volumes:
|
||||
- /var/lib/mailman/core:/opt/mailman/
|
||||
- /var/lib/mailman/import:/opt/import
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
- database
|
||||
environment:
|
||||
- DATABASE_URL=mysql+pymysql://mailman:{{ mailman3_db_password }}@127.0.0.1:3306/mailmandb?charset=utf8mb4&use_unicode=1
|
||||
- DATABASE_TYPE=mysql
|
||||
- DATABASE_CLASS=mailman.database.mysql.MySQLDatabase
|
||||
- HYPERKITTY_URL=http://127.0.0.1:8000/hyperkitty
|
||||
- HYPERKITTY_API_KEY={{ mailman3_hyperkitty_api_key }}
|
||||
- SMTP_HOST=localhost
|
||||
- MM_HOSTNAME=localhost
|
||||
- MAILMAN_REST_USER=restadmin
|
||||
- MAILMAN_REST_PASSWORD={{ mailman3_rest_password }}
|
||||
network_mode: host
|
||||
#user: mailman
|
||||
|
||||
mailman-web:
|
||||
image: docker.io/maxking/mailman-web:0.4
|
||||
restart: always
|
||||
container_name: mailman-web
|
||||
depends_on:
|
||||
- database
|
||||
volumes:
|
||||
- /var/lib/mailman/import:/opt/import
|
||||
- /var/lib/mailman/web-data:/opt/mailman-web-data
|
||||
- /var/lib/mailman/web/settings.py:/opt/mailman-web/settings.py
|
||||
environment:
|
||||
# Testing to see if these are really necessary
|
||||
#- MAILMAN_ADMIN_USER={{ mailman3_admin_user }}
|
||||
#- MAILMAN_ADMIN_EMAIL={{ mailman3_admin_email }}
|
||||
- SERVE_FROM_DOMAIN=lists.opendev.org
|
||||
- DJANGO_ALLOWED_HOSTS={{ mm_domains }}
|
||||
- DATABASE_TYPE=mysql
|
||||
- DATABASE_URL=mysql://mailman:{{ mailman3_db_password }}@127.0.0.1:3306/mailmandb?charset=utf8mb4
|
||||
- HYPERKITTY_API_KEY={{ mailman3_hyperkitty_api_key }}
|
||||
- SECRET_KEY={{ mailman3_django_secret_key }}
|
||||
- DYLD_LIBRARY_PATH=/usr/local/mysql/lib/
|
||||
- MAILMAN_HOSTNAME=localhost
|
||||
- MAILMAN_REST_URL=http://127.0.0.1:8001
|
||||
- MAILMAN_REST_USER=restadmin
|
||||
- MAILMAN_REST_PASSWORD={{ mailman3_rest_password }}
|
||||
- POSTORIUS_TEMPLATE_BASE_URL=http://127.0.0.1:8000
|
||||
- SMTP_HOST=localhost
|
||||
network_mode: host
|
||||
#user: mailman
|
||||
|
||||
database:
|
||||
environment:
|
||||
MYSQL_DATABASE: mailmandb
|
||||
MYSQL_USER: mailman
|
||||
MYSQL_PASSWORD: {{ mailman3_db_password }}
|
||||
MYSQL_ROOT_PASSWORD: {{ mailman3_db_root_password }}
|
||||
image: docker.io/library/mariadb:10.6
|
||||
restart: always
|
||||
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
volumes:
|
||||
- /var/lib/mailman/database:/var/lib/mysql
|
||||
- /var/lib/mailman/99-max_allowed_packet.cnf:/etc/mysql/conf.d/99-max_allowed_packet.cnf:ro
|
||||
network_mode: host
|
6
playbooks/roles/mailman3/templates/domain_aliases.j2
Normal file
6
playbooks/roles/mailman3/templates/domain_aliases.j2
Normal file
@ -0,0 +1,6 @@
|
||||
# /etc/aliases.domain
|
||||
{% for k, v in exim_domain_aliases|dictsort %}
|
||||
{% if v %}
|
||||
{{ k }}: {{ v }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
69
playbooks/roles/mailman3/templates/mailman.vhost.j2
Normal file
69
playbooks/roles/mailman3/templates/mailman.vhost.j2
Normal file
@ -0,0 +1,69 @@
|
||||
<VirtualHost *:80>
|
||||
ServerName {{ mailman_sites.0.listdomain }}
|
||||
{% for site in mailman_sites[1:] -%}
|
||||
ServerAlias {{ site.listdomain }}
|
||||
{% endfor -%}
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/{{ mailman_sites.0.listdomain }}-error.log
|
||||
|
||||
# Possible values include: debug, info, notice, warn, error, crit,
|
||||
# alert, emerg.
|
||||
LogLevel warn
|
||||
|
||||
CustomLog ${APACHE_LOG_DIR}/{{ mailman_sites.0.listdomain }}-access.log combined
|
||||
|
||||
# Use mod rewrite to redirect as we want to preserve the FQDN for each
|
||||
# mm3 vhost.
|
||||
RewriteEngine On
|
||||
RewriteRule "/(.*)" "https://%{HTTP_HOST}/$1" [R=301]
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost *:443>
|
||||
ServerName {{ mailman_sites.0.listdomain }}
|
||||
{% for site in mailman_sites[1:] -%}
|
||||
ServerAlias {{ site.listdomain }}
|
||||
{% endfor -%}
|
||||
ServerAdmin webmaster@openstack.org
|
||||
ErrorLog ${APACHE_LOG_DIR}/{{ mailman_sites.0.listdomain }}-ssl-error.log
|
||||
LogLevel warn
|
||||
CustomLog ${APACHE_LOG_DIR}/{{ mailman_sites.0.listdomain }}-ssl-access.log combined
|
||||
|
||||
SSLEngine on
|
||||
SSLProtocol All -SSLv2 -SSLv3
|
||||
# Note: this list should ensure ciphers that provide forward secrecy
|
||||
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!AES256:!aNULL:!eNULL:!MD5:!DSS:!PSK:!SRP
|
||||
SSLHonorCipherOrder on
|
||||
|
||||
SSLCertificateFile /etc/letsencrypt-certs/{{ inventory_hostname }}/{{ inventory_hostname }}.cer
|
||||
SSLCertificateKeyFile /etc/letsencrypt-certs/{{ inventory_hostname }}/{{ inventory_hostname }}.key
|
||||
SSLCertificateChainFile /etc/letsencrypt-certs/{{ inventory_hostname }}/ca.cer
|
||||
|
||||
Alias /static /var/lib/mailman/web-data/static
|
||||
Alias /favicon.ico /var/lib/mailman/web-data/static/hyperkitty/img/favicon.ico
|
||||
|
||||
<Location "/admin">
|
||||
Require local
|
||||
</Location>
|
||||
|
||||
RewriteEngine On
|
||||
RewriteRule "/pipermail/(.*)" "/var/lib/mailman/web-data/mm2archives/%{HTTP_HOST}/public/$1"
|
||||
RewriteRule "/cgi-bin/mailman/listinfo/(.*)" "https://%{HTTP_HOST}/postorius/lists/$1.%{HTTP_HOST}/"
|
||||
RewriteRule "/cgi-bin/mailman/listinfo" "https://%{HTTP_HOST}/postorius/lists/"
|
||||
|
||||
ProxyPassMatch ^/static/ !
|
||||
ProxyPass "/" "uwsgi://localhost:8080/"
|
||||
|
||||
<Directory /var/lib/mailman/web-data/static/>
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
<Directory /var/lib/mailman/web-data/mm2archives/>
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
10
playbooks/service-lists3.yaml
Normal file
10
playbooks/service-lists3.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
# Maintaing a todo list here as a central accounting file
|
||||
# TODO Test mailman dmarc settings
|
||||
# TODO fix container uid/gid mismatch with bind mounted contents
|
||||
# this breaks xapian
|
||||
- hosts: "mailman3:!disabled"
|
||||
name: "Configure mailman3 servers"
|
||||
roles:
|
||||
- iptables
|
||||
- install-docker
|
||||
- mailman3
|
294
playbooks/zuul/files/host_vars/lists99.opendev.org.yaml
Normal file
294
playbooks/zuul/files/host_vars/lists99.opendev.org.yaml
Normal file
@ -0,0 +1,294 @@
|
||||
mailman_list_password: notarealpassword
|
||||
mailman3_db_password: Eith5vii5beezohc
|
||||
mailman3_db_root_password: eiloh9Edohngaeri
|
||||
mailman3_hyperkitty_api_key: Thosai4Xomeque9e
|
||||
mailman3_django_secret_key: ohki3ohWusai8tee
|
||||
mailman3_rest_password: OhTo3doh5ohsuope
|
||||
mailman3_admin_user: admin
|
||||
mailman3_admin_email: infra-root@openstack.org
|
||||
mailman3_admin_password: AeNie8vegeiquei1
|
||||
mm_domains: 'lists.openstack.org:lists.zuul-ci.org:lists.airshipit.org:lists.starlingx.io:lists.opendev.org:lists.openinfra.dev:lists.katacontainers.io'
|
||||
exim_local_domains: "@:{{ mm_domains }}"
|
||||
exim_enable_spf: true
|
||||
exim_aliases:
|
||||
root: "{{ ','.join(listadmins|default([])) }}"
|
||||
interop-wg: openstack-discuss
|
||||
openstack: openstack-discuss
|
||||
openstack-dev: openstack-discuss
|
||||
openstack-infra: openstack-discuss
|
||||
openstack-operators: openstack-discuss
|
||||
openstack-security: openstack-discuss
|
||||
openstack-sigs: openstack-discuss
|
||||
openstack-tc: openstack-discuss
|
||||
user-committee: openstack-discuss
|
||||
airship-discuss-owner: spam
|
||||
community-owner: spam
|
||||
edge-computing-owner: spam
|
||||
foundation-board-confidential-owner: spam
|
||||
foundation-board-owner: spam
|
||||
foundation-owner: spam
|
||||
legal-discuss-owner: spam
|
||||
mailman-owner: spam
|
||||
marketing-owner: spam
|
||||
openstack-announce-owner: spam
|
||||
openstack-docs-owner: spam
|
||||
openstack-fr-owner: spam
|
||||
openstack-i18n-owner: spam
|
||||
openstack-infra-owner: spam
|
||||
openstack-ko-owner: spam
|
||||
openstack-qa-owner: spam
|
||||
product-wg-owner: spam
|
||||
user-committee-owner: spam
|
||||
spam: ':fail: delivery temporarily disabled due to ongoing spam flood'
|
||||
# TODO It would be better to bypass verification for postorius@listdomain
|
||||
# and set a :fail: rule for anyone trying to send email to this addr.
|
||||
# But that requires updating our main exim config so that needs more thought.
|
||||
postorius: ':blackhole: outgoing email only from this address'
|
||||
exim_domain_aliases:
|
||||
community@lists.openstack.org: community@lists.openinfra.dev
|
||||
edge-computing@lists.openstack.org: edge-computing@lists.opendev.org
|
||||
foundation@lists.openstack.org: foundation@lists.openinfra.dev
|
||||
foundation-board@lists.openstack.org: foundation-board@lists.openinfra.dev
|
||||
foundation-board-confidential@lists.openstack.org: foundation-board-confidential@lists.openinfra.dev
|
||||
goldmembers@lists.openstack.org: goldmembers@lists.openinfra.dev
|
||||
marketing@lists.openstack.org: marketing@lists.openinfra.dev
|
||||
staff@lists.openstack.org: staff@lists.openinfra.dev
|
||||
summit-programming-committee@lists.openinfra.dev: summit-track-chairs@lists.openinfra.dev
|
||||
summitsponsors@lists.openstack.org: summitsponsors@lists.openinfra.dev
|
||||
exim_routers:
|
||||
- mailman_verp_router: |
|
||||
{% raw -%}
|
||||
driver = dnslookup
|
||||
condition = ${if or{{eq{$sender_host_address}{127.0.0.1}}\
|
||||
{eq{$sender_host_address}{::1}}}{yes}{no}}
|
||||
{% endraw %}
|
||||
domains = !+local_domains
|
||||
ignore_target_hosts = <; 0.0.0.0; \
|
||||
64.94.110.11; \
|
||||
127.0.0.0/8; \
|
||||
::1/128;fe80::/10;fe \
|
||||
c0::/10;ff00::/8
|
||||
senders = "*-bounces@*"
|
||||
transport = mailman_verp_smtp
|
||||
- dnslookup: '{{ exim_dnslookup_router }}'
|
||||
- system_aliases: '{{ exim_system_aliases_router }}'
|
||||
- domain_aliases: |
|
||||
driver = redirect
|
||||
allow_fail
|
||||
allow_defer
|
||||
data = ${lookup{$local_part@$domain}lsearch{/etc/aliases.domain}}
|
||||
file_transport = address_file
|
||||
pipe_transport = address_pipe
|
||||
- localuser: '{{ exim_localuser_router }}'
|
||||
- mailman_copy: |
|
||||
driver = accept
|
||||
domains = lists.openstack.org
|
||||
local_parts = openstack-discuss
|
||||
transport = local_copy
|
||||
unseen
|
||||
- mailman_router: |
|
||||
driver = accept
|
||||
domains = {{ mm_domains }}
|
||||
local_part_suffix = -admin : \
|
||||
-bounces : -bounces+* : \
|
||||
-confirm : -confirm+* : \
|
||||
-join : -leave : \
|
||||
-owner : -request : \
|
||||
-subscribe : -unsubscribe
|
||||
local_part_suffix_optional
|
||||
require_files = /var/lib/mailman/core/var/lists/${local_part}.${domain}
|
||||
transport = mailman_transport
|
||||
exim_transports:
|
||||
- local_copy: |
|
||||
driver = appendfile
|
||||
file = /var/mail/$local_part
|
||||
group = mail
|
||||
mode = 0660
|
||||
- mailman_transport: |
|
||||
debug_print = "Email for mailman"
|
||||
driver = smtp
|
||||
protocol = lmtp
|
||||
allow_localhost
|
||||
hosts = localhost
|
||||
port = 8024
|
||||
rcpt_include_affixes = true
|
||||
- mailman_verp_smtp: |
|
||||
driver = smtp
|
||||
headers_add = Errors-To: ${return_path}
|
||||
headers_remove = Errors-To
|
||||
max_rcpt = 1
|
||||
return_path = ${local_part:$return_path}+$local_part=$domain@${domain:$return_path}
|
||||
mailman_multihost: true
|
||||
mailman_sites:
|
||||
# First entry in this list is the primary web domain
|
||||
- listdomain: lists.opendev.org
|
||||
install_languages: ['en']
|
||||
lists:
|
||||
- name: computing-force-network
|
||||
description: 'Organizing efforts around Computing Force Network related area'
|
||||
owner: 'niujie@outlook.com'
|
||||
- name: edge-computing
|
||||
description: 'Organizing efforts around the edge-computing focus area.'
|
||||
owner: 'ildiko@openinfra.dev'
|
||||
- name: floss-mooc
|
||||
description: 'Discussions & Coordination around the FLOSS MOOC being collaboratively developed here: https://gitlab.com/mooc-floss/mooc-floss'
|
||||
owner: 'knelson@openinfra.dev'
|
||||
- name: nbmp-discuss
|
||||
description: 'Collaborating on Network Based Media Processing related platform and infrastructure systems usage and development.'
|
||||
owner: 'ildiko@openstack.org'
|
||||
- name: openinfralabs
|
||||
description: 'Discussion of the OpenInfra Labs academic and research resource sharing effort'
|
||||
owner: 'mnaser@vexxhost.com'
|
||||
- name: rust-vmm
|
||||
description: 'Collaborating on Rust-based virtual machine monitors.'
|
||||
owner: 'claire@openstack.org'
|
||||
- name: rustyk8s
|
||||
description: 'Collaborating on Rust-based Kubernetes API.'
|
||||
owner: 'allison@lohutok.net'
|
||||
- name: service-announce
|
||||
description: 'Announcement list for OpenDev services.'
|
||||
owner: 'cboylan@sapwetik.org'
|
||||
- name: service-discuss
|
||||
description: 'Discussion list for OpenDev services.'
|
||||
owner: 'cboylan@sapwetik.org'
|
||||
- name: service-incident
|
||||
description: 'Private list for OpenDev incident coordination.'
|
||||
owner: 'cboylan@sapwetik.org'
|
||||
private: true
|
||||
- listdomain: lists.airshipit.org
|
||||
install_languages: ['en']
|
||||
lists:
|
||||
- name: airship-announce
|
||||
description: 'Announcements of Airship releases and other important information.'
|
||||
owner: 'jonathan@openstack.org'
|
||||
- name: airship-discuss
|
||||
description: 'Discussion of Airship usage and development.'
|
||||
owner: 'jonathan@openstack.org'
|
||||
- name: airship-embargo-notice
|
||||
description: 'Embargoed security vulnerability announcements for Airship consumers.'
|
||||
owner: 'andrew.walters@att.com'
|
||||
private: true
|
||||
- name: airship-job-failures
|
||||
description: 'Notification messages for failures from CICD jobs.'
|
||||
owner: 'roman.gorshunov@att.com'
|
||||
- name: airship-security
|
||||
description: 'Public Airship security advisories.'
|
||||
owner: 'andrew.walters@att.com'
|
||||
- listdomain: lists.katacontainers.io
|
||||
install_languages: ['en']
|
||||
lists:
|
||||
- name: embargo-notice
|
||||
description: 'Announcements of embargoed notices for the Kata Containers project'
|
||||
owner: 'jonathan@openstack.org'
|
||||
private: true
|
||||
- name: kata-dev
|
||||
description: 'Kata Containers Development Mailing List (not for usage questions)'
|
||||
owner: 'jonathan@openstack.org'
|
||||
- name: kata-hypervisor
|
||||
description: 'Discussion of security and virtualization targeted at container use cases'
|
||||
owner: 'jonathan@openstack.org'
|
||||
- listdomain: lists.openinfra.dev
|
||||
install_languages: ['en']
|
||||
lists:
|
||||
- name: community
|
||||
description: 'The OpenInfra Community team is the main contact point for anybody running a local OpenInfra Group.'
|
||||
owner: 'allison@openinfra.dev'
|
||||
- name: foundation
|
||||
description: 'General discussion list for activities of the OpenInfra Foundation'
|
||||
owner: 'jonathan@openinfra.dev'
|
||||
- name: foundation-board
|
||||
description: 'OpenInfra Foundation Board of Directors'
|
||||
owner: 'jonathan@openinfra.dev'
|
||||
- name: foundation-board-confidential
|
||||
description: 'OpenInfra Foundation Board of Directors'
|
||||
owner: 'jonathan@openinfra.dev'
|
||||
private: true
|
||||
- name: goldmembers
|
||||
description: 'The discussion list for Gold Members of the OpenInfra Foundation'
|
||||
owner: 'jonathan@openinfra.dev'
|
||||
private: true
|
||||
- name: marketing
|
||||
description: 'The OpenInfra Marketing list is the meant to facilitate discussion and best practice sharing among marketers and event organizers in the OpenInfra community.'
|
||||
owner: 'allison@openinfra.dev'
|
||||
- name: staff
|
||||
description: 'Private list for OpenInfra Foundation staff members'
|
||||
owner: 'mark@openinfra.dev'
|
||||
private: true
|
||||
- name: summit-track-chairs
|
||||
description: 'OpenInfra Summit track chair communications'
|
||||
owner: 'erin@openinfra.dev'
|
||||
private: true
|
||||
- name: summitsponsors
|
||||
description: 'Coordination among OpenInfra Summit event sponsors'
|
||||
owner: 'erin@openinfra.dev'
|
||||
private: true
|
||||
- listdomain: lists.openstack.org
|
||||
install_languages: ['de', 'fr', 'it', 'ko', 'ru', 'vi', 'zh_TW']
|
||||
lists:
|
||||
- name: embargo-notice
|
||||
description: 'Announcements to stakeholders for embargoed security vulnerabilities.'
|
||||
owner: 'fungi@yuggoth.org'
|
||||
private: true
|
||||
- name: legal-discuss
|
||||
description: 'Discussions on legal matters related to the project'
|
||||
owner: 'thierry@openinfra.dev'
|
||||
- name: openstack-announce
|
||||
description: 'Key announcements about OpenStack & Security advisories'
|
||||
owner: 'fungi@yuggoth.org'
|
||||
- name: openstack-discuss
|
||||
description: 'Discussion of OpenStack usage and development.'
|
||||
owner: 'fungi@yuggoth.org'
|
||||
- name: openstack-es
|
||||
description: 'Lista de correo acerca de OpenStack en español'
|
||||
owner: 'flavio@redhat.com'
|
||||
- name: openstack-fr
|
||||
description: 'List of the OpenStack french user group'
|
||||
owner: 'erwan@erwan.com'
|
||||
- name: openstack-hpc
|
||||
description: 'High-Performance Computing OpenStack List'
|
||||
owner: 'brian.schott@nimbisservices.com'
|
||||
- name: openstack-i18n
|
||||
description: 'List of the OpenStack Internationalization team.'
|
||||
owner: 'guoyingc@cn.ibm.com'
|
||||
- name: openstack-it
|
||||
description: 'Discussioni su OpenStack in italiano'
|
||||
owner: 'stefano@openstack.org'
|
||||
- name: openstack-ko
|
||||
description: 'OpenStack Korea Community Discussions in Korean (오픈스택 한국 커뮤니티 메일링리스트)'
|
||||
owner: 'ianyrchoi@gmail.com'
|
||||
- name: openstack-mentoring
|
||||
description: 'List to coordinate interactions between mentors and mentees of the OpenStack mentoring program. Also for questions about the mentoring program (i.e. how to get involved, how it works, etc.'
|
||||
owner: 'amy@demarco.com'
|
||||
- name: openstack-stable-maint
|
||||
description: 'A mailing list for the OpenStack Stable Branch test reports.'
|
||||
owner: 'tony@bakeyournoodle.com'
|
||||
- name: openstack-zh
|
||||
description: 'OpenStack社区中文讨论群组'
|
||||
owner: 'yeluaiesec@gmail.com'
|
||||
- name: release-announce
|
||||
description: 'Announcement of official OpenStack releases.'
|
||||
owner: 'thierry@openstack.org'
|
||||
- name: release-job-failures
|
||||
description: 'Notification messages for failures from release-related build jobs.'
|
||||
owner: 'doug@doughellmann.com'
|
||||
- listdomain: lists.starlingx.io
|
||||
install_languages: ['en']
|
||||
lists:
|
||||
- name: starlingx-announce
|
||||
description: 'Announcements of StarlingX releases and other important information.'
|
||||
owner: 'jonathan@openstack.org'
|
||||
- name: starlingx-discuss
|
||||
description: 'Discussion of StarlingX usage and development.'
|
||||
owner: 'jonathan@openstack.org'
|
||||
- listdomain: lists.zuul-ci.org
|
||||
install_languages: ['en']
|
||||
lists:
|
||||
- name: zuul-announce
|
||||
description: 'Announcements of Zuul releases and other important information.'
|
||||
owner: 'corvus@inaugust.com'
|
||||
- name: zuul-discuss
|
||||
description: 'Discussion of Zuul usage and development.'
|
||||
owner: 'corvus@inaugust.com'
|
||||
- name: zuul-jobs-failures
|
||||
description: 'Gets notifications about zuul-jobs periodic job failures.'
|
||||
owner: 'ssbarnea@redhat.com'
|
16
playbooks/zuul/lists3-alias-logs.yaml
Normal file
16
playbooks/zuul/lists3-alias-logs.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
# We need to do this in a run playbook so that we copy logs even
|
||||
# when the run playbooks fail. Failure in the run playbooks prevents the
|
||||
# test playbook from running.
|
||||
- hosts: "mailman3"
|
||||
tasks:
|
||||
- name: Alias mailman-web logs
|
||||
file:
|
||||
state: link
|
||||
src: /var/lib/mailman/web-data/logs
|
||||
path: /var/lib/mailman/mailman-web-logs
|
||||
|
||||
- name: Alias mailman-core logs
|
||||
file:
|
||||
state: link
|
||||
src: /var/lib/mailman/core/var/logs
|
||||
path: /var/lib/mailman/mailman-core-logs
|
@ -151,6 +151,14 @@
|
||||
- host_vars/paste99.opendev.org.yaml
|
||||
- host_vars/refstack01.openstack.org.yaml
|
||||
- host_vars/review99.opendev.org.yaml
|
||||
- name: Write lists99 host_vars.
|
||||
# This file is special because it has raw tags in it that we need to
|
||||
# carry through. I can't figure out a better way to do that then copying
|
||||
# it directly rather than treating it as a template.
|
||||
copy:
|
||||
src: "files/host_vars/lists99.opendev.org.yaml"
|
||||
dest: "/etc/ansible/hosts/host_vars/lists99.opendev.org.yaml"
|
||||
|
||||
- name: Display group membership
|
||||
command: ansible localhost -m debug -a 'var=groups'
|
||||
- name: Run base.yaml
|
||||
|
19
playbooks/zuul/test-lists3.yaml
Normal file
19
playbooks/zuul/test-lists3.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
- hosts: "mailman3"
|
||||
tasks:
|
||||
- name: Force hyperkitty to populate info about the new lists we created
|
||||
command: docker exec mailman-web ./manage.py runjobs hourly
|
||||
|
||||
- name: Update /etc/hosts in order to test mm3 vhosts
|
||||
lineinfile:
|
||||
state: present
|
||||
backrefs: yes
|
||||
path: /etc/hosts
|
||||
regexp: '^127\.0\.0\.1\s+(.*)$'
|
||||
line: '127.0.0.1 \1 {{ mm_site.listdomain }}'
|
||||
loop: "{{ mailman_sites }}"
|
||||
loop_control:
|
||||
loop_var: mm_site
|
||||
|
||||
- name: Run selenium container
|
||||
include_role:
|
||||
name: run-selenium
|
61
testinfra/test_lists_opendev_org.py
Normal file
61
testinfra/test_lists_opendev_org.py
Normal file
@ -0,0 +1,61 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from util import take_screenshots
|
||||
|
||||
testinfra_hosts = ['lists99.opendev.org']
|
||||
|
||||
def test_mariadb_listening(host):
|
||||
mariadb_port = host.socket("tcp://127.0.0.1:3306")
|
||||
assert mariadb_port.is_listening
|
||||
|
||||
def test_mailman3_web_listening(host):
|
||||
mailman_web = host.socket("tcp://0.0.0.0:8000")
|
||||
assert mailman_web.is_listening
|
||||
mailman_uwsgi = host.socket("tcp://0.0.0.0:8080")
|
||||
assert mailman_uwsgi.is_listening
|
||||
|
||||
def test_mailman3_core_listening(host):
|
||||
mailman_rest = host.socket("tcp://127.0.0.1:8001")
|
||||
assert mailman_rest.is_listening
|
||||
mailman_lmtp = host.socket("tcp://127.0.0.1:8024")
|
||||
assert mailman_lmtp.is_listening
|
||||
|
||||
def test_apache2_listening(host):
|
||||
apache2_http = host.socket("tcp://0.0.0.0:80")
|
||||
assert apache2_http.is_listening
|
||||
apache2_https = host.socket("tcp://0.0.0.0:443")
|
||||
assert apache2_https.is_listening
|
||||
|
||||
def test_mailman3_screenshots(host):
|
||||
shots = (
|
||||
("https://lists.opendev.org:443", None, "mm3-opendev-main.png"),
|
||||
("https://lists.opendev.org:443/hyperkitty/",
|
||||
None, "mm3-opendev-archives.png"),
|
||||
("https://lists.opendev.org:443"
|
||||
"/hyperkitty/list/service-discuss@lists.opendev.org/",
|
||||
None, "mm3-opendev-list.png"),
|
||||
("https://lists.opendev.org:443"
|
||||
"/accounts/login/?next=/postorius/lists/",
|
||||
None, "mm3-opendev-login.png"),
|
||||
("https://lists.openstack.org:443", None, "mm3-openstack-main.png"),
|
||||
("https://lists.openstack.org:443/hyperkitty/",
|
||||
None, "mm3-openstack-archives.png"),
|
||||
("https://lists.openstack.org:443"
|
||||
"/hyperkitty/list/openstack-discuss@lists.openstack.org/",
|
||||
None, "mm3-openstack-list.png"),
|
||||
("https://lists.openstack.org:443"
|
||||
"/accounts/login/?next=/postorius/lists/",
|
||||
None, "mm3-openstack-login.png"),
|
||||
)
|
||||
|
||||
take_screenshots(host, shots)
|
28
tools/mm3-migrate.sh
Normal file
28
tools/mm3-migrate.sh
Normal file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
s=$1
|
||||
test -z "$s" && echo 'Specify the list FQDN to migrate!' && exit 1
|
||||
echo "*** starting at $(date -Is) ***"
|
||||
set -x
|
||||
for m in $(
|
||||
ls -d /var/lib/mailman/import/$s/lists/* \
|
||||
| grep -v /mailman$ \
|
||||
| cut -d/ -f8
|
||||
); do
|
||||
time sudo docker-compose -f /etc/mailman-compose/docker-compose.yaml \
|
||||
exec -T -u mailman mailman-core mailman import21 $m@$s \
|
||||
/opt/import/$s/lists/$m/config.pck
|
||||
time sudo docker-compose -f /etc/mailman-compose/docker-compose.yaml \
|
||||
exec -T -u mailman mailman-web python3 manage.py hyperkitty_import -l \
|
||||
$m@$s /opt/import/$s/archives/private/$m.mbox/$m.mbox
|
||||
time sudo docker-compose -f /etc/mailman-compose/docker-compose.yaml \
|
||||
exec -T -u mailman mailman-web python3 manage.py \
|
||||
update_index_one_list $m@$s
|
||||
done
|
||||
sudo mv /var/lib/mailman/import/$s/archives \
|
||||
/var/lib/mailman/web-data/mm2archives/$s
|
||||
for a in /var/lib/mailman/web-data/mm2archives/$s/public/*; do
|
||||
sudo ln -fs ../private/`basename $a` $a
|
||||
done
|
||||
set +x
|
||||
echo "*** completed at $(date -Is) ***"
|
@ -571,9 +571,23 @@
|
||||
- inventory/service/host_vars/lists.katacontainers.io.yaml
|
||||
- playbooks/roles/iptables/
|
||||
- playbooks/roles/base/exim
|
||||
- playbooks/roles/mailman
|
||||
- playbooks/roles/mailman/
|
||||
- playbooks/service-lists.yaml
|
||||
|
||||
- job:
|
||||
name: infra-prod-service-lists3
|
||||
parent: infra-prod-service-base
|
||||
description: Run service-lists3.yaml playbook.
|
||||
vars:
|
||||
playbook_name: service-lists3.yaml
|
||||
files:
|
||||
- inventory/base
|
||||
- inventory/service/host_vars/lists01.opendev.org.yaml
|
||||
- playbooks/roles/iptables/
|
||||
- playbooks/roles/base/exim
|
||||
- playbooks/roles/mailman3/
|
||||
- playbooks/service-lists3.yaml
|
||||
|
||||
# Run AFS changes separately so we can make sure to only do one at a time
|
||||
# (turns out quorum is nice to have)
|
||||
- job:
|
||||
|
@ -30,6 +30,7 @@
|
||||
soft: true
|
||||
- system-config-run-kerberos
|
||||
- system-config-run-lists
|
||||
- system-config-run-lists3
|
||||
- system-config-run-nodepool:
|
||||
dependencies:
|
||||
- name: opendev-buildset-registry
|
||||
@ -181,6 +182,7 @@
|
||||
soft: true
|
||||
- system-config-run-kerberos
|
||||
- system-config-run-lists
|
||||
- system-config-run-lists3
|
||||
- system-config-run-nodepool:
|
||||
dependencies:
|
||||
- name: opendev-buildset-registry
|
||||
@ -463,6 +465,12 @@
|
||||
soft: true
|
||||
- name: infra-prod-letsencrypt
|
||||
soft: true
|
||||
- infra-prod-service-lists3: &infra-prod-service-lists3
|
||||
dependencies:
|
||||
- name: infra-prod-service-borg-backup
|
||||
soft: true
|
||||
- name: infra-prod-letsencrypt
|
||||
soft: true
|
||||
- infra-prod-service-mirror: &infra-prod-service-mirror
|
||||
dependencies:
|
||||
- name: infra-prod-letsencrypt
|
||||
@ -605,6 +613,7 @@
|
||||
- infra-prod-service-keycloak: *infra-prod-service-keycloak
|
||||
- infra-prod-service-meetpad: *infra-prod-service-meetpad
|
||||
- infra-prod-service-lists: *infra-prod-service-lists
|
||||
- infra-prod-service-lists3: *infra-prod-service-lists3
|
||||
- infra-prod-service-mirror: *infra-prod-service-mirror
|
||||
- infra-prod-service-nodepool: *infra-prod-service-nodepool
|
||||
- infra-prod-service-static: *infra-prod-service-static
|
||||
|
@ -276,7 +276,7 @@
|
||||
- inventory/service/host_vars/lists.katacontainers.io.yaml
|
||||
- inventory/service/group_vars/mailman.yaml
|
||||
- playbooks/roles/base/exim
|
||||
- playbooks/roles/mailman
|
||||
- playbooks/roles/mailman/
|
||||
- playbooks/service-lists.yaml
|
||||
- playbooks/test-lists.yaml
|
||||
- playbooks/zuul/templates/host_vars/lists.openstack.org.yaml.j2
|
||||
@ -304,6 +304,49 @@
|
||||
'/var/log/apache2': logs
|
||||
'/var/log/mailman': logs
|
||||
|
||||
- job:
|
||||
name: system-config-run-lists3
|
||||
# We don't use the system-config-run-containers base job because we
|
||||
# are consuming upstream containers only.
|
||||
parent: system-config-run
|
||||
description: |
|
||||
Run the playbook for a mailman3 list server.
|
||||
timeout: 3600
|
||||
nodeset:
|
||||
nodes:
|
||||
- <<: *bridge_node_x86
|
||||
- name: lists99.opendev.org
|
||||
label: ubuntu-jammy
|
||||
groups:
|
||||
- <<: *bastion_group
|
||||
required-projects:
|
||||
- opendev/system-config
|
||||
files:
|
||||
- playbooks/bootstrap-bridge.yaml
|
||||
- inventory/service/host_vars/lists01.opendev.org.yaml
|
||||
- inventory/service/group_vars/mailman3.yaml
|
||||
- playbooks/roles/base/exim
|
||||
- playbooks/roles/mailman3
|
||||
- playbooks/service-lists3.yaml
|
||||
- playbooks/test-lists3.yaml
|
||||
- playbooks/zuul/files/host_vars/lists99.opendev.org.yaml
|
||||
- testinfra/test_lists_opendev_org.py
|
||||
vars:
|
||||
run_playbooks:
|
||||
- playbooks/letsencrypt.yaml
|
||||
- playbooks/service-lists3.yaml
|
||||
# Run this twice to check idempotency
|
||||
- playbooks/service-lists3.yaml
|
||||
- playbooks/zuul/lists3-alias-logs.yaml
|
||||
run_test_playbook: playbooks/zuul/test-lists3.yaml
|
||||
host-vars:
|
||||
lists99.opendev.org:
|
||||
host_copy_output:
|
||||
'/var/log/acme.sh': logs
|
||||
'/var/log/apache2': logs
|
||||
'/var/lib/mailman/mailman-web-logs': logs
|
||||
'/var/lib/mailman/mailman-core-logs': logs
|
||||
|
||||
- job:
|
||||
name: system-config-run-nodepool
|
||||
parent: system-config-run
|
||||
|
Loading…
x
Reference in New Issue
Block a user