A short link to this page is https://wiki.list.org/x/17892066

Clear message

How to Install Mailman 3 on a Debian 10 Server.

This document is a How-To on installing Mailman 3 on a Debian 10 server. The server environment will include Debian 10, NGINX, Let's Encrypt, Postfix, and PostgreSQL.

Prepare Server Environment

1. Create a VPS running Debian 10. I recommend using Linode. The server should be a minimum of 1 CPU and 2 Gigabyte of Memory. 25-50 Gb of storage should be sufficient.

2. Log into the server as root.

$ ssh root@your_server_ip

3. Create a New User: mailman

# adduser mailman

You will be asked some questions about this new user when running the above command. Please make sure you use a strong password for mailman as it will be typically known that any server running Mailman 3 will have a mailman user setup on it.

4. I recommend setting up a basic firewall to tighten up security on this Mailman 3 server. UFW is one that can be installed on a Debian 10 server:

# apt update
# apt install ufw

Once UFW is installed, you need to make sure you allow the various applications that Mailman 3 will be using through UFW. Some of these applications are the following: OpenSSH, Nginx Full, and Postfix.

So here is an example of what to do immediately after you install UFW:

# ufw app list

Output
Available applications:
 . . .
 OpenSSH
 . . .

This tells us what available applications we can configure UFW to allow. So let's add OpenSSH to UFW:

# ufw allow OpenSSH

Now we can enable UFW:

# ufw enable

You can see what is allowed through the UFW firewall by running the following command:

# ufw status

Output
Status: active

To             Action   From
--             ------   ----
OpenSSH          ALLOW    Anywhere
OpenSSH (v6)     ALLOW    Anywhere (v6)

Webserver Installation: NGINX

1. Both Django, Postorius, and Hyperkitty requires a web server. So let's install NGINX.

apt install nginx

2. Now that Nginx is installed, we need to allow it through the UFW Firewall.

# ufw allow 'Nginx Full'

Let's verify the change.

# ufw status

Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx HTTP                 ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

3. Let's make sure Nginx is running.

# systemctl status nginx

Output
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2019-07-03 12:52:54 UTC; 4min 23s ago
     Docs: man:nginx(8)
 Main PID: 3942 (nginx)
    Tasks: 3 (limit: 4719)
   Memory: 6.1M
   CGroup: /system.slice/nginx.service
           ├─3942 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ├─3943 nginx: worker process
           └─3944 nginx: worker process

If your output has Active: active (running) then you are good to go.

With Nginx confirmed to be running you should be able to access it via your server' IP address:

http://your_server_ipaddress

Create a NGINX Server Block For Your Mailman 3 Domain

This section shows how I set up a Mailman 3 domain for my Debian 10 Mailman 3/Postorius/Hyperkitty installations. YMMV.

# nano /etc/nginx/conf.d/listdomain.com.conf

Add the following to listdomain.com.conf

server {
        listen 80;
        listen [::]:80;

        server_name listdomain.com;

        location / {
                proxy_pass http://127.0.0.1:8000;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_redirect off;
        }

        location /static/ {
                alias /opt/mailman/mm/static/;
        }


}

# nginx -t

# nginx -s reload

Securing Your Nginx Installation: Let's Encrypt

1. The first step in securing Nginx is to install Certbot. This means first installing the dependencies for Certbot.

# apt install python3-acme python3-certbot python3-mock python3-openssl python3-pkg-resources python3-pyparsing python3-zope.interface

Now we are ready to install Certbot:

# apt install python3-certbot-nginx

Normally you would need to allow SSL traffic through the AFW firewall but we have already done previously in this how-to so we can continue on.

2. The next step is to fetch a SSL certificate for your Mailman 3 list domain name. This how-to assumes you know how to add a server block to Nginx. I keep my server blocks in /etc/nginx/conf.d/. You will need to make sure you have a server block setup already for your domain name before proceeding.

To obtain a SSL certificate for your domain name run:

# certbot --nginx -d listdomain.com

Certbox will go through its motions. At the end it is going to ask you whether you want to redirect all HTTP traffic to HTTPS. Choose 2 if yes which is what I recommend doing.

That's it! We are now ready to install Postfix because after all, Mailman 3 needs to send out mail.

Mail Server Installation: Postfix

1. Ok, we are now ready to install Postfix. The first thing we do here is install mailtuils:

# apt install mailutils

Now we install Postfix:

# apt install postfix

