diff options
Diffstat (limited to 'nixpkgs')
-rw-r--r-- | nixpkgs/nixos/modules/services/mail/public-inbox.nix | 440 |
1 files changed, 212 insertions, 228 deletions
diff --git a/nixpkgs/nixos/modules/services/mail/public-inbox.nix b/nixpkgs/nixos/modules/services/mail/public-inbox.nix index d503f5aa2ef6..c45ea7385b96 100644 --- a/nixpkgs/nixos/modules/services/mail/public-inbox.nix +++ b/nixpkgs/nixos/modules/services/mail/public-inbox.nix @@ -4,8 +4,9 @@ with lib; let cfg = config.services.public-inbox; + stateDir = "/var/lib/public-inbox"; - inboxesDir = "/var/lib/public-inbox/inboxes"; + inboxesDir = "${stateDir}/inboxes"; inboxPath = name: "${inboxesDir}/${name}"; gitPath = name: "${inboxPath name}/all.git"; @@ -48,25 +49,12 @@ let (concatStrings (map ({ name, value }: gitConfig name value) configList)); environment = { - PI_EMERGENCY = "/var/lib/public-inbox/emergency"; + PI_EMERGENCY = "${stateDir}/emergency"; PI_CONFIG = configFile; }; envList = mapAttrsToList (n: v: "${n}=${v}") environment; - # Can't use pkgs.linkFarm, - # because Postfix rejects .forward if it's a symlink. - home = pkgs.runCommand "public-inbox-home" { - forward = '' - |"env ${concatStringsSep " " envList} PATH=\"${makeBinPath cfg.path}:$PATH\" ${cfg.package}/bin/public-inbox-mda ${escapeShellArgs cfg.mda.args} - ''; - passAsFile = [ "forward" ]; - } '' - mkdir $out - ln -s /var/lib/public-inbox/spamassassin $out/.spamassassin - cp $forwardPath $out/.forward - ''; - psgi = pkgs.writeText "public-inbox.psgi" '' #!${cfg.package.fullperl} -w # Copyright (C) 2014-2019 all contributors <meta@public-inbox.org> @@ -99,236 +87,219 @@ let in { - options = { - services.public-inbox = { - enable = mkEnableOption "the public-inbox mail archiver"; + options.services.public-inbox = { + enable = mkEnableOption "the public-inbox mail archiver"; + package = mkOption { + type = types.package; + default = pkgs.public-inbox; + description = "public-inbox package to use."; + }; + path = mkOption { + type = with types; listOf package; + default = []; + example = literalExample "with pkgs; [ spamassassin ]"; + description = '' + Additional packages to place in the path of public-inbox-mda, + public-inbox-watch, etc. + ''; + }; + inboxes = mkOption { + description = '' + Inboxes to configure, where attribute names are inbox names. + ''; + type = with types; loaOf (submodule { + options = { + address = mkOption { + type = listOf str; + example = "example-discuss@example.org"; + }; - package = mkOption { - type = types.package; - default = pkgs.public-inbox; - description = '' - public-inbox package to use with the public-inbox module - ''; - }; + url = mkOption { + type = nullOr str; + default = null; + example = "https://example.org/lists/example-discuss"; + description = '' + URL where this inbox can be accessed over HTTP + ''; + }; - path = mkOption { - type = with types; listOf package; - default = []; - example = literalExample "with pkgs; [ spamassassin ]"; - description = '' - Additional packages to place in the path of public-inbox-mda, - public-inbox-watch, etc. - ''; - }; + description = mkOption { + type = str; + example = "user/dev discussion of public-inbox itself"; + description = '' + User-visible description for the repository + ''; + }; - inboxes = mkOption { - description = '' - Inboxes to configure, where attribute names are inbox names - ''; - type = with types; loaOf (submodule { - options = { - address = mkOption { - type = listOf str; - example = "example-discuss@example.org"; - }; - - url = mkOption { - type = nullOr str; - default = null; - example = "https://example.org/lists/example-discuss"; - description = '' - URL where this inbox can be accessed over HTTP - ''; - }; - - description = mkOption { - type = str; - example = "user/dev discussion of public-inbox itself"; - description = '' - User-visible description for the repository - ''; - }; - - config = mkOption { - type = attrs; - default = {}; - description = '' - Additional structured config for the inbox - ''; - }; - - newsgroup = mkOption { - type = nullOr str; - default = null; - description = '' - NNTP group name for the inbox - ''; - }; - - watch = mkOption { - type = listOf str; - default = []; - description = '' - Paths for public-inbox-watch(1) to monitor for new mail - ''; - example = [ "maildir:/path/to/test.example.com.git" ]; - }; - - watchHeader = mkOption { - type = nullOr str; - default = null; - example = "List-Id:<test@example.com>"; - description = '' - If specified, public-inbox-watch(1) will only process - mail containing a matching header. - ''; - }; + config = mkOption { + type = attrs; + default = {}; + description = '' + Additional structured config for the inbox + ''; }; - }); - }; - mda = { - args = mkOption { - type = with types; listOf str; - default = []; - description = '' - Command-line arguments to pass to public-inbox-mda(1). - ''; - }; + newsgroup = mkOption { + type = nullOr str; + default = null; + description = '' + NNTP group name for the inbox + ''; + }; - spamCheck = mkOption { - type = with types; nullOr (enum [ "spamc" ]); - default = "spamc"; - description = '' - If set to spamc, public-inbox-mda(1) will filter spam - using SpamAssassin - ''; - }; - }; + watch = mkOption { + type = listOf str; + default = []; + description = '' + Paths for public-inbox-watch(1) to monitor for new mail + ''; + example = [ "maildir:/path/to/test.example.com.git" ]; + }; - watch = { - spamCheck = mkOption { - type = with types; nullOr (enum [ "spamc" ]); - default = "spamc"; - description = '' - If set to spamc, public-inbox-watch(1) will filter spam - using SpamAssassin - ''; + watchHeader = mkOption { + type = nullOr str; + default = null; + example = "List-Id:<test@example.com>"; + description = '' + If specified, public-inbox-watch(1) will only process + mail containing a matching header. + ''; + }; }; + }); + }; - watchSpam = mkOption { - type = with types; nullOr str; - default = null; - example = "maildir:/path/to/spam"; - description = '' - If set, mail in this maildir will be trained as spam and - deleted from all watched inboxes - ''; - }; + mda = { + args = mkOption { + type = with types; listOf str; + default = []; + description = '' + Command-line arguments to pass to public-inbox-mda(1). + ''; }; - http = { - mounts = mkOption { - type = with types; listOf str; - default = [ "/" ]; - example = [ "/lists/archives" ]; - description = '' - Root paths or URLs that public-inbox will be served on. - If domain parts are present, only requests to those - domains will be accepted. - ''; - }; - - listenStreams = mkOption { - type = with types; listOf str; - default = [ "/run/public-inbox-httpd.sock" ]; - description = '' - systemd.socket(5) ListenStream values for the - public-inbox-httpd service to listen on - ''; - }; + spamCheck = mkOption { + type = with types; nullOr (enum [ "spamc" ]); + default = "spamc"; + description = '' + If set to spamc, public-inbox-mda(1) will filter spam + using SpamAssassin + ''; }; + }; - nntp = { - listenStreams = mkOption { - type = with types; listOf str; - default = [ "0.0.0.0:119" "0.0.0.0:563" ]; - description = '' - systemd.socket(5) ListenStream values for the - public-inbox-nntpd service to listen on - ''; - }; - - cert = mkOption { - type = with types; nullOr str; - default = null; - example = "/path/to/fullchain.pem"; - description = '' - Path to TLS certificate to use for public-inbox NNTP connections - ''; - }; - - key = mkOption { - type = with types; nullOr str; - default = null; - example = "/path/to/key.pem"; - description = '' - Path to TLS key to use for public-inbox NNTP connections - ''; - }; + watch = { + spamCheck = mkOption { + type = with types; nullOr (enum [ "spamc" ]); + default = "spamc"; + description = '' + If set to spamc, public-inbox-watch(1) will filter spam + using SpamAssassin + ''; + }; - extraGroups = mkOption { - type = with types; listOf str; - default = []; - example = [ "tls" ]; - description = '' - Secondary groups to assign to the systemd DynamicUser - running public-inbox-nntpd, in addition to the - public-inbox group. This is useful for giving - public-inbox-nntpd access to a TLS certificate / key, for - example. - ''; - }; + watchSpam = mkOption { + type = with types; nullOr str; + default = null; + example = "maildir:/path/to/spam"; + description = '' + If set, mail in this maildir will be trained as spam and + deleted from all watched inboxes + ''; }; + }; - nntpServer = mkOption { + http = { + enable = mkEnableOption "the public-inbox HTTP server"; + mounts = mkOption { type = with types; listOf str; - default = []; - example = [ "nntp://news.public-inbox.org" "nntps://news.public-inbox.org" ]; + default = [ "/" ]; + example = [ "/lists/archives" ]; description = '' - NNTP URLs to this public-inbox instance + Root paths or URLs that public-inbox will be served on. + If domain parts are present, only requests to those + domains will be accepted. ''; }; - - wwwListing = mkOption { - type = with types; enum [ "all" "404" "match=domain" ]; - default = "404"; + listenStreams = mkOption { + type = with types; listOf str; + default = [ "/run/public-inbox-httpd.sock" ]; description = '' - Controls which lists (if any) are listed for when the root - public-inbox URL is accessed over HTTP. + systemd.socket(5) ListenStream values for the + public-inbox-httpd service to listen on ''; }; - - spamAssassinRules = mkOption { - type = with types; nullOr path; - default = "${cfg.package.sa_config}/user/.spamassassin/user_prefs"; + }; + nntp = { + enable = mkEnableOption "the public-inbox NNTP server"; + listenStreams = mkOption { + type = with types; listOf str; + default = [ "0.0.0.0:119" "0.0.0.0:563" ]; description = '' - SpamAssassin configuration specific to public-inbox + systemd.socket(5) ListenStream values for the + public-inbox-nntpd service to listen on ''; }; + cert = mkOption { + type = with types; nullOr str; + default = null; + example = "/path/to/fullchain.pem"; + description = "Path to TLS certificate to use for public-inbox NNTP connections"; + }; + key = mkOption { + type = with types; nullOr str; + default = null; + example = "/path/to/key.pem"; + description = "Path to TLS key to use for public-inbox NNTP connections."; + }; - config = mkOption { - type = with types; attrsOf attrs; - default = {}; + extraGroups = mkOption { + type = with types; listOf str; + default = []; + example = [ "tls" ]; description = '' - Additional structured config for the public-inbox config file + Secondary groups to assign to the systemd DynamicUser + running public-inbox-nntpd, in addition to the + public-inbox group. This is useful for giving + public-inbox-nntpd access to a TLS certificate / key, for + example. ''; }; }; - }; - config = mkIf cfg.enable { + nntpServer = mkOption { + type = with types; listOf str; + default = []; + example = [ "nntp://news.public-inbox.org" "nntps://news.public-inbox.org" ]; + description = '' + NNTP URLs to this public-inbox instance + ''; + }; + wwwListing = mkOption { + type = with types; enum [ "all" "404" "match=domain" ]; + default = "404"; + description = '' + Controls which lists (if any) are listed for when the root + public-inbox URL is accessed over HTTP. + ''; + }; + + spamAssassinRules = mkOption { + type = with types; nullOr path; + default = "${cfg.package.sa_config}/user/.spamassassin/user_prefs"; + description = "SpamAssassin configuration specific to public-inbox."; + }; + + config = mkOption { + type = with types; attrsOf attrs; + default = {}; + description = '' + Additional structured config for the public-inbox config file + ''; + }; + }; + config = mkIf cfg.enable { assertions = [ { assertion = config.services.spamassassin.enable || !useSpamAssassin; message = '' @@ -349,25 +320,38 @@ in } ]; - users.users.public-inbox = { - inherit home; - group = "public-inbox"; - isSystemUser = true; - }; - users.groups.public-inbox = {}; + users = { + users.public-inbox = { + # Use runCommand instead of linkFarm, + # because Postfix rejects .forward if it's a symlink. + home = pkgs.runCommand "public-inbox-home" { + forward = '' + |"env ${concatStringsSep " " envList} PATH=\"${makeBinPath cfg.path}:$PATH\" ${cfg.package}/bin/public-inbox-mda ${escapeShellArgs cfg.mda.args} + ''; + passAsFile = [ "forward" ]; + } '' + mkdir $out + ln -s ${stateDir}/spamassassin $out/.spamassassin + cp $forwardPath $out/.forward + ''; + group = "public-inbox"; + isSystemUser = true; + }; + groups.public-inbox = {}; + }; - systemd.sockets.public-inbox-httpd = { + systemd.sockets.public-inbox-httpd = mkIf cfg.http.enable { inherit (cfg.http) listenStreams; wantedBy = [ "sockets.target" ]; }; - systemd.sockets.public-inbox-nntpd = { + systemd.sockets.public-inbox-nntpd = mkIf cfg.nntp.enable { inherit (cfg.nntp) listenStreams; wantedBy = [ "sockets.target" ]; }; - systemd.services.public-inbox-httpd = { + systemd.services.public-inbox-httpd = mkIf cfg.http.enable { inherit environment; serviceConfig.ExecStart = "${cfg.package}/bin/public-inbox-httpd ${psgi}"; serviceConfig.NonBlocking = true; @@ -375,7 +359,7 @@ in serviceConfig.SupplementaryGroups = [ "public-inbox" ]; }; - systemd.services.public-inbox-nntpd = { + systemd.services.public-inbox-nntpd = mkIf cfg.nntp.enable { inherit environment; serviceConfig.ExecStart = escapeShellArgs ( [ "${cfg.package}/bin/public-inbox-nntpd" ] ++ @@ -398,14 +382,14 @@ in }; system.activationScripts.public-inbox = stringAfter [ "users" ] '' - install -m 0755 -o public-inbox -g public-inbox -d /var/lib/public-inbox + install -m 0755 -o public-inbox -g public-inbox -d ${stateDir} install -m 0750 -o public-inbox -g public-inbox -d ${inboxesDir} - install -m 0700 -o public-inbox -g public-inbox -d /var/lib/public-inbox/emergency + install -m 0700 -o public-inbox -g public-inbox -d ${stateDir}/emergency ${optionalString useSpamAssassin '' - install -m 0700 -o spamd -d /var/lib/public-inbox/spamassassin + install -m 0700 -o spamd -d ${stateDir}/spamassassin ${optionalString (cfg.spamAssassinRules != null) '' - ln -sf ${cfg.spamAssassinRules} /var/lib/public-inbox/spamassassin/user_prefs + ln -sf ${cfg.spamAssassinRules} ${stateDir}/spamassassin/user_prefs ''} ''} @@ -436,7 +420,7 @@ in fi '') cfg.inboxes)} - for inbox in /var/lib/public-inbox/inboxes/*/; do + for inbox in ${stateDir}/inboxes/*/; do ls -1 "$inbox" | grep -q '^xap' && continue # This should be idempotent, but only do it for new @@ -450,6 +434,6 @@ in ''; environment.systemPackages = with pkgs; [ cfg.package ]; - }; + meta.maintainers = with lib.maintainers; [ julm ]; } |