Mailman 3 installieren: Unterschied zwischen den Versionen

Aus Hostsharing Wiki
Zur Navigation springen Zur Suche springen
KKeine Bearbeitungszusammenfassung
 
(14 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 8: Zeile 8:
== Mailman Core ==
== Mailman Core ==
Für die Installation von Mailman Core sind folgende Kommandos auszuführen:
Für die Installation von Mailman Core sind folgende Kommandos auszuführen:
$ pip3 install --user pipenv
 
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profile
<syntaxhighlight lang="bash" line>
source ~/.profile
pip3 install --user pipenv
mkdir ~/mailman
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profile
cd ~/mailman
source ~/.profile
pipenv install mailman
mkdir ~/mailman
pipenv install psycopg2-binary # Für PostgreSQL
cd ~/mailman
pipenv install pymysql # Für MySQL
pipenv install mailman
pipenv install mailman_hyperkitty
pipenv install psycopg2-binary # Für PostgreSQL
pipenv install pymysql # Für MySQL
</syntaxhighlight>


Hinweis: Das Kommando <code>pipenv</code> muss immer im Verzeichnis <code>~/mailman</code> ausgeführt werden.
Hinweis: Das Kommando <code>pipenv</code> muss immer im Verzeichnis <code>~/mailman</code> ausgeführt werden.


Anschließend wird das Verzeichnis für die Konfigurationsdatei angelegt:
Anschließend wird das Verzeichnis für die Konfigurationsdatei angelegt:
$ mkdir -p ~/mailman/etc
<syntaxhighlight lang="bash">
mkdir -p ~/mailman/etc
</syntaxhighlight>


Die Konfiguration wird in die Datei <code>~/mailman/core/etc/mailman.cfg</code> geschrieben:
Die Konfiguration wird in die Datei <code>~/mailman/core/etc/mailman.cfg</code> geschrieben:
[mailman]
 
site_owner: admin@example.org
 
default_language: de
<syntaxhighlight lang="ini" line>
[mailman]
[paths.here]
site_owner: admin@example.org
var_dir: $cwd/core
default_language: de
 
[database] # https://mailman.readthedocs.io/en/latest/src/mailman/docs/database.html
[paths.here]
class: mailman.database.postgresql.PostgreSQLDatabase
var_dir: $cwd/core
url: postgres://myuser:mypassword@mypghost/mailman
 
# Fallls MySQL verwendet:
[database] # https://mailman.readthedocs.io/en/latest/src/mailman/docs/database.html
#class: mailman.database.mysql.MySQLDatabase
class: mailman.database.postgresql.PostgreSQLDatabase
#url: mysql+pymysql://myuser:mypassword@mymysqlhost/mailman?charset=utf8&use_unicode=1
url: postgresql://myuser:mypassword@mypghost/mailman
# SQLite ist Standard, wenn nichts konfiguriert ist
# Fallls MySQL verwendet:
#class: mailman.database.mysql.MySQLDatabase
[webservice] # REST Service von Mailman. Wird von [[#Web_Frontend|Web Frontend]] verwendet
#url: mysql+pymysql://myuser:mypassword@mymysqlhost/mailman?charset=utf8&use_unicode=1
port: 8001 # ändern, falls belegt
# SQLite ist Standard, wenn nichts konfiguriert ist
admin_user: restadmin
 
admin_pass: restpass
[webservice] # REST Service von Mailman. Wird von [[#Web_Frontend|Web Frontend]] verwendet
port: 8001 # ändern, falls belegt
[mta]
admin_user: restadmin
smtp_host: xyz00.hostsharing.net
admin_pass: restpass
smtp_port: 4587
 
smtp_user: xyz00-lists
[mta]
smtp_pass: secret
smtp_host: xyz00.hostsharing.net
smtp_secure_mode: starttls
smtp_port: 4587
# https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html
smtp_user: xyz00-lists
# NullMTA, da MTA nicht selbst konfiguriert werden kann
smtp_pass: secret
incoming: mailman.mta.null.NullMTA
smtp_secure_mode: starttls
lmtp_port: 8024 # ändern, falls belegt
# https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html
# NullMTA, da MTA nicht selbst konfiguriert werden kann
[runner.nntp]
incoming: mailman.mta.null.NullMTA
# Runner für [https://de.wikipedia.org/wiki/Network_News_Transfer_Protocol NNTP] Gateway ausschalten  
lmtp_port: 8024 # ändern, falls belegt
start: no
 
[runner.nntp]
[archiver.hyperkitty]
# Runner für [https://de.wikipedia.org/wiki/Network_News_Transfer_Protocol NNTP] Gateway ausschalten  
class: mailman_hyperkitty.Archiver
start: no
enable: yes
 
# $HOME muss durch den tatsächlichen Pfad zum Benutzerverzeichnis ersetzt werden
[archiver.hyperkitty]
configuration: $HOME/mailman/core/etc/mailman-hyperkitty.cfg
class: mailman_hyperkitty.Archiver
enable: yes
# $HOME muss durch den tatsächlichen Pfad zum Benutzerverzeichnis ersetzt werden
configuration: $HOME/mailman/core/etc/mailman-hyperkitty.cfg
</syntaxhighlight>


Zugriffsrechte einschränken:
Zugriffsrechte einschränken:
$ chmod 0600 ~/mailman/core/etc/mailman.cfg
<syntaxhighlight lang="bash">chmod 0600 ~/mailman/core/etc/mailman.cfg</syntaxhighlight>


Damit Hyperkitty als [[#Web_Frontend|Web Frontend]] für das Archiv verwendet werden kann, ist in die Datei <code>~/mailman/var/etc/mailman-hyperkitty.cfg</code> Foglendes zu schreiben:
Damit Hyperkitty als [[#Web_Frontend|Web Frontend]] für das Archiv verwendet werden kann, ist in die Datei <code>~/mailman/core/etc/mailman-hyperkitty.cfg</code> Foglendes zu schreiben:
[general]
<syntaxhighlight lang="ini" line>
base_url: <nowiki>https://lists.example.org/hyperkitty/</nowiki>
[general]
# Muss identisch mit Key in Hyperkitty sein (s.u.)
base_url: https://lists.example.org/hyperkitty/
api_key: SecretArchiverAPIKey
# Muss identisch mit Key in Hyperkitty sein (s.u.)
api_key: SecretArchiverAPIKey
</syntaxhighlight>


Zugriffsrechte einschränken:
Zugriffsrechte einschränken:
$ chmod 0600 ~/mailman/var/etc/mailman-hyperkitty.cfg
<syntaxhighlight lang="bash">chmod 0600 ~/mailman/core/etc/mailman-hyperkitty.cfg</syntaxhighlight>


Kommando ''mailman'' anlegen:
Kommando ''mailman'' anlegen:
$ cat <<'EOD' >~/.local/bin/mailman
<syntaxhighlight lang="bash" line>
#!/bin/sh
cat <<'EOD' >~/.local/bin/mailman
#!/bin/sh
export MAILMAN_CONFIG_FILE=$HOME/mailman/core/etc/mailman.cfg
 
cd ~/mailman
export MAILMAN_CONFIG_FILE=$HOME/mailman/core/etc/mailman.cfg
pipenv run mailman "$@"
cd ~/mailman
EOD
pipenv run mailman "$@"
EOD
chmod +x ~/.local/bin/mailman
 
chmod +x ~/.local/bin/mailman
</syntaxhighlight>


Hinweis: Da in <code>mailman</code> das Verzeichnis gewechselt wird, funktionieren relative Pfadangaben als Argument nicht bzw. nur, wenn man sich bereits in <code>~/mailman</code> befindet.
Hinweis: Da in <code>mailman</code> das Verzeichnis gewechselt wird, funktionieren relative Pfadangaben als Argument nicht bzw. nur, wenn man sich bereits in <code>~/mailman</code> befindet.
Zeile 91: Zeile 105:
Nun kann mit <code>mailman info</code> nochmal die aktuelle Konfiguration geprüft werden.
Nun kann mit <code>mailman info</code> nochmal die aktuelle Konfiguration geprüft werden.
Danach kann Mailman gestartet werden:
Danach kann Mailman gestartet werden:
  $ mailman start
  mailman start


== Web Frontend ==
== Web Frontend ==
Zeile 97: Zeile 111:


Zunächst werden die Redirects aus der <code>.htaccess</code> gelöscht:
Zunächst werden die Redirects aus der <code>.htaccess</code> gelöscht:
$ echo "" > ~/doms/lists.example.org/htdocs-ssl/.htaccess
<syntaxhighlight lang="bash">echo "" > ~/doms/lists.example.org/htdocs-ssl/.htaccess</syntaxhighlight>


Anschließend werden die erforderlichen Python-Pakete installiert:
Anschließend werden die erforderlichen Python-Pakete installiert:
$ cd ~/mailman
<syntaxhighlight lang="bash">
pipenv install mailman-web
cd ~/mailman
pipenv install mailman-web
</syntaxhighlight>


Um Plattenplatz freizugeben, kann optional der Pip Cache gelöscht werden:
Um Plattenplatz freizugeben, kann optional der Pip Cache gelöscht werden:
$ pipenv --clear
<syntaxhighlight lang="bash">pipenv --clear</syntaxhighlight>


Zur Konfiguration von Hyperkitty wird die IP-Adresse benötigt, von der die Anfragen von Mailman Core kommen. Diese kann wie folgt ermittelt werden:
Zur Konfiguration von Hyperkitty wird die IP-Adresse benötigt, von der die Anfragen von Mailman Core kommen. Diese kann wie folgt ermittelt werden:
$ cat <<EOD >~/doms/lists.example.org/htdocs-ssl/ip.php
<syntaxhighlight lang="bash" line>
<?php
cat <<EOD >~/doms/lists.example.org/htdocs-ssl/ip.php
echo \$_SERVER['REMOTE_ADDR'] . "\n";
<?php
EOD
echo \$_SERVER['REMOTE_ADDR'] . "\n";
curl <nowiki>https://lists.example.org/ip.php</nowiki>
EOD
rm ~/doms/lists.example.org/htdocs-ssl/ip.php
 
curl <nowiki>https://lists.example.org/ip.php</nowiki>
rm ~/doms/lists.example.org/htdocs-ssl/ip.php
</syntaxhighlight>


Die Konfiguration wird nun in Die Datei <code>~/mailman/web/settings.py</code> geschrieben:
Die Konfiguration wird nun in Die Datei <code>~/mailman/web/settings.py</code> geschrieben:
# See https://mailman-web.readthedocs.io/en/latest/settings.html
<syntaxhighlight lang="python" line>
# See https://mailman-web.readthedocs.io/en/latest/settings.html
from mailman_web.settings.base import *
 
from mailman_web.settings.mailman import *
from mailman_web.settings.base import *
from mailman_web.settings.mailman import *
BASE_DIR = os.path.join(os.environ['HOME'], 'mailman', 'web')
 
BASE_DIR = os.path.join(os.environ['HOME'], 'mailman', 'web')
# Default path where static files will be placed.
 
# 'collectstatic' command will copy all the static files here.
# Default path where static files will be placed.
# Alias this location from your webserver to `/static`
# 'collectstatic' command will copy all the static files here.
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# Alias this location from your webserver to `/static`
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# Make sure that the directory is created or Django will fail on start.
 
LOGGING['handlers']['file']['filename'] = os.path.join(BASE_DIR, 'logs', 'mailmanweb.log')
# Make sure that the directory is created or Django will fail on start.
LOGGING['handlers']['file']['filename'] = os.path.join(BASE_DIR, 'logs', 'mailmanweb.log')
# Change path of Whoosh index
 
HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(BASE_DIR, 'whoosh_index')
# Change path of Whoosh index
HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(BASE_DIR, 'whoosh_index')
# django-compressor
 
# https://pypi.python.org/pypi/django_compressor
# django-compressor
COMPRESS_PRECOMPILERS = (
# https://pypi.python.org/pypi/django_compressor
    ('text/x-scss', 'sass -t compressed {infile} {outfile}'),
COMPRESS_PRECOMPILERS = (
    ('text/x-sass', 'sass -t compressed {infile} {outfile}'),
  ('text/x-scss', 'sass -t compressed {infile} {outfile}'),
)
  ('text/x-sass', 'sass -t compressed {infile} {outfile}'),
)
# https://django-q.readthedocs.io/en/latest/configure.html
 
# 1 worker is probably enough. (Default is 3.)
# https://django-q.readthedocs.io/en/latest/configure.html
Q_CLUSTER['workers'] = 1
# 1 worker is probably enough. (Default is 3.)
Q_CLUSTER['workers'] = 1
# Default list of admins who receive the emails from error logging.
 
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
# Default list of admins who receive the emails from error logging.
ADMINS = (
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
    ('Mailman Admin', 'admin@example.org'),
ADMINS = (
)
    ('Mailman Admin', 'admin@example.org'),
# Database setup.
)
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
# Database setup.
DATABASES = {
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
    'default': {
DATABASES = {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Für MySQL: django.db.backends.mysql
    'default': {
        'HOST': 'localhost',
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Für MySQL: django.db.backends.mysql
        'NAME': 'database_name',
        'HOST': 'localhost',
        'USER': 'database_user',
        'NAME': 'database_name',
        'PASSWORD': 'database_password',
        'USER': 'database_user',
    }
        'PASSWORD': 'database_password',
}
    }
}
# Hosts/domain names that are valid for this site; required if DEBUG is False.
 
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
# Hosts/domain names that are valid for this site; required if DEBUG is False.
ALLOWED_HOSTS = [
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
    'lists.example.org',
ALLOWED_HOSTS = [
]
    'lists.example.org',
]
# A secret key for a particular Django installation. This is used to provide
 
# cryptographic signing, and should be set to a unique, unpredictable value.
# A secret key for a particular Django installation. This is used to provide
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
# cryptographic signing, and should be set to a unique, unpredictable value.
SECRET_KEY = 'change-this-on-your-production-server'
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
SECRET_KEY = 'change-this-on-your-production-server'
# Mailman Core default API Path
 
MAILMAN_REST_API_URL = '<nowiki>http://localhost:8001</nowiki>'
# Mailman Core default API Path
# Mailman Core API user
MAILMAN_REST_API_URL = 'http://localhost:8001'
MAILMAN_REST_API_USER = 'restadmin'
# Mailman Core API user
# Mailman Core API user's password.
MAILMAN_REST_API_USER = 'restadmin'
MAILMAN_REST_API_PASS = 'restpass'
# Mailman Core API user's password.
# Mailman Core Shared archiving key. This value is set in the
MAILMAN_REST_API_PASS = 'restpass'
# mailman-hyperkitty's configuration file.
# Mailman Core Shared archiving key. This value is set in the
MAILMAN_ARCHIVER_KEY = 'SecretArchiverAPIKey'
# mailman-hyperkitty's configuration file.
# Host for Mailman Core, from where Hyperkitty will accept connections
MAILMAN_ARCHIVER_KEY = 'SecretArchiverAPIKey'
# for archiving.
# Host for Mailman Core, from where Hyperkitty will accept connections
MAILMAN_ARCHIVER_FROM = ('<IP von Mailman Core>')
# for archiving.
MAILMAN_ARCHIVER_FROM = ('<IP von Mailman Core>')
# Base URL where Django/Mailman-web would be listening for requests. Used by
 
# Mailman Core for fetching templates.
# Base URL where Django/Mailman-web would be listening for requests. Used by
POSTORIUS_TEMPLATE_BASE_URL = 'https://lists.example.org'
# Mailman Core for fetching templates.
POSTORIUS_TEMPLATE_BASE_URL = 'https://lists.example.org'
# Sender in emails sent out by Postorius.
 
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-DEFAULT_FROM_EMAIL
# Sender in emails sent out by Postorius.
DEFAULT_FROM_EMAIL = 'postorius@lists.example.org'
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-DEFAULT_FROM_EMAIL
DEFAULT_FROM_EMAIL = 'postorius@lists.example.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,
# If you enable email reporting for error messages, this is where those emails
# otherwise the emails may get rejected.
# will appear to be coming from. Make sure you set a valid domain name,
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SERVER_EMAIL
# otherwise the emails may get rejected.
SERVER_EMAIL = 'django@lists.example.org'
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SERVER_EMAIL
SERVER_EMAIL = 'django@lists.example.org'
# Configuration used to send emails.
 
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
# Configuration used to send emails.
EMAIL_HOST = 'xyz00.hostsharing.net'
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
EMAIL_PORT = 4587
EMAIL_HOST = 'xyz00.hostsharing.net'
EMAIL_USE_TLS = True
EMAIL_PORT = 4587
EMAIL_HOST_USER = 'xyz00-lists'
EMAIL_USE_TLS = True
EMAIL_HOST_PASSWORD = 'secret'
EMAIL_HOST_USER = 'xyz00-lists'
EMAIL_TIMEOUT = 60
EMAIL_HOST_PASSWORD = 'secret'
EMAIL_TIMEOUT = 60
# A string representing the time zone for this installation.
 
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TIME_ZONE
# A string representing the time zone for this installation.
TIME_ZONE = 'Europe/Berlin'
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TIME_ZONE
TIME_ZONE = 'Europe/Berlin'
# A string representing the language code for this installation.
 
# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
# A string representing the language code for this installation.
LANGUAGE_CODE = 'de-de'
# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = 'de-de'
# Disable support for gravatars in HyperKitty and Postorius.
 
# https://docs.mailman3.org/projects/hyperkitty/en/latest/install.html#customization
# Disable support for gravatars in HyperKitty and Postorius.
HYPERKITTY_ENABLE_GRAVATAR = False
# https://docs.mailman3.org/projects/hyperkitty/en/latest/install.html#customization
HYPERKITTY_ENABLE_GRAVATAR = False
# Hinweis: In der derzeit aktuellen Version (1.3.5) der Komponente
 
# django-mailman3 wird obige Variable nicht berücksichtigt. Deshalb kann die
# Hinweis: In der derzeit aktuellen Version (1.3.5) der Komponente
# folgende Direktive nur mit dem Entwicklungsstand aus git einkommentiert werden.
# django-mailman3 wird obige Variable nicht berücksichtigt. Deshalb kann die
# django_gravatar is not required, anymore.
# folgende Direktive nur mit dem Entwicklungsstand aus git einkommentiert werden.
#INSTALLED_APPS.remove('django_gravatar')
# django_gravatar is not required, anymore.
#INSTALLED_APPS.remove('django_gravatar')
</syntaxhighlight>


Zugriffsrechte einschränken:
Zugriffsrechte einschränken:
$ chmod 600 ~/mailman/web/settings.py
<syntaxhighlight lang="bash">chmod 600 ~/mailman/web/settings.py</syntaxhighlight>


Hinweis: Wird die Konfiguration geändert, nachdem das Web Frontend aufgerufen wurde, muss es neu gestartet werden:
Hinweis: Wird die Konfiguration geändert, nachdem das Web Frontend aufgerufen wurde, muss es neu gestartet werden:
$ mkdir -p ~/doms/lists.example.org/app-ssl/tmp
<syntaxhighlight lang="bash" line>
touch ~/doms/lists.example.org/app-ssl/tmp/restart.txt
mkdir -p ~/doms/lists.example.org/app-ssl/tmp
touch ~/doms/lists.example.org/app-ssl/tmp/restart.txt
</syntaxhighlight>


Das für Logs definierte Verzeichnis anlegen:
Das für Logs definierte Verzeichnis anlegen:
$ mkdir -p ~/mailman/web/logs
<syntaxhighlight lang="bash">mkdir -p ~/mailman/web/logs</syntaxhighlight>


Damit per Django verfügbare Kommandos leicht ausgeführt werden können, wird der Befehl ''mailman-web'' eingerichtet:
Damit per Django verfügbare Kommandos leicht ausgeführt werden können, wird der Befehl ''mailman-web'' eingerichtet:
$ cat <<'EOD' >~/.local/bin/mailman-web
<syntaxhighlight lang="bash" line>
#!/bin/sh
cat <<'EOD' >~/.local/bin/mailman-web
#!/bin/sh
export MAILMAN_WEB_CONFIG=$HOME/mailman/web/settings.py
 
cd ~/mailman
export MAILMAN_WEB_CONFIG=$HOME/mailman/web/settings.py
pipenv run mailman-web "$@"
cd ~/mailman
EOD
pipenv run mailman-web "$@"
EOD
chmod +x ~/.local/bin/mailman-web
chmod +x ~/.local/bin/mailman-web
</syntaxhighlight>


Anschließend wird das Datenbankschema eingerichtet:
Anschließend wird das Datenbankschema eingerichtet:
$ mailman-web migrate
<syntaxhighlight lang="bash">mailman-web migrate</syntaxhighlight>


Mit dem folgenden Kommando werden statische Daten für das Web Frontend ins konfiguriete Verzeichnis geschrieben:
Mit dem folgenden Kommando werden statische Daten für das Web Frontend ins konfiguriete Verzeichnis geschrieben:
$ mailman-web collectstatic
<syntaxhighlight lang="bash">mailman-web collectstatic</syntaxhighlight>


Nun müssen die statischen Dateien für das Web Frontend noch per HTTPS verfügbar gemacht werden:
Nun müssen die statischen Dateien für das Web Frontend noch per HTTPS verfügbar gemacht werden:
$ ln -s ~/mailman/mailman-suite/mailman-suite_project/static ~/doms/lists.example.org/htdocs-ssl/
<syntaxhighlight lang="bash">ln -s ~/mailman/mailman-suite/mailman-suite_project/static ~/doms/lists.example.org/htdocs-ssl/</syntaxhighlight>


Zum Anlegen des Administrators des Web Frontends wird dieser Befehl ausgeführt:
Zum Anlegen des Administrators des Web Frontends wird dieser Befehl ausgeführt:
$ mailman-web createsuperuser
<syntaxhighlight lang="bash">mailman-web createsuperuser</syntaxhighlight>


Da die Übersetzungsdateien nur in Mailman Core, jedoch nicht bei den Web Frontend Komponenten im Binärformat enthalten sind, muss die Konvertierung nachgeholt werden:
Da die Übersetzungsdateien nur in Mailman Core, jedoch nicht bei den Web Frontend Komponenten im Binärformat enthalten sind, muss die Konvertierung nachgeholt werden:
$ for pofile in $(find $(pipenv --venv) -path '*/locale/*/LC_MESSAGES/*.po'); do
<syntaxhighlight lang="bash" line>
    mofile=${pofile/.po/.mo}
for pofile in $(find $(pipenv --venv) -path '*/locale/*/LC_MESSAGES/*.po'); do
    if [ ! -f $mofile ] || [ $pofile -nt $mofile ]; then
    mofile=${pofile/.po/.mo}
      echo $pofile
    if [ ! -f $mofile ] || [ $pofile -nt $mofile ]; then
      msgfmt $pofile -o $mofile -v
      echo $pofile
    fi
      msgfmt $pofile -o $mofile -v
done
    fi
done
</syntaxhighlight>


Damit das Web Frontend per [[Phusion_Passenger|Phusion Passenger]] geladen werden kann:
Damit das Web Frontend per [[Phusion_Passenger|Phusion Passenger]] geladen werden kann:
$ cat <<EOD >~/doms/lists.example.org/app-ssl/passenger_wsgi.py
 
import os
<syntaxhighlight lang="python" line>
import subprocess
cat <<EOD >~/doms/lists.example.org/app-ssl/passenger_wsgi.py
import sys
import os
import subprocess
os.environ['LANG'] = 'C.UTF-8'
import sys
os.environ['LC_ALL'] = 'C.UTF-8'
 
os.environ['LANG'] = 'C.UTF-8'
HOME = os.environ['HOME']
os.environ['LC_ALL'] = 'C.UTF-8'
PIPENV = os.path.join(HOME, '.local', 'bin', 'pipenv')
 
PIPFILE_DIR = os.path.join(HOME, 'mailman')
HOME = os.environ['HOME']
PIPENV_PYTHON = subprocess.check_output([PIPENV, '--py'], cwd=PIPFILE_DIR).strip().decode('utf-8')
PIPENV = os.path.join(HOME, '.local', 'bin', 'pipenv')
if sys.executable != PIPENV_PYTHON:
PIPFILE_DIR = os.path.join(HOME, 'mailman')
    os.execl(PIPENV_PYTHON, PIPENV_PYTHON, *sys.argv)
PIPENV_PYTHON = subprocess.check_output([PIPENV, '--py'], cwd=PIPFILE_DIR).strip().decode('utf-8')
if sys.executable != PIPENV_PYTHON:
os.environ['MAILMAN_WEB_CONFIG'] = os.path.join(HOME, 'mailman', 'web', 'settings.py')
    os.execl(PIPENV_PYTHON, PIPENV_PYTHON, *sys.argv)
from mailman_web.wsgi import application
 
EOD
os.environ['MAILMAN_WEB_CONFIG'] = os.path.join(HOME, 'mailman', 'web', 'settings.py')
from mailman_web.wsgi import application
EOD
</syntaxhighlight>


Nun steht das Web Frontend unter <code><nowiki>https://lists.example.org/</nowiki></code> zur Verfügung. Über die Django Administration sollte unter <code><nowiki>https://lists.example.org/admin/sites/site/1/change/</nowiki></code> die Domäne angepasst werden.
Nun steht das Web Frontend unter <code><nowiki>https://lists.example.org/</nowiki></code> zur Verfügung. Über die Django Administration sollte unter <code><nowiki>https://lists.example.org/admin/sites/site/1/change/</nowiki></code> die Domäne angepasst werden.
Zeile 293: Zeile 322:
Da die MTA-Konfiguration nicht direkt angepasst werden kann, ist ein Hilfskonstrukt erforderlich: Mittels ''.forward-Datei'' werden eingehende Mails an das Programm <code>msmtp</code> weitergeleitet, welches diese per [https://de.wikipedia.org/wiki/Local_Mail_Transfer_Protocol LMTP] bei Mailman abliefert. msmtp ist auf den Managed Servern vorinstalliert.
Da die MTA-Konfiguration nicht direkt angepasst werden kann, ist ein Hilfskonstrukt erforderlich: Mittels ''.forward-Datei'' werden eingehende Mails an das Programm <code>msmtp</code> weitergeleitet, welches diese per [https://de.wikipedia.org/wiki/Local_Mail_Transfer_Protocol LMTP] bei Mailman abliefert. msmtp ist auf den Managed Servern vorinstalliert.


  $ MM_LMTP_PORT=8024 # In Mailman Core konfigurierter Port
  MM_LMTP_PORT=8024 # In Mailman Core konfigurierter Port
  cat <<'EOD' >.forward+mailman
  cat <<EOD >.forward+mailman
  "|/usr/bin/msmtp --host=localhost --port=$MM_LMTP_PORT --protocol=lmtp --read-envelope-from \$(echo \$ORIGINAL_RECIPIENT | sed 's/+.\+@/@/')"
  "|/usr/bin/msmtp --host=localhost --port=$MM_LMTP_PORT --protocol=lmtp --read-envelope-from \$(echo \$ORIGINAL_RECIPIENT | sed 's/+.\+@/@/')"
  EOD
  EOD
Zeile 304: Zeile 333:
== Dienste starten und überwachen ==
== Dienste starten und überwachen ==
Für die beiden benötigten Dienste kann ''monit'' wie folgt konfiguriert werden:
Für die beiden benötigten Dienste kann ''monit'' wie folgt konfiguriert werden:
$ mkdir monit
 
cat <<EOD >~/.monitrc
<syntaxhighlight lang="bash" line>
set daemon 60
mkdir monit
    with start delay 90
cat <<EOD >~/.monitrc
set httpd unixsocket $HOME/monit/monit.sock
set daemon 60
    permission 600
    with start delay 90
    allow mailman:monit
set httpd unixsocket $HOME/monit/monit.sock
set mailserver localhost
    permission 600
set mail-format { from: monit@lists.example.org }
    allow mailman:monit
set alert admin@example.org
set mailserver localhost
set logfile $HOME/monit/monit.log
set mail-format { from: monit@lists.example.org }
set idfile $HOME/monit/monit.id
set alert admin@example.org
set pidfile $HOME/monit/monit.pid
set logfile $HOME/monit/monit.log
set statefile $HOME/monit/monit.state
set idfile $HOME/monit/monit.id
set pidfile $HOME/monit/monit.pid
check process mailman
set statefile $HOME/monit/monit.state
    pidfile $HOME/mailman/core/master.pid
 
    start program = "$HOME/.local/bin/mailman start"
check process mailman
    stop program = "$HOME/.local/bin/mailman stop"
    pidfile $HOME/mailman/core/master.pid
    restart program = "$HOME/.local/bin/mailman restart"
    start program = "$HOME/.local/bin/mailman start"
    stop program = "$HOME/.local/bin/mailman stop"
check process mailman-web-qcluster
    restart program = "$HOME/.local/bin/mailman restart"
    matching "mailman-web qcluster"
 
    start program = "/bin/bash -c 'nohup $HOME/.local/bin/mailman-web qcluster >>$HOME/mailman/web/logs/qcluster.log 2>&1 &'"
check process mailman-web-qcluster
    stop program = "/usr/bin/pkill -f 'mailman-web qcluster'"
    matching "mailman-web qcluster"
    depends on mailman
    start program = "/bin/bash -c 'nohup $HOME/.local/bin/mailman-web qcluster >>$HOME/mailman/web/logs/qcluster.log 2>&1 &'"
EOD
    stop program = "/usr/bin/pkill -f 'mailman-web qcluster'"
    depends on mailman
EOD
</syntaxhighlight>


Dienste starten:
Dienste starten:
$ monit
<syntaxhighlight lang="bash">monit</syntaxhighlight>


Für <code>mailman-web qcluster</code> kann alternativ ein minütlich laufender Cron Job verwendet werden.
Für <code>mailman-web qcluster</code> kann alternativ ein minütlich laufender Systemd Timer verwendet werden.


== Logrotation ==
== Logrotation ==
Die Rotation der Logdateien kann so konfiguriert werden:
Die Rotation der Logdateien kann so konfiguriert werden:
$ cat <<EOD >~/logrotate.conf
 
compress
<syntaxhighlight lang="bash" line>
delaycompress
cat <<EOD >~/logrotate.conf
missingok
compress
notifempty
delaycompress
dateext
missingok
notifempty
$HOME/monit/monit.log {
dateext
    rotate 1
 
    weekly
$HOME/monit/monit.log {
    maxsize 1M
  rotate 1
}
  weekly
  maxsize 1M
$HOME/mailman/core/logs/*.log {
}
    rotate 6
 
    daily
$HOME/mailman/core/logs/*.log {
    sharedscripts
  rotate 6
    postrotate
  daily
        $HOME/.local/bin/mailman reopen >/dev/null ||:
  sharedscripts
    endscript
  postrotate
}
    $HOME/.local/bin/mailman reopen >/dev/null ||:
  endscript
$HOME/mailman/web/logs/mailmanweb.log {
}
    rotate 6
 
    daily
$HOME/mailman/web/logs/mailmanweb.log {
}
  rotate 6
  daily
$HOME/mailman/web/logs/qcluster.log {
}
    rotate 1
 
    size 100k
$HOME/mailman/web/logs/qcluster.log {
    postrotate
  rotate 1
        /usr/bin/monit restart mailman-web-qcluster >/dev/null ||:
  size 100k
    endscript
  postrotate
}
    /usr/bin/monit restart mailman-web-qcluster >/dev/null ||:
EOD
  endscript
}
EOD
</syntaxhighlight>


Hinweis: <code>qcluster.log</code> wird hier nur bei Überschreiten der definierten Größe rotiert, um regelmäßige Mails von ''monit'' zu vermeiden.
Hinweis: <code>qcluster.log</code> wird hier nur bei Überschreiten der definierten Größe rotiert, um regelmäßige Mails von ''monit'' zu vermeiden.
Zeile 379: Zeile 414:
== Cron Jobs ==
== Cron Jobs ==
Für Mailman sind verschiedene Cron Jobs erforderlich. Zudem sollen nach einem Neustart die <code>monit</code> Dienste gestartet werden und täglich eine Logrotation erfolgen. Die Einrichtung kann so erfolgen (eine bereits existierende crontab wird überschrieben):
Für Mailman sind verschiedene Cron Jobs erforderlich. Zudem sollen nach einem Neustart die <code>monit</code> Dienste gestartet werden und täglich eine Logrotation erfolgen. Die Einrichtung kann so erfolgen (eine bereits existierende crontab wird überschrieben):
$ cat <<EOD | crontab -
 
MAILTO=admin@example.org
<syntaxhighlight lang="bash" line>
HOME=$HOME
cat <<EOD | crontab -
PATH=$HOME/.local/bin:/usr/bin:/bin:/usr/sbin
MAILTO=admin@example.org
HOME=$HOME
@reboot rm -f \$HOME/monit/monit.pid \$HOME/mailman/core/master.pid && monit
PATH=$HOME/.local/bin:/usr/bin:/bin:/usr/sbin
 
@daily logrotate -s \$HOME/.logrotate_state \$HOME/logrotate.conf
@reboot rm -f \$HOME/monit/monit.pid \$HOME/mailman/core/master.pid && monit
 
# Send periodic digests.
@daily logrotate -s \$HOME/.logrotate_state \$HOME/logrotate.conf
@daily mailman digests --send
 
# Send periodic digests.
* * * * * mailman-web runjobs minutely
@daily mailman digests --send
2,17,32,47 * * * * mailman-web runjobs quarter_hourly
 
@hourly  mailman-web runjobs hourly
* * * * * mailman-web runjobs minutely
@daily  mailman-web runjobs daily
2,17,32,47 * * * * mailman-web runjobs quarter_hourly
@weekly  mailman-web runjobs weekly
@hourly  mailman-web runjobs hourly
@monthly mailman-web runjobs monthly
@daily  mailman-web runjobs daily
@yearly  mailman-web runjobs yearly
@weekly  mailman-web runjobs weekly
EOD
@monthly mailman-web runjobs monthly
@yearly  mailman-web runjobs yearly
EOD
</syntaxhighlight>


Soll eine existierende crontab nicht überschrieben werden, muss das Kommando <code>crontab -e</code> ausgeführt und die crontab entsprechend angepasst werden. (Dabei <code>\$HOME</code> mit <code>$HOME</code> und <code>$HOME</code> mit dem Pfad des Benutzerverzeichnisses ersetzen.)
Soll eine existierende crontab nicht überschrieben werden, muss das Kommando <code>crontab -e</code> ausgeführt und die crontab entsprechend angepasst werden. (Dabei <code>\$HOME</code> mit <code>$HOME</code> und <code>$HOME</code> mit dem Pfad des Benutzerverzeichnisses ersetzen.)
Zeile 404: Zeile 442:
== Liste anlegen ==
== Liste anlegen ==
Damit Mailman tatsächlich genutzt werden kann, muss natürlich eine Liste eingerichtet werden.
Damit Mailman tatsächlich genutzt werden kann, muss natürlich eine Liste eingerichtet werden.
$ mailman create meine-erste-liste@lists.example.org # Alternativ über Web Frontend
<syntaxhighlight lang=bash>mailman create meine-erste-liste@lists.example.org # Alternativ über Web Frontend</syntaxhighlight>
 
Außerdem müssen die E-Mail Adressen für die Mailingliste angelegt werden, im HSAdmin. Zum Beispiel für die Liste meine-erste-liste: meine-erste-liste, meine-erste-liste-join, meine-erste-liste-leave, meine-erste-liste-owner, für die Domain lists.example.org. Die E-Mails sollen in das Postfach gehen, wo mailman installiert ist.
Alternativ kann eine Catch-All Adresse eingerichtet werden, damit alle E-Mails an die Subdomain in das Postfach vom mailman gehen. Der Catch-All ist laut Postfix Regeln eine Adresse mit einem leeren lokalen Teil (siehe auch der Screenshot in der [[Sympa_installieren#Neue_Liste_einrichten|entsprechenden Anleitung von Sympa]]).
 
== Die Selbst-Registrierung von Benutzern verhindern ==
 
Per Default kann sich jede Person im Mailman3 ein Benutzerkonto anlegen. Wenn das nicht erwünscht ist, kann in der Datei <code>var/etc/settings.py</code> die folgende Zeile hinzugefügt werden:
 
<syntaxhighlight lang="python">
ACCOUNT_ADAPTER = 'django_mailman3.views.user_adapter.DisableSignupAdapter'
</syntaxhighlight>
 
Es können in diesem Fall im Django Backend durch den Administrator Benutzerkonten angelegt werden, auf https://lists.example.org/admin/auth/user/


== Update ==
== Update ==
Zeile 410: Zeile 461:


Python-Pakete für die Aktualisierungen vorliegen ausgeben:
Python-Pakete für die Aktualisierungen vorliegen ausgeben:
$ cd ~/mailman
pipenv update --outdated


Vor dem eigentlichen Update empfiehlt es sich, die Release Notes (zumindest von Mailman) zu lesen und auf relevante Änderungen zu prüfen.
<syntaxhighlight lang="bash">
cd ~/mailman
pipenv update --outdated
</syntaxhighlight>
 
Vor dem eigentlichen Update empfiehlt es sich, die Release Notes (zumindest von [https://docs.mailman3.org/projects/mailman/en/latest/src/mailman/docs/NEWS.html Mailman]) zu lesen und auf relevante Änderungen zu prüfen.
 
Mailman stoppen:
<syntaxhighlight lang="bash">
monit stop mailman
</syntaxhighlight>


Update der Pakete:
Update der Pakete:
$ pipenv update
 
<syntaxhighlight lang="bash">
pipenv update
</syntaxhighlight>


Ggf. Pip Cache löschen:
Ggf. Pip Cache löschen:
$ pipenv --clear


Abschließend die Dienste neu starten:
<syntaxhighlight lang="bash">
$ monit restart mailman
pipenv --clear
monit restart mailman-web-qcluster
</syntaxhighlight>
 
Datenbankmigrationen durchführen:
<syntaxhighlight lang="bash">
mailman-web makemigrations
mailman-web migrate
</syntaxhighlight>


Übersetzungen aktualisieren:
Übersetzungen aktualisieren:
$ for pofile in $(find $(pipenv --venv) -path '*/locale/*/LC_MESSAGES/*.po'); do
<syntaxhighlight lang="bash" line>
    mofile=${pofile/.po/.mo}
for pofile in $(find $(pipenv --venv) -path '*/locale/*/LC_MESSAGES/*.po'); do
    if [ ! -f $mofile ] || [ $pofile -nt $mofile ]; then
  mofile=${pofile/.po/.mo}
      echo $pofile
  if [ ! -f $mofile ] || [ $pofile -nt $mofile ]; then
      msgfmt $pofile -o $mofile -v
    echo $pofile
    fi
    msgfmt $pofile -o $mofile -v
done
    fi
done
</syntaxhighlight>
 
Statische Dateien aktualisieren:
<syntaxhighlight lang="bash">mailman-web collectstatic -c</syntaxhighlight>
 
Abschließend die Dienste wieder starten:
<syntaxhighlight lang="bash">
monit start mailman
monit start mailman-web-qcluster
</syntaxhighlight>


Web Frontend neu starten:
Web Frontend neu starten:
$ mkdir -p ~/doms/lists.example.org/app-ssl/tmp
<syntaxhighlight lang="bash">
touch ~/doms/lists.example.org/app-ssl/tmp/restart.txt
mkdir -p ~/doms/lists.example.org/app-ssl/tmp
touch ~/doms/lists.example.org/app-ssl/tmp/restart.txt
</syntaxhighlight>
 


[[Kategorie:HSDoku]]
[[Kategorie:HSDoku]]

Aktuelle Version vom 3. Dezember 2024, 13:18 Uhr

Die folgende Anleitung zur Installation von Mailman 3 auf Hostsharing geht davon aus, dass als Domäne lists.example.org und als Domänennutzer xyz00-lists verwendet wird. Es ist zu empfehlen, auszuführende Befehle und Konfigurationen vorab auf zu ersetzende Werte zu prüfen. Alle Befehle sind als Benutzer xyz00-lists zu starten. Damit mehrere aufeinander folgende Shell-Kommandos leichter kopiert werden können, wird nur vor das jeweils erste Kommando ein $ gesetzt. Zum Verständnis mancher der folgenden Anweisungen kann es hilfreich sein, die Mailman-Dokumentation gelesen und sich mit Pipenv beschäftigt zu haben.

Achtung: Mailman 3 benötigt zahlreiche Hintergrundprozesse, was beim Managed Webspace zusätzliche Kosten verursacht.

Datenbank

Zunächst muss eine PostgreSQL- oder MySQL-Datenbank angelegt werden. (Mailman läuft auch mit SQLite, ist aber für den Produktivbetrieb nicht empfohlen.) Je nach gewählter Datenbank unterscheiden sich manche Schritte geringfügig, was an den entsprechenden Stellen dokumentiert ist.

Mailman Core

Für die Installation von Mailman Core sind folgende Kommandos auszuführen:

pip3 install --user pipenv
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profile
source ~/.profile
mkdir ~/mailman
cd ~/mailman
pipenv install mailman
pipenv install mailman_hyperkitty
pipenv install psycopg2-binary # Für PostgreSQL
pipenv install pymysql # Für MySQL

Hinweis: Das Kommando pipenv muss immer im Verzeichnis ~/mailman ausgeführt werden.

Anschließend wird das Verzeichnis für die Konfigurationsdatei angelegt:

mkdir -p ~/mailman/etc

Die Konfiguration wird in die Datei ~/mailman/core/etc/mailman.cfg geschrieben:


[mailman]
site_owner: admin@example.org
default_language: de

[paths.here]
var_dir: $cwd/core

[database] # https://mailman.readthedocs.io/en/latest/src/mailman/docs/database.html
class: mailman.database.postgresql.PostgreSQLDatabase
url: postgresql://myuser:mypassword@mypghost/mailman
# Fallls MySQL verwendet:
#class: mailman.database.mysql.MySQLDatabase
#url: mysql+pymysql://myuser:mypassword@mymysqlhost/mailman?charset=utf8&use_unicode=1
# SQLite ist Standard, wenn nichts konfiguriert ist

[webservice] # REST Service von Mailman. Wird von [[#Web_Frontend|Web Frontend]] verwendet
port: 8001 # ändern, falls belegt
admin_user: restadmin
admin_pass: restpass

[mta]
smtp_host: xyz00.hostsharing.net
smtp_port: 4587
smtp_user: xyz00-lists
smtp_pass: secret
smtp_secure_mode: starttls
# https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html
# NullMTA, da MTA nicht selbst konfiguriert werden kann
incoming: mailman.mta.null.NullMTA
lmtp_port: 8024 # ändern, falls belegt

[runner.nntp]
# Runner für [https://de.wikipedia.org/wiki/Network_News_Transfer_Protocol NNTP] Gateway ausschalten 
start: no

[archiver.hyperkitty]
class: mailman_hyperkitty.Archiver
enable: yes
# $HOME muss durch den tatsächlichen Pfad zum Benutzerverzeichnis ersetzt werden
configuration: $HOME/mailman/core/etc/mailman-hyperkitty.cfg

Zugriffsrechte einschränken:

chmod 0600 ~/mailman/core/etc/mailman.cfg

Damit Hyperkitty als Web Frontend für das Archiv verwendet werden kann, ist in die Datei ~/mailman/core/etc/mailman-hyperkitty.cfg Foglendes zu schreiben:

[general]
base_url: https://lists.example.org/hyperkitty/
# Muss identisch mit Key in Hyperkitty sein (s.u.)
api_key: SecretArchiverAPIKey

Zugriffsrechte einschränken:

chmod 0600 ~/mailman/core/etc/mailman-hyperkitty.cfg

Kommando mailman anlegen:

cat <<'EOD' >~/.local/bin/mailman
#!/bin/sh

export MAILMAN_CONFIG_FILE=$HOME/mailman/core/etc/mailman.cfg
cd ~/mailman
pipenv run mailman "$@"
EOD

chmod +x ~/.local/bin/mailman

Hinweis: Da in mailman das Verzeichnis gewechselt wird, funktionieren relative Pfadangaben als Argument nicht bzw. nur, wenn man sich bereits in ~/mailman befindet.

Nun kann mit mailman info nochmal die aktuelle Konfiguration geprüft werden. Danach kann Mailman gestartet werden:

mailman start

Web Frontend

In diesem Abschnitt wird die Installation des Web Frontends beschrieben.

Zunächst werden die Redirects aus der .htaccess gelöscht:

echo "" > ~/doms/lists.example.org/htdocs-ssl/.htaccess

Anschließend werden die erforderlichen Python-Pakete installiert:

cd ~/mailman
pipenv install mailman-web

Um Plattenplatz freizugeben, kann optional der Pip Cache gelöscht werden:

pipenv --clear

Zur Konfiguration von Hyperkitty wird die IP-Adresse benötigt, von der die Anfragen von Mailman Core kommen. Diese kann wie folgt ermittelt werden:

cat <<EOD >~/doms/lists.example.org/htdocs-ssl/ip.php
<?php
echo \$_SERVER['REMOTE_ADDR'] . "\n";
EOD

curl <nowiki>https://lists.example.org/ip.php</nowiki>
rm ~/doms/lists.example.org/htdocs-ssl/ip.php

Die Konfiguration wird nun in Die Datei ~/mailman/web/settings.py geschrieben:

# See https://mailman-web.readthedocs.io/en/latest/settings.html

from mailman_web.settings.base import *
from mailman_web.settings.mailman import *

BASE_DIR = os.path.join(os.environ['HOME'], 'mailman', 'web')

# Default path where static files will be placed.
# 'collectstatic' command will copy all the static files here.
# Alias this location from your webserver to `/static`
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

# Make sure that the directory is created or Django will fail on start.
LOGGING['handlers']['file']['filename'] = os.path.join(BASE_DIR, 'logs', 'mailmanweb.log')

# Change path of Whoosh index
HAYSTACK_CONNECTIONS['default']['PATH'] = os.path.join(BASE_DIR, 'whoosh_index')

# django-compressor
# https://pypi.python.org/pypi/django_compressor
COMPRESS_PRECOMPILERS = (
  ('text/x-scss', 'sass -t compressed {infile} {outfile}'),
  ('text/x-sass', 'sass -t compressed {infile} {outfile}'),
)

# https://django-q.readthedocs.io/en/latest/configure.html
# 1 worker is probably enough. (Default is 3.)
Q_CLUSTER['workers'] = 1

# Default list of admins who receive the emails from error logging.
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = (
    ('Mailman Admin', 'admin@example.org'),
)
# Database setup.
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Für MySQL: django.db.backends.mysql
        'HOST': 'localhost',
        'NAME': 'database_name',
        'USER': 'database_user',
        'PASSWORD': 'database_password',
    }
}

# Hosts/domain names that are valid for this site; required if DEBUG is False.
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [
    'lists.example.org',
]

# A secret key for a particular Django installation. This is used to provide
# cryptographic signing, and should be set to a unique, unpredictable value.
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
SECRET_KEY = 'change-this-on-your-production-server'

# Mailman Core default API Path
MAILMAN_REST_API_URL = 'http://localhost:8001'
# Mailman Core API user
MAILMAN_REST_API_USER = 'restadmin'
# Mailman Core API user's password.
MAILMAN_REST_API_PASS = 'restpass'
# Mailman Core Shared archiving key. This value is set in the
# mailman-hyperkitty's configuration file.
MAILMAN_ARCHIVER_KEY = 'SecretArchiverAPIKey'
# Host for Mailman Core, from where Hyperkitty will accept connections
# for archiving.
MAILMAN_ARCHIVER_FROM = ('<IP von Mailman Core>')

# Base URL where Django/Mailman-web would be listening for requests. Used by
# Mailman Core for fetching templates.
POSTORIUS_TEMPLATE_BASE_URL = 'https://lists.example.org'

# Sender in emails sent out by Postorius.
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-DEFAULT_FROM_EMAIL
DEFAULT_FROM_EMAIL = 'postorius@lists.example.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/dev/ref/settings/#std:setting-SERVER_EMAIL
SERVER_EMAIL = 'django@lists.example.org'

# Configuration used to send emails.
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
EMAIL_HOST = 'xyz00.hostsharing.net'
EMAIL_PORT = 4587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'xyz00-lists'
EMAIL_HOST_PASSWORD = 'secret'
EMAIL_TIMEOUT = 60

# A string representing the time zone for this installation.
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TIME_ZONE
TIME_ZONE = 'Europe/Berlin'

# A string representing the language code for this installation.
# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = 'de-de'

# Disable support for gravatars in HyperKitty and Postorius.
# https://docs.mailman3.org/projects/hyperkitty/en/latest/install.html#customization
HYPERKITTY_ENABLE_GRAVATAR = False

# Hinweis: In der derzeit aktuellen Version (1.3.5) der Komponente
# django-mailman3 wird obige Variable nicht berücksichtigt. Deshalb kann die
# folgende Direktive nur mit dem Entwicklungsstand aus git einkommentiert werden.
# django_gravatar is not required, anymore.
#INSTALLED_APPS.remove('django_gravatar')

Zugriffsrechte einschränken:

chmod 600 ~/mailman/web/settings.py

Hinweis: Wird die Konfiguration geändert, nachdem das Web Frontend aufgerufen wurde, muss es neu gestartet werden:

mkdir -p ~/doms/lists.example.org/app-ssl/tmp
touch ~/doms/lists.example.org/app-ssl/tmp/restart.txt

Das für Logs definierte Verzeichnis anlegen:

mkdir -p ~/mailman/web/logs

Damit per Django verfügbare Kommandos leicht ausgeführt werden können, wird der Befehl mailman-web eingerichtet:

cat <<'EOD' >~/.local/bin/mailman-web
#!/bin/sh

export MAILMAN_WEB_CONFIG=$HOME/mailman/web/settings.py
cd ~/mailman
pipenv run mailman-web "$@"
EOD
chmod +x ~/.local/bin/mailman-web

Anschließend wird das Datenbankschema eingerichtet:

mailman-web migrate

Mit dem folgenden Kommando werden statische Daten für das Web Frontend ins konfiguriete Verzeichnis geschrieben:

mailman-web collectstatic

Nun müssen die statischen Dateien für das Web Frontend noch per HTTPS verfügbar gemacht werden:

ln -s ~/mailman/mailman-suite/mailman-suite_project/static ~/doms/lists.example.org/htdocs-ssl/

Zum Anlegen des Administrators des Web Frontends wird dieser Befehl ausgeführt:

mailman-web createsuperuser

Da die Übersetzungsdateien nur in Mailman Core, jedoch nicht bei den Web Frontend Komponenten im Binärformat enthalten sind, muss die Konvertierung nachgeholt werden:

for pofile in $(find $(pipenv --venv) -path '*/locale/*/LC_MESSAGES/*.po'); do
    mofile=${pofile/.po/.mo}
    if [ ! -f $mofile ] || [ $pofile -nt $mofile ]; then
      echo $pofile
      msgfmt $pofile -o $mofile -v
    fi
done

Damit das Web Frontend per Phusion Passenger geladen werden kann:

cat <<EOD >~/doms/lists.example.org/app-ssl/passenger_wsgi.py
import os
import subprocess
import sys

os.environ['LANG'] = 'C.UTF-8'
os.environ['LC_ALL'] = 'C.UTF-8'

HOME = os.environ['HOME']
PIPENV = os.path.join(HOME, '.local', 'bin', 'pipenv')
PIPFILE_DIR = os.path.join(HOME, 'mailman')
PIPENV_PYTHON = subprocess.check_output([PIPENV, '--py'], cwd=PIPFILE_DIR).strip().decode('utf-8')
if sys.executable != PIPENV_PYTHON:
    os.execl(PIPENV_PYTHON, PIPENV_PYTHON, *sys.argv)

os.environ['MAILMAN_WEB_CONFIG'] = os.path.join(HOME, 'mailman', 'web', 'settings.py')
from mailman_web.wsgi import application
EOD

Nun steht das Web Frontend unter https://lists.example.org/ zur Verfügung. Über die Django Administration sollte unter https://lists.example.org/admin/sites/site/1/change/ die Domäne angepasst werden.

Mails an Mailman weiterleiten

Da die MTA-Konfiguration nicht direkt angepasst werden kann, ist ein Hilfskonstrukt erforderlich: Mittels .forward-Datei werden eingehende Mails an das Programm msmtp weitergeleitet, welches diese per LMTP bei Mailman abliefert. msmtp ist auf den Managed Servern vorinstalliert.

MM_LMTP_PORT=8024 # In Mailman Core konfigurierter Port
cat <<EOD >.forward+mailman
"|/usr/bin/msmtp --host=localhost --port=$MM_LMTP_PORT --protocol=lmtp --read-envelope-from \$(echo \$ORIGINAL_RECIPIENT | sed 's/+.\+@/@/')"
EOD

Der sed Befehl ist erforderlich, damit Mails mit Plus Addressing mit der eigentlichen Empfängeradresse bei Mailman ankommen.

Für die Domain lists.example.org wird in HSAdmin oder per hssscript eine Catchall-Adresse mit xyz00-lists+mailman als Ziel eingerichtet. Bei einer Catchall-Adresse wird als localpart ein leerer String angegeben.

Dienste starten und überwachen

Für die beiden benötigten Dienste kann monit wie folgt konfiguriert werden:

mkdir monit
cat <<EOD >~/.monitrc
set daemon 60
    with start delay 90
set httpd unixsocket $HOME/monit/monit.sock
    permission 600
    allow mailman:monit
set mailserver localhost
set mail-format { from: monit@lists.example.org }
set alert admin@example.org
set logfile $HOME/monit/monit.log
set idfile $HOME/monit/monit.id
set pidfile $HOME/monit/monit.pid
set statefile $HOME/monit/monit.state

check process mailman
    pidfile $HOME/mailman/core/master.pid
    start program = "$HOME/.local/bin/mailman start"
    stop program = "$HOME/.local/bin/mailman stop"
    restart program = "$HOME/.local/bin/mailman restart"

check process mailman-web-qcluster
    matching "mailman-web qcluster"
    start program = "/bin/bash -c 'nohup $HOME/.local/bin/mailman-web qcluster >>$HOME/mailman/web/logs/qcluster.log 2>&1 &'"
    stop program = "/usr/bin/pkill -f 'mailman-web qcluster'"
    depends on mailman
EOD

Dienste starten:

monit

Für mailman-web qcluster kann alternativ ein minütlich laufender Systemd Timer verwendet werden.

Logrotation

Die Rotation der Logdateien kann so konfiguriert werden:

cat <<EOD >~/logrotate.conf
compress
delaycompress
missingok
notifempty
dateext

$HOME/monit/monit.log {
  rotate 1
  weekly
  maxsize 1M
}

$HOME/mailman/core/logs/*.log {
  rotate 6
  daily
  sharedscripts
  postrotate
    $HOME/.local/bin/mailman reopen >/dev/null ||:
  endscript
}

$HOME/mailman/web/logs/mailmanweb.log {
  rotate 6
  daily
}

$HOME/mailman/web/logs/qcluster.log {
  rotate 1
  size 100k
  postrotate
    /usr/bin/monit restart mailman-web-qcluster >/dev/null ||:
  endscript
}
EOD

Hinweis: qcluster.log wird hier nur bei Überschreiten der definierten Größe rotiert, um regelmäßige Mails von monit zu vermeiden.

Cron Jobs

Für Mailman sind verschiedene Cron Jobs erforderlich. Zudem sollen nach einem Neustart die monit Dienste gestartet werden und täglich eine Logrotation erfolgen. Die Einrichtung kann so erfolgen (eine bereits existierende crontab wird überschrieben):

cat <<EOD | crontab -
MAILTO=admin@example.org
HOME=$HOME
PATH=$HOME/.local/bin:/usr/bin:/bin:/usr/sbin

@reboot rm -f \$HOME/monit/monit.pid \$HOME/mailman/core/master.pid && monit

@daily logrotate -s \$HOME/.logrotate_state \$HOME/logrotate.conf

# Send periodic digests.
@daily mailman digests --send

* * * * * mailman-web runjobs minutely
2,17,32,47 * * * * mailman-web runjobs quarter_hourly
@hourly  mailman-web runjobs hourly
@daily   mailman-web runjobs daily
@weekly  mailman-web runjobs weekly
@monthly mailman-web runjobs monthly
@yearly  mailman-web runjobs yearly
EOD

Soll eine existierende crontab nicht überschrieben werden, muss das Kommando crontab -e ausgeführt und die crontab entsprechend angepasst werden. (Dabei \$HOME mit $HOME und $HOME mit dem Pfad des Benutzerverzeichnisses ersetzen.)

Liste anlegen

Damit Mailman tatsächlich genutzt werden kann, muss natürlich eine Liste eingerichtet werden.

mailman create meine-erste-liste@lists.example.org # Alternativ über Web Frontend

Außerdem müssen die E-Mail Adressen für die Mailingliste angelegt werden, im HSAdmin. Zum Beispiel für die Liste meine-erste-liste: meine-erste-liste, meine-erste-liste-join, meine-erste-liste-leave, meine-erste-liste-owner, für die Domain lists.example.org. Die E-Mails sollen in das Postfach gehen, wo mailman installiert ist. Alternativ kann eine Catch-All Adresse eingerichtet werden, damit alle E-Mails an die Subdomain in das Postfach vom mailman gehen. Der Catch-All ist laut Postfix Regeln eine Adresse mit einem leeren lokalen Teil (siehe auch der Screenshot in der entsprechenden Anleitung von Sympa).

Die Selbst-Registrierung von Benutzern verhindern

Per Default kann sich jede Person im Mailman3 ein Benutzerkonto anlegen. Wenn das nicht erwünscht ist, kann in der Datei var/etc/settings.py die folgende Zeile hinzugefügt werden:

ACCOUNT_ADAPTER = 'django_mailman3.views.user_adapter.DisableSignupAdapter'

Es können in diesem Fall im Django Backend durch den Administrator Benutzerkonten angelegt werden, auf https://lists.example.org/admin/auth/user/

Update

Mailman lässt sich wie im Folgenden beschrieben aktualisieren.

Python-Pakete für die Aktualisierungen vorliegen ausgeben:

cd ~/mailman
pipenv update --outdated

Vor dem eigentlichen Update empfiehlt es sich, die Release Notes (zumindest von Mailman) zu lesen und auf relevante Änderungen zu prüfen.

Mailman stoppen:

monit stop mailman

Update der Pakete:

pipenv update

Ggf. Pip Cache löschen:

pipenv --clear

Datenbankmigrationen durchführen:

mailman-web makemigrations
mailman-web migrate

Übersetzungen aktualisieren:

for pofile in $(find $(pipenv --venv) -path '*/locale/*/LC_MESSAGES/*.po'); do
  mofile=${pofile/.po/.mo}
  if [ ! -f $mofile ] || [ $pofile -nt $mofile ]; then
    echo $pofile
    msgfmt $pofile -o $mofile -v
    fi
done

Statische Dateien aktualisieren:

mailman-web collectstatic -c

Abschließend die Dienste wieder starten:

monit start mailman
monit start mailman-web-qcluster

Web Frontend neu starten:

mkdir -p ~/doms/lists.example.org/app-ssl/tmp
touch ~/doms/lists.example.org/app-ssl/tmp/restart.txt