Mailman
Requires at least NixOS 20.03; the services.mailman
module in NixOS 19.09 is insufficient.
This example includes:
- Postfix as the MTA
- uwsgi to host Mailman's web interface and archives (Postorius and Hyperkitty)
- nginx to terminate TLS, proxy to uwsgi, and serve static assets
- letsencrypt to acquire TLS certificates for nginx
{ config, pkgs, ... }:
let
OWNER_EMAIL = "postmaster@example.org"; # Change this!
MAILMAN_HOST = "mailman.example.org"; # Change this!
in
{
services.postfix = {
enable = true;
relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
config = {
transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
};
};
services.mailman = {
enable = true;
siteOwner = OWNER_EMAIL;
webUser = config.services.uwsgi.user;
hyperkitty.enable = true;
webHosts = [MAILMAN_HOST];
};
# Make sure that uwsgi gets restarted if any django settings change.
# I'm not sure why this isn't covered by the "before" and
# "requiredBy" settings present in mailman-web.service. Maybe
# because it's a oneshot and not a daemon?
systemd.services.uwsgi.restartTriggers = [
config.environment.etc."mailman3/settings.py".source
];
# Tweak permissions so nginx can read and serve the static assets
# (/var/lib/mailman-web defaults to mode 0600)
systemd.services.uwsgi.preStart = ''
chmod o+x /var/lib/mailman-web
'';
services.uwsgi = {
enable = true;
plugins = ["python3"];
instance = {
type = "normal";
pythonPackages = (
# TODO: I hope there is a nicer way of doing this:
self: with self.override {
overrides = self: super: { django = self.django_1_11; };
}; [ mailman-web ]
);
socket = "127.0.0.1:33140";
wsgi-file = "${config.services.mailman.webRoot}/mailman_web/wsgi.py";
chdir = "/var/lib/mailman-web";
master = true;
processes = 4;
vacuum = true;
};
};
security.acme.email = OWNER_EMAIL;
security.acme.acceptTerms = true;
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts.${MAILMAN_HOST} = {
enableACME = true;
forceSSL = true;
locations."/static/".alias = "/var/lib/mailman-web/static/";
locations."/".extraConfig = ''
uwsgi_pass 127.0.0.1:33140;
include ${config.services.nginx.package}/conf/uwsgi_params;
'';
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
}