Add a readme to the repository.

This commit is contained in:
Abhilash Raj
2017-04-05 01:55:40 -07:00
parent 1844d0412a
commit c135b427c2

200
README.md Normal file
View File

@@ -0,0 +1,200 @@
GNU Mailman 3 Deployment with Docker
====================================
This repository hosts code for two docker images `maxking/mailman-core` and
`maxking/mailman-web` both of which are meant to deploy [GNU Mailman 3][1] in
a production environment.
[Docker][2] is a container ecosystem which can run containers on several
platforms. It consists of a tool called [docker-compose][3] which can be used to
run multi-container applications. This repository consists of a
[`docker-compose.yaml`](docker-compose.yaml) file which is a set of
configurations that can be used to deploy the [Mailman 3 Suite][4].
Dependencies
============
- Docker
- Docker-compose
To run this you first need to download docker for whichever operating system you
are using. You can find documentation about [how to install][5]. It is
recomended to use these instead of the one from your package managers. After you
have downloaded and installed docker, install docker-compose from [here][6].
Running
=======
To run the containers, simply run:
```bash
$ docker-compose up
```
This command will do several things, most importantly:
- Run a wsgi server using [`uwsgi`][7] for the Mailman's Django based web
frontend listening on http://172.19.199.3:8000/. It will run 2 worker
processes with 4 threads each. You may want to change the setting
`ALLOWED_HOSTS` in the settings before deploying the application in
production.
- Run a postgresql server with a default database, username and password as
mentioned in the `docker-compose.yaml`. You will have to change configuration
files too if you change any of these.
- Run mailman-core listening an LMTP server at http://172.19.199.2:8024/ for
messages from MTA. You will have to configure your MTA to send messages at
this address.
Some more details about what the above system achives is mentioned below. If you
are only going to deploy a simple configuration, you don't need to read
this. However, these are very easy to understand if you know how docker works.
- First create a bridge network called `mailman` in the
`docker-compose.yaml`. It will probably be named something else in your
machine, but it will use the `172.19.199.0/24` as subnet. All the containers
mentioned (mailman-core, mailman-web, database) will join this network and are
assigned static IPs. The host operating system is available at `172.19.199.1`
from within these containers.
- Spin off mailman-core container which has a static IP address of
`172.19.199.2` in the mailman bridge network created above. It has
GNU Mailman 3 core running inside it. Mailman core's REST API is available at
port 8000 and LMTP server listens at port 8024.
- Spin off mailman-web container which has a django application running with
both Mailman's web frontend Portorius and Mailman's Web based Archiver
running. [Uwsgi][7] server is used to run a web server with the configuration
provided in this repository [here](web/assets/settings.py). You may want to
change the setting `ALLOWED_HOSTS` in the settings before deploying the
application in production.
- Spin off a postgresql database container which is used by both mailman-core
and mailman-web as their primary database.
- mailman-core mounts `/opt/mailman/core` from host OS at `/opt/mailman` in the
container. Mailman's var directory is stored there so that it is accesible
from the host operating system. Mailman's configuration file is also expected
to be present there. A [production level
configuration](core/assets/mailman.cfg) is provided, but please do not change
anything there without the complete knowledge. Mailman also needs another
configuration file called
[mailman-hyperkitty.cfg](core/assets/mailman-hyperkitty.cfg) and is also
expected to be at `/opt/mailman/core/` on the host OS.
- mailman-web mounts `/opt/mailman/web` from the host OS to
`/opt/mailman-web-data` in the container. It consists of the logs and
settings.py file for Django.
- database mounts `/opt/mailman/database` at `/var/lib/postgresql/data` so that
postgresql can persists its data even if the database containers are
updated/changed/removed.
Setting up your MTA
===================
This setup assumes that the MTA is actually present on the host. In future it is
possible to provide a way to actually expect nothing from the host and have
everything running inside containers.
It is recomended to use [Exim4][8] along with this setup. Technically, it
possible to use any other MTA like postfix too, but I haven't yet been able to
figure out a clean way to communicate with postfix on the host.
Exim should be setup to relay emails from `172.19.199.3` and `172.19.199.2`. The
mailman specific configuration is provided in the repository at
`core/assets/exim`. There are three files
- [25_mm_macros](core/assets/exim/25_mm3_macros) to be placed at
`/etc/exim4/conf.d/main/25_mm3_macros` in a typical debian instal of
exim4. Please change MY_DOMAIN_NAME to the domain name that will be used to
serve mailman. Multi-domains setups will be added later.
- [455_mm3_router](core/assets/exim/455_mm3_router) to be placed at
`/etc/exim4/conf.d/main/455_mm3_router` in a typical debian instal of exim4.
- [55_mm3_transport](core/assets/exim/55_mm3_transport) to be placed at
`/etc/exim4/conf.d/main/55_mm3_transport` in a typical debian instal of exim4.
Setting up your web server
==========================
Although mailman-web runs uwsgi which can be used a full fledged web server, it
is recomended to run it behind a webserver like apache or nginx. I have included
setup instructions for nginx, but it is not difficult to find setup instructios
for Apache and Django.
Add the following to your nging's `/etc/nginx/site-available/default`
```
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name MY_SERVER_NAME;
location /static/ {
alias /opt/mailman/web/static/;
}
ssl_certificate /etc/letsencrypt/live/MY_DOMAIN_NAME/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/MY_DOMAIN_NAME/privkey.pem;
location / {
# First attempt to serve request as file, then
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://172.19.199.3:8000;
}
}
```
Please change MY_SERVER_NAME above to the domain name you will be serving the
Web UI from. It doesn't have to be same as the one used for Exim(or any MTA).
Also, change `ssl_certificate` and `ssl_certificate_key` options to point at
your SSL certificate and ceritfiicate keys. If you don't happen to have one, you
can get one for free from [Lets Encrypt][9]. They have a very nifty tool called
[certbot][10] that can be used to obtain the SSL certificates typically stored
in the location mentioned above in the configuraiton if you replace
MY_DOMAIN_NAME with your domain name.
SSL Certificates from Lets Encrypt need to be renewed every 90 days. You can
setup a cron job to do the job. I have this small shell script(certbot-renew.sh)
that you can put up in `/etc/cron.monthly` to get the job done.
```
#! /bin/bash
cd /opt/letsencrypt/
./certbot-auto --config /etc/letsencrypt/renewal/MY_DOMAIN_NAME.conf certonly
if [ $? -ne 0 ]
then
ERRORLOG=`tail /var/log/letsencrypt/letsencrypt.log`
echo -e "The Let's Encrypt cert has not been renewed! \n \n" \
$ERRORLOG
else
nginx -s reload
fi
exit 0
```
Please do not forget to make the script executable (chmod +x certbot-renew.sh).
[1]: http://list.org
[2]: https://www.docker.com/
[3]: https://docs.docker.com/compose/
[4]: http://docs.mailman3.org/en/latest/
[5]: https://docs.docker.com/engine/installation/
[6]: https://docs.docker.com/compose/install/
[7]: https://uwsgi-docs.readthedocs.io/en/latest/
[8]: http://exim.org/
[9]: https://letsencrypt.org/
[10]: https://certbot.eff.org/