Installation Mailman auf Docker

Dies ist der zweite Beitrag über meinen Weg zu einem eigenen Mailinglisten Server auf Basis eines Docker Container. Meine ersten Erkenntnisse hatte ich hier dokumentiert. Die Installation ist an die Original Dokumentation angelehnt hat aber einige persönliche Erweiterungen.

Um den Webzugriff auf den Administrationsbereich für den Beginn erst einmal abzusichern richte in einem neuen Nginx virtual host eine Konfiguration für den späteren Proxy ein der über eine Kennwort geschützt ist

vi /etc/nginx/conf.d/host.conf>

  location / {
  uwsgi_pass 172.19.199.3:8080;
  		include uwsgi_params;
  		uwsgi_read_timeout 300;
  auth_basic "Restricted";
  auth_basic_user_file /etc/nginx/.htpasswd;
  }
  location /static {
     alias /opt/mailman/web/static;
     auth_basic "Restricted";
     auth_basic_user_file /etc/nginx/.htpasswd;
  }

Das Kennwort für diesen Proxy können wir mit htpasswd erstellen

  htpasswd -c /etc/nginx/.htpasswd <yourlistadmin>

Wenn wir jetzt auf die Seite https:// gehen werden wir zuerst nach dem Kennwort gefragt und dann nach einer Weile bekommen wir einen Timeout da ja noch gar kein Dienst dort arbeitet. Aber der kommt gleich und ist dann schon abgesichert.

Dann geht es los mit der eigentlichen Installation

  cd /opt/
  mkdir -p /opt/mailman/core
  mkdir -p /opt/mailman/web
  git clone https://github.com/maxking/docker-mailman
  cd docker-mailman

Docker-Compose ist ein Werkzeug mit dem man Anwendungen auf verschiedene Docker Container verteilen kann so das sie in einen kleinen Docker Netzwerk “zusammenarbeiten”. In dieser Fall ist es so das die wichtigsten Anwendungseinstellungen für Mailman als Umgebungsvariablen gesetzt werden. Diese sind gemäß Doku einzurichten

Zuerst muss docker-compose installiert werden

 pip install docker-compose
 vi docker-compose.yml
  HYPERKITTY_API_KEY=<ein key den ich aus keepassx genommen haben >
  SECRET_KEY=<noch ein geheimer key>
  SERVE_FROM_DOMAIN=www.yourdomain.de
  MAILMAN_ADMIN_USER=postmaster
  MAILMAN_ADMIN_EMAIL=postmaster@yourdomain.de

Dann geht es los. Docker-Compose hold sich die notwendigen Images und baut die 3 Container mit dem internen Netzwerk.

    docker-compose up -d
    Creating network "docker-mailman_mailman" with driver "bridge"
    Pulling database (postgres:9.6-alpine)...
    9.6-alpine: Pulling from library/postgres
    4fe2ade4980c: Pull complete
    ...
    ...
    e9f65487e6d9: Pull complete
    Digest: sha256:5f243ac0a7f3057757da445ff38031e1cd24d016b91fc3bf5e747e7a15547580
    Status: Downloaded newer image for postgres:9.6-alpine
    Pulling mailman-core (maxking/mailman-core:0.2)...
    0.2: Pulling from maxking/mailman-core
    81033e7c1d6a: Pull complete
    ...
    ...
    fafc78d0f4a7: Pull complete
    Digest: sha256:bc874d6b48aada777fe8da61ecc1532ea3dae29064f190603ba80299527b62bf
    Status: Downloaded newer image for maxking/mailman-core:0.2
    Pulling mailman-web (maxking/mailman-web:0.2)...
    0.2: Pulling from maxking/mailman-web
    911c6d0c7995: Pull complete
    ...
    ...
    1976ee7ab302: Pull complete
    Digest: sha256:c534d7d8bf412ea79988fbf98730f332ba084b5fa19a6510b5d8baef57863469
    Status: Downloaded newer image for maxking/mailman-web:0.2
    Creating docker-mailman_database_1 ... done
    Creating mailman-core              ... done
    Creating mailman-web               ... done

