about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/services/mail/mailman.nix
blob: 11dd5cb48db04154a6f442cf1b0fa4b858d77764 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{ config, pkgs, lib, ... }:          # mailman.nix

with lib;

let

  cfg = config.services.mailman;

  pythonEnv = pkgs.python3.withPackages (ps: [ps.mailman]);

  mailmanExe = with pkgs; stdenv.mkDerivation {
    name = "mailman-" + python3Packages.mailman.version;
    unpackPhase = ":";
    installPhase = ''
      mkdir -p $out/bin
      sed >"$out/bin/mailman" <"${pythonEnv}/bin/mailman" \
        -e "2 iexport MAILMAN_CONFIG_FILE=/etc/mailman.cfg"
      chmod +x $out/bin/mailman
    '';
  };

  mailmanCfg = ''
    [mailman]
    site_owner: ${cfg.siteOwner}
    layout: fhs

    [paths.fhs]
    bin_dir: ${pkgs.python3Packages.mailman}/bin
    var_dir: /var/lib/mailman
    queue_dir: $var_dir/queue
    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
  '';

in {

  ###### interface

  options = {

    services.mailman = {

      enable = mkOption {
        type = types.bool;
        default = false;
        description = "Enable Mailman on this host. Requires an active Postfix installation.";
      };

      siteOwner = mkOption {
        type = types.str;
        default = "postmaster";
        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
          be sent to this address. It should point to a human.
        '';
      };


    };
  };

  ###### implementation

  config = mkIf cfg.enable {

    assertions = [
      { 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 ];
      etc."mailman.cfg".text = mailmanCfg;
    };

    services.postfix = {
      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" ];
        # Mailman uses recipient delimiters, so we don't need special handling.
        owner_request_special = "no";
      };
    };

    systemd.services.mailman = {
      description = "GNU Mailman Master Process";
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        ExecStart = "${mailmanExe}/bin/mailman start";
        ExecStop = "${mailmanExe}/bin/mailman stop";
        User = "mailman";
        Type = "forking";
        StateDirectory = "mailman";
        StateDirectoryMode = "0700";
        RuntimeDirectory = "mailman";
        PIDFile = "/run/mailman/master.pid";
      };
    };

  };

}