# Migration *Mailman2* vers *Mailman3* ## Installation de *Mailman3* via Docker et docker-compose ### Limites et Pré-requis #### Limites Cette procédure ne traite que du cas suivant: - Serveur *SMTP* utilisé: *Postfix* - Système de base de données utilisée: *Postgres* - Serveur mandataire inverse `Apache Httpd` #### Prérequis 1. Un système Linux fonctionnel sur lequel - sont installés les paquets suivants: - git - postfix - docker - docker-compose (Un binaire souvent bien plus récent que celui proposé par le gestionnaire de paquets de la distribution peut être installé [directement à partir du dépôt Git](https://github.com/docker/compose/releases/).) 2. L'accès à un serveur *SMTP*, idéalement *Postfix* 3. L'accès à une base de données *Postgres* ### Installation 1. Cloner le dépôt suivant: - https://github.com/maxking/docker-mailman ```bash git clone https://github.com/maxking/docker-mailman ``` 2. Éditer le fichier `docker-compose.yaml` (Il est probablement possible de faire la même chose à l'aide d'un fichier `.env` ou `docker-compose.override.yaml`) - Pour le service `mailman-core`: - Renseigner les variables d'environnement suivantes: | Variable | Commentaire (valeur) | | ------------------ | ---------------------------------- | | MTA | Le type de MTA utilisé (`postfix`) | | SMTP_HOST | Le FQDN du serveur SMTP utilisé | | SMTP_PORT | Le port du serveur SMTP utilisé (`25`) | | DATABASE_URL | Le DSN d'accès à la base de données `postgresql://:@:/` | | DATABASE_TYPE | `postgres`) | | DATABASE_CLASS | `mailman.database.postgresql.PostgreSQLDatabase` | | HYPERKITTY_API_KEY | Random encodé en base64: ie `head -c 64 /dev/random \| base64` | - Définir le volume `/opt/mailman/mailman/core:/opt/mailman/` Le volume est un volume *local bind*, le répertoire `/opt/mailman/mailman/core` devra être être crée sur la machine hôte hébergeant le container. Le répertoire peut prendre n'importe quelle valeur adaptée à la situation. - Définir la politique de redémarrage du service à `always` - Pour le service `mailman-web`: - Renseigner les variables d'environnement suivantes: | Variable | Commentaire | | --------------------- | ------------------------------------ | | SMTP_HOST | Le FQDN du serveur SMTP utilisé | | SMTP_PORT | Le port du serveur SMTP utilisé (`25`) | | DJANGO_ALLOWED_HOSTS | Le FQDN par lequel sera accédée l'interface web i.e: `lists.example.com` | | SERVE_FROM_DOMAIN | | Le FQDN par lequel sera accédée l'interface web i.e: `lists.example.com` | | DATABASE_URL | Le DSN d'accès à la base de données `postgresql://:@:/` | | DATABASE_TYPE | `postgres` | | HYPERKITTY_API_KEY | La même clef que définie pour le service `mailman-core` | | SECRET_KEY | Random encodé en base64: ie `head -c 64 /dev/random \| base64` | | MAILMAN_ADMIN_USER | Le nom d'utilisateur de l'administrateur par défaut | | MAILMAN_ADMIN_EMAIL | L'adresse de courriel valide de l'administrateur | - Définir le volume `/opt/mailman/mailman/web:/opt/mailman-web-data` Le volume est un volume *local bind*, le répertoire `/opt/mailman/mailman/web` devra être être créé sur la machine hôte hébergeant le container (voir plus bas). Le répertoire peut prendre n'importe quelle valeur adaptée à la situation. - Définir la politique de redémarrage du service à `always` - Modifier la commande d'exécution du container en ajoutant l'option `--check-static` avec pour argument le volume contenant les fichiers statiques ```yaml command: ["uwsgi", "--ini", "/opt/mailman-web/uwsgi.ini", "--check-static", "/opt/mailman-web-data"] ``` - Définir l'interface réseau d'écoute du service web en ajustant les `ports` du conteneur ```yaml ports: - "192.168.1.2:8000:8000" # HTTP (on suppose que l'adresse LAN de l'hôte est 192.168.1.2) - "127.0.0.1:8080:8080" # uwsgi (reste en écoute sur l'interface loopback) ``` 3. Créer les répertoires qui serviront de volumes aux containers ```bash mkdir -p /opt/mailman/mailman/core /opt/mailman/mailman/web chown root: /opt/mailman/mailman/core /opt/mailman/mailman/web chmod 755 /opt/mailman/mailman/core /opt/mailman/mailman/web ``` #### Exemple de configuration du service `mailman-core` ```yaml mailman-core: image: maxking/mailman-core:0.4 restart: always container_name: mailman-core hostname: mailman-core volumes: - /opt/mailman/mailman/core:/opt/mailman/ stop_grace_period: 30s environment: - MTA=postfix - SMTP_HOST=smtp.example.com - SMTP_PORT=25 - DATABASE_URL=postgresql://user:password@database_host/database - DATABASE_TYPE=postgres - DATABASE_CLASS=mailman.database.postgresql.PostgreSQLDatabase - HYPERKITTY_API_KEY=1+wZYpHz0d9F+rItSSWuwby09R04ZLm19xONOdutzsJc/irGaWnuhO4NTIKTicEC57CG0+QsjHbf/YbNsBZhsA== ports: - "127.0.0.1:8001:8001" # API - "127.0.0.1:8024:8024" # LMTP - incoming emails networks: mailman: ``` #### Exemple de configuration du service `mailman-web` ```yaml mailman-web: image: maxking/mailman-web:0.4 restart: always container_name: mailman-web hostname: mailman-web links: - mailman-core:mailman-core volumes: - /opt/mailman3/mailman/web:/opt/mailman-web-data environment: - SMTP_HOST=smtp.example.com - SMTP_PORT=25 - DJANGO_ALLOWED_HOSTS=lists.example.com - DATABASE_TYPE=postgres - DATABASE_URL=postgresql://user:password@database_host/database - SERVE_FROM_DOMAIN=lists.example.com - MAILMAN_ADMIN_USER=admin - SECRET_KEY=ArtYpfQ7pfcekjA3+uv0xG0n6QlXXQ0Ywk1cP5Pks3R7WIGovBdWiSZ10aDhpjbS3h4GVUX4is/Do0b90Rkx7w== - MAILMAN_ADMIN_EMAIL=admin@exampple.com - HYPERKITTY_API_KEY=1+wZYpHz0d9F+rItSSWuwby09R04ZLm19xONOdutzsJc/irGaWnuhO4NTIKTicEC57CG0+QsjHbf/YbNsBZhsA== ports: - "192.168.1.2:8000:8000" # HTTP - "127.0.0.1:8080:8080" # uwsgi command: ["uwsgi", "--ini", "/opt/mailman-web/uwsgi.ini", "--check-static", "/opt/mailman-web-data"] networks: mailman: ``` ### Démarrage des containers - Démarrer les containers à l'aide la commande suivante: ```bash docker-compose up -d ``` **Note**: - La création d'un service système permettant le redémarrage du conteneur est laissé au bon soin de l'administrateur du système :) - Les conteneurs prennent un certains temps pour démarrer, notamment la première fois. - L'interface d'administration des listes sera accessible sur l'adresse *IP* définie dans les ports du service `mailman-web` (`192.168.1.2`). ### Trouble shooting Les logs sont accessibles à l'aide de la commande suivante: ```bash docker-compose logs ``` Pour voir les logs défiler en direct, utiliser l'option `-f` ```bash docker-compose logs -f ``` ### Documentation officielle et références - [https://github.com/maxking/docker-mailman](https://github.com/maxking/docker-mailman) - [https://docs.mailman3.org/en/latest/](https://docs.mailman3.org/en/latest/) ## Configuration du serveur mandataire inverse (*reverse-proxy*) Le service proposé par les conteneurs ne propose pas de chiffrement *SSL/TLS*. Un serveur mandataire inverse est donc nécesaire pour accéder au service via *https*. Le serveur mandataire n'a pas nécessité à être installé sur l'hôte hébergeant les conteneurs. Le fichier de configuration d'un hôte virtuel *Apache* est fourni tel quel. À vous de l'adapter à votre cas. À noter que `192.168.1.1` est l'adresse *IP* du serveur mandataire inverse pas celle de l'hôte hébergeant les conteneurs qui est défini par la variable `BACKEND_HOST`. ```apache # ReverseProxy with https redirect template # Written by Doug Le Tough # ###################### Define FQDN lists.example.com Define BACKEND_HOST mailman-backend.local Define BACKEND_PORT 8000 ServerName ${FQDN} ### All HTTP requests are converted to HTTPS requests RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} ErrorLog "/var/log/httpd/${FQDN}_error.log" CustomLog "/var/log/httpd/${FQDN}_access.log" Combined Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" ServerName ${FQDN} ProxyPreserveHost On SSLEngine on SSLCertificateFile /etc/dehydrated/certs/${FQDN}/cert.pem SSLCertificateKeyFile /etc/dehydrated/certs/${FQDN}/privkey.pem SSLCertificateChainFile /etc/dehydrated/certs/${FQDN}/fullchain.pem RequestHeader set X_FORWARDED_PROTO 'https' ProxyPass / http://${BACKEND_HOST}:${BACKEND_PORT}/ ProxyPassReverse / http://${BACKEND_HOST}:${BACKEND_PORT}/ ErrorLog "/var/log/httpd/${FQDN}_error.log" CustomLog "/var/log/httpd/${FQDN}_access.log" Combined ``` ### Configuration de *Postfix* 1. Modifier le fichier de configuration principale de *Postfix* (`/etc/postfix/main.cf`) de manière à - prendre en charge le réseau des containers (`172.19.199.0/24`) ```postfix mynetworks = 172.19.199.0/24, 127.0.0.0/8, 192.168.1.0/24, ``` - prendre en charge la liste des domaines et adresse de destinations des listes confiugurée dans *Mailman3* ```postfix transport_maps = regexp:/opt/mailman/mailman/core/var/data/postfix_lmtp local_recipient_maps = regexp:/opt/mailman/mailman/core/var/data/postfix_lmtp relay_domains = regexp:/opt/mailman/mailman/core/var/data/postfix_domains ``` - Redémarrer le service *Postfix* pour prendre en compte les modifications. ## Export, création et import des listes et utilisateurs 1. Se connecter via *SSH* sur l'hôte hébergrant *Mailman2* et exporter la liste des utilisateurs pour chacune des listes à l'aide du script suivant ```bash for LIST in $(list_lists | awk '{print $1}' | sed -e 1d); do echo $LIST; list_members $LIST > ${LIST}.txt done ``` Un fichier texte contenant la liste des utilisateurs sera créé dansle répertoire courant pour chacune des listes définies dans *Mailman2*. 2. Accéder à l'interface d'administration *web* de *Mailman3* à l'aide de l'URL définie sur le serveur mandataire inverse. - Pour chacune des listes dont le nom s'est affiché à l'étape précédante: - Créer et configurer une liste du même nom - Dans `Paramètres / Atténuations DMARC`: - Bien vérifier que `Atténuation DMARC inconditionnelle` est à `oui` - Dans `Opérations goupées / Abonnement en masse`: - Copier la liste des utilisateurs dans le champs `Adresses de courriel à inscrire en nombre` - Cocher `Pré-confirmé`, `Pré-approuvées` et `Pré-vérifiées` pour ne pas obliger les utilisateur à confirmer la création de leur compte - Décocher `Invitation` - Sélectionner `Non` à `Envoyer un message d'accueil` pour ne pas spammer les utilisateurs avec un courriel de bienvenue. - Cliquer sur `Subscribe users`