system-config/playbooks/roles/mailman3/tasks/main.yaml
Jeremy Stanley eec60a2cb9 Restart Mailman 3 containers when configs change
Add a handler for restarting Mailman 3 containers if they're up, and
notify it from all of the copy tasks for configuration files. Check
for the uwsgi processes that Django runs under to determine whether
the containers are running.

Change-Id: I73be59be773fdde100999c7872520aab1d9e2066
2023-08-17 15:52:26 +00:00

352 lines
9.4 KiB
YAML

# The old mailman2 exim config refers to this file. Write it out
# to make basic testing happy, but we may need to clean it up or
# modify it for mailman3.
- name: Write /etc/aliases.domain
template:
src: "domain_aliases.j2"
dest: "/etc/aliases.domain"
mode: '0444'
- name: Create Mailman Group
group:
name: mailman
gid: 10010
system: yes
- name: Create Mailman User
user:
name: mailman
uid: 10010
comment: Mailman User
shell: /bin/bash
home: /var/lib/mailman
group: mailman
create_home: yes
system: yes
#### Install Mailman ####
- name: Ensure Mailman core volume directory exists
file:
state: directory
path: "/var/lib/mailman/core"
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
owner: 100
group: 65533
mode: '0755'
- name: Copy our mailman-extra.cfg for mailman-core
template:
src: mailman-extra.cfg.j2
dest: /var/lib/mailman/core/mailman-extra.cfg
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
owner: 100
group: 65533
mode: '0644'
notify: mailman restart containers
- name: Ensure Mailman database volume directory exists
file:
state: directory
path: "/var/lib/mailman/database"
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
owner: 999
group: 999
mode: '0755'
- name: Ensure Mailman web volume directories exist
file:
state: directory
path: "/var/lib/mailman/{{ item }}"
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
owner: 100
group: 101
mode: '0755'
loop:
- import
- web
- web-data
- web-data/fulltext_index
- web-data/mm2archives
- name: Copy our overridden settings.py for mailman-web
copy:
src: web-settings.py
dest: /var/lib/mailman/web/settings.py
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
owner: 100
group: 101
mode: '0644'
notify: mailman restart containers
- name: Check for initial setup flag file
stat:
path: /var/lib/mailman/bootstrapped
register: _mailman_bootstrapped
# https://docs.mailman3.org/en/latest/faq.html#the-domain-name-displayed-in-hyperkitty-shows-example-com-or-something-else
- name: Temporarily turn off magic domain guessing
lineinfile:
state: present
backrefs: yes
path: /var/lib/mailman/web/settings.py
regexp: '^SITE_ID = 0$'
line: 'SITE_ID = 1'
when: not _mailman_bootstrapped.stat.exists
- name: Copy our settings_local.py for mailman-web
copy:
src: web-settings_local.py
dest: /var/lib/mailman/web-data/settings_local.py
# TODO: undo for https://github.com/maxking/docker-mailman/issues/550
owner: 100
group: 101
mode: '0644'
notify: mailman restart containers
- name: Copy our max_allowed_packet override config
copy:
src: 99-max_allowed_packet.cnf
dest: /var/lib/mailman/99-max_allowed_packet.cnf
owner: 999
group: 999
mode: '0644'
notify: mailman restart containers
- name: Ensure /etc/mailman-compose directory
file:
state: directory
path: /etc/mailman-compose
mode: '0755'
- name: Put docker-compose file in place
template:
src: docker-compose.yaml.j2
dest: /etc/mailman-compose/docker-compose.yaml
mode: '0600'
notify: mailman restart containers
- name: Run docker-compose pull
shell:
cmd: docker-compose pull
chdir: /etc/mailman-compose/
- name: Run docker-compose up
shell:
cmd: docker-compose up -d
chdir: /etc/mailman-compose/
register: mailman_dcup
- name: Run docker prune to cleanup unneeded images
shell:
cmd: docker image prune -f
- name: Install apache2
package:
name:
- apache2
- apache2-utils
state: present
- name: Apache modules
apache2_module:
state: present
name: "{{ a2_mod }}"
loop:
- authz_host
- proxy
- proxy_uwsgi
- ssl
- rewrite
loop_control:
loop_var: a2_mod
notify: mailman restart apache2
- name: Make sure packaged default site disabled
command: a2dissite 000-default.conf
args:
removes: /etc/apache2/sites-enabled/000-default.conf
- name: Create mailman vhost config
template:
src: mailman.vhost.j2
dest: "/etc/apache2/sites-enabled/50-{{ mailman_sites.0.listdomain }}.conf"
owner: root
group: root
mode: '0644'
notify: mailman reload apache2
- name: Enable apache2 server
service:
name: "apache2"
enabled: yes
#### Configure Mailman Services ####
- name: Wait for mm3 REST API to be up and running
uri:
url: 'http://localhost:8001/3.1/domains'
url_username: restadmin
url_password: "{{ mailman3_rest_password }}"
force_basic_auth: yes
method: GET
register: mm_rest_api_up
delay: 1
retries: 300
until: mm_rest_api_up and mm_rest_api_up.status == 200
no_log: true
# It has been difficult to nail down a reliable mathod for determining
# when the database is sufficiently populated that we can create the django
# admin user. We apply a number of approaches in response to this. If we
# can identify a single method that is reliable this list can be trimmed.
- name: Wait for DB to be populated
command: >
docker exec mailman-compose_database_1 bash -c
'mysql -u mailman -p"$MYSQL_PASSWORD" -D mailmandb -e
"SHOW TABLES LIKE \"auth_user\";"'
register: django_db_exists
delay: 1
retries: 300
until: django_db_exists.stdout_lines | length > 1 and django_db_exists.stdout_lines[1] == "auth_user"
- name: Wait for DB to be populated second approach
command: >
docker exec mailman-core sh -c 'alembic -c /usr/lib/python*/site-packages/mailman/config/alembic.cfg current'
register: alembic_version
delay: 1
retries: 300
until: alembic_version.stdout_lines | length > 0 and "(head)" in alembic_version.stdout_lines[0]
- name: Wait for DB to be populated third approach
shell: >
docker exec mailman-web bash -c
'python3 manage.py showmigrations' |
grep -q '^ \[ \] [0-9]\+_.*'
register: django_db_migrations
delay: 1
retries: 300
failed_when: false
# When grep stops matching the empty '[ ]' that indicates all migrations
# are marked with '[X]' and are complete. Grep returns non zero when we
# reach this point.
until: django_db_migrations.rc != 0
- name: Check if django admin user exists
command: >
docker exec mailman-compose_database_1 bash -c
'mysql -u mailman -p"$MYSQL_PASSWORD" -D mailmandb -e
"SELECT COUNT(id) FROM auth_user WHERE id = 1 AND is_superuser = 1;"'
register: django_admin_exists
- name: Create django admin user
when: django_admin_exists.stdout_lines[1] == "0"
command: >
docker exec mailman-web bash -c
"DJANGO_SUPERUSER_PASSWORD={{ mailman3_admin_password }}
python3 manage.py createsuperuser --no-input
--username {{ mailman3_admin_user }}
--email '{{ mailman3_admin_email }}'"
no_log: true
- name: Complete new server bootstrapping
when: not _mailman_bootstrapped.stat.exists
block:
- name: Run docker-compose down
shell:
cmd: docker-compose down
chdir: /etc/mailman-compose/
- name: Turn magic domain guessing back on
lineinfile:
state: present
backrefs: yes
path: /var/lib/mailman/web/settings.py
regexp: '^SITE_ID = 0$'
line: 'SITE_ID = 1'
- name: Create the bootstrapped flag file
copy:
content: ""
dest: /var/lib/mailman/bootstrapped
force: no
owner: 100
group: 101
mode: '0644'
- name: Run docker-compose up
shell:
cmd: docker-compose up -d
chdir: /etc/mailman-compose/
- name: Wait for mm3 REST API to be up and running
uri:
url: 'http://localhost:8001/3.1/domains'
url_username: restadmin
url_password: "{{ mailman3_rest_password }}"
force_basic_auth: yes
method: GET
register: mm_rest_api_up
delay: 1
retries: 300
until: mm_rest_api_up and mm_rest_api_up.status == 200
no_log: true
- name: Create lists in mm3
include_tasks: create_lists.yaml
loop: "{{ mailman_sites }}"
loop_control:
loop_var: mm_site
#### Logrotate for service logs ####
- name: Rotate mailman logs
include_role:
name: logrotate
vars:
logrotate_rotate: 90
logrotate_file_name: '/var/lib/mailman/web-data/logs/*.log'
#### Database Backups ####
- name: Create db backup dest
file:
state: directory
path: /var/backups/mailman-mariadb
mode: 0700
owner: root
group: root
- name: Set up cron job to backup the database
cron:
name: mailman-db-backup
state: present
user: root
job: >
/usr/local/bin/docker-compose -f /etc/mailman-compose/docker-compose.yaml exec -T database
bash -c '/usr/bin/mysqldump --opt --databases mailmandb --single-transaction -uroot -p"$MYSQL_ROOT_PASSWORD"' |
gzip -9 > /var/backups/mailman-mariadb/mailman-mariadb.sql.gz
minute: 14
hour: 5
- name: Rotate db backups
include_role:
name: logrotate
vars:
logrotate_file_name: /var/backups/mailman-mariadb/mailman-mariadb.sql.gz
logrotate_compress: false
- name: Setup db backup streaming job
block:
- name: Create backup streaming config dir
file:
path: /etc/borg-streams
state: directory
- name: Create db streaming file
copy:
content: >-
/usr/local/bin/docker-compose -f /etc/mailman-compose/docker-compose.yaml exec -T database
bash -c '/usr/bin/mysqldump --skip-extended-insert --databases mailmandb --single-transaction -uroot -p"$MYSQL_ROOT_PASSWORD"'
dest: /etc/borg-streams/mysql