DEBOPS.MAILMAN(5)

NAME
debops.mailman - Manage Mailman installation using Ansible

SYNOPSIS

debops service/mailman [--limit group,host,...] [--diff] [--check] [--tags tag1,tag2,...] [--skip-tags tag1,tag2,...] [<ansible-playbook options>] ...

DESCRIPTION

The debops.mailman Ansible role can be used to create and manage mailing lists using GNU Mailman <https://list.org/> service. The role is designed to install and configure Mailman 3 using Debian packages, and will automatically integrate with PostgreSQL or MariaDB database for configuration storage and Postfix for SMTP services.

By default the role provides configuration for debops.postfix role to configure the SMTP server integration, as well as debops.nginx role to configure access to the web control panel.

GETTING STARTED

  Important installation steps

The default installation will configure the Mailman service under the lists.<example.org> DNS domain. This can be changed using the mailman__fqdn variable.

On installation, if the LDAP support is not enabled, the role will create an initial superuser account with a random password. The default superuser account will use the login name specified in the mailman__superuser_name variable and e-mail address specified in the mailman__superuser_email variable. They are based on the facts defined by the debops.core role, but you might want to redefine them beforehand in the inventory to be sure that the validation e-mail is sent to the correct e-mail account.

After the role configures Mailman, you should go to the https://lists.example.org/ website (make sure that the DNS record is configured). The default superuser account has a random password assigned to it, so the first step is to request a password change by specifying your admin e-mail address. When you get the e-mail, you will be able to specify your own password. After logging in again, you will receive another e-mail request to confirm the authenticity of the account - when you confirm that you are who you say you are in the web interface, you will be able to login as the site administrator.

The Postorius/HyperKitty web interface uses example.com as the default "website" defined in the Django framework. You will have to change that to your preferred domain using the https://lists.example.org/admin/ interface. In the Django admin page, in the "Pages" section, click "Modify", "example.com" and change the default site domain to your preferred one. After this you can create a new domain for the mailing lists, and a new mailing list in the Postorius web interface.

  LDAP integration

If the LDAP environment is configured on the host, the role will configure the LDAP support in the Django framework to allow the users in the UNIX Administrators group to login as superuser accounts. You should be able to login with your username and password defined in LDAP directory, and the confirmation e-mail should be sent to your e-mail account.

  SMTP service integration

The debops.mailman role provides the configuration for debops.postfix Ansible role which are used in the example playbook. The configuration is defined in the mailman__postfix__dependent_maincf variable and is passed to the role via role dependent variables.

  HTTP service integration

The role provides configuration for debops.nginx role which will configure the Mailman web interface using nginx service.

  Example inventory

To configure Mailman on a host, you need to add it to [debops_service_mailman] Ansible inventory group. Some other services will also need to be configured as well. The role integrates with the Postfix service using the debops.postfix role. A database is needed; role can use either PostgreSQL or MariaDB service, depending on which one is available. If none of them are installed, a fallback to SQLite3 database will happen automatically.

An example inventory configuration:

[debops_all_hosts]
hostname    ansible_host=hostname.example.org
[debops_service_postgresql_server]
hostname
[debops_service_postfix]
hostname
[debops_service_mailman]
hostname

  Example playbook

The debops.mailman uses a set of other roles to configure additional services like HTTP and SMTP server. Here's an example playbook with all of the required DebOps services:

