nixos/mailman: add support for the Mailman Web UI (Postorius & Hyperkitty)
This commit is contained in:
@@ -6,14 +6,14 @@ let
|
||||
|
||||
cfg = config.services.mailman;
|
||||
|
||||
pythonEnv = pkgs.python3.withPackages (ps: [ps.mailman]);
|
||||
mailmanPyEnv = pkgs.python3.withPackages (ps: [ps.mailman ps.mailman-hyperkitty]);
|
||||
|
||||
mailmanExe = with pkgs; stdenv.mkDerivation {
|
||||
name = "mailman-" + python3Packages.mailman.version;
|
||||
unpackPhase = ":";
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
sed >"$out/bin/mailman" <"${pythonEnv}/bin/mailman" \
|
||||
sed >"$out/bin/mailman" <"${mailmanPyEnv}/bin/mailman" \
|
||||
-e "2 iexport MAILMAN_CONFIG_FILE=/etc/mailman.cfg"
|
||||
chmod +x $out/bin/mailman
|
||||
'';
|
||||
@@ -28,13 +28,40 @@ let
|
||||
bin_dir: ${pkgs.python3Packages.mailman}/bin
|
||||
var_dir: /var/lib/mailman
|
||||
queue_dir: $var_dir/queue
|
||||
template_dir: $var_dir/templates
|
||||
log_dir: $var_dir/log
|
||||
lock_dir: $var_dir/lock
|
||||
etc_dir: /etc
|
||||
ext_dir: $etc_dir/mailman.d
|
||||
pid_file: /run/mailman/master.pid
|
||||
'' + optionalString (cfg.hyperkittyApiKey != null) ''
|
||||
[archiver.hyperkitty]
|
||||
class: mailman_hyperkitty.Archiver
|
||||
enable: yes
|
||||
configuration: ${pkgs.writeText "mailman-hyperkitty.cfg" mailmanHyperkittyCfg}
|
||||
'';
|
||||
|
||||
mailmanHyperkittyCfg = ''
|
||||
[general]
|
||||
# This is your HyperKitty installation, preferably on the localhost. This
|
||||
# address will be used by Mailman to forward incoming emails to HyperKitty
|
||||
# for archiving. It does not need to be publicly available, in fact it's
|
||||
# better if it is not.
|
||||
base_url: ${cfg.hyperkittyBaseUrl}
|
||||
|
||||
# Shared API key, must be the identical to the value in HyperKitty's
|
||||
# settings.
|
||||
api_key: ${cfg.hyperkittyApiKey}
|
||||
'';
|
||||
|
||||
djangoPyEnv = pkgs.python3.withPackages (x: with x; [postorius hyperkitty]);
|
||||
|
||||
djangoExe = with pkgs; stdenv.mkDerivation {
|
||||
name = "mailman-django-" + python3Packages.mailman.version;
|
||||
unpackPhase = ":";
|
||||
installPhase = "install -D ${djangoPyEnv}/bin/django-admin $out/bin/mailman-django-admin";
|
||||
};
|
||||
|
||||
in {
|
||||
|
||||
###### interface
|
||||
@@ -51,7 +78,7 @@ in {
|
||||
|
||||
siteOwner = mkOption {
|
||||
type = types.str;
|
||||
default = "postmaster";
|
||||
default = "postmaster@example.org";
|
||||
description = ''
|
||||
Certain messages that must be delivered to a human, but which can't
|
||||
be delivered to a list owner (e.g. a bounce from a list owner), will
|
||||
@@ -59,6 +86,51 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
webRoot = mkOption {
|
||||
type = types.path;
|
||||
default = pkgs.python3Packages.mailman-web.override { serverEMail = cfg.siteOwner;
|
||||
archiverKey = cfg.hyperkittyApiKey;
|
||||
allowedHosts = cfg.webHosts;
|
||||
};
|
||||
defaultText = "pkgs.python3Packages.mailman-web";
|
||||
description = ''
|
||||
The web root for the Hyperkity + Postorius apps provided by Mailman.
|
||||
This variable can be set, of course, but it mainly exists so that site
|
||||
admins can refer to it in their own hand-written httpd configuration files.
|
||||
'';
|
||||
};
|
||||
|
||||
webHosts = mkOption {
|
||||
type = types.listOf types.string;
|
||||
default = [];
|
||||
description = ''
|
||||
The list of hostnames and/or IP addresses from which the Mailman Web
|
||||
UI will accept requests. By default, "localhost" and "127.0.0.1" are
|
||||
enabled. All additional names under which your web server accepts
|
||||
requests for the UI must be listed here or incoming requests will be
|
||||
rejected.
|
||||
'';
|
||||
};
|
||||
|
||||
hyperkittyBaseUrl = mkOption {
|
||||
type = types.str;
|
||||
default = "http://localhost/hyperkitty/";
|
||||
description = ''
|
||||
Where can Mailman connect to Hyperkitty's internal API, preferably on
|
||||
localhost?
|
||||
'';
|
||||
};
|
||||
|
||||
hyperkittyApiKey = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The shared secret used to authenticate Mailman's internal
|
||||
communication with Hyperkitty. Must be set to enable support for the
|
||||
Hyperkitty archiver. Note that this secret is going to be visible to
|
||||
all local users in the Nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
@@ -71,25 +143,22 @@ in {
|
||||
{ assertion = cfg.enable -> config.services.postfix.enable;
|
||||
message = "Mailman requires Postfix";
|
||||
}
|
||||
{ assertion = config.services.postfix.recipientDelimiter == "+";
|
||||
message = "Postfix's recipientDelimiter must be set to '+'.";
|
||||
}
|
||||
];
|
||||
|
||||
users.users.mailman = { description = "GNU Mailman"; isSystemUser = true; };
|
||||
|
||||
environment = {
|
||||
systemPackages = [ mailmanExe ];
|
||||
systemPackages = [ mailmanExe djangoExe pkgs.sassc ];
|
||||
etc."mailman.cfg".text = mailmanCfg;
|
||||
};
|
||||
|
||||
services.postfix = {
|
||||
relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ];
|
||||
recipientDelimiter = "+"; # bake recipient addresses in mail envelopes via VERP
|
||||
config = {
|
||||
transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
|
||||
local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
|
||||
# Mailman uses recipient delimiters, so we don't need special handling.
|
||||
owner_request_special = "no";
|
||||
owner_request_special = "no"; # Mailman handles -owner addresses on its own
|
||||
};
|
||||
};
|
||||
|
||||
@@ -109,6 +178,112 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.mailman-web = {
|
||||
description = "Init Postorius DB";
|
||||
before = [ "httpd.service" ];
|
||||
wantedBy = [ "httpd.service" ];
|
||||
script = ''
|
||||
${djangoExe}/bin/mailman-django-admin migrate --pythonpath ${cfg.webRoot} --settings settings
|
||||
rm -rf static
|
||||
${djangoExe}/bin/mailman-django-admin collectstatic --pythonpath ${cfg.webRoot} --settings settings
|
||||
${djangoExe}/bin/mailman-django-admin compress --pythonpath ${cfg.webRoot} --settings settings
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = config.services.httpd.user;
|
||||
Type = "oneshot";
|
||||
StateDirectory = "mailman-web";
|
||||
StateDirectoryMode = "0700";
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.mailman-daily = {
|
||||
description = "Trigger daily Mailman events";
|
||||
startAt = "daily";
|
||||
serviceConfig = {
|
||||
ExecStart = "${mailmanExe}/bin/mailman digests --send";
|
||||
User = "mailman";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hyperkitty = {
|
||||
enable = cfg.hyperkittyApiKey != null;
|
||||
description = "GNU Hyperkitty QCluster Process";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "mailman.service" "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${djangoExe}/bin/mailman-django-admin qcluster --pythonpath ${cfg.webRoot} --settings settings";
|
||||
User = config.services.httpd.user;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hyperkitty-minutely = {
|
||||
enable = cfg.hyperkittyApiKey != null;
|
||||
description = "Trigger minutely Hyperkitty events";
|
||||
startAt = "minutely";
|
||||
serviceConfig = {
|
||||
ExecStart = "${djangoExe}/bin/mailman-django-admin runjobs minutely --pythonpath ${cfg.webRoot} --settings settings";
|
||||
User = config.services.httpd.user;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hyperkitty-quarter-hourly = {
|
||||
enable = cfg.hyperkittyApiKey != null;
|
||||
description = "Trigger quarter-hourly Hyperkitty events";
|
||||
startAt = "*:00/15";
|
||||
serviceConfig = {
|
||||
ExecStart = "${djangoExe}/bin/mailman-django-admin runjobs quarter_hourly --pythonpath ${cfg.webRoot} --settings settings";
|
||||
User = config.services.httpd.user;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hyperkitty-hourly = {
|
||||
enable = cfg.hyperkittyApiKey != null;
|
||||
description = "Trigger hourly Hyperkitty events";
|
||||
startAt = "hourly";
|
||||
serviceConfig = {
|
||||
ExecStart = "${djangoExe}/bin/mailman-django-admin runjobs hourly --pythonpath ${cfg.webRoot} --settings settings";
|
||||
User = config.services.httpd.user;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hyperkitty-daily = {
|
||||
enable = cfg.hyperkittyApiKey != null;
|
||||
description = "Trigger daily Hyperkitty events";
|
||||
startAt = "daily";
|
||||
serviceConfig = {
|
||||
ExecStart = "${djangoExe}/bin/mailman-django-admin runjobs daily --pythonpath ${cfg.webRoot} --settings settings";
|
||||
User = config.services.httpd.user;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hyperkitty-weekly = {
|
||||
enable = cfg.hyperkittyApiKey != null;
|
||||
description = "Trigger weekly Hyperkitty events";
|
||||
startAt = "weekly";
|
||||
serviceConfig = {
|
||||
ExecStart = "${djangoExe}/bin/mailman-django-admin runjobs weekly --pythonpath ${cfg.webRoot} --settings settings";
|
||||
User = config.services.httpd.user;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hyperkitty-yearly = {
|
||||
enable = cfg.hyperkittyApiKey != null;
|
||||
description = "Trigger yearly Hyperkitty events";
|
||||
startAt = "yearly";
|
||||
serviceConfig = {
|
||||
ExecStart = "${djangoExe}/bin/mailman-django-admin runjobs yearly --pythonpath ${cfg.webRoot} --settings settings";
|
||||
User = config.services.httpd.user;
|
||||
WorkingDirectory = "/var/lib/mailman-web";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user