about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorPeter Simons <simons@cryp.to>2019-09-01 20:33:47 +0200
committerPeter Simons <simons@cryp.to>2019-09-11 12:19:23 +0200
commit72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b (patch)
tree81677e67bda83b285e09402e65edba846d1f9980 /nixos
parent14854f20bb8002fa70828c820233ec05b177d04f (diff)
downloadnixlib-72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b.tar
nixlib-72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b.tar.gz
nixlib-72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b.tar.bz2
nixlib-72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b.tar.lz
nixlib-72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b.tar.xz
nixlib-72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b.tar.zst
nixlib-72c7ba5aba1d8dde9da8f4e7b5805edb30cbad7b.zip
nixos/mailman: add support for the Mailman Web UI (Postorius & Hyperkitty)
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/services/mail/mailman.nix193
1 files changed, 184 insertions, 9 deletions
diff --git a/nixos/modules/services/mail/mailman.nix b/nixos/modules/services/mail/mailman.nix
index 11dd5cb48db0..93f4d8899553 100644
--- a/nixos/modules/services/mail/mailman.nix
+++ b/nixos/modules/services/mail/mailman.nix
@@ -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";
+      };
+    };
+
   };
 
 }