Eigentlich sollte man jetzt mit diesem Befehl auf dem Server “etwas html” bekommen

   curl http://172.19.199.3:8000/postorius/lists/
   curl: (7) Failed to connect to 172.19.199.3 port 8000: Keine Route zum Zielrechner

Mit “docker ps” kann man sehen welche Container laufen. Wie man sieht fehlt hier einer.

   docker ps
   CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS              PORTS               NAMES
   67b5ae7fcb64        postgres:9.6-alpine   "docker-entrypoint.s…"   About a minute ago   Up About a minute   5432/tcp            docker-mailman_database_1

Im Logfile habe ich diese Zeile gefunden die auf ein Zugriffsrechteproblem hinweist.

  mkdir: can't create directory '/opt/mailman-web-data/logs/': Permission denied

Warum das so ist habe ich nicht verstanden aber nach einem Wechsel des Owner ging es dann

  ls -ls /opt/mailman/
  insgesamt 12K
  4,0K drwxr-xr-x  2 root   root   4,0K Sep 15 10:33 core
  4,0K drwx------ 19 952038 951968 4,0K Sep 15 10:24 database
  4,0K drwxr-xr-x  2 root   root   4,0K Sep 15 10:33 web

  chown 951968:951968 web -R
  chown 951968:951968 core -R

  docker ps
  CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                NAMES
  e7f531a065d0        maxking/mailman-web:0.2    "docker-entrypoint.s…"   16 minutes ago      Up 7 seconds        8000/tcp, 8080/tcp   mailman-web
  b48b8757512e        maxking/mailman-core:0.2   "docker-entrypoint.s…"   16 minutes ago      Up 8 seconds        8001/tcp, 8024/tcp   mailman-core
  67b5ae7fcb64        postgres:9.6-alpine        "docker-entrypoint.s…"   16 minutes ago      Up 16 minutes       5432/tcp             docker-mailman_database_1

dann liefert auch dieser Befehl html zurück

 curl http://172.19.199.3:8000/postorius/lists/

Ich musste dann noch etwas länger mit dem statischen Alias in der Nginx Konfiguration kämpfen aber das lag an meinen Standardeinstellungen die ich für meine Webserver im allgemeinen einrichte.

Dann bekam ich endlich die richtig formatierte Startseite.

Anbindung Postfix zu Mailman

Die Anbindung des Docker Containers an Postfix geschieht in zwei Richtungen, von “Innen” nach “Außen” und umgekehrt.

Da ich in meinem Fall einen konfigurierten Postfix Server habe der schon Mails für andere Domainen außerhalb von Mailman empfängt bin ich mit der Standardkonfiguration nicht erfolgreich gewesen. Es wurden dann nämlich alle alte Adressen als unbekannt abgewiesen.

Mit folgenden Änderungen war ich dann am Ende erfolgreich

 vi /etc/postfix/main.cf
  mydestination = ........, yourserver.de
  mynetworks ...... 172.19.199.3
  recipient_delimiter = +
  unknown_local_recipient_reject_code = 550
  owner_request_special = no
  transport_maps = regexp:/opt/mailman/core/var/data/postfix_lmtp
  local_recipient_maps = proxy:unix:passwd.byname $alias_maps regexp:/opt/mailman/core/var/data/postfix_lmtp
  relay_domains = regexp:/opt/mailman/core/var/data/postfix_domains $mydestination

  /etc/init.d/postfix reload

Auf die relay_domains kann man vermutlich erst einmal verzichten wenn man nicht dynamisch durch Endbenutzer neue Domainen anlegen möchte.

Anbindung Mailman zu Postfix

Damit das Mailman-Core im Container auch jemanden hat bei dem er Nachrichten abliefern kann konnte ich die Standardeinstellungen der Doku verwenden.