---
- name: Manage Mailman service
  collections: [ 'debops.debops', 'debops.roles01',
                 'debops.roles02', 'debops.roles03' ]
  hosts: [ 'debops_service_mailman' ]
  become: True
  environment: '{{ inventory__environment | d({})
                   | combine(inventory__group_environment | d({}))
                   | combine(inventory__host_environment  | d({})) }}'
  pre_tasks:
    - name: Prepare postfix environment
      import_role:
        name: 'postfix'
        tasks_from: 'main_env'
      vars:
        postfix__dependent_maincf:
          - role: 'mailman'
            config: '{{ mailman__postfix__dependent_maincf }}'
      tags: [ 'role::postfix', 'role::secret', 'role::ferm' ]
  roles:
    - role: keyring
      tags: [ 'role::keyring', 'skip::keyring', 'role::nginx' ]
      keyring__dependent_apt_keys:
        - '{{ nginx__keyring__dependent_apt_keys }}'
    - role: secret
      tags: [ 'role::secret', 'role::postfix' ]
      secret__directories:
        - '{{ postfix__secret__directories }}'
    - role: apt_preferences
      tags: [ 'role::apt_preferences', 'skip::apt_preferences' ]
      apt_preferences__dependent_list:
        - '{{ nginx__apt_preferences__dependent_list }}'
    - role: ferm
      tags: [ 'role::ferm', 'skip::ferm' ]
      ferm__dependent_rules:
        - '{{ nginx__ferm__dependent_rules }}'
        - '{{ postfix__ferm__dependent_rules }}'
    - role: python
      tags: [ 'role::python', 'skip::python' ]
      python__dependent_packages3:
        - '{{ ldap__python__dependent_packages3 | d([]) }}'
        - '{{ nginx__python__dependent_packages3 }}'
        - '{{ mailman__python__dependent_packages3 }}'
      python__dependent_packages2:
        - '{{ ldap__python__dependent_packages2 | d([]) }}'
        - '{{ nginx__python__dependent_packages2 }}'
        - '{{ mailman__python__dependent_packages2 }}'
    - role: ldap
      tags: [ 'role::ldap', 'skip::ldap' ]
      ldap__dependent_tasks:
        - '{{ mailman__ldap__dependent_tasks }}'
      when: mailman__ldap_enabled|bool
    - role: postfix
      tags: [ 'role::postfix', 'skip::postfix' ]
      postfix__dependent_maincf:
        - role: 'mailman'
          config: '{{ mailman__postfix__dependent_maincf }}'
    - role: nginx
      tags: [ 'role::nginx', 'skip::nginx' ]
      nginx__dependent_servers:
        - '{{ mailman__nginx__dependent_servers }}'
      nginx__dependent_upstreams:
        - '{{ mailman__nginx__dependent_upstreams }}'
    - role: mailman
      tags: [ 'role::mailman', 'skip::mailman' ]

MIGRATION FROM MAILMAN 2.X TO MAILMAN 3.X

  Overview

Before doing the migration, review the official migration instructions <https://docs.mailman3.org/en/latest/migration.html> to get an overview of the procedure.

The debops.mailman role does not support installation of Mailman 2.1 and Mailman 3 on the same host. You should create a new host for the Mailman site and import the list configuration as well as the list archives from the old one. Don't remove the old Mailman 2.1 installation just yet, you might need it to modify the list configuration files in case the import doesn't work. For example, there are known issues with the bounce_info configuration not being parsable by Mailman 3. You can use the existing Mailman installation <https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/thread/JEPMB3HW4FI57EUMOST4L7BD2ILIIS3P/> to reset these values.

  Example migration steps

Here's an example migration procedure of the example-list@lists.example.org mailing list, based on the Mailman packages distributed in Debian. We assume that both hosts (old Mailman 2.x installation and new Mailman 3.x installation) are running and are accessible only from the Ansible Controller, cannot communicate directly. The procedure can be performed before the Mailman 3 website is available publicly.

  Old Mailman 2.1.x host

Reset bounce information for a given list:

# Switch to 'root' account
sudo -i
# Reset bounce configuration (repeat for each list)
echo 'bounce_info = {}' > /tmp/reset_bounceinfo.py
config_list -i /tmp/reset_bounceinfo.py example-list
# Create tarball w list configuration and archives
tar -czvf /tmp/example-list.tar.gz -C /var/lib/mailman \
    lists/example-list/config.pck \
    archives/private/example-list.mbox/example-list.mbox

  Ansible Controller

Copy the tarball between the old Mailman 2.1.x host and new Mailman 3.x host:

scp -3 old-mailman:/tmp/example-list.tar.gz \
       new-mailman:/tmp/example-list.tar.gz

  New Mailman 3.x host