2. Now you will be presented with an interactive dialogue:

General type of mail configuration: Internet Site

System Mail Name: server hostname

3. Let's configure Postfix now. Open the main Postfix configuration file:

# nano /etc/postfix/main.cf

4. Make sure inet_interfaces is set to all:

inet_interfaces = all

5. Now let's set myhostname and mydestination:

myhostname = server_hostname
mydestination = $myhostname, localhost.$myhostname, localhost

6. Add some additional settings for Mailman 3 to work and quality of life after the following line:

inet_protocols = all

unknown_local_recipient_reject_code = 550
owner_request_special = no
always_add_missing_headers = yes

transport_maps =
    hash:/opt/mailman/mm/var/data/postfix_lmtp
local_recipient_maps =
    hash:/opt/mailman/mm/var/data/postfix_lmtp
relay_domains =
    hash:/opt/mailman/mm/var/data/postfix_domains
default_destination_recipient_limit = 30
default_destination_concurrency_limit = 15

header_checks = regexp:/etc/postfix/header_checks

Save and close the file.

7. Run #nano /etc/postfix/header_checks and add the following:

/^Subject:/     WARN

Save and close the file.

8. Time to apply the changes:

# systemctl restart postfix

9. The final step is to allow postfix through the firewall:

# ufw allow postfix

Now you have a working SMTP server and it's time to install and set up a database server for Mailman 3.

Database Server Installation: Postgres

1. So, the first step is to install several packages, some of these are needed for later steps:

# apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib curl

2. Now that PostgreSQL is installed, let's create the Mailman database and user. First let's open up a Postgres session by typing the following:

# sudo -u postgres psql

Now let's create the Mailman database:

postgres=# CREATE DATABASE mailman;

Now let's create the Mailman user:

postgres=# CREATE USER mailman WITH PASSWORD 'secure-password';

The following is recommended for setting up a Django project which is what is needed for the installation of Postorius and Hyperkitty:

postgres=# ALTER ROLE mailman SET client_encoding TO 'utf8';
postgres=# ALTER ROLE mailman SET default_transaction_isolation TO 'read committed';
postgres=# ALTER ROLE mailman SET timezone TO 'UTC';

The timezone part can be customized to reflect your geographical setting.

The last step is to give access to the mailman user to administer the mailman database:

postgres=# GRANT ALL PRIVILEGES ON DATABASE mailman TO mailman;

To finish this section out, exit the PostgreSQL prompt:

postgres=# \q

Setup of a Python Virtual Environment

Let's make sure we have Python 3 installed.

# apt install python3 python3-venv

Now we are going to be using a virtual environment to install Mailman 3. So let's install that too:

# apt install virtualenv python3-virtualenv

Installation of Potentially Needed Applications

Now that we have a working web, email and database server it’s time to install a number of potentially needed applications. Install the following applications as root:

# apt install sassc lynx
# apt install memcached
# apt install fail2ban
# apt install gettext

Install Dart Sass

# cd /usr/local/lib
# wget https://github.com/sass/dart-sass/releases/download/1.32.5/dart-sass-1.32.5-linux-x64.tar.gz
# tar -xf dart-sass-1.32.5-linux-x64.tar.gz
# chmod -R o-w dart-sass
# ln -s /usr/local/lib/dart-sass/sass /usr/local/bin/sass
# rm -f dart-sass-1.32.5-linux-x64.tar.gz

Test Dart Sass Installation

# sass --version

If you are using Dart Sass, then make sure you set COMPRESS_PRECOMPILERS within settings_local.py to the following:

COMPRESS_PRECOMPILERS = (
   ('text/x-scss', 'sass --style compressed {infile} {outfile}'),
   ('text/x-sass', 'sass --style compressed {infile} {outfile}'),
)

Setup Directories and Files for Mailman 3

Ok, now we need to create some directories and files.

Directories:

# mkdir -p /opt/mailman/mm/bin/ 
# mkdir /opt/mailman/mm/var/

Files:

# touch /opt/mailman/mm/init.py (empty)

# touch /opt/mailman/mm/mailman.cfg sample

# touch /opt/mailman/mm/mailman-hyperkitty.cfg sample

# touch /opt/mailman/mm/settings_local.py sample

# touch /opt/mailman/mm/settings.py (copy of the mailman-suite settings.py file but with DEBUG = False)

# touch /opt/mailman/mm/urls.py sample

# touch /opt/mailman/mm/wsgi.py sample

