From 4e90aba03d269430d2b37e9b95d6fd811ed66682 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Feb 2021 16:28:45 +0100
Subject: [PATCH 01/37] [mailman] Welcome Mailman3

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 hosts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hosts b/hosts
index 0377e043..80ff7ef9 100644
--- a/hosts
+++ b/hosts
@@ -112,7 +112,6 @@ charybde.adm.crans.org
 # silice.adm.crans.org
 
 [postfix]
-mailman.adm.crans.org
 redisdead.adm.crans.org
 zamok.adm.crans.org
 
@@ -191,6 +190,7 @@ kenobi.adm.crans.org
 kiwi.adm.crans.org
 kiwijuice.adm.crans.org
 linx.adm.crans.org
+mailman.adm.crans.org
 monitoring.adm.crans.org
 owl.adm.crans.org
 owncloud.adm.crans.org
-- 
GitLab


From 6a7247578d818f29e10c202947347415b650bd9b Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Feb 2021 16:48:50 +0100
Subject: [PATCH 02/37] Don't deploy scripts in the root playbook

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 toto.yml | 7 +++++++
 1 file changed, 7 insertions(+)
 create mode 100755 toto.yml

diff --git a/toto.yml b/toto.yml
new file mode 100755
index 00000000..68d7849f
--- /dev/null
+++ b/toto.yml
@@ -0,0 +1,7 @@
+#!/usr/bin/env ansible-playbook
+---
+
+- hosts: mailman.adm.crans.org
+  tasks:
+    - ansible.builtin.debug:
+        msg: "{{ ansible_env }}"
-- 
GitLab


From 64a4bbcdd6a3c2c7c5d5e6bb598de70c130128f2 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Feb 2021 18:50:54 +0100
Subject: [PATCH 03/37] [mailman] declare interface

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 host_vars/mailman.adm.crans.org.yml | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 host_vars/mailman.adm.crans.org.yml

diff --git a/host_vars/mailman.adm.crans.org.yml b/host_vars/mailman.adm.crans.org.yml
new file mode 100644
index 00000000..c6f8791b
--- /dev/null
+++ b/host_vars/mailman.adm.crans.org.yml
@@ -0,0 +1,4 @@
+---
+interfaces:
+  adm: eth0
+  srv: eth1
-- 
GitLab


From 236a9f80c18c76414cc9da85f81445d3bf1e9f0d Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Feb 2021 19:14:14 +0100
Subject: [PATCH 04/37] Don't commit debug files

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 toto.yml | 7 -------
 1 file changed, 7 deletions(-)
 delete mode 100755 toto.yml

diff --git a/toto.yml b/toto.yml
deleted file mode 100755
index 68d7849f..00000000
--- a/toto.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env ansible-playbook
----
-
-- hosts: mailman.adm.crans.org
-  tasks:
-    - ansible.builtin.debug:
-        msg: "{{ ansible_env }}"
-- 
GitLab


From 368bdfe5edf5401fa4e78e276d001928fae002b5 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Feb 2021 20:12:09 +0100
Subject: [PATCH 05/37] [mailman3] Apply permissions to the folder
 /var/lib/mailman3

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 25a41d47..6bc4b2d7 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -34,6 +34,13 @@
     - mailman-hyperkitty.cfg
   notify: Restart mailman3
 
+- name: Apply permissions to the mailman directory
+  file:
+    path: /var/lib/mailman3
+    state: directory
+    owner: list
+    group: list
+
 # You will need to setup postgres
 # sudo -u postgres createuser -P mailman3web
 # sudo -u postgres createdb -O mailman3web mailman3web
-- 
GitLab


From ad4f6259926682afe64ddf6316d2d9ed584bf8d7 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Feb 2021 20:19:38 +0100
Subject: [PATCH 06/37] [mailman] Setup database host

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 plays/mailman.yml                                | 14 +++++++++-----
 roles/mailman3/templates/mailman3/mailman.cfg.j2 |  2 +-
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/plays/mailman.yml b/plays/mailman.yml
index ac7afd00..4f05430a 100755
--- a/plays/mailman.yml
+++ b/plays/mailman.yml
@@ -25,11 +25,15 @@
   vars:
     mailman3:
       site_owner: root@crans.org
-      database_pass: "{{ vault.mailman3_database_pass }}"
-      restadmin_pass: "{{ vault.mailman3_restadmin_pass }}"
-      archiver_key: "{{ vault.mailman3_archiver_key }}"
-      web_secret_key: "{{ vault.mailman3_web_secret_key }}"
-      web_database_pass: "{{ vault.mailman3_web_database_pass }}"
+      database_user: "mailman3"
+      database_pass: "{{ vault_mailman3_database_pass }}"
+      database_host: "172.16.10.1"
+      database_port: 5432
+      database_name: "mailman3"
+      restadmin_pass: "{{ vault_mailman3_restadmin_pass }}"
+      archiver_key: "{{ vault_mailman3_archiver_key }}"
+      web_secret_key: "{{ vault_mailman3_web_secret_key }}"
+      web_database_pass: "{{ vault_mailman3_web_database_pass }}"
       web_domain: "mailman.crans.org"
   roles:
     - mailman3
diff --git a/roles/mailman3/templates/mailman3/mailman.cfg.j2 b/roles/mailman3/templates/mailman3/mailman.cfg.j2
index 4dbccacc..00f723ef 100644
--- a/roles/mailman3/templates/mailman3/mailman.cfg.j2
+++ b/roles/mailman3/templates/mailman3/mailman.cfg.j2
@@ -172,7 +172,7 @@ class: mailman.database.postgresql.PostgreSQLDatabase
 # 'configuration' substitutions.
 #url: sqlite:///$DATA_DIR/mailman.db
 #url: mysql+pymysql://mailman3:mmpass@localhost/mailman3?charset=utf8&use_unicode=1
-url: postgres://mailman3:{{ mailman3.database_pass }}@localhost/mailman3
+url: postgres://{{ mailman3.database_user }}:{{ mailman3.database_pass }}@{{ mailman3.database_host }}:{{ mailman3.database_port }}/{{ mailman3.database_name }}
 
 debug: no
 
-- 
GitLab


From 4b76b1a7bf0231d0925aefa01d7d16219dea2468 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Feb 2021 21:31:00 +0100
Subject: [PATCH 07/37] [mailman] Use pepcransification of certbot

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 host_vars/mailman.adm.crans.org.yml               |  3 +++
 hosts                                             |  3 +++
 plays/mailman.yml                                 |  4 +++-
 roles/mailman3/tasks/main.yml                     | 15 +--------------
 .../templates/nginx/sites-available/mailman3.j2   |  6 +++---
 5 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/host_vars/mailman.adm.crans.org.yml b/host_vars/mailman.adm.crans.org.yml
index c6f8791b..84b3a34d 100644
--- a/host_vars/mailman.adm.crans.org.yml
+++ b/host_vars/mailman.adm.crans.org.yml
@@ -2,3 +2,6 @@
 interfaces:
   adm: eth0
   srv: eth1
+
+loc_certbot:
+  domains: "*.crans.org"
diff --git a/hosts b/hosts
index 80ff7ef9..782d8eee 100644
--- a/hosts
+++ b/hosts
@@ -92,6 +92,9 @@ linx.adm.crans.org
 [mailman]
 redisdead.adm.crans.org
 
+[mailman]
+mailman.adm.crans.org
+
 [monitoring]
 monitoring.adm.crans.org
 
diff --git a/plays/mailman.yml b/plays/mailman.yml
index 4f05430a..e64869f1 100755
--- a/plays/mailman.yml
+++ b/plays/mailman.yml
@@ -21,8 +21,9 @@
     - nginx
 
 # Deploy Mailman3
-- hosts: mailman.adm.crans.org
+- hosts: mailman
   vars:
+    certbot: '{{ glob_certbot | default({}) | combine(loc_certbot | default({})) }}'
     mailman3:
       site_owner: root@crans.org
       database_user: "mailman3"
@@ -36,5 +37,6 @@
       web_database_pass: "{{ vault_mailman3_web_database_pass }}"
       web_domain: "mailman.crans.org"
   roles:
+    - certbot
     - mailman3
     - postfix-mailman3
diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 6bc4b2d7..cd041253 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -11,8 +11,6 @@
       - postgresql
       - python3-pip  # CAS
       - python3-lxml  # CAS
-      - certbot  # cert
-      - python3-certbot-nginx
     install_recommends: false
   register: apt_result
   retries: 3
@@ -68,19 +66,8 @@
     state: link
   notify: Restart nginx
 
-- name: Create /etc/letsencrypt/conf.d
-  file:
-    path: /etc/letsencrypt/conf.d
-    state: directory
-
-- name: Add Certbot configuration
-  template:
-    src: "letsencrypt/conf.d/mailman.ini.j2"
-    dest: "/etc/letsencrypt/conf.d/mailman.ini"
-    mode: 0644
-
 - name: Indicate role in motd
   template:
     src: update-motd.d/05-service.j2
-    dest: /etc/update-motd.d/05-mailman3
+    dest: /etc/update-motd.d/04-mailman3
     mode: 0755