Extract the tarball contents:

cd /tmp
tar -zxvf example-list.tar.gz

Create new mailing list and import the old configuration and archives:

# Switch to 'root' account
sudo -i
mailman create example-list@lists.example.org
mailman import21 example-list@lists.example.org /tmp/lists/example-list/config.pck
# Import list archives
/usr/share/mailman3-web/manage.py hyperkitty_import \
    -l example-list@lists.example.org \
    /tmp/archives/private/example-list.mbox/example-list.mbox
# Refresh archive index
/usr/share/mailman3-web/manage.py update_index

After these steps, you should be able to see the mailing list information in the Postorious interface, as well as the mailing list archives in HyperKitty.

DEFAULT VARIABLE DETAILS

Some of debops.mailman default variables have more extensive configuration than simple strings or lists, here you can find documentation and examples for them.

  mailman__core_configuration

The mailman__core_*_configuration variables define the contents of the /etc/mailman3/mailman.cfg configuration file. You can read Mailman 3 documentation <https://mailman.readthedocs.io/en/latest/src/mailman/config/docs/config.html> to find more about possible configuration options.

The same syntax is used in the mailman__hyperkitty_*_configuration variables to define the contents of the /etc/mailman3/mailman-hyperkitty.cfg configuration file.

  Examples

You can see the contents of the mailman__core_original_configuration for the default contents of the configuration file defined in YAML, and the mailman__core_default_configuration for the configuration options changed from the defaults which are used by the role.

  Syntax

Each configuration option is defined as a YAML dictionary with specific parameters:

name
    Required. The name of the configuration file section. The entries with the same name parameter are merged together which can be used to modify already defined configuration entries from the Ansible inventory.

state
    Optional. Define the state of the configuration section. If not specified or present, a given configuration section will be included in the generated configuration file. If absent, the section will not be included in the configuration file.

    If the value is hidden, the section will be included but its header ([section]) will not.

    If the value is ignore, a given configuration entry will not be evaluated during role execution. This can be used to conditionally enable or disable features.

separator
    Optional, boolean. If defined and True, the secion will have an additional empty line before it for cosmetic reasons.

comment
    Optional. A string or YAML text block with additional comments about a given configuration section.

options
    Optional. YAML list which contains the Mailman 3 configuration options in a given section. The options parameters from multiple configuration entries with the same name parameter are merged together; this can be used to modify the already defined configuration options from the Ansible inventory.

    Each configuration option is defined using a YAML dictionary with specific parameters:

name
    Required. The name of the configuration option. Entries with the same name are merged together which can be used to modify previously defined configuration options.

option
    Optional. If multiple variations of the same option are defined (for example a class database configuration option), they need to be defined in configuration entries with an unique name parameter. This however will be an issue in the actual configuration file.

    The option parameter can be used to specify the configuration option name to use instead of the name parameter.

value
    Required. The value which should be set for a given Mailman 3 configuration option. It can be a number, a string, a boolean or a YAML list of strings which will be joined together using spaces.

comment
    Optional. A string or YAML text block with a comment about a given configuration option.

separator
    Optional, boolean. If defined and True, the option will have an additional empty line before it for cosmetic reasons.

state
    Optional. Define the state of a given configuration option. If not specified or present, the option will be included in the configuration file. If absent, the option will not be included in the configuration file. If ignore, a given configuration entry will not be evaluated during role execution. If comment, the option will be present in the configuration file, but commented out.

  mailman__web_configuration

The mailman__web_*_configuration variables define the contents of the /etc/mailman3/mailman-web.py configuration file.

  Examples

Change the randomly selected Libravatar image generation engine <https://wiki.libravatar.org/api/> to one of: mm (simple avatar), identicon, monsterid, wavatar, retro, robohash, pagan:

mailman__web_configuration:
  - name: 'gravatar_default_image'
    value: 'identicon'

You can see the contents of the mailman__web_original_configuration for the default contents of the configuration file defined in YAML, and the mailman__web_default_configuration for the configuration options changed from the defaults which are used by the role.

  Syntax