vi /opt/mailman/core/mailman-extra.cfg
   [mta]
   incoming: mailman.mta.postfix.LMTP
   outgoing: mailman.mta.deliver.deliver
   lmtp_host: 172.19.199.2
   lmtp_port: 8024
   smtp_host: 172.19.199.1
   smtp_port: 25
   configuration: /etc/postfix-mailman.cfg

Auch diese Datei braucht den richtigen Owner sonst knallt es später

 chown  952068:952068 /opt/mailman/core/mailman-extra.cfg

Damit die Weboberfläche auch Mails versenden kann sind diese Änderungen notwendig:

vi settings_local.py
    USE_SSL = False
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = '172.19.199.1'
    EMAIL_PORT = 25
    DEFAULT_FROM_EMAIL = "lists@yourserver.de"
    SERVER_EMAIL = "postmaster@yourserver.de"

Dazu kam noch das Bekanntgeben der neuen Netzwerkadresse und Mail Domaine im Host Postfix

  vi /etc/postfix/main.cf
   mydestination = ........, yourserver.de
   mynetworks ...... 172.19.199.3

/etc/init.d/postfix reload

Dann kann man sich über die Weboberfläche ein Passwordreset des “postmaster” durchführen und nachdem man die Mailadresse bestätigt hat bekommt man die Admin Oberfläche.

Als erstes richten wir eine neue Maildomaine ein:

Und dann unsere erste Maillingliste

und können uns dann direkt bei der Liste anmelden

im Hintergrund hat jetzt Mailman zwei Konfigurationsdateien für den Postfix angepasst

 more /opt/mailman/core/var/data/postfix_domains
     # AUTOMATICALLY GENERATED BY MAILMAN ON 2018-09-16 08:26:45
     #
     # This file is generated by Mailman, and is kept in sync with the binary hash
     # file.  YOU SHOULD NOT MANUALLY EDIT THIS FILE unless you know what you're
     # doing, and can keep the two files properly in sync.  If you screw it up,
     # you're on your own.
     /^yourserver\.de$/ yourserver.de


 more /opt/mailman/core/var/data/postfix_lmtp
    # AUTOMATICALLY GENERATED BY MAILMAN ON 2018-09-16 08:26:45
    # This file is generated by Mailman, and is kept in sync with the binary hash
    # file.  YOU SHOULD NOT MANUALLY EDIT THIS FILE unless you know what you're
    # doing, and can keep the two files properly in sync.  If you screw it up,
    # you're on your own.
    # Aliases which are visible only in the @yourserver.de domain.
    /^firstlist@yourserver\.de$/                  lmtp:[172.19.199.2]:8024
    /^firstlist-bounces(\+.*)?@yourserver\.de$/   lmtp:[172.19.199.2]:8024
    /^firstlist-confirm(\+.*)?@yourserver\.de$/   lmtp:[172.19.199.2]:8024
    /^firstlist-join@yourserver\.de$/             lmtp:[172.19.199.2]:8024
    /^firstlist-leave@yourserver\.de$/            lmtp:[172.19.199.2]:8024
    /^firstlist-owner@yourserver\.de$/            lmtp:[172.19.199.2]:8024
    /^firstlist-request@yourserver\.de$/          lmtp:[172.19.199.2]:8024
    /^firstlist-subscribe@yourserver\.de$/        lmtp:[172.19.199.2]:8024
    /^firstlist-unsubscribe@yourserver\.de$/      lmtp:[172.19.199.2]:8024

Freischaltung in Rspamd

Da ich hier rspamd verwende wurde der Docker Mailversand zu Beginn enorm verzögert. Eine Freischaltung der IP Adresse hat dann geholfen

  vi /etc/rspamd/local.d/ip.map
    172.19.199.2

Danach konnte ich dann schön die ersten Diskussionen starten.