diff --git a/roles/mailman3/templates/nginx/sites-available/mailman3.j2 b/roles/mailman3/templates/nginx/sites-available/mailman3.j2
index 47ae1ebe..2d664910 100644
--- a/roles/mailman3/templates/nginx/sites-available/mailman3.j2
+++ b/roles/mailman3/templates/nginx/sites-available/mailman3.j2
@@ -42,8 +42,8 @@ server {
     server_tokens off;
 
     # SSL common conf
-    ssl_certificate /etc/letsencrypt/live/mailman.crans.org/fullchain.pem;
-    ssl_certificate_key /etc/letsencrypt/live/mailman.crans.org/privkey.pem;
+    ssl_certificate /etc/letsencrypt/live/crans.org/fullchain.pem;
+    ssl_certificate_key /etc/letsencrypt/live/crans.org/privkey.pem;
     ssl_session_timeout 1d;
     ssl_session_cache shared:MozSSL:10m;
     ssl_session_tickets off;
@@ -55,7 +55,7 @@ server {
     # Enable OCSP Stapling, point to certificate chain
     ssl_stapling on;
     ssl_stapling_verify on;
-    ssl_trusted_certificate /etc/letsencrypt/live/mailman.crans.org/chain.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/crans.org/chain.pem;
 
     location / {
         uwsgi_pass mailman3;
-- 
GitLab


From 32492e0e7ee5bc311ea43d9fdbe607cea46109d9 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Thu, 4 Feb 2021 12:27:15 +0100
Subject: [PATCH 08/37] [mailman] Install sassc in order to compile css files

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index cd041253..57ad9799 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -5,12 +5,13 @@
   apt:
     update_cache: true
     name:
+      - dbconfig-no-thanks  # Do not autoconfigure database
       - mailman3-full
       - nginx
-      - dbconfig-no-thanks  # Do not autoconfigure database
       - postgresql
       - python3-pip  # CAS
       - python3-lxml  # CAS
+      - sassc
     install_recommends: false
   register: apt_result
   retries: 3
-- 
GitLab


From c6ae6454594a7d8ebebc91db57f4c256f5b6c483 Mon Sep 17 00:00:00 2001
From: ynerant <ynerant@crans.org>
Date: Thu, 11 Feb 2021 23:37:43 +0100
Subject: [PATCH 09/37] =?UTF-8?q?[mailman3]=20R=C3=A9paration=20a=20poster?=
 =?UTF-8?q?iori=20du=20chemin=20du=20certificat?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: ynerant <ynerant@crans.org>
---
 roles/postfix-mailman3/templates/postfix/main.cf.j2 | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/roles/postfix-mailman3/templates/postfix/main.cf.j2 b/roles/postfix-mailman3/templates/postfix/main.cf.j2
index 3cc7c11d..805159d5 100644
--- a/roles/postfix-mailman3/templates/postfix/main.cf.j2
+++ b/roles/postfix-mailman3/templates/postfix/main.cf.j2
@@ -16,8 +16,8 @@ delay_warning_time = 4h
 compatibility_level = 2
 
 # TLS parameters
-smtpd_tls_cert_file=/etc/letsencrypt/live/mailman.crans.org/fullchain.pem
-smtpd_tls_key_file=/etc/letsencrypt/live/mailman.crans.org/privkey.pem
+smtpd_tls_cert_file=/etc/letsencrypt/live/crans.org/fullchain.pem
+smtpd_tls_key_file=/etc/letsencrypt/live/crans.org/privkey.pem
 smtpd_use_tls=yes
 smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
 smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
-- 
GitLab


From 23a02adf11bf5a85600b6105ae4ec2738d6a73df Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 28 Feb 2021 17:38:12 +0100
Subject: [PATCH 10/37] [mailman3] Pepcransification

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml                        | 34 +++++++++++++++++++
 host_vars/mailman.adm.crans.org.yml           |  3 --
 plays/mailman.yml                             | 15 ++------
 .../templates/mailman3/mailman-web.py.j2      | 21 +++++++-----
 .../templates/mailman3/mailman.cfg.j2         | 10 +++---
 .../templates/postfix/main.cf.j2              | 10 +++---
 6 files changed, 59 insertions(+), 34 deletions(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index fe7a0de7..c9813ae2 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -1,4 +1,12 @@
 ---
+loc_certbot:
+  - dns_rfc2136_server: '172.16.10.147'
+    dns_rfc2136_name: certbot_challenge.
+    dns_rfc2136_secret: "{{ vault.certbot_dns_secret }}"
+    mail: root@crans.org
+    certname: crans.org
+    domains: "*.crans.org"
+
 loc_nginx:
   service_name: mailman
   default_server: lists.crans.org
@@ -59,3 +67,29 @@ loc_nginx:
           params:
             - "alias /var/lib/mailman/archives/public"
             - "autoindex on"
+
+glob_mailman3:
+  site_owner: root@crans.org
+  database:
+    user: "mailman3"
+    pass: "{{ vault.mailman3_database_pass }}"
+    host: "{{ query('ldap', 'ip', 'tealc', 'adm') | ipv4 | first }}"
+    port: 5432
+    name: "mailman3"
+  web_database:
+    user: "mailman3web"
+    pass: "{{ vault.mailman3_web_database_pass }}"
+    host: "{{ query('ldap', 'ip', 'tealc', 'adm') | ipv4 | first }}"
+    port: 5432
+    name: "mailman3web"
+  smtp:
+    host: "{{ query('ldap', 'ip', 'redisdead', 'adm') | ipv4 | first }}"
+    port: 25
+    user: ""
+    pass: ""
+  restadmin_pass: "{{ vault.mailman3_restadmin_pass }}"
+  archiver_key: "{{ vault.mailman3_archiver_key }}"
+  web_secret_key: "{{ vault.mailman3_web_secret_key }}"
+  web_domain: "mailman.crans.org"
+  default_domain: "crans.org"
+  postfix_domain: "crans.org"
diff --git a/host_vars/mailman.adm.crans.org.yml b/host_vars/mailman.adm.crans.org.yml
index 84b3a34d..c6f8791b 100644
--- a/host_vars/mailman.adm.crans.org.yml
+++ b/host_vars/mailman.adm.crans.org.yml
@@ -2,6 +2,3 @@
 interfaces:
   adm: eth0
   srv: eth1
-
-loc_certbot:
-  domains: "*.crans.org"
diff --git a/plays/mailman.yml b/plays/mailman.yml
index e64869f1..a115d96c 100755
--- a/plays/mailman.yml
+++ b/plays/mailman.yml
@@ -23,19 +23,8 @@
 # Deploy Mailman3
 - hosts: mailman
   vars:
-    certbot: '{{ glob_certbot | default({}) | combine(loc_certbot | default({})) }}'
-    mailman3:
-      site_owner: root@crans.org
-      database_user: "mailman3"
-      database_pass: "{{ vault_mailman3_database_pass }}"
-      database_host: "172.16.10.1"
-      database_port: 5432
-      database_name: "mailman3"
-      restadmin_pass: "{{ vault_mailman3_restadmin_pass }}"
-      archiver_key: "{{ vault_mailman3_archiver_key }}"
-      web_secret_key: "{{ vault_mailman3_web_secret_key }}"
-      web_database_pass: "{{ vault_mailman3_web_database_pass }}"
-      web_domain: "mailman.crans.org"
+    certbot: '{{ loc_certbot | default(glob_certbot | default([])) }}'
+    mailman3: '{{ glob_mailman3 | default({}) | combine(loc_mailman3 | default({})) }}'
   roles:
     - certbot
     - mailman3
diff --git a/roles/mailman3/templates/mailman3/mailman-web.py.j2 b/roles/mailman3/templates/mailman3/mailman-web.py.j2
index 48c4bb10..2a09d209 100644
--- a/roles/mailman3/templates/mailman3/mailman-web.py.j2
+++ b/roles/mailman3/templates/mailman3/mailman-web.py.j2
@@ -81,15 +81,15 @@ DATABASES = {
         'ENGINE': 'django.db.backends.postgresql_psycopg2',
         #'ENGINE': 'django.db.backends.mysql',
         # DB name or path to database file if using sqlite3.
-        'NAME': 'mailman3web',
+        'NAME': '{{ mailman3.web_database.name }}',
         # The following settings are not used with sqlite3:
-        'USER': 'mailman3web',
-        'PASSWORD': '{{ mailman3.web_database_pass }}',
+        'USER': '{{ mailman3.web_database.user }}',
+        'PASSWORD': '{{ mailman3.web_database.pass }}',
         # HOST: empty for localhost through domain sockets or '127.0.0.1' for
         # localhost through TCP.
-        'HOST': '127.0.0.1',
+        'HOST': '{{ mailman3.web_database.host }}',
         # PORT: set to empty string for default.
-        'PORT': '',
+        'PORT': {{ mailman3.web_database.port }},
         # OPTIONS: Extra parameters to use when connecting to the database.
         'OPTIONS': {
             # Set sql_mode to 'STRICT_TRANS_TABLES' for MySQL. See
@@ -138,21 +138,21 @@ USE_TZ = True
 
 
 # Set default domain for email addresses.
-EMAILNAME = 'crans.org'  # A changer en prod
+EMAILNAME = '{{ mailman3.default_domain }}'  # A changer en prod
 
 # If you enable internal authentication, this is the address that the emails
 # will appear to be coming from. Make sure you set a valid domain name,
 # otherwise the emails may get rejected.
 # https://docs.djangoproject.com/en/1.8/ref/settings/#default-from-email
 # DEFAULT_FROM_EMAIL = "mailing-lists@you-domain.org"
-DEFAULT_FROM_EMAIL = 'contact@{}'.format(EMAILNAME)
+DEFAULT_FROM_EMAIL = f'contact@{EMAILNAME}'
 
 # If you enable email reporting for error messages, this is where those emails
 # will appear to be coming from. Make sure you set a valid domain name,
 # otherwise the emails may get rejected.
 # https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-SERVER_EMAIL
 # SERVER_EMAIL = 'root@your-domain.org'
-SERVER_EMAIL = 'root@{}'.format(EMAILNAME)
+SERVER_EMAIL = f'root@{EMAILNAME}'
 
 
 # Django Allauth
@@ -195,6 +195,11 @@ SOCIALACCOUNT_PROVIDERS = {
 # 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_PRECOMPILERS = (
+  ('text/less', 'lessc {infile} {outfile}'),
+  ('text/x-scss', 'sassc -t compressed {infile} {outfile}'),
+  ('text/x-sass', 'sassc -t compressed {infile} {outfile}'),
+)
 COMPRESS_OFFLINE = True
 
 POSTORIUS_TEMPLATE_BASE_URL = 'http://localhost/mailman3/'
diff --git a/roles/mailman3/templates/mailman3/mailman.cfg.j2 b/roles/mailman3/templates/mailman3/mailman.cfg.j2
index 00f723ef..0d670df9 100644
--- a/roles/mailman3/templates/mailman3/mailman.cfg.j2
+++ b/roles/mailman3/templates/mailman3/mailman.cfg.j2
@@ -172,7 +172,7 @@ class: mailman.database.postgresql.PostgreSQLDatabase
 # 'configuration' substitutions.
 #url: sqlite:///$DATA_DIR/mailman.db
 #url: mysql+pymysql://mailman3:mmpass@localhost/mailman3?charset=utf8&use_unicode=1
-url: postgres://{{ mailman3.database_user }}:{{ mailman3.database_pass }}@{{ mailman3.database_host }}:{{ mailman3.database_port }}/{{ mailman3.database_name }}
+url: postgres://{{ mailman3.database.user }}:{{ mailman3.database.pass }}@{{ mailman3.database.host }}:{{ mailman3.database.port }}/{{ mailman3.database.name }}
 
 debug: no
 
@@ -252,10 +252,10 @@ outgoing: mailman.mta.deliver.deliver
 
 # How to connect to the outgoing MTA.  If smtp_user and smtp_pass is given,
 # then Mailman will attempt to log into the MTA when making a new connection.
-smtp_host: localhost
-smtp_port: 25
-smtp_user:
-smtp_pass:
+smtp_host: {{ mailman3.smtp.host }}
+smtp_port: {{ mailman3.smtp.port }}
+smtp_user: {{ mailman3.smtp.user }}
+smtp_pass: {{ mailman3.smtp.pass }}
 
 # Where the LMTP server listens for connections.  Use 127.0.0.1 instead of
 # localhost for Postfix integration, because Postfix only consults DNS
diff --git a/roles/postfix-mailman3/templates/postfix/main.cf.j2 b/roles/postfix-mailman3/templates/postfix/main.cf.j2
index 805159d5..5dc3a1ec 100644
--- a/roles/postfix-mailman3/templates/postfix/main.cf.j2
+++ b/roles/postfix-mailman3/templates/postfix/main.cf.j2
@@ -3,7 +3,7 @@
 # This postfix configuration set up a MTA only to send and receive mailing list mails
 
 # When a mail is sent to @localhost, this domain will be used
-myorigin = crans.org
+myorigin = {{ mailman3.postfix_domain }}
 
 smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
 biff = no
@@ -16,8 +16,8 @@ delay_warning_time = 4h
 compatibility_level = 2
 
 # TLS parameters
-smtpd_tls_cert_file=/etc/letsencrypt/live/crans.org/fullchain.pem
-smtpd_tls_key_file=/etc/letsencrypt/live/crans.org/privkey.pem
+smtpd_tls_cert_file=/etc/letsencrypt/live/{{ mailman3.postfix_domain }}/fullchain.pem
+smtpd_tls_key_file=/etc/letsencrypt/live/{{ mailman3.postfix_domain }}/privkey.pem
 smtpd_use_tls=yes
 smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
 smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
@@ -40,8 +40,8 @@ inet_interfaces = all
 inet_protocols = all
 
 # Do not use gethostname
-myhostname = {{ ansible_hostname }}.crans.org
-mydomain = crans.org
+myhostname = {{ ansible_hostname }}.{{ mailman3.postfix_domain }}
+mydomain = {{ mailman3.postfix_domain }}
 
 # Softbounce, ask remote mail server to send the mail again if error
 # Do not keep it active in production!
-- 
GitLab


From b74d5e0bf1fd40c198a65adb664f0d00a70bf39e Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 28 Feb 2021 17:46:16 +0100
Subject: [PATCH 11/37] [mailman3] Drop mailman2 configuration

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml                        |  61 --
 hosts                                         |   3 -
 plays/mailman.yml                             |  20 -
 roles/mailman/handlers/main.yml               |   5 -
 roles/mailman/tasks/main.yml                  |  47 --
 .../mailman/templates/mailman/create.html.j2  |  13 -
 roles/mailman/templates/mailman/mm_cfg.py.j2  | 226 ------
 .../nginx/snippets/fastcgi-mailman.conf.j2    |  18 -
 .../templates/update-motd.d/05-mailman.j2     |   3 -
 .../usr/lib/mailman/Mailman/htmlformat.py.j2  | 742 ------------------
 10 files changed, 1138 deletions(-)
 delete mode 100644 roles/mailman/handlers/main.yml
 delete mode 100644 roles/mailman/tasks/main.yml
 delete mode 100644 roles/mailman/templates/mailman/create.html.j2
 delete mode 100644 roles/mailman/templates/mailman/mm_cfg.py.j2
 delete mode 100644 roles/mailman/templates/nginx/snippets/fastcgi-mailman.conf.j2
 delete mode 100755 roles/mailman/templates/update-motd.d/05-mailman.j2
 delete mode 100644 roles/mailman/templates/usr/lib/mailman/Mailman/htmlformat.py.j2

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index c9813ae2..d101e33b 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -7,67 +7,6 @@ loc_certbot:
     certname: crans.org
     domains: "*.crans.org"
 
-loc_nginx:
-  service_name: mailman
-  default_server: lists.crans.org
-  default_ssl_server: lists.crans.org
-  auth_passwd:
-    Stop: "$apr1$NXaV5H7Q$J3ora3Jo5h775Y1nm93PN1"
-  deploy_robots_file: true
-  servers:
-    - server_name:
-      - lists.crans.org
-      ssl: crans.org
-      root: "/usr/lib/cgi-bin/mailman/"
-      index:
-        - index.htm
-        - index.html
-      locations:
-        - filter: "/error/"
-          params:
-            - "internal"
-            - "alias /var/www/html/"
-        - filter: "/create"
-          params:
-            - "default_type text/html"
-            - "alias /etc/mailman/create.html"
-        - filter: "~ ^/$"
-          params:
-            - "return 302 https://lists.crans.org/listinfo"
-        - filter: "/"
-          params:
-            - "include \"/etc/nginx/snippets/fastcgi-mailman.conf\""
-        - filter: "~ ^/listinfo"
-          params:
-            - "satisfy any"
-            - "include \"/etc/nginx/snippets/fastcgi-mailman.conf\""
-            - "allow 185.230.76.0/22"
-            - "allow 2a0c:700:0::/40"
-            - "deny all"
-            - "auth_basic \"On n'aime pas les spambots, donc on a mis un mot de passe. Le login est Stop et le mot de passe est Spam.\""
-            - "auth_basic_user_file /etc/nginx/passwd"
-            - "error_page 401 /error/401.html"
-        - filter: "~ ^/admin"
-          params:
-            - "satisfy any"
-            - "include \"/etc/nginx/snippets/fastcgi-mailman.conf\""
-            - "allow 185.230.76.0/22"
-            - "allow 2a0c:700:0::/40"
-            - "deny all"
-            - "auth_basic \"On n'aime pas les spambots, donc on a mis un mot de passe. Le login est Stop et le mot de passe est Spam.\""
-            - "auth_basic_user_file /etc/nginx/passwd"
-            - "error_page 401 /error/401.html"
-        - filter: "/images/mailman"
-          params:
-            - "alias /usr/share/images/mailman"
-        - filter: "/robots.txt"
-          params:
-            - "alias /var/www/robots.txt"
-        - filter: "/archives"
-          params:
-            - "alias /var/lib/mailman/archives/public"
-            - "autoindex on"
-
 glob_mailman3:
   site_owner: root@crans.org
   database:
diff --git a/hosts b/hosts
index 782d8eee..58e24a4a 100644
--- a/hosts
+++ b/hosts
@@ -89,9 +89,6 @@ sputnik.adm.crans.org
 [linx]
 linx.adm.crans.org
 
-[mailman]
-redisdead.adm.crans.org
-
 [mailman]
 mailman.adm.crans.org
 
diff --git a/plays/mailman.yml b/plays/mailman.yml
index a115d96c..2182e778 100755
--- a/plays/mailman.yml
+++ b/plays/mailman.yml
@@ -1,25 +1,5 @@
 #!/usr/bin/env ansible-playbook
 ---
-# Deploy Mailman
-- hosts: redisdead.adm.crans.org
-  vars:
-    mailman:
-      site_list: "nounou"
-      default_url: "https://lists.crans.org/"
-      default_host: "lists.crans.org"
-      default_language: "fr"
-      custom_logo: "crans_icon_dark.svg"
-      custom_logo_name: "crans.svg"
-      custom_logo_url: "https://www.crans.org/"
-      custom_logo_alt: "CRANS"
-    spamassassin: "SpamAssassin_crans"
-    smtphost: "smtp.adm.crans.org"
-    mynetworks: ['138.231.0.0/16', '185.230.76.0/22', '2a0c:700:0::/40']
-    nginx: '{{ glob_nginx | default({}) | combine(loc_nginx | default({})) }}'
-  roles:
-    - mailman
-    - nginx
-
 # Deploy Mailman3
 - hosts: mailman
   vars:
diff --git a/roles/mailman/handlers/main.yml b/roles/mailman/handlers/main.yml
deleted file mode 100644
index 77550456..00000000
--- a/roles/mailman/handlers/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-- name: Reload mailman
-  systemd:
-    name: mailman
-    state: reloaded
diff --git a/roles/mailman/tasks/main.yml b/roles/mailman/tasks/main.yml
deleted file mode 100644
index 9a74a41e..00000000
--- a/roles/mailman/tasks/main.yml
+++ /dev/null
@@ -1,47 +0,0 @@
----
-- name: Install mailman and SpamAssassin
-  apt:
-    update_cache: true
-    name:
-      - mailman
-      - spamassassin
-  register: apt_result
-  retries: 3
-  until: apt_result is succeeded
-
-- name: Deploy mailman config
-  template:
-    src: "mailman/{{ item }}.j2"
-    dest: "/etc/mailman/{{ item }}"
-    mode: 0755
-  loop:
-    - mm_cfg.py
-    - create.html
-  notify: Reload mailman
-
-- name: Deploy mailman snippet
-  template:
-    src: "nginx/snippets/fastcgi-mailman.conf.j2"
-    dest: "/etc/nginx/snippets/fastcgi-mailman.conf"
-    owner: root
-    group: root
-    mode: 0644
-
-# Fanciness
-- name: Deploy custom logo
-  copy:
-    src: "{{ mailman.custom_logo }}"
-    dest: "/usr/share/images/mailman/{{ mailman.custom_logo_name }}"
-
-- name: Deploy custom logo
-  template:
-    src: usr/lib/mailman/Mailman/htmlformat.py.j2
-    dest: /usr/lib/mailman/Mailman/htmlformat.py
-    mode: 0755
-  notify: Reload mailman
-
-- name: Indicate role in motd
-  template:
-    src: update-motd.d/05-mailman.j2
-    dest: /etc/update-motd.d/05-mailman
-    mode: 0755
diff --git a/roles/mailman/templates/mailman/create.html.j2 b/roles/mailman/templates/mailman/create.html.j2
deleted file mode 100644
index 68236402..00000000
--- a/roles/mailman/templates/mailman/create.html.j2
+++ /dev/null
@@ -1,13 +0,0 @@
-{{ ansible_header | comment('xml') }}
-
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<title>Creation de mailing list</title>
-</head>
-
-<body>
-<h1>Creation de mailing list</h1>
-Il faut s'adresser a nounou arobase crans point org.
-</body>
-</html>
diff --git a/roles/mailman/templates/mailman/mm_cfg.py.j2 b/roles/mailman/templates/mailman/mm_cfg.py.j2
deleted file mode 100644
index 25f82461..00000000
--- a/roles/mailman/templates/mailman/mm_cfg.py.j2
+++ /dev/null
@@ -1,226 +0,0 @@
-{{ ansible_header | comment }}
-# -*- python -*-
-
-# Copyright (C) 1998,1999,2000 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program 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 this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301 USA
-
-
-"""This is the module which takes your site-specific settings.
-
-From a raw distribution it should be copied to mm_cfg.py.  If you
-already have an mm_cfg.py, be careful to add in only the new settings
-you want.  The complete set of distributed defaults, with annotation,
-are in ./Defaults.  In mm_cfg, override only those you want to
-change, after the
-
-  from Defaults import *
-
-line (see below).
-
-Note that these are just default settings - many can be overridden via the
-admin and user interfaces on a per-list or per-user basis.
-
-Note also that some of the settings are resolved against the active list
-setting by using the value as a format string against the
-list-instance-object's dictionary - see the distributed value of
-DEFAULT_MSG_FOOTER for an example."""
-
-
-#######################################################
-#    Here's where we get the distributed defaults.    #
-
-from Defaults import *
-
-
-#####
-# General system-wide defaults
-#####
-
-# Should image logos be used?  Set this to 0 to disable image logos from "our
-# sponsors" and just use textual links instead (this will also disable the
-# shortcut "favicon").  Otherwise, this should contain the URL base path to
-# the logo images (and must contain the trailing slash)..  If you want to
-# disable Mailman's logo footer altogther, hack
-# Mailman/htmlformat.py:MailmanLogo(), which also contains the hardcoded links
-# and image names.
-IMAGE_LOGOS = '/images/mailman/'
-
-#-------------------------------------------------------------
-# The name of the list Mailman uses to send password reminders
-# and similar. Don't change if you want mailman-owner to be
-# a valid local part.
-MAILMAN_SITE_LIST = '{{ mailman.site_list }}'
-
-DEFAULT_URL= '{{ mailman.default_url }}'
-DEFAULT_URL_PATTERN = 'https://%s/'
-add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)
-
-#-------------------------------------------------------------
-# Default domain for email addresses of newly created MLs
-DEFAULT_EMAIL_HOST = '{{ mailman.default_host }}'
-#-------------------------------------------------------------
-# Default host for web interface of newly created MLs
-DEFAULT_URL_HOST   = '{{ mailman.default_host }}'
-#-------------------------------------------------------------
-# Required when setting any of its arguments.
-add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)
-
-#-------------------------------------------------------------
-# Do we send monthly reminders?
-DEFAULT_SEND_REMINDERS = No
-
-# Normally when a site administrator authenticates to a web page with the site
-# password, they get a cookie which authorizes them as the list admin.  It
-# makes me nervous to hand out site auth cookies because if this cookie is
-# cracked or intercepted, the intruder will have access to every list on the
-# site.  OTOH, it's dang handy to not have to re-authenticate to every list on
-# the site.  Set this value to Yes to allow site admin cookies.
-ALLOW_SITE_ADMIN_COOKIES = Yes
-
-#####
-# Archive defaults
-#####
-
-PUBLIC_ARCHIVE_URL = '{{ mailman.default_url }}archives/%(listname)s'
-
-# Are archives on or off by default?
-DEFAULT_ARCHIVE = Off
-
-# Are archives public or private by default?
-# 0=public, 1=private
-DEFAULT_ARCHIVE_PRIVATE = 1
-
-# Pipermail assumes that messages bodies contain US-ASCII text.
-# Change this option to define a different character set to be used as
-# the default character set for the archive.  The term "character set"
-# is used in MIME to refer to a method of converting a sequence of
-# octets into a sequence of characters.  If you change the default
-# charset, you might need to add it to VERBATIM_ENCODING below.
-DEFAULT_CHARSET = 'utf-8'
-
-# Most character set encodings require special HTML entity characters to be
-# quoted, otherwise they won't look right in the Pipermail archives.  However
-# some character sets must not quote these characters so that they can be
-# rendered properly in the browsers.  The primary issue is multi-byte
-# encodings where the octet 0x26 does not always represent the & character.
-# This variable contains a list of such characters sets which are not
-# HTML-quoted in the archives.
-VERBATIM_ENCODING = ['utf-8']
-
-#####
-# General defaults
-#####
-
-# The default language for this server.  Whenever we can't figure out the list
-# context or user context, we'll fall back to using this language.  See
-# LC_DESCRIPTIONS below for legal values.
-DEFAULT_SERVER_LANGUAGE = '{{ mailman.default_language }}'
-
-# How many members to display at a time on the admin cgi to unsubscribe them
-# or change their options?
-DEFAULT_ADMIN_MEMBER_CHUNKSIZE = 50
-
-# set this variable to Yes to allow list owners to delete their own mailing
-# lists.  You may not want to give them this power, in which case, setting
-# this variable to No instead requires list removal to be done by the site
-# administrator, via the command line script bin/rmlist.
-#OWNERS_CAN_DELETE_THEIR_OWN_LISTS = No
-
-# Set this variable to Yes to allow list owners to set the "personalized"
-# flags on their mailing lists.  Turning these on tells Mailman to send
-# separate email messages to each user instead of batching them together for
-# delivery to the MTA.  This gives each member a more personalized message,
-# but can have a heavy impact on the performance of your system.
-#OWNERS_CAN_ENABLE_PERSONALIZATION = No
-
-#####
-# List defaults.  NOTE: Changing these values does NOT change the
-# configuration of an existing list.  It only defines the default for new
-# lists you subsequently create.
-#####
-
-# Should a list, by default be advertised?  What is the default maximum number
-# of explicit recipients allowed?  What is the default maximum message size
-# allowed?
-DEFAULT_LIST_ADVERTISED = Yes
-
-# {header-name: regexp} spam filtering - we include some for example sake.
-DEFAULT_BOUNCE_MATCHING_HEADERS = """
-# Les lignes commencant par # sont des commentairtes.
-#from: .*-owner@yahoogroups.com
-#from: .*@uplinkpro.com
-#from: .*@coolstats.comic.com
-#from: .*@trafficmagnet.com
-#from: .*@hotmail.com
-#X-Reject: 450
-#X-Reject: 554
-"""
-
-# Mailman can be configured to strip any existing Reply-To: header, or simply
-# extend any existing Reply-To: with one based on the above setting.
-DEFAULT_FIRST_STRIP_REPLY_TO = Yes
-
-# SUBSCRIBE POLICY
-# 0 - open list (only when ALLOW_OPEN_SUBSCRIBE is set to 1) **
-# 1 - confirmation required for subscribes
-# 2 - admin approval required for subscribes
-# 3 - both confirmation and admin approval required
-#
-# ** please do not choose option 0 if you are not allowing open
-# subscribes (next variable)
-DEFAULT_SUBSCRIBE_POLICY = 3
-
-# Is the list owner notified of subscribes/unsubscribes?
-DEFAULT_ADMIN_NOTIFY_MCHANGES = Yes
-
-# Do we send monthly reminders?
-DEFAULT_SEND_REMINDERS = No
-
-# What should happen to non-member posts which do not match explicit
-# non-member actions?
-# 0 = Accept
-# 1 = Hold
-# 2 = Reject
-# 3 = Discard
-DEFAULT_GENERIC_NONMEMBER_ACTION = 1
-
-# Use spamassassin automatically
-GLOBAL_PIPELINE.insert(5, '{{ spamassassin }}')
-# Discard messages with score higher than ...
-SPAMASSASSIN_DISCARD_SCORE = 8
-# Hold in moderation messages with score higher than ...
-SPAMASSASSIN_HOLD_SCORE = 2.1
-
-# Add SpamAssassin administration interface on gui
-# To make it work, you need to edit Gui/__init__.py
-# with
-# from SpamAssassin import SpamAssassin
-ADMIN_CATEGORIES.append("spamassassin")
-
-# Add header to keep
-PLAIN_DIGEST_KEEP_HEADERS.append('X-Spam-Score')
-
-# configure MTA
-MTA = 'Postfix'
-SMTPHOST = '{{ smtphost }}'
-SMTP_MAX_RCPTS = 50
-
-
-POSTFIX_STYLE_VIRTUAL_DOMAINS = ["{{ mailman.default_host }}"]
-
-# Note - if you're looking for something that is imported from mm_cfg, but you
-# didn't find it above, it's probably in /usr/lib/mailman/Mailman/Defaults.py.
diff --git a/roles/mailman/templates/nginx/snippets/fastcgi-mailman.conf.j2 b/roles/mailman/templates/nginx/snippets/fastcgi-mailman.conf.j2
deleted file mode 100644
index d3215c7f..00000000
--- a/roles/mailman/templates/nginx/snippets/fastcgi-mailman.conf.j2
+++ /dev/null
@@ -1,18 +0,0 @@
-{{ ansible_header | comment }}
-
-# regex to split $uri to $fastcgi_script_name and $fastcgi_path
-fastcgi_split_path_info (^/[^/]*)(.*)$;
-
-# check that the PHP script exists before passing it
-try_files $fastcgi_script_name =404;
-
-# Bypass the fact that try_files resets $fastcgi_path_info
-# see: http://trac.nginx.org/nginx/ticket/321
-set $path_info $fastcgi_path_info;
-fastcgi_param PATH_INFO $path_info;
-
-# Let NGINX handle errors
-fastcgi_intercept_errors on;
-
-include /etc/nginx/fastcgi.conf;
-fastcgi_pass unix:/var/run/fcgiwrap.socket;
diff --git a/roles/mailman/templates/update-motd.d/05-mailman.j2 b/roles/mailman/templates/update-motd.d/05-mailman.j2
deleted file mode 100755
index d3fee0db..00000000
--- a/roles/mailman/templates/update-motd.d/05-mailman.j2
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/tail +14
-{{ ansible_header | comment }}
-> Mailman a été déployé sur cette machine. Voir /etc/mailman/ et /var/lib/mailman/.
diff --git a/roles/mailman/templates/usr/lib/mailman/Mailman/htmlformat.py.j2 b/roles/mailman/templates/usr/lib/mailman/Mailman/htmlformat.py.j2
deleted file mode 100644
index 3f10f131..00000000
--- a/roles/mailman/templates/usr/lib/mailman/Mailman/htmlformat.py.j2
+++ /dev/null
@@ -1,742 +0,0 @@
-{{ ansible_header | comment }}
-# Copyright (C) 1998-2018 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program 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 this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-
-"""Library for program-based construction of an HTML documents.
-
-Encapsulate HTML formatting directives in classes that act as containers
-for python and, recursively, for nested HTML formatting objects.
-"""
-
-
-# Eventually could abstract down to HtmlItem, which outputs an arbitrary html
-# object given start / end tags, valid options, and a value.  Ug, objects
-# shouldn't be adding their own newlines.  The next object should.
-
-
-import types
-
-from Mailman import mm_cfg
-from Mailman import Utils
-from Mailman.i18n import _, get_translation
-
-from Mailman.CSRFcheck import csrf_token
-
-SPACE = ' '
-EMPTYSTRING = ''
-NL = '\n'
-
-
-
-# Format an arbitrary object.
-def HTMLFormatObject(item, indent):
-    "Return a presentation of an object, invoking their Format method if any."
-    if type(item) == type(''):
-        return item
-    elif not hasattr(item, "Format"):
-        return `item`
-    else:
-        return item.Format(indent)
-
-def CaseInsensitiveKeyedDict(d):
-    result = {}
-    for (k,v) in d.items():
-        result[k.lower()] = v
-    return result
-
-# Given references to two dictionaries, copy the second dictionary into the
-# first one.
-def DictMerge(destination, fresh_dict):
-    for (key, value) in fresh_dict.items():
-        destination[key] = value
-
-class Table:
-    def __init__(self, **table_opts):
-        self.cells = []
-        self.cell_info = {}
-        self.row_info = {}
-        self.opts = table_opts
-
-    def AddOptions(self, opts):
-        DictMerge(self.opts, opts)
-
-    # Sets all of the cells.  It writes over whatever cells you had there
-    # previously.
-
-    def SetAllCells(self, cells):
-        self.cells = cells
-
-    # Add a new blank row at the end
-    def NewRow(self):
-        self.cells.append([])
-
-    # Add a new blank cell at the end
-    def NewCell(self):
-        self.cells[-1].append('')
-
-    def AddRow(self, row):
-        self.cells.append(row)
-
-    def AddCell(self, cell):
-        self.cells[-1].append(cell)
-
-    def AddCellInfo(self, row, col, **kws):
-        kws = CaseInsensitiveKeyedDict(kws)
-        if not self.cell_info.has_key(row):
-            self.cell_info[row] = { col : kws }
-        elif self.cell_info[row].has_key(col):
-            DictMerge(self.cell_info[row], kws)
-        else:
-            self.cell_info[row][col] = kws
-
-    def AddRowInfo(self, row, **kws):
-        kws = CaseInsensitiveKeyedDict(kws)
-        if not self.row_info.has_key(row):
-            self.row_info[row] = kws
-        else:
-            DictMerge(self.row_info[row], kws)
-
-    # What's the index for the row we just put in?
-    def GetCurrentRowIndex(self):
-        return len(self.cells)-1
-
-    # What's the index for the col we just put in?
-    def GetCurrentCellIndex(self):
-        return len(self.cells[-1])-1
-
-    def ExtractCellInfo(self, info):
-        valid_mods = ['align', 'valign', 'nowrap', 'rowspan', 'colspan',
-                      'bgcolor']
-        output = ''
-
-        for (key, val) in info.items():
-            if not key in valid_mods:
-                continue
-            if key == 'nowrap':
-                output = output + ' NOWRAP'
-                continue
-            else:
-                output = output + ' %s="%s"' % (key.upper(), val)
-
-        return output
-
-    def ExtractRowInfo(self, info):
-        valid_mods = ['align', 'valign', 'bgcolor']
-        output = ''
-
-        for (key, val) in info.items():
-            if not key in valid_mods:
-                continue
-            output = output + ' %s="%s"' % (key.upper(), val)
-
-        return output
-
-    def ExtractTableInfo(self, info):
-        valid_mods = ['align', 'width', 'border', 'cellspacing', 'cellpadding',
-                      'bgcolor']
-
-        output = ''
-
-        for (key, val) in info.items():
-            if not key in valid_mods:
-                continue
-            if key == 'border' and val == None:
-                output = output + ' BORDER'
-                continue
-            else:
-                output = output + ' %s="%s"' % (key.upper(), val)
-
-        return output
-
-    def FormatCell(self, row, col, indent):
-        try:
-            my_info = self.cell_info[row][col]
-        except:
-            my_info = None
-
-        output = '\n' + ' '*indent + '<td'
-        if my_info:
-            output = output + self.ExtractCellInfo(my_info)
-        item = self.cells[row][col]
-        item_format = HTMLFormatObject(item, indent+4)
-        output = '%s>%s</td>' % (output, item_format)
-        return output
-
-    def FormatRow(self, row, indent):
-        try:
-            my_info = self.row_info[row]
-        except:
-            my_info = None
-
-        output = '\n' + ' '*indent + '<tr'
-        if my_info:
-            output = output + self.ExtractRowInfo(my_info)
-        output = output + '>'
-
-        for i in range(len(self.cells[row])):
-            output = output + self.FormatCell(row, i, indent + 2)
-
-        output = output + '\n' + ' '*indent + '</tr>'
-
-        return output
-
-    def Format(self, indent=0):
-        output = '\n' + ' '*indent + '<table'
-        output = output + self.ExtractTableInfo(self.opts)
-        output = output + '>'
-
-        for i in range(len(self.cells)):
-            output = output + self.FormatRow(i, indent + 2)
-
-        output = output + '\n' + ' '*indent + '</table>\n'
-
-        return output
-
-
-class Link:
-    def __init__(self, href, text, target=None):
-        self.href = href
-        self.text = text
-        self.target = target
-
-    def Format(self, indent=0):
-        texpr = ""
-        if self.target != None:
-            texpr = ' target="%s"' % self.target
-        return '<a href="%s"%s>%s</a>' % (HTMLFormatObject(self.href, indent),
-                                          texpr,
-                                          HTMLFormatObject(self.text, indent))
-
-class FontSize:
-    """FontSize is being deprecated - use FontAttr(..., size="...") instead."""
-    def __init__(self, size, *items):
-        self.items = list(items)
-        self.size = size
-
-    def Format(self, indent=0):
-        output = '<font size="%s">' % self.size
-        for item in self.items:
-            output = output + HTMLFormatObject(item, indent)
-        output = output + '</font>'
-        return output
-
-class FontAttr:
-    """Present arbitrary font attributes."""
-    def __init__(self, *items, **kw):
-        self.items = list(items)
-        self.attrs = kw
-
-    def Format(self, indent=0):
-        seq = []
-        for k, v in self.attrs.items():
-            seq.append('%s="%s"' % (k, v))
-        output = '<font %s>' % SPACE.join(seq)
-        for item in self.items:
-            output = output + HTMLFormatObject(item, indent)
-        output = output + '</font>'
-        return output
-
-
-class Container:
-    def __init__(self, *items):
-        if not items:
-            self.items = []
-        else:
-            self.items = items
-
-    def AddItem(self, obj):
-        self.items.append(obj)
-
-    def Format(self, indent=0):
-        output = []
-        for item in self.items:
-            output.append(HTMLFormatObject(item, indent))
-        return EMPTYSTRING.join(output)
-
-
-class Label(Container):
-    align = 'right'
-
-    def __init__(self, *items):
-        Container.__init__(self, *items)
-
-    def Format(self, indent=0):
-        return ('<div align="%s">' % self.align) + \
-               Container.Format(self, indent) + \
-               '</div>'
-
-
-# My own standard document template.  YMMV.
-# something more abstract would be more work to use...
-
-class Document(Container):
-    title = None
-    language = None
-    bgcolor = mm_cfg.WEB_BG_COLOR
-    suppress_head = 0
-
-    def set_language(self, lang=None):
-        self.language = lang
-
-    def set_bgcolor(self, color):
-        self.bgcolor = color
-
-    def SetTitle(self, title):
-        self.title = title
-
-    def Format(self, indent=0, **kws):
-        charset = 'us-ascii'
-        if self.language and Utils.IsLanguage(self.language):
-            charset = Utils.GetCharSet(self.language)
-        output = ['Content-Type: text/html; charset=%s' % charset]
-        output.append('Cache-control: no-cache\n')
-        if not self.suppress_head:
-            kws.setdefault('bgcolor', self.bgcolor)
-            tab = ' ' * indent
-            output.extend([tab,
-                           '<HTML>',
-                           '<HEAD>'
-                           ])
-            if mm_cfg.IMAGE_LOGOS:
-                output.append('<LINK REL="SHORTCUT ICON" HREF="%s">' %
-                              (mm_cfg.IMAGE_LOGOS + mm_cfg.SHORTCUT_ICON))
-            # Hit all the bases
-            output.append('<META http-equiv="Content-Type" '
-                          'content="text/html; charset=%s">' % charset)
-            if self.title:
-                output.append('%s<TITLE>%s</TITLE>' % (tab, self.title))
-            # Add CSS to visually hide some labeling text but allow screen
-            # readers to read it.
-            output.append("""\
-<style type="text/css">
-    div.hidden
-        {position:absolute;
-        left:-10000px;
-        top:auto;
-        width:1px;
-        height:1px;
-        overflow:hidden;}
-</style>
-""")
-            if mm_cfg.WEB_HEAD_ADD:
-                output.append(mm_cfg.WEB_HEAD_ADD)
-            output.append('%s</HEAD>' % tab)
-            quals = []
-            # Default link colors
-            if mm_cfg.WEB_VLINK_COLOR:
-                kws.setdefault('vlink', mm_cfg.WEB_VLINK_COLOR)
-            if mm_cfg.WEB_ALINK_COLOR:
-                kws.setdefault('alink', mm_cfg.WEB_ALINK_COLOR)
-            if mm_cfg.WEB_LINK_COLOR:
-                kws.setdefault('link', mm_cfg.WEB_LINK_COLOR)
-            for k, v in kws.items():
-                quals.append('%s="%s"' % (k, v))
-            output.append('%s<BODY %s' % (tab, SPACE.join(quals)))
-            # Language direction
-            direction = Utils.GetDirection(self.language)
-            output.append('dir="%s">' % direction)
-        # Always do this...
-        output.append(Container.Format(self, indent))
-        if not self.suppress_head:
-            output.append('%s</BODY>' % tab)
-            output.append('%s</HTML>' % tab)
-        return NL.join(output)
-
-    def addError(self, errmsg, tag=None):
-        if tag is None:
-            tag = _('Error: ')
-        self.AddItem(Header(3, Bold(FontAttr(
-            _(tag), color=mm_cfg.WEB_ERROR_COLOR, size='+2')).Format() +
-                            Italic(errmsg).Format()))
-
-
-class HeadlessDocument(Document):
-    """Document without head section, for templates that provide their own."""
-    suppress_head = 1
-
-
-class StdContainer(Container):
-    def Format(self, indent=0):
-        # If I don't start a new I ignore indent
-        output = '<%s>' % self.tag
-        output = output + Container.Format(self, indent)
-        output = '%s</%s>' % (output, self.tag)
-        return output
-
-
-class QuotedContainer(Container):
-    def Format(self, indent=0):
-        # If I don't start a new I ignore indent
-        output = '<%s>%s</%s>' % (
-            self.tag,
-            Utils.websafe(Container.Format(self, indent)),
-            self.tag)
-        return output
-
-class Header(StdContainer):
-    def __init__(self, num, *items):
-        self.items = items
-        self.tag = 'h%d' % num
-
-class Address(StdContainer):
-    tag = 'address'
-
-class Underline(StdContainer):
-    tag = 'u'
-
-class Bold(StdContainer):
-    tag = 'strong'
-
-class Italic(StdContainer):
-    tag = 'em'
-
-class Preformatted(QuotedContainer):
-    tag = 'pre'
-
-class Subscript(StdContainer):
-    tag = 'sub'
-
-class Superscript(StdContainer):
-    tag = 'sup'
-
-class Strikeout(StdContainer):
-    tag = 'strike'
-
-class Center(StdContainer):
-    tag = 'center'
-
-class Form(Container):
-    def __init__(self, action='', method='POST', encoding=None,
-                       mlist=None, contexts=None, user=None, *items):
-        apply(Container.__init__, (self,) +  items)
-        self.action = action
-        self.method = method
-        self.encoding = encoding
-        self.mlist = mlist
-        self.contexts = contexts
-        self.user = user
-
-    def set_action(self, action):
-        self.action = action
-
-    def Format(self, indent=0):
-        spaces = ' ' * indent
-        encoding = ''
-        if self.encoding:
-            encoding = 'enctype="%s"' % self.encoding
-        output = '\n%s<FORM action="%s" method="%s" %s>\n' % (
-            spaces, self.action, self.method, encoding)
-        if self.mlist:
-            output = output + \
-                '<input type="hidden" name="csrf_token" value="%s">\n' \
-                % csrf_token(self.mlist, self.contexts, self.user)
-        output = output + Container.Format(self, indent+2)
-        output = '%s\n%s</FORM>\n' % (output, spaces)
-        return output
-
-
-class InputObj:
-    def __init__(self, name, ty, value, checked, **kws):
-        self.name = name
-        self.type = ty
-        self.value = value
-        self.checked = checked
-        self.kws = kws
-
-    def Format(self, indent=0):
-        charset = get_translation().charset() or 'us-ascii'
-        output = ['<INPUT name="%s" type="%s" value="%s"' %
-                  (self.name, self.type, self.value)]
-        for item in self.kws.items():
-            output.append('%s="%s"' % item)
-        if self.checked:
-            output.append('CHECKED')
-        output.append('>')
-        ret = SPACE.join(output)
-        if self.type == 'TEXT' and isinstance(ret, unicode):
-            ret = ret.encode(charset, 'xmlcharrefreplace')
-        return ret
-
-
-class SubmitButton(InputObj):
-    def __init__(self, name, button_text):
-        InputObj.__init__(self, name, "SUBMIT", button_text, checked=0)
-
-class PasswordBox(InputObj):
-    def __init__(self, name, value='', size=mm_cfg.TEXTFIELDWIDTH):
-        InputObj.__init__(self, name, "PASSWORD", value, checked=0, size=size)
-
-class TextBox(InputObj):
-    def __init__(self, name, value='', size=mm_cfg.TEXTFIELDWIDTH):
-        if isinstance(value, str):
-            safevalue = Utils.websafe(value)
-        else:
-            safevalue = value
-        InputObj.__init__(self, name, "TEXT", safevalue, checked=0, size=size)
-
-class Hidden(InputObj):
-    def __init__(self, name, value=''):
-        InputObj.__init__(self, name, 'HIDDEN', value, checked=0)
-
-class TextArea:
-    def __init__(self, name, text='', rows=None, cols=None, wrap='soft',
-                 readonly=0):
-        if isinstance(text, str):
-            # Double escape HTML entities in non-readonly areas.
-            doubleescape = not readonly
-            safetext = Utils.websafe(text, doubleescape)
-        else:
-            safetext = text
-        self.name = name
-        self.text = safetext
-        self.rows = rows
-        self.cols = cols
-        self.wrap = wrap
-        self.readonly = readonly
-
-    def Format(self, indent=0):
-        charset = get_translation().charset() or 'us-ascii'
-        output = '<TEXTAREA NAME=%s' % self.name
-        if self.rows:
-            output += ' ROWS=%s' % self.rows
-        if self.cols:
-            output += ' COLS=%s' % self.cols
-        if self.wrap:
-            output += ' WRAP=%s' % self.wrap
-        if self.readonly:
-            output += ' READONLY'
-        output += '>%s</TEXTAREA>' % self.text
-        if isinstance(output, unicode):
-            output = output.encode(charset, 'xmlcharrefreplace')
-        return output
-
-class FileUpload(InputObj):
-    def __init__(self, name, rows=None, cols=None, **kws):
-        apply(InputObj.__init__, (self, name, 'FILE', '', 0), kws)
-
-class RadioButton(InputObj):
-    def __init__(self, name, value, checked=0, **kws):
-        apply(InputObj.__init__, (self, name, 'RADIO', value, checked), kws)
-
-class CheckBox(InputObj):
-    def __init__(self, name, value, checked=0, **kws):
-        apply(InputObj.__init__, (self, name, "CHECKBOX", value, checked), kws)
-
-class VerticalSpacer:
-    def __init__(self, size=10):
-        self.size = size
-    def Format(self, indent=0):
-        output = '<spacer type="vertical" height="%d">' % self.size
-        return output
-
-class WidgetArray:
-    Widget = None
-
-    def __init__(self, name, button_names, checked, horizontal, values):
-        self.name = name
-        self.button_names = button_names
-        self.checked = checked
-        self.horizontal = horizontal
-        self.values = values
-        assert len(values) == len(button_names)
-        # Don't assert `checked' because for RadioButtons it is a scalar while
-        # for CheckedBoxes it is a vector.  Subclasses will assert length.
-
-    def ischecked(self, i):
-        raise NotImplemented
-
-    def Format(self, indent=0):
-        t = Table(cellspacing=5)
-        items = []
-        for i, name, value in zip(range(len(self.button_names)),
-                                  self.button_names,
-                                  self.values):
-            ischecked = (self.ischecked(i))
-            item = ('<label>' +
-                    self.Widget(self.name, value, ischecked).Format() +
-                    name + '</label>')
-            items.append(item)
-            if not self.horizontal:
-                t.AddRow(items)
-                items = []
-        if self.horizontal:
-            t.AddRow(items)
-        return t.Format(indent)
-
-class RadioButtonArray(WidgetArray):
-    Widget = RadioButton
-
-    def __init__(self, name, button_names, checked=None, horizontal=1,
-                 values=None):
-        if values is None:
-            values = range(len(button_names))
-        # BAW: assert checked is a scalar...
-        WidgetArray.__init__(self, name, button_names, checked, horizontal,
-                             values)
-
-    def ischecked(self, i):
-        return self.checked == i
-
-class CheckBoxArray(WidgetArray):
-    Widget = CheckBox
-
-    def __init__(self, name, button_names, checked=None, horizontal=0,
-                 values=None):
-        if checked is None:
-            checked = [0] * len(button_names)
-        else:
-            assert len(checked) == len(button_names)
-        if values is None:
-            values = range(len(button_names))
-        WidgetArray.__init__(self, name, button_names, checked, horizontal,
-                             values)
-
-    def ischecked(self, i):
-        return self.checked[i]
-
-class UnorderedList(Container):
-    def Format(self, indent=0):
-        spaces = ' ' * indent
-        output = '\n%s<ul>\n' % spaces
-        for item in self.items:
-            output = output + '%s<li>%s\n' % \
-                     (spaces, HTMLFormatObject(item, indent + 2))
-        output = output + '%s</ul>\n' % spaces
-        return output
-
-class OrderedList(Container):
-    def Format(self, indent=0):
-        spaces = ' ' * indent
-        output = '\n%s<ol>\n' % spaces
-        for item in self.items:
-            output = output + '%s<li>%s\n' % \
-                     (spaces, HTMLFormatObject(item, indent + 2))
-        output = output + '%s</ol>\n' % spaces
-        return output
-
-class DefinitionList(Container):
-    def Format(self, indent=0):
-        spaces = ' ' * indent
-        output = '\n%s<dl>\n' % spaces
-        for dt, dd in self.items:
-            output = output + '%s<dt>%s\n<dd>%s\n' % \
-                     (spaces, HTMLFormatObject(dt, indent+2),
-                      HTMLFormatObject(dd, indent+2))
-        output = output + '%s</dl>\n' % spaces
-        return output
-
-
-
-# Logo constants
-#
-# These are the URLs which the image logos link to.  The Mailman home page now
-# points at the gnu.org site instead of the www.list.org mirror.
-#
-from mm_cfg import MAILMAN_URL
-PYTHON_URL  = 'http://www.python.org/'
-GNU_URL     = 'http://www.gnu.org/'
-CUSTOM_URL  = '{{ mailman.custom_logo_url }}'
-
-# The names of the image logo files.  These are concatentated onto
-# mm_cfg.IMAGE_LOGOS (not urljoined).
-DELIVERED_BY = 'mailman.jpg'
-PYTHON_POWERED = 'PythonPowered.png'
-GNU_HEAD = 'gnu-head-tiny.jpg'
-CUSTOM_LOGO = '{{ mailman.custom_logo_name }}'
-
-
-def MailmanLogo():
-    t = Table(border=0, width='100%')
-
-    version = mm_cfg.VERSION
-    mmlink = _("Delivered by Mailman")
-    pylink = _("Python Powered")
-    gnulink = _("GNU's Not Unix")
-    customlink = _("{{ mailman.custom_logo_alt }}")
-    if mm_cfg.SITE_LINK:
-        sitelink = mm_cfg.SITE_TEXT
-
-    if mm_cfg.IMAGE_LOGOS:
-        def logo(file, alt, base=mm_cfg.IMAGE_LOGOS):
-            return '<img src="%s" alt="%s" border="0" />' % \
-              (base + file, alt)
-        mmlink = logo(DELIVERED_BY, mmlink)
-        pylink = logo(PYTHON_POWERED, pylink)
-        gnulink = logo(GNU_HEAD, gnulink)
-        customlink = logo(CUSTOM_LOGO, customlink)
-        if mm_cfg.SITE_LINK:
-            sitelink = logo(mm_cfg.SITE_LOGO, sitelink, "")
-
-    mmlink = Link(MAILMAN_URL, mmlink + _('<br>version %(version)s'))
-    pylink = Link(PYTHON_URL, pylink)
-    gnulink = Link(GNU_URL, gnulink)
-    customlink = Link(CUSTOM_URL, customlink)
-    links = [mmlink, pylink, gnulink, customlink]
-    if mm_cfg.SITE_LINK:
-        if mm_cfg.SITE_URL:
-            sitelink = Link(mm_cfg.SITE_URL, sitelink)
-        links.append(sitelink)
-    t.AddRow(links)
-    return t
-
-
-class SelectOptions:
-   def __init__(self, varname, values, legend,
-                selected=0, size=1, multiple=None):
-      self.varname  = varname
-      self.values   = values
-      self.legend   = legend
-      self.size     = size
-      self.multiple = multiple
-      # we convert any type to tuple, commas are needed
-      if not multiple:
-         if type(selected) == types.IntType:
-             self.selected = (selected,)
-         elif type(selected) == types.TupleType:
-             self.selected = (selected[0],)
-         elif type(selected) == types.ListType:
-             self.selected = (selected[0],)
-         else:
-             self.selected = (0,)
-
-   def Format(self, indent=0):
-      spaces = " " * indent
-      items  = min( len(self.values), len(self.legend) )
-
-      # jcrey: If there is no argument, we return nothing to avoid errors
-      if items == 0:
-          return ""
-
-      text = "\n" + spaces + "<Select name=\"%s\"" % self.varname
-      if self.size > 1:
-          text = text + " size=%d" % self.size
-      if self.multiple:
-          text = text + " multiple"
-      text = text + ">\n"
-
-      for i in range(items):
-          if i in self.selected:
-              checked = " Selected"
-          else:
-              checked = ""
-
-          opt = " <option value=\"%s\"%s> %s </option>" % (
-              self.values[i], checked, self.legend[i])
-          text = text + spaces + opt + "\n"
-
-      return text + spaces + '</Select>'
-- 
GitLab


From 90a6c623ede93680fc813cf06b501d6d959e3c31 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 28 Feb 2021 18:03:06 +0100
Subject: [PATCH 12/37] [mailman3] Use nginx role

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml                        | 52 +++++++++++++
 plays/mailman.yml                             |  2 +
 roles/mailman3/handlers/main.yml              |  5 --
 roles/mailman3/tasks/main.yml                 | 16 +---
 .../letsencrypt/conf.d/mailman.ini.j2         | 23 ------
 .../nginx/sites-available/mailman3.j2         | 76 -------------------
 .../nginx/sites-available/service.j2          |  4 +-
 7 files changed, 57 insertions(+), 121 deletions(-)
 delete mode 100644 roles/mailman3/templates/letsencrypt/conf.d/mailman.ini.j2
 delete mode 100644 roles/mailman3/templates/nginx/sites-available/mailman3.j2

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index d101e33b..f04dd88f 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -7,6 +7,58 @@ loc_certbot:
     certname: crans.org
     domains: "*.crans.org"
 
+loc_nginx:
+  service_name: mailman3
+  upstreams:
+    - name: mailman3
+      server: "unix:/run/mailman3-web/uwsgi.sock fail_timeout=0"
+  servers:
+    - ssl: false
+      server_name:
+        - "localhost"
+      locations:
+        - filter: "/"
+          params:
+            - "uwsgi_pass mailman3"
+            - "include /etc/nginx/uwsgi_params"
+
+    - ssl: crans.org
+      default: true
+      server_name:
+        - "mailman.crans.org"
+      locations:
+        - filter: "/"
+          params:
+            - "uwsgi_pass mailman3"
+            - "satisfy any"
+            - "allow 185.230.76.0/22"
+            - "allow 2a0c:700:0::/40"
+            - "deny all"
+            - "auth_basic \"On n'aime pas les spambots, donc on a mis un mot de passe. Le login est Stop et le mot de passe est Spam.\""
+            - "auth_basic_user_file /etc/nginx/passwd"
+            - "error_page 401 /error/401.html"
+
+        - filter: "/mailman3/static"
+          params:
+            - "alias /var/lib/mailman3/web/static"
+
+        - filter: "/mailman3/static/favicon.ico"
+          params:
+            - "alias /var/lib/mailman3/web/static/postorius/img/favicon.ico"
+
+        - filter: "/error/"
+          params:
+            - "internal"
+            - "alias /var/www/"
+
+        - filter: "/robots.txt"
+          params:
+            - "alias /var/www/robots.txt"
+
+  auth_passwd:
+    Stop: "$apr1$NXaV5H7Q$J3ora3Jo5h775Y1nm93PN1"  # Spam
+  deploy_robots_file: true
+
 glob_mailman3:
   site_owner: root@crans.org
   database:
diff --git a/plays/mailman.yml b/plays/mailman.yml
index 2182e778..ae0231f6 100755
--- a/plays/mailman.yml
+++ b/plays/mailman.yml
@@ -5,7 +5,9 @@
   vars:
     certbot: '{{ loc_certbot | default(glob_certbot | default([])) }}'
     mailman3: '{{ glob_mailman3 | default({}) | combine(loc_mailman3 | default({})) }}'
+    nginx: '{{ glob_nginx | default({}) | combine(loc_nginx | default({})) }}'
   roles:
     - certbot
+    - nginx
     - mailman3
     - postfix-mailman3
diff --git a/roles/mailman3/handlers/main.yml b/roles/mailman3/handlers/main.yml
index 01c64c13..cea84667 100644
--- a/roles/mailman3/handlers/main.yml
+++ b/roles/mailman3/handlers/main.yml
@@ -8,8 +8,3 @@
   service:
     name: mailman3-web
     state: restarted
-
-- name: Restart nginx
-  service:
-    name: nginx
-    state: restarted
diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 57ad9799..6c507eaa 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -7,7 +7,6 @@
     name:
       - dbconfig-no-thanks  # Do not autoconfigure database
       - mailman3-full
-      - nginx
       - postgresql
       - python3-pip  # CAS
       - python3-lxml  # CAS
@@ -54,21 +53,8 @@
     group: www-data
   notify: Restart mailman3-web
 
-- name: Configure nginx site
-  template:
-    src: nginx/sites-available/mailman3.j2
-    dest: /etc/nginx/sites-available/mailman3
-  notify: Restart nginx
-
-- name: Enable nginx site
-  file:
-    src: /etc/nginx/sites-available/mailman3
-    dest: /etc/nginx/sites-enabled/mailman3
-    state: link
-  notify: Restart nginx
-
 - name: Indicate role in motd
   template:
     src: update-motd.d/05-service.j2
-    dest: /etc/update-motd.d/04-mailman3
+    dest: /etc/update-motd.d/05-mailman3
     mode: 0755
diff --git a/roles/mailman3/templates/letsencrypt/conf.d/mailman.ini.j2 b/roles/mailman3/templates/letsencrypt/conf.d/mailman.ini.j2
deleted file mode 100644
index a5e63741..00000000
--- a/roles/mailman3/templates/letsencrypt/conf.d/mailman.ini.j2
+++ /dev/null
@@ -1,23 +0,0 @@
-{{ ansible_header | comment }}
-
-# To generate the certificate, please use the following command
-# certbot --config /etc/letsencrypt/conf.d/mailman.ini certonly
-
-# Use a 4096 bit RSA key instead of 2048
-rsa-key-size = 4096
-
-# Always use the staging/testing server
-# server = https://acme-staging.api.letsencrypt.org/directory
-
-# Uncomment and update to register with the specified e-mail address
-email = {{ mailman3.site_owner }}
-
-# Uncomment to use a text interface instead of ncurses
-text = True
-
-# Use DNS-01 challenge
-authenticator = nginx
-
-# Domains
-cert-name = mailman.crans.org
-domains = mailman.crans.org
diff --git a/roles/mailman3/templates/nginx/sites-available/mailman3.j2 b/roles/mailman3/templates/nginx/sites-available/mailman3.j2
deleted file mode 100644
index 2d664910..00000000
--- a/roles/mailman3/templates/nginx/sites-available/mailman3.j2
+++ /dev/null
@@ -1,76 +0,0 @@
-{{ ansible_header | comment }}
-
-upstream mailman3 {
-    server unix:/run/mailman3-web/uwsgi.sock fail_timeout=0;
-}
-
-# Local hyperkitty API
-server {
-    listen 80;
-    listen [::]:80;
-
-    server_name localhost;
-
-    location / {
-        uwsgi_pass mailman3;
-        include /etc/nginx/uwsgi_params;
-    }
-
-    # Log into separate log files
-    access_log /var/log/nginx/mailman3_access.log combined;
-    error_log /var/log/nginx/mailman3_error.log;
-}
-
-# Redirect http://mailman.crans.org to https://mailman.crans.org
-server {
-    listen 80;
-    listen [::]:80;
-
-    server_name mailman.crans.org;
-
-    location / {
-        return 302 https://$host$request_uri;
-    }
-}
-
-# Reverse proxify https://mailman.crans.org to UWSGI
-server {
-    listen 443 ssl http2;
-    listen [::]:443 ssl http2;
-
-    server_name mailman.crans.org;
-    server_tokens off;
-
-    # SSL common conf
-    ssl_certificate /etc/letsencrypt/live/crans.org/fullchain.pem;
-    ssl_certificate_key /etc/letsencrypt/live/crans.org/privkey.pem;
-    ssl_session_timeout 1d;
-    ssl_session_cache shared:MozSSL:10m;
-    ssl_session_tickets off;
-    ssl_dhparam /etc/letsencrypt/dhparam;
-    ssl_protocols TLSv1.2 TLSv1.3;
-    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
-    ssl_prefer_server_ciphers off;
-
-    # Enable OCSP Stapling, point to certificate chain
-    ssl_stapling on;
-    ssl_stapling_verify on;
-    ssl_trusted_certificate /etc/letsencrypt/live/crans.org/chain.pem;
-
-    location / {
-        uwsgi_pass mailman3;
-        include /etc/nginx/uwsgi_params;
-    }
-
-    location /mailman3/static {
-        alias /var/lib/mailman3/web/static;
-    }
-
-    location /mailman3/static/favicon.ico {
-        alias /var/lib/mailman3/web/static/postorius/img/favicon.ico;
-    }
-
-    # Log into separate log files
-    access_log /var/log/nginx/mailman3_access.log combined;
-    error_log /var/log/nginx/mailman3_error.log;
-}
diff --git a/roles/nginx/templates/nginx/sites-available/service.j2 b/roles/nginx/templates/nginx/sites-available/service.j2
index 297d069d..66c95249 100644
--- a/roles/nginx/templates/nginx/sites-available/service.j2
+++ b/roles/nginx/templates/nginx/sites-available/service.j2
@@ -91,8 +91,8 @@ server {
     listen [::]:443{% if server.default is defined and server.default %} default_server{% endif %} ssl;
     include "/etc/nginx/snippets/options-ssl.{{ server.ssl }}.conf";
     {% else -%}
-    listen 80 default;
-    listen [::]:80 default;
+    listen 80{% if server.default is defined and server.default %} default_server{% endif %};
+    listen [::]:80{% if server.default is defined and server.default %} default_server{% endif %};
     {% endif -%}
 
     server_name {{ server.server_name|join(" ") }};
-- 
GitLab


From f2a7114ecf294486ffc65a10088097d23be6ca69 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 28 Feb 2021 18:12:01 +0100
Subject: [PATCH 13/37] [mailman3] Install django-allauth-cas from PIP

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 6c507eaa..6d08eca8 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -1,6 +1,4 @@
 ---
-# You will need to do after: sudo pip3 install django-allauth-cas
-# Yes, it is horrible but we need Debian Python3 to see this django app.
 - name: Install mailman3
   apt:
     update_cache: true
@@ -16,10 +14,13 @@
   retries: 3
   until: apt_result is succeeded
 
+- name: Install django-allauth-cas from PIP
+  pip:
+    name: django-allauth-cas
+
 # You will need to setup postgres
 # sudo -u postgres createuser -P mailman3
 # sudo -u postgres createdb -O mailman3 mailman3
-# Test with: psql -U mailman3 -W -d mailman3 -h localhost
 - name: Configure mailman3
   template:
     src: "mailman3/{{ item }}.j2"
@@ -42,7 +43,6 @@
 # You will need to setup postgres
 # sudo -u postgres createuser -P mailman3web
 # sudo -u postgres createdb -O mailman3web mailman3web
-# Test with: psql -U mailman3web -W -d mailman3web -h localhost
 # Then migrate data: sudo /usr/share/mailman3-web/manage.py migrate
 - name: Configure mailman3-web
   template:
-- 
GitLab


From 20efa747fcf6a1198a199649d1d6da0065483c7f Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 28 Feb 2021 18:30:21 +0100
Subject: [PATCH 14/37] [mailman3] Don't deploy postgresql with mailman3

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 6d08eca8..0859be55 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -3,9 +3,7 @@
   apt:
     update_cache: true
     name:
-      - dbconfig-no-thanks  # Do not autoconfigure database
       - mailman3-full
-      - postgresql
       - python3-pip  # CAS
       - python3-lxml  # CAS
       - sassc
-- 
GitLab


From 8a0bb4401da1077b17850c1ed098cf8bcccbabe5 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 28 Feb 2021 18:43:13 +0100
Subject: [PATCH 15/37] [mailman3] Missing nginx parameter

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index f04dd88f..5e941314 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -30,6 +30,7 @@ loc_nginx:
         - filter: "/"
           params:
             - "uwsgi_pass mailman3"
+            - "include /etc/nginx/uwsgi_params"
             - "satisfy any"
             - "allow 185.230.76.0/22"
             - "allow 2a0c:700:0::/40"
-- 
GitLab


From 81ded3ea46e380971a0b07fe71068c5825d011a9 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 1 Mar 2021 14:36:45 +0100
Subject: [PATCH 16/37] [mailman3] Mailman is reverse-proxyfied

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml              | 2 +-
 group_vars/reverseproxy.yml         | 2 +-
 host_vars/mailman.adm.crans.org.yml | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index 5e941314..011cc736 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -22,7 +22,7 @@ loc_nginx:
             - "uwsgi_pass mailman3"
             - "include /etc/nginx/uwsgi_params"
 
-    - ssl: crans.org
+    - ssl: false
       default: true
       server_name:
         - "mailman.crans.org"
diff --git a/group_vars/reverseproxy.yml b/group_vars/reverseproxy.yml
index 734bc323..6e2aa801 100644
--- a/group_vars/reverseproxy.yml
+++ b/group_vars/reverseproxy.yml
@@ -43,7 +43,7 @@ glob_reverseproxy:
     - {from: owncloud.crans.org, to: 172.16.10.136}
     - {from: linx.crans.org, to: "172.16.10.119:8080"}
     - {from: belenios.crans.org, to: 172.16.10.111}
-    # - {from: mailman.crans.org, to: 10.231.136.180}
+    - {from: mailman.crans.org, to: 172.16.10.110}
 
     # Zamok
     - {from: perso.crans.org, to: 172.16.10.31}
diff --git a/host_vars/mailman.adm.crans.org.yml b/host_vars/mailman.adm.crans.org.yml
index c6f8791b..2eb6f993 100644
--- a/host_vars/mailman.adm.crans.org.yml
+++ b/host_vars/mailman.adm.crans.org.yml
@@ -1,4 +1,4 @@
 ---
 interfaces:
   adm: eth0
-  srv: eth1
+  srv_nat: eth1
-- 
GitLab


From 79ae6fa60a01dfe07152550e4d418950a4192014 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 1 Mar 2021 14:55:55 +0100
Subject: [PATCH 17/37] [mailman3] Update postfix configuration of Redisdead

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/postfix/templates/postfix/main.cf.j2   | 15 +++------------
 roles/postfix/templates/postfix/master.cf.j2 |  5 -----
 roles/postfix/templates/postfix/transport.j2 |  6 ++----
 3 files changed, 5 insertions(+), 21 deletions(-)

diff --git a/roles/postfix/templates/postfix/main.cf.j2 b/roles/postfix/templates/postfix/main.cf.j2
index fabff795..8605c235 100644
--- a/roles/postfix/templates/postfix/main.cf.j2
+++ b/roles/postfix/templates/postfix/main.cf.j2
@@ -20,21 +20,12 @@ mynetworks = 127.0.0.0/8, [::1]/128
 # Destinations acceptees
 mydestination = {{ ansible_hostname }}, $myhostname, localhost, localhost.$mydomain
 {% if postfix.primary or not postfix.secondary %}
-                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu
+                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu, lists.crans.org
 {% endif %}
 # Domaine relaye par ce MX
 relay_domains = $mydestination
-{% if postfix.mailman or postfix.public %}
-                lists.$mydomain
-{% endif %}
 {% if postfix.secondary %}
-                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu
-{% endif %}
-{% if postfix.mailman %}
-relay_recipient_maps =
-    hash:/var/local/re2o-services/mail-server/generated/virtual
-    hash:/var/lib/mailman/data/virtual-mailman
-mailman_destination_recipient_limit = 1
+                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu, lists.crans.org
 {% endif %}
 # Etre notifie ou non de l'arrive de nouveaux mails
 {% if postfix.primary or postfix.secondary %}
@@ -48,7 +39,6 @@ biff = yes
 # il faut enlever ca.
 soft_bounce = no
 
-smtpd_reject_unlisted_sender = yes
 {% if not postfix.primary and not postfix.secondary %}
 # On delivre dans des maildir
 mail_spool_directory = /home/mail/
@@ -151,6 +141,7 @@ smtpd_sender_restrictions = permit_mynetworks
 {% endif %}
                             reject_non_fqdn_sender
                             reject_unknown_sender_domain
+                            reject_unlisted_sender
 
 ## Dit à postfix de jeter toute socket vers un serveur de policy après une
 ## utilisation. Il en recrée donc une nouvelle, ce qui permet d'éviter
diff --git a/roles/postfix/templates/postfix/master.cf.j2 b/roles/postfix/templates/postfix/master.cf.j2
index 909bbee8..04ddafd7 100644
--- a/roles/postfix/templates/postfix/master.cf.j2
+++ b/roles/postfix/templates/postfix/master.cf.j2
@@ -140,8 +140,3 @@ scalemail-backend unix -   n   n   -   2   pipe
   flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store $${nexthop} $${user} $${extension}
 # only used by postfix-tls
 tlsmgr    unix  -       -       n       300     1       tlsmgr
-{% if postfix.mailman %}
-mailman   unix  -       n       n       -       -       pipe
-      flags=FR user=list
-      argv=/var/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
-{% endif %}
diff --git a/roles/postfix/templates/postfix/transport.j2 b/roles/postfix/templates/postfix/transport.j2
index 77e92b2b..954c3b01 100644
--- a/roles/postfix/templates/postfix/transport.j2
+++ b/roles/postfix/templates/postfix/transport.j2
@@ -2,10 +2,8 @@
 # Transport des mails
 
 {% if postfix.mailman %}
-# Les mailing-listes sont delivrees localement
-lists.crans.org              mailman:
-{% else %}
-lists.crans.org              smtp:[lists.adm.crans.org]
+# Les mailing-listes sont delivrees sur un serveur à part
+lists.crans.org              smtp:[{{ query('ldap', 'ip', 'mailman', 'adm') | ipv4 | first }}]
 {% endif %}
 {% if postfix.primary or postfix.secondary %}
 # C'est le serveur des adherents qui fait les livraisons des
-- 
GitLab


From ee31feffe9aa230664e0835773670848205a1fb4 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 1 Mar 2021 17:57:55 +0100
Subject: [PATCH 18/37] [mailman3] Add mailman-web shortcut for Django
 interaction

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 0859be55..deefe6dc 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -51,6 +51,12 @@
     group: www-data
   notify: Restart mailman3-web
 
+- name: Add symlink for mailman3-web
+  file:
+    src: /usr/share/mailman3-web/manage.py
+    dest: /usr/local/bin/mailman-web
+    state: link
+
 - name: Indicate role in motd
   template:
     src: update-motd.d/05-service.j2
-- 
GitLab


From 95d6086863810887ee229ef01cbdced3e9a5e2a2 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 1 Mar 2021 18:13:19 +0100
Subject: [PATCH 19/37] [mailman3] Automatically apply migrations and compress
 static files

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index deefe6dc..f71d8803 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -41,7 +41,6 @@
 # You will need to setup postgres
 # sudo -u postgres createuser -P mailman3web
 # sudo -u postgres createdb -O mailman3web mailman3web
-# Then migrate data: sudo /usr/share/mailman3-web/manage.py migrate
 - name: Configure mailman3-web
   template:
     src: mailman3/mailman-web.py.j2
@@ -57,6 +56,18 @@
     dest: /usr/local/bin/mailman-web
     state: link
 
+- name: Migrate Django database
+  django_manage:
+    command: migrate
+    project_path: /usr/share/mailman3-web
+  notify: Restart mailman3-web
+
+- name: Compress static files
+  django_manage:
+    command: compress
+    project_path: /usr/share/mailman3-web
+  notify: Restart mailman3-web
+
 - name: Indicate role in motd
   template:
     src: update-motd.d/05-service.j2
-- 
GitLab


From 5c939e45e31de423b6ae703c260393b0f9b9af20 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 1 Mar 2021 18:14:54 +0100
Subject: [PATCH 20/37] [mailman3] IPython is pretty

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index f71d8803..43b7c332 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -4,6 +4,7 @@
     update_cache: true
     name:
       - mailman3-full
+      - python3-ipython  # Prettier shell
       - python3-pip  # CAS
       - python3-lxml  # CAS
       - sassc
-- 
GitLab


From d8f6d333f37ab46a9e680fb06d6ff97062d7d445 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 1 Mar 2021 19:39:44 +0100
Subject: [PATCH 21/37] [mailman3] Update 401 error for mailman

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index 011cc736..e7fca996 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -50,7 +50,7 @@ loc_nginx:
         - filter: "/error/"
           params:
             - "internal"
-            - "alias /var/www/"
+            - "alias /var/www/html/"
 
         - filter: "/robots.txt"
           params:
-- 
GitLab


From ef172cbf49c548302ff2de877c12daac24efe64a Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Tue, 2 Mar 2021 08:51:00 +0100
Subject: [PATCH 22/37] [Mailman3] Collect static files

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 43b7c332..3592dceb 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -63,6 +63,12 @@
     project_path: /usr/share/mailman3-web
   notify: Restart mailman3-web
 
+- name: Collect static files
+  django_manage:
+    command: collectstatic
+    project_path: /usr/share/mailman3-web
+  notify: Restart mailman3-web
+
 - name: Compress static files
   django_manage:
     command: compress
-- 
GitLab


From ae4aa2b9e2336f084d26f1d2bf564079ce07811d Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Tue, 2 Mar 2021 11:15:15 +0100
Subject: [PATCH 23/37] [mailman3] Mailman 3 is translated under Bullseye

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/templates/mailman3/mailman-web.py.j2 | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/roles/mailman3/templates/mailman3/mailman-web.py.j2 b/roles/mailman3/templates/mailman3/mailman-web.py.j2
index 2a09d209..81e856a2 100644
--- a/roles/mailman3/templates/mailman3/mailman-web.py.j2
+++ b/roles/mailman3/templates/mailman3/mailman-web.py.j2
@@ -203,12 +203,3 @@ COMPRESS_PRECOMPILERS = (
 COMPRESS_OFFLINE = True
 
 POSTORIUS_TEMPLATE_BASE_URL = 'http://localhost/mailman3/'
-
-# Add translations, this will be useless in Debian Bullseye
-LANGUAGES = [
-    ('en', 'English'),
-    ('fr', 'Français'),
-]
-LOCALE_PATHS = [
-    '/etc/mailman3/locale',
-]
-- 
GitLab


From 07ab008447bc7ce94c18e445cc67d8f93d32910b Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Wed, 3 Mar 2021 11:37:15 +0100
Subject: [PATCH 24/37] [mailman3] Run django-admin commands as www-data

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 3592dceb..181cbc19 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -61,18 +61,24 @@
   django_manage:
     command: migrate
     project_path: /usr/share/mailman3-web
+  become: true
+  become_user: www-data
   notify: Restart mailman3-web
 
 - name: Collect static files
   django_manage:
     command: collectstatic
     project_path: /usr/share/mailman3-web
+  become: true
+  become_user: www-data
   notify: Restart mailman3-web
 
 - name: Compress static files
   django_manage:
     command: compress
     project_path: /usr/share/mailman3-web
+  become: true
+  become_user: www-data
   notify: Restart mailman3-web
 
 - name: Indicate role in motd
-- 
GitLab


From b085b774ad5c5aa99da35b12fce27af78dc85e1e Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 7 Mar 2021 19:07:40 +0100
Subject: [PATCH 25/37] [mailman] variable postfix.mailman is now useless

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 host_vars/boeing.adm.crans.org.yml           | 1 -
 host_vars/redisdead.adm.crans.org.yml        | 1 -
 host_vars/sputnik.adm.crans.org.yml          | 1 -
 roles/postfix/templates/postfix/transport.j2 | 4 +---
 4 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/host_vars/boeing.adm.crans.org.yml b/host_vars/boeing.adm.crans.org.yml
index fe9d1c69..882cb80d 100644
--- a/host_vars/boeing.adm.crans.org.yml
+++ b/host_vars/boeing.adm.crans.org.yml
@@ -7,5 +7,4 @@ postfix:
   secondary: true
   public: true
   dkim: true
-  mailman: false
   titanic: true
diff --git a/host_vars/redisdead.adm.crans.org.yml b/host_vars/redisdead.adm.crans.org.yml
index 8228a1d0..999c2eb4 100644
--- a/host_vars/redisdead.adm.crans.org.yml
+++ b/host_vars/redisdead.adm.crans.org.yml
@@ -8,7 +8,6 @@ postfix:
   secondary: false
   public: true
   dkim: true
-  mailman: true
   titanic: false
 
 to_backup:
diff --git a/host_vars/sputnik.adm.crans.org.yml b/host_vars/sputnik.adm.crans.org.yml
index 7e6ff41c..0ad18335 100644
--- a/host_vars/sputnik.adm.crans.org.yml
+++ b/host_vars/sputnik.adm.crans.org.yml
@@ -4,7 +4,6 @@ postfix:
   secondary: true
   public: true
   dkim: true
-  mailman: false
   titanic: false
 
 to_backup:
diff --git a/roles/postfix/templates/postfix/transport.j2 b/roles/postfix/templates/postfix/transport.j2
index 954c3b01..87cd249d 100644
--- a/roles/postfix/templates/postfix/transport.j2
+++ b/roles/postfix/templates/postfix/transport.j2
@@ -1,11 +1,9 @@
 {{ ansible_header | comment }}
 # Transport des mails
 
-{% if postfix.mailman %}
+{% if postfix.primary or postfix.secondary %}
 # Les mailing-listes sont delivrees sur un serveur à part
 lists.crans.org              smtp:[{{ query('ldap', 'ip', 'mailman', 'adm') | ipv4 | first }}]
-{% endif %}
-{% if postfix.primary or postfix.secondary %}
 # C'est le serveur des adherents qui fait les livraisons des
 # adresses clubs et adherents
 crans.org                    smtp:[users.adm.crans.org]
-- 
GitLab


From e242818ae9f895c109220156752df91a72c22eba Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 7 Mar 2021 19:08:45 +0100
Subject: [PATCH 26/37] [mailman/certbot] Certbot is already generating a
 wildcard certificate

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index e7fca996..842f513d 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -1,12 +1,4 @@
 ---
-loc_certbot:
-  - dns_rfc2136_server: '172.16.10.147'
-    dns_rfc2136_name: certbot_challenge.
-    dns_rfc2136_secret: "{{ vault.certbot_dns_secret }}"
-    mail: root@crans.org
-    certname: crans.org
-    domains: "*.crans.org"
-
 loc_nginx:
   service_name: mailman3
   upstreams:
-- 
GitLab


From 77d292713fc6ab5a37f4fe8c8cc19e872fc8ac7d Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 7 Mar 2021 19:16:44 +0100
Subject: [PATCH 27/37] [mailman] Use multiple domains for mailman-web

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml                              | 4 +++-
 roles/mailman3/templates/mailman3/mailman-web.py.j2 | 6 +++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index 842f513d..19a39300 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -74,6 +74,8 @@ glob_mailman3:
   restadmin_pass: "{{ vault.mailman3_restadmin_pass }}"
   archiver_key: "{{ vault.mailman3_archiver_key }}"
   web_secret_key: "{{ vault.mailman3_web_secret_key }}"
-  web_domain: "mailman.crans.org"
+  web_domains:
+    - "mailman.crans.org"
+    - "lists.crans.org"
   default_domain: "crans.org"
   postfix_domain: "crans.org"
diff --git a/roles/mailman3/templates/mailman3/mailman-web.py.j2 b/roles/mailman3/templates/mailman3/mailman-web.py.j2
index 81e856a2..1d0c46f8 100644
--- a/roles/mailman3/templates/mailman3/mailman-web.py.j2
+++ b/roles/mailman3/templates/mailman3/mailman-web.py.j2
@@ -16,9 +16,9 @@ ADMINS = (
 # is meant to run behind a webserver reverse proxy anyway.
 ALLOWED_HOSTS = [
     "localhost",  # Archiving API from Mailman, keep it.
-    "{{ mailman3.web_domain }}",
-    # Add here all production URLs you may have.
-    #'*'
+{% for domain in mailman3.web_domains %}
+    "{{ domain }}",
+{% endfor %}
 ]
 
 # Mailman API credentials
-- 
GitLab


From e9f1cf265b39481d4ce671caecd1d62465014fad Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 8 Mar 2021 15:23:39 +0100
Subject: [PATCH 28/37] [mailman] Install dedicated modules instead of sourcing
 them from /usr/scripts

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml                       | 7 +++++--
 roles/mailman3/templates/mailman3/mailman-web.py.j2 | 6 +-----
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index 181cbc19..f73b5800 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -13,9 +13,12 @@
   retries: 3
   until: apt_result is succeeded
 
-- name: Install django-allauth-cas from PIP
+- name: Install Crans python modules
   pip:
-    name: django-allauth-cas
+    name: "{{ item }}"
+  loop:
+    - git+https://gitlab.crans.org/nounous/mailman-crans-theme.git
+    - git+https://gitlab.crans.org/nounous/allauth-cas-crans.git
 
 # You will need to setup postgres
 # sudo -u postgres createuser -P mailman3
diff --git a/roles/mailman3/templates/mailman3/mailman-web.py.j2 b/roles/mailman3/templates/mailman3/mailman-web.py.j2
index 1d0c46f8..2f201cfb 100644
--- a/roles/mailman3/templates/mailman3/mailman-web.py.j2
+++ b/roles/mailman3/templates/mailman3/mailman-web.py.j2
@@ -30,12 +30,8 @@ MAILMAN_ARCHIVER_FROM = ('127.0.0.1', '::1')
 
 # Application definition
 
-# Add allauth_cas_crans path
-import sys
-sys.path.insert(0, "/usr/scripts/mailman")
-
 INSTALLED_APPS = (
-    'mailman_theme_crans',  # override templates
+    'mailman_crans_theme',  # override templates
     'hyperkitty',
     'postorius',
     'django_mailman3',
-- 
GitLab


From 6c038c10b4f35579c706cefda0c8912759e0ed81 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Tue, 9 Mar 2021 13:42:31 +0100
Subject: [PATCH 29/37] [mailman] Symlink mailman-web is included in latest
 version

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/mailman3/tasks/main.yml | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/roles/mailman3/tasks/main.yml b/roles/mailman3/tasks/main.yml
index f73b5800..b6f84d9a 100644
--- a/roles/mailman3/tasks/main.yml
+++ b/roles/mailman3/tasks/main.yml
@@ -54,12 +54,6 @@
     group: www-data
   notify: Restart mailman3-web
 
-- name: Add symlink for mailman3-web
-  file:
-    src: /usr/share/mailman3-web/manage.py
-    dest: /usr/local/bin/mailman-web
-    state: link
-
 - name: Migrate Django database
   django_manage:
     command: migrate
-- 
GitLab


From 84cb6585d24e7beff49a369ea21f55177a7233b4 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Thu, 25 Mar 2021 11:26:38 +0100
Subject: [PATCH 30/37] [mailman] Mailman has a public IP

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml              | 2 +-
 host_vars/mailman.adm.crans.org.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index 19a39300..8d50c9d9 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -17,7 +17,7 @@ loc_nginx:
     - ssl: false
       default: true
       server_name:
-        - "mailman.crans.org"
+        - "lists.crans.org"
       locations:
         - filter: "/"
           params:
diff --git a/host_vars/mailman.adm.crans.org.yml b/host_vars/mailman.adm.crans.org.yml
index 2eb6f993..c6f8791b 100644
--- a/host_vars/mailman.adm.crans.org.yml
+++ b/host_vars/mailman.adm.crans.org.yml
@@ -1,4 +1,4 @@
 ---
 interfaces:
   adm: eth0
-  srv_nat: eth1
+  srv: eth1
-- 
GitLab


From abbfd96a376c0abf1a8670129413b16e91c761cb Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Thu, 25 Mar 2021 11:29:05 +0100
Subject: [PATCH 31/37] [mailman] Mailman is relayed

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 roles/postfix/templates/postfix/main.cf.j2 | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/roles/postfix/templates/postfix/main.cf.j2 b/roles/postfix/templates/postfix/main.cf.j2
index 8605c235..091677c8 100644
--- a/roles/postfix/templates/postfix/main.cf.j2
+++ b/roles/postfix/templates/postfix/main.cf.j2
@@ -20,12 +20,13 @@ mynetworks = 127.0.0.0/8, [::1]/128
 # Destinations acceptees
 mydestination = {{ ansible_hostname }}, $myhostname, localhost, localhost.$mydomain
 {% if postfix.primary or not postfix.secondary %}
-                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu, lists.crans.org
+                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu
 {% endif %}
 # Domaine relaye par ce MX
 relay_domains = $mydestination
+                lists.$mydomain
 {% if postfix.secondary %}
-                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu, lists.crans.org
+                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu
 {% endif %}
 # Etre notifie ou non de l'arrive de nouveaux mails
 {% if postfix.primary or postfix.secondary %}
-- 
GitLab


From c3cd94f6e67c1c79e62270c4427a81282dd4d9e0 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Thu, 25 Mar 2021 16:54:12 +0100
Subject: [PATCH 32/37] [opendkim] Pepcransification

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/opendkim.yml                       | 21 +++++++++++++++++++
 hosts                                         | 18 +++++++++-------
 plays/mailman.yml                             |  2 ++
 plays/postfix.yml                             |  3 +--
 roles/opendkim/tasks/main.yml                 | 10 ++++-----
 roles/opendkim/templates/opendkim/KeyTable.j2 |  2 +-
 .../templates/opendkim/SigningTable.j2        |  5 +++--
 .../opendkim/keys/crans.org/mail.txt.j2       |  1 -
 .../mail.private.j2 => key.private.j2}        |  0
 .../templates/opendkim/keys/key.txt.j2        |  1 +
 .../templates/postfix/main.cf.j2              |  4 ++++
 11 files changed, 49 insertions(+), 18 deletions(-)
 create mode 100644 group_vars/opendkim.yml
 delete mode 100644 roles/opendkim/templates/opendkim/keys/crans.org/mail.txt.j2
 rename roles/opendkim/templates/opendkim/keys/{crans.org/mail.private.j2 => key.private.j2} (100%)
 create mode 100644 roles/opendkim/templates/opendkim/keys/key.txt.j2

diff --git a/group_vars/opendkim.yml b/group_vars/opendkim.yml
new file mode 100644
index 00000000..d69a6b5d
--- /dev/null
+++ b/group_vars/opendkim.yml
@@ -0,0 +1,21 @@
+---
+glob_opendkim:
+  domain: "crans.org"
+  selector: "mail"
+  signing:
+    - "*@crans.org"
+    - "*@crans.fr"
+    - "*@crans.eu"
+  trust:
+    - "185.230.79.0/26"
+    - "172.16.3.0/24"
+    - "172.16.10.0/24"
+    - "2a0c:700:0:2::/64"
+    - "2a0c:700:0:3::/64"
+    - "2a0c:700:0:10::/64"
+    - "*@crans.org"
+    - "*@crans.fr"
+    - "*@crans.eu"
+  txt_record: |
+    mail._domainkey IN TXT "v=DKIM1; k=rsa; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtwkNVd9Mmz8S4WcfuPk0X2drG39gS8+uxAv8igRILgzWeN8j2hjeZesl8pm/1UTVU87bYcdfUgXiGfQy9nR5p/Vmt2kS7sXk9nsJ/VYENgb3IJQ6paWupSTFMyeKycJ4ZHCEZB/bVvifoG6vLKqW5jpsfCiOcfdcgXATn0UPuVx9t93yRrhoEMntMv9TSodjqd3FKCtJUoh5cNQHo0T6dWKtxoIgNi/mvZ92D/IACwu/XOU+Rq9fnoEI8GukBQUR5AkP0B/JrvwWXWX/3EjY8X37ljEX0XUdq/ShzTl5iK+CM83stgkFUQh/rpww5mnxYEW3X4uirJ7VJHmY4KPoIU+2DPjLQj9Hz63CMWY3Ks2pXWzxD3V+GI1aJTMFOv2LeHnI3ScqFaKj9FR4ZKMb0OW2BEFBIY3J3aeo/paRwdbVCMM7twDtZY9uInR/NhVa1v9hlOxwp4/2pGSKQYoN2CkAZ1Alzwf8M3EONLKeiC43JLYwKH1uBB1oikSVhMnLjG0219XvfG/tphyoOqJR/bCc2rdv5pLwKUl4wVuygfpvOw12bcvnTfYuk/BXzVHg9t4H8k/DJR6GAoeNAapXIS8AfAScF8QdKfplhKLJyQGJ6lQ75YD9IwRAN0oV+8NTjl46lI/C+b7mpfXCew+p6YPwfNvV2shiR0Ez8ZGUQIcCAwEAAQ==" ; ----- DKIM key mail for crans.org
+  private_key: "{{ vault.opendkim_private_key }}"
diff --git a/hosts b/hosts
index 58e24a4a..30e139d5 100644
--- a/hosts
+++ b/hosts
@@ -79,13 +79,6 @@ jitsi.adm.crans.org
 [keepalived:children]
 routeurs_vm
 
-[slapd]
-tealc.adm.crans.org
-sam.adm.crans.org
-daniel.adm.crans.org
-jack.adm.crans.org
-sputnik.adm.crans.org
-
 [linx]
 linx.adm.crans.org
 
@@ -111,6 +104,10 @@ wiki
 charybde.adm.crans.org
 # silice.adm.crans.org
 
+[opendkim:children]
+mailman
+postfix
+
 [postfix]
 redisdead.adm.crans.org
 zamok.adm.crans.org
@@ -143,6 +140,13 @@ routeur-daniel.adm.crans.org
 routeur-jack.adm.crans.org
 routeur-sam.adm.crans.org
 
+[slapd]
+tealc.adm.crans.org
+sam.adm.crans.org
+daniel.adm.crans.org
+jack.adm.crans.org
+sputnik.adm.crans.org
+
 [thelounge]
 irc.adm.crans.org
 zamok.adm.crans.org
diff --git a/plays/mailman.yml b/plays/mailman.yml
index ae0231f6..45fb45e3 100755
--- a/plays/mailman.yml
+++ b/plays/mailman.yml
@@ -6,8 +6,10 @@
     certbot: '{{ loc_certbot | default(glob_certbot | default([])) }}'
     mailman3: '{{ glob_mailman3 | default({}) | combine(loc_mailman3 | default({})) }}'
     nginx: '{{ glob_nginx | default({}) | combine(loc_nginx | default({})) }}'
+    opendkim: '{{ loc_opendkim | default(glob_opendkim | default([])) }}'
   roles:
     - certbot
     - nginx
     - mailman3
     - postfix-mailman3
+    - opendkim
diff --git a/plays/postfix.yml b/plays/postfix.yml
index 0a76001c..6750239d 100755
--- a/plays/postfix.yml
+++ b/plays/postfix.yml
@@ -12,8 +12,7 @@
         domains: "*.crans.org"
     bind:
       masters: "{{ lookup('re2oapi', 'get_role', 'dns-authoritary-master')[0] }}"
-    opendkim:
-        private_key: "{{ vault.opendkim_private_key }}"
+    opendkim: "{{ glob_opendkim | default({}) | combine(loc_opendkim | default({})) }}"
     policyd:
       mail: root@crans.org
       exemptions: "{{ lookup('re2oapi', 'get_role', 'user-server')[0] }}"
diff --git a/roles/opendkim/tasks/main.yml b/roles/opendkim/tasks/main.yml
index 6488bdb7..0278c4ef 100644
--- a/roles/opendkim/tasks/main.yml
+++ b/roles/opendkim/tasks/main.yml
@@ -11,7 +11,7 @@
 
 - name: Ensure opendkim directories are here
   file:
-    path: /etc/opendkim/keys/crans.org
+    path: "/etc/opendkim/keys/{{ opendkim.domain }}"
     state: directory
     mode: 0750
     owner: opendkim
@@ -40,11 +40,11 @@
 
 - name: Deploy opendkim key
   template:
-    src: opendkim/keys/crans.org/{{ item }}.j2
-    dest: /etc/opendkim/keys/crans.org/{{ item }}
+    src: "opendkim/keys/key.{{ item }}.j2"
+    dest: "/etc/opendkim/keys/{{ opendkim.domain }}/{{ opendkim.selector }}.{{ item }}"
     mode: 0600
     owner: opendkim
     group: opendkim
   loop:
-    - mail.private
-    - mail.txt
+    - "private"
+    - "txt"
diff --git a/roles/opendkim/templates/opendkim/KeyTable.j2 b/roles/opendkim/templates/opendkim/KeyTable.j2
index 86ffcee4..f2d56ada 100644
--- a/roles/opendkim/templates/opendkim/KeyTable.j2
+++ b/roles/opendkim/templates/opendkim/KeyTable.j2
@@ -1 +1 @@
-mail._domainkey.crans.org crans.org:mail:/etc/opendkim/keys/crans.org/mail.private
+{{ opendkim.selector }}._domainkey.{{ opendkim.domain }} {{ opendkim.domain }}:{{ opendkim.selector }}:/etc/opendkim/keys/{{ opendkim.domain }}/{{ opendkim.selector }}.private
diff --git a/roles/opendkim/templates/opendkim/SigningTable.j2 b/roles/opendkim/templates/opendkim/SigningTable.j2
index d845dc68..fdbc834b 100644
--- a/roles/opendkim/templates/opendkim/SigningTable.j2
+++ b/roles/opendkim/templates/opendkim/SigningTable.j2
@@ -1,2 +1,3 @@
-*@crans.org mail._domainkey.crans.org
-*@crans.eu  mail._domainkey.crans.org
+{% for pattern in opendkim.signing %}
+{{ pattern }} {{ opendkim.selector }}._domainkey.{{ opendkim.domain }}
+{% endfor %}
diff --git a/roles/opendkim/templates/opendkim/keys/crans.org/mail.txt.j2 b/roles/opendkim/templates/opendkim/keys/crans.org/mail.txt.j2
deleted file mode 100644
index 9a787ee1..00000000
--- a/roles/opendkim/templates/opendkim/keys/crans.org/mail.txt.j2
+++ /dev/null
@@ -1 +0,0 @@
-mail._domainkey IN TXT "v=DKIM1; k=rsa; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtwkNVd9Mmz8S4WcfuPk0X2drG39gS8+uxAv8igRILgzWeN8j2hjeZesl8pm/1UTVU87bYcdfUgXiGfQy9nR5p/Vmt2kS7sXk9nsJ/VYENgb3IJQ6paWupSTFMyeKycJ4ZHCEZB/bVvifoG6vLKqW5jpsfCiOcfdcgXATn0UPuVx9t93yRrhoEMntMv9TSodjqd3FKCtJUoh5cNQHo0T6dWKtxoIgNi/mvZ92D/IACwu/XOU+Rq9fnoEI8GukBQUR5AkP0B/JrvwWXWX/3EjY8X37ljEX0XUdq/ShzTl5iK+CM83stgkFUQh/rpww5mnxYEW3X4uirJ7VJHmY4KPoIU+2DPjLQj9Hz63CMWY3Ks2pXWzxD3V+GI1aJTMFOv2LeHnI3ScqFaKj9FR4ZKMb0OW2BEFBIY3J3aeo/paRwdbVCMM7twDtZY9uInR/NhVa1v9hlOxwp4/2pGSKQYoN2CkAZ1Alzwf8M3EONLKeiC43JLYwKH1uBB1oikSVhMnLjG0219XvfG/tphyoOqJR/bCc2rdv5pLwKUl4wVuygfpvOw12bcvnTfYuk/BXzVHg9t4H8k/DJR6GAoeNAapXIS8AfAScF8QdKfplhKLJyQGJ6lQ75YD9IwRAN0oV+8NTjl46lI/C+b7mpfXCew+p6YPwfNvV2shiR0Ez8ZGUQIcCAwEAAQ==" ; ----- DKIM key mail for crans.org
diff --git a/roles/opendkim/templates/opendkim/keys/crans.org/mail.private.j2 b/roles/opendkim/templates/opendkim/keys/key.private.j2
similarity index 100%
rename from roles/opendkim/templates/opendkim/keys/crans.org/mail.private.j2
rename to roles/opendkim/templates/opendkim/keys/key.private.j2
diff --git a/roles/opendkim/templates/opendkim/keys/key.txt.j2 b/roles/opendkim/templates/opendkim/keys/key.txt.j2
new file mode 100644
index 00000000..8c6fc1cf
--- /dev/null
+++ b/roles/opendkim/templates/opendkim/keys/key.txt.j2
@@ -0,0 +1 @@
+{{ opendkim.txt_record }}
diff --git a/roles/postfix-mailman3/templates/postfix/main.cf.j2 b/roles/postfix-mailman3/templates/postfix/main.cf.j2
index 5dc3a1ec..5e1e6b36 100644
--- a/roles/postfix-mailman3/templates/postfix/main.cf.j2
+++ b/roles/postfix-mailman3/templates/postfix/main.cf.j2
@@ -22,6 +22,10 @@ smtpd_use_tls=yes
 smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
 smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
 
+# OpenDKIM
+smtpd_milters = inet:localhost:12301
+non_smtpd_milters = inet:localhost:12301
+
 # See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
 # information on enabling SSL in the smtp client.
 
-- 
GitLab


From 1785d7f095ceb04084faba15d18058f722ffd78e Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Thu, 25 Mar 2021 17:24:59 +0100
Subject: [PATCH 33/37] [mailman] Setup DKIM configuration

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml                           | 16 ++++++++++------
 plays/mailman.yml                                |  2 +-
 .../templates/mailman3/mailman-web.py.j2         |  2 +-
 roles/mailman3/templates/mailman3/mailman.cfg.j2 |  8 ++++----
 4 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index 8d50c9d9..99cccb3c 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -66,16 +66,20 @@ glob_mailman3:
     host: "{{ query('ldap', 'ip', 'tealc', 'adm') | ipv4 | first }}"
     port: 5432
     name: "mailman3web"
-  smtp:
-    host: "{{ query('ldap', 'ip', 'redisdead', 'adm') | ipv4 | first }}"
-    port: 25
-    user: ""
-    pass: ""
   restadmin_pass: "{{ vault.mailman3_restadmin_pass }}"
   archiver_key: "{{ vault.mailman3_archiver_key }}"
   web_secret_key: "{{ vault.mailman3_web_secret_key }}"
   web_domains:
-    - "mailman.crans.org"
+    - "lists2.crans.org"
     - "lists.crans.org"
   default_domain: "crans.org"
   postfix_domain: "crans.org"
+
+loc_opendkim:
+  domain: "lists.crans.org"
+  selector: "lists"
+  signing:
+    - "*@lists2.crans.org"
+  txt_record: |
+    lists._domainkey IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7jkgGjxZvQDbgFIuqb59lt7O1Jg6DFTSBxFlTfBW+3MF+AFjBR3AZ/UXwDA1vH4UTZqq0fWN6y6wqE/F7+HDjpqZGGuygZWTGVbBxwiKSjc2kq2mz7kLisE3a/jP8kyQDdb7fWrtTw9fxYu+Ygs0744otjRsui/ZK6zbrO8XQfd5UYnj4IGALeIuVFVLmwTY+VL/xWR/UjcfxgAprRfH0ec8PGlrxhpeLhUSJxw3Q6QfTnDsIpWLfJdgxILGa58TmhH6d+faxa1OIP37wswPjkDykmMFsCQJX9P7mXXR0+1FIRhhNpfCRXXj37udbIezDEMfA15rWSoYinPU+x7i6LhfJD7G40p1oDBiaOimZ8D/PUDAtoWRQeFiNOOQmNqDaVwlaOMvIZH2ZFD2I0eJIDb2FBYqhTb5GVyhKPePqT5FZE0s8SXqvYRNUWHuomS79kfo4TC74UPlavIbyCVTFlLi5ujc5RANm/FuH2w3ns1+YAlCeoblzwVdgN+h4/DI5kI88+0Hf+HCfQg+rPQL7ak7Wszo0iWvYUZ8t+IPbNDcVm5YI6koqkWGgfMrC0bDI5r+ZQACK15Fi6x3tV0umhytgRQWG9MyK61diNIc1LFsyL2lD0oOAjlpDlVSpUnXKhjRPq4YdaIojlgGSsWsq8sBhQTCY5DNHUuJLL1iPqsCAwEAAQ=="  ; ----- DKIM key lists for lists.crans.org
+  private_key: "{{ vault.opendkim_private_key_mailman }}"
diff --git a/plays/mailman.yml b/plays/mailman.yml
index 45fb45e3..cd80ad80 100755
--- a/plays/mailman.yml
+++ b/plays/mailman.yml
@@ -6,7 +6,7 @@
     certbot: '{{ loc_certbot | default(glob_certbot | default([])) }}'
     mailman3: '{{ glob_mailman3 | default({}) | combine(loc_mailman3 | default({})) }}'
     nginx: '{{ glob_nginx | default({}) | combine(loc_nginx | default({})) }}'
-    opendkim: '{{ loc_opendkim | default(glob_opendkim | default([])) }}'
+    opendkim: '{{ glob_opendkim | combine(loc_opendkim | default({})) }}'
   roles:
     - certbot
     - nginx
diff --git a/roles/mailman3/templates/mailman3/mailman-web.py.j2 b/roles/mailman3/templates/mailman3/mailman-web.py.j2
index 2f201cfb..3ee09a03 100644
--- a/roles/mailman3/templates/mailman3/mailman-web.py.j2
+++ b/roles/mailman3/templates/mailman3/mailman-web.py.j2
@@ -159,7 +159,7 @@ ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https"
 # Social auth
 #
 SOCIALACCOUNT_PROVIDERS = {
-    'crans': {}
+    'crans': {},
     #'openid': {
     #    'SERVERS': [
     #        dict(id='yahoo',
diff --git a/roles/mailman3/templates/mailman3/mailman.cfg.j2 b/roles/mailman3/templates/mailman3/mailman.cfg.j2
index 0d670df9..d01a11dc 100644
--- a/roles/mailman3/templates/mailman3/mailman.cfg.j2
+++ b/roles/mailman3/templates/mailman3/mailman.cfg.j2
@@ -252,10 +252,10 @@ outgoing: mailman.mta.deliver.deliver
 
 # How to connect to the outgoing MTA.  If smtp_user and smtp_pass is given,
 # then Mailman will attempt to log into the MTA when making a new connection.
-smtp_host: {{ mailman3.smtp.host }}
-smtp_port: {{ mailman3.smtp.port }}
-smtp_user: {{ mailman3.smtp.user }}
-smtp_pass: {{ mailman3.smtp.pass }}
+smtp_host: localhost
+smtp_port: 25
+smtp_user:
+smtp_pass:
 
 # Where the LMTP server listens for connections.  Use 127.0.0.1 instead of
 # localhost for Postfix integration, because Postfix only consults DNS
-- 
GitLab


From ea246dd7ad1e12b03d65d0b7e1bbbd69a6f4f302 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sat, 10 Apr 2021 15:51:06 +0200
Subject: [PATCH 34/37] [mailman3] Add mailman in the postfix group to prevent
 nullmailer installation

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 hosts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hosts b/hosts
index 30e139d5..e191f476 100644
--- a/hosts
+++ b/hosts
@@ -114,6 +114,7 @@ zamok.adm.crans.org
 
 [postfix:children]
 freebox
+mailman
 ovh_physical
 
 [radius:children]
-- 
GitLab


From bd43cff36d81fea3364880e779795db0945fe1e3 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Sun, 11 Apr 2021 19:50:38 +0200
Subject: [PATCH 35/37] [mailman3] Use lists.crans.org as web entrypoint

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/reverseproxy.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/group_vars/reverseproxy.yml b/group_vars/reverseproxy.yml
index 6e2aa801..cbb73a0c 100644
--- a/group_vars/reverseproxy.yml
+++ b/group_vars/reverseproxy.yml
@@ -43,7 +43,7 @@ glob_reverseproxy:
     - {from: owncloud.crans.org, to: 172.16.10.136}
     - {from: linx.crans.org, to: "172.16.10.119:8080"}
     - {from: belenios.crans.org, to: 172.16.10.111}
-    - {from: mailman.crans.org, to: 172.16.10.110}
+    - {from: lists.crans.org, to: 172.16.10.110}
 
     # Zamok
     - {from: perso.crans.org, to: 172.16.10.31}
-- 
GitLab


From ac691ed19ecdeb408895492b45da875e22f790c5 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 12 Apr 2021 16:24:18 +0200
Subject: [PATCH 36/37] [mailman3] drop lists2.crans.org

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 group_vars/mailman.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/group_vars/mailman.yml b/group_vars/mailman.yml
index 99cccb3c..aa2eef5a 100644
--- a/group_vars/mailman.yml
+++ b/group_vars/mailman.yml
@@ -70,7 +70,6 @@ glob_mailman3:
   archiver_key: "{{ vault.mailman3_archiver_key }}"
   web_secret_key: "{{ vault.mailman3_web_secret_key }}"
   web_domains:
-    - "lists2.crans.org"
     - "lists.crans.org"
   default_domain: "crans.org"
   postfix_domain: "crans.org"
@@ -79,7 +78,7 @@ loc_opendkim:
   domain: "lists.crans.org"
   selector: "lists"
   signing:
-    - "*@lists2.crans.org"
+    - "*@lists.crans.org"
   txt_record: |
     lists._domainkey IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7jkgGjxZvQDbgFIuqb59lt7O1Jg6DFTSBxFlTfBW+3MF+AFjBR3AZ/UXwDA1vH4UTZqq0fWN6y6wqE/F7+HDjpqZGGuygZWTGVbBxwiKSjc2kq2mz7kLisE3a/jP8kyQDdb7fWrtTw9fxYu+Ygs0744otjRsui/ZK6zbrO8XQfd5UYnj4IGALeIuVFVLmwTY+VL/xWR/UjcfxgAprRfH0ec8PGlrxhpeLhUSJxw3Q6QfTnDsIpWLfJdgxILGa58TmhH6d+faxa1OIP37wswPjkDykmMFsCQJX9P7mXXR0+1FIRhhNpfCRXXj37udbIezDEMfA15rWSoYinPU+x7i6LhfJD7G40p1oDBiaOimZ8D/PUDAtoWRQeFiNOOQmNqDaVwlaOMvIZH2ZFD2I0eJIDb2FBYqhTb5GVyhKPePqT5FZE0s8SXqvYRNUWHuomS79kfo4TC74UPlavIbyCVTFlLi5ujc5RANm/FuH2w3ns1+YAlCeoblzwVdgN+h4/DI5kI88+0Hf+HCfQg+rPQL7ak7Wszo0iWvYUZ8t+IPbNDcVm5YI6koqkWGgfMrC0bDI5r+ZQACK15Fi6x3tV0umhytgRQWG9MyK61diNIc1LFsyL2lD0oOAjlpDlVSpUnXKhjRPq4YdaIojlgGSsWsq8sBhQTCY5DNHUuJLL1iPqsCAwEAAQ=="  ; ----- DKIM key lists for lists.crans.org
   private_key: "{{ vault.opendkim_private_key_mailman }}"
-- 
GitLab


From 41782852499ca59a1f6c18924eebefd2ee758de6 Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <ynerant@crans.org>
Date: Mon, 12 Apr 2021 16:31:19 +0200
Subject: [PATCH 37/37] [opendkim] Fix trusted hosts

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
---
 .../templates/opendkim/TrustedHosts.j2        | 22 +++----------------
 1 file changed, 3 insertions(+), 19 deletions(-)

diff --git a/roles/opendkim/templates/opendkim/TrustedHosts.j2 b/roles/opendkim/templates/opendkim/TrustedHosts.j2
index 73c84818..64f8e8a9 100644
--- a/roles/opendkim/templates/opendkim/TrustedHosts.j2
+++ b/roles/opendkim/templates/opendkim/TrustedHosts.j2
@@ -1,19 +1,3 @@
-127.0.0.1
-localhost
-::1
-
-138.231.136.0/21
-138.231.144.0/21
-
-10.231.136.0/24
-10.2.9.0/24
-
-2a0c:700:0:1::/64
-2a0c:700:0:2::/64
-2a0c:700:0:21::/64
-2a0c:700:0:22::/64
-2a0c:700:0:23::/64
-
-*.crans.org
-*.crans.fr
-*.crans.eu
+{% for host in opendkim.trust -%}
+{{ host }}
+{% endfor %}
-- 
GitLab