Each configuration option is defined as a YAML dictionary with specific parameters:

name
    Required. The name of the configuration option. Entries with the same name are merged together which can be used to modify previously defined configuration options.

option
    Optional. If multiple variations of the same option are defined (for example a databases database configuration option), they need to be defined in configuration entries with an unique name parameter. This however will be an issue in the actual configuration file.

    The option parameter can be used to specify the configuration option name to use instead of the name parameter.

value
    Optional. The value which should be set for a given Mailman 3 configuration option. It can be a number, a string, a boolean or a YAML list. More complicated values are defined using other parameters.

options
    Optional. YAML list which contains the Mailman 3 Web configuration options in a given section. The options parameters from multiple configuration entries with the same name parameter are merged together; this can be used to modify the already defined configuration options from the Ansible inventory.

    Each configuration option is defined using a string which is included as-is, or a YAML dictionary with specific parameters:

name
    The string to be included in the list. Entries with the same name are merged together which can be used to modify previously defined configuration options.

comment
    Optional. A string or YAML text block with a comment about a given configuration item.

state
    Optional. Define the state of a given configuration item. If not specified or present, the item will be included in the configuration file. If absent, the item will not be included in the configuration file. If ignore, a given configuration entry will not be evaluated during role execution. If comment, the item will be present in the configuration file, but commented out.

type
    Optional. Modify the value generated by the role:

    If the type is set to tuple, the list defined in the value or options parameters will be rendered as a Python tuple.

    If the type is set to raw, the value contents will be included as-is in the generated configuration file. This can be used to include small snippets of Python code specified as strings.

config
    Optional. YAML dictionary with the configuration rendered in the final file using the to_nice_json Ansible filter. This parameter can be used to define dictionary-based configuration options. The config parameters from configuration entries with the same name parameter replace each other in order of appearance.

raw Optional. String or YAML text block which will be included in the generated configuration file as-is. This can be used to include Python code in the generated configuration file that cannot be expressed otherwise.

comment
    Optional. A string or YAML text block with a comment about a given configuration option.

separator
    Optional, boolean. If defined and True, the option will have an additional empty line before it for cosmetic reasons.

state
    Optional. Define the state of a given configuration option. If not specified or present, the option will be included in the configuration file. If absent, the option will not be included in the configuration file. If ignore, a given configuration entry will not be evaluated during role execution. If comment, the option will be present in the configuration file, but commented out.

copy_id_from
    Optional. Specify the name parameter of a different configuration option; the configuration entry with this parameter will copy the internal "id" value of the specified configuration entry. This can be used to reorder configuration entries in the finial generated configuration file.

weight
    Optional. Positive or negative number which can be used to affect the position of a given configuration option in the generated file. Specifying a positive number will lower the option within the file (more weight), specifying a negative number will raise the option (less weight). This can be used to reorder configuration entries in the finial generated configuration file.

  mailman__templates

The mailman__*_templates variables can be used to define Mailman 3 templates <https://mailman.readthedocs.io/en/stable/src/mailman/rest/docs/templates.html> stored in the filesystem. The files will be stored in subdirectories under /var/lib/mailman3/templates/ directory and can be used change how Mailman processes mailing list messages.

  Examples

Remove the default message footer in all lists (this is enabled by default):

mailman__templates:
  - name: 'site/en/list:member:generic:footer.txt'
    content: ''

  Syntax

Each template is defined by a YAML dictionary with specific parameters:

name
    Required. A path relative to the /var/lib/mailman3/templates/ directory with the template filename, ending with .txt extension. Any subdirectories will be created automatically, if not present. Configuration entries with the same name parameter are merged together in order of appearance.

state
    Optional. If not specified or present, the template file will be generated. If absent, the template file will be removed.

content
    Optional. String or YAML text block with contents of the generated template. If not specified, the template will be empty.

AUTHOR
Maciej Delmanowski

COPYRIGHT
2014-2022, Maciej Delmanowski, Nick Janetakis, Robin Schneider and others