# touch /opt/mailman/mm/gunicorn.conf sample

Now let's create a symlink for Mailman 3 logs:

# cd /opt/mailman/mm
# ln -s /opt/mailman/mm/var/logs logs 

This symlink will be broken. Don't freak out! The /opt/mailman/mm/var/logs directory will be created when we install Mailman 3.

Now we need to create some executables for Mailman 3.

/opt/mailman/mm/bin/django-admin sample Script to run Django management commands.

/opt/mailman/mm/bin/mailman sample Script to run mailman commands.

/opt/mailman/mm/bin/mailman-post-update sample Script to update static web and run migrations following a software update.

/opt/mailman/mm/bin/gunicorn sample Script to start Gunicorn.

Make sure /opt/mailman and everything below is owned by mailman.mailman.

# chown -R mailman.mailman /opt/mailman

Modify the mailman.cfg, mailman-hyperkitty.cfg, and settings_local.py files to match your particular server setup. Make sure you add the Postgresql password for the mailman db user in mailman.cfg as that is hard to miss.

Create and Enter Virtual Environment

Make sure you are doing this step as the mailman user:

# su mailman

# python3 -m venv /opt/mailman/mm/venv

# source /opt/mailman/mm/venv/bin/activate

To leave the virtual environment:

# deactivate

Installation of Additional Applications via PIP

Before proceeding, make sure you are logged in as the mailman user AND you are in your virtual environment. The directory you should be in is /opt/mailman/mm.

# pip install wheel

# pip install psycopg2-binary

# pip install pylibmc

# pip install gunicorn

# pip install mailman

# pip install hyperkitty

When installing Hyperkitty via pip, you may run into the following error:

  • error: Can not find Rust compiler

This is due to changes in the Cryptography module which is required by Django. If you run into this error, here is how to fix it.

A. Install the latest version of Rust (ref: https://www.rust-lang.org/tools/install):

# cd ~ (done as root user)
# curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# rustc --version (to verify installation)

B. Now install additional software:

# apt-get install build-essential libssl-dev libffi-dev python3-dev cargo

Now proceed to reinstalling the Hyperkitty module and everything else:

# pip install hyperkitty

# pip install postorius

# pip install mailman-hyperkitty

# pip install whoosh

# pip install importlib_resources==1.1.0

Once the above packages are installed run “mailman info” in your virtual environment. That will install Mailman core into your /opt/mailman/mm/var directory.

Setup Startup Scripts

Setup your systemd startup scripts and place them in /lib/systemd/system/. Finally, we need to arrange that all the services are running. Generally, the OS has taken care of init, upstart or systemd scripts for Postfix, the web server, PostgreSQL and memcached, but other things that need to be run are Mailman core, Django's qcluster and Gunicorn if that is used.

Post Installation Tasks

Now it is time to run the Mailman Post Update script:

(venv) # /opt/mailman/mm/bin/mailman-post-update

Create Django Superuser

The next item to do is create an admin user for the Django interface. To do that run:

# /opt/mailman/mm/bin/django-admin createsuperuser

It will prompt you for a username, email address and password. After the above script finishes its course, its time to get back to root:

(venv) # deactivate

mailman@ # exit

Start Mailman 3 Core, Django, and Gunicorn

Start mailman, django, and gunicorn using the above created system scripts:

Mailman 3 Core

# systemctl start mailman

Django

# systemctl start qcluster

Gunicorn

# systemctl start gunicorn

Setup Cron Jobs

Log in as Mailman user:

# su mailman

crontab -e

Add the following cron entries:

@hourly  /opt/mailman/mm/bin/django-admin runjobs hourly
@daily   /opt/mailman/mm/bin/django-admin runjobs daily
@weekly  /opt/mailman/mm/bin/django-admin runjobs weekly
@monthly /opt/mailman/mm/bin/django-admin runjobs monthly
@yearly  /opt/mailman/mm/bin/django-admin runjobs yearly
0,15,30,45 * * * * /opt/mailman/mm/bin/django-admin runjobs quarter_hourly
* * * * * /opt/mailman/mm/bin/django-admin runjobs minutely

# Send periodic digests.
30 3 * * * /opt/mailman/mm/bin/mailman digests --periodic

# Send request reminder for MM 3. Like the checkdbs job for 2.1
0 8 * * * /opt/mailman/mm/bin/mailman notify

Setup Xapian for Indexing Archives

How to keep Mailman 3 Updated