{ pkgs, lib, config, ... }: with lib; let mailman3 = import ./release.nix { }; cfg = config.services.mailman3; usePostgresql = cfg.database.type == "postgresql"; useSqlite = cfg.database.type == "sqlite3"; useMysql = cfg.database.type == "mysql"; usePostfix = cfg.mta.type == "postfix"; configFile_postfix = pkgs.writeText "postfix.cfg" '' [postfix] transport_file_type: hash postmap_command: ${pkgs.postfix}/bin/postmap ''; configFile = pkgs.writeText "mailman.cfg" '' # This File was automatically generated by the mailman3 nixos submodule. # Do not manually edit this file. [mailman] site_owner: ${cfg.site_owner} layout: custom [paths.custom] archive_dir: ${cfg.paths.archive_dir} bin_dir: ${cfg.paths.bin_dir} cache_dir: ${cfg.paths.cache_dir} data_dir: ${cfg.paths.data_dir} etc_dir: ${cfg.paths.etc_dir} lock_dir: ${cfg.paths.lock_dir} log_dir: ${cfg.paths.log_dir} messages_dir: ${cfg.paths.messages_dir} template_dir: ${cfg.paths.template_dir} var_dir: ${cfg.paths.var_dir} lock_file: ${cfg.paths.lock_file} pid_file: ${cfg.paths.pid_file} # The Database Documentation can be found here: # https://mailman.readthedocs.io/en/latest/src/mailman/docs/database.html # https://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls [database] ${optionalString useSqlite '' [database] url: sqlite:///${cfg.database.socket} ''} ${optionalString usePostgresql '' class: mailman.database.postgresql.PostgreSQLDatabase url: postgres://${cfg.database.user}:#dbpass#@${database.host}:${toString cfg.database.port}/${cfg.database.name} ''} ${optionalString useMysql '' class: mailman.database.mysql.MySQLDatabase url: mysql+pymysql://${cfg.database.user}:#dbpass#@${cfg.database.host}:${toString cfg.database.port}/${cfg.database.name}?charset=utf8&use_unicode=1 ''} [mta] incoming: ${cfg.mta.incoming} outgoing: ${cfg.mta.outgoing} lmtp_host: ${cfg.mta.lmtp_host} lmtp_port: ${toString cfg.mta.lmtp_port} smtp_host: ${cfg.mta.smtp_host} smtp_port: ${toString cfg.mta.smtp_port} smtp_user: ${cfg.mta.smtp_user} smtp_pass: #smtppass# # One of smtp/smtps/starttls, specifies the protocol Mailman will use when # connecting. Typically will correspond to smtp_port: 25 -> smtp, 465 -> smtps, # 587 -> starttls. smtp_secure_mode: smtp configuration: ${configFile_postfix} [ARC] enabled: no ${cfg.extraConfig} ''; in { options.services.mailman3 = { enable = mkOption { type = types.bool; default = false; example = true; description = '' Wether to enable mailman3 mailing list management system (core). ''; }; site_owner = mkOption { type = types.str; default = "changeme@example.com"; description = '' mailman3 site owner address. ''; }; user = mkOption { type = types.str; default = "mailman3"; description = '' User account under which mailman runs. ''; }; database = { type = mkOption { type = types.enum [ "sqlite3" "mysql" "postgres" ]; default = "sqlite3"; example = "mysql"; description = '' Database type to use. ''; }; host = mkOption { type = types.str; default = "172.0.0.1"; description = '' Database host adress. ''; }; port = mkOption { type = types.nullOr types.int; default = null; description = '' ''; }; name = mkOption { type = types.str; default = "mailman3"; description = '' Database name. ''; }; user = mkOption { type = types.str; default = "mailman3"; description = '' Database user. ''; }; password = mkOption { type = types.str; default = ""; description = '' The password corresponding to . Warning: this is stored in cleartext in the Nix store! Use instead. ''; }; passwordFile = mkOption { type = types.nullOr types.path; default = null; example = "/run/keys/mailman3-dbpassword"; description = '' A file containing the password corresponding to . ''; }; socket = mkOption { type = types.nullOr types.path; default = null; example = "/run/mysqld/mysqld.sock"; description = "Path to the unix socket file to use for authentication."; }; }; paths = { archive_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/archives"; description = '' ''; }; bin_dir = mkOption { type = types.str; default = "${mailman3.core}/bin"; description = '' ''; }; cache_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/cache"; description = '' ''; }; data_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/data"; description = '' ''; }; etc_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/etc"; description = '' ''; }; lock_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/locks"; description = '' ''; }; log_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/logs"; description = '' ''; }; messages_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/messages"; description = '' ''; }; template_dir = mkOption { type = types.str; default = "${cfg.paths.var_dir}/templates"; description = '' ''; }; var_dir = mkOption { type = types.str; default = "/var/lib/mailman3"; description = '' ''; }; lock_file = mkOption { type = types.path; default = "${cfg.paths.lock_dir}/master.lck"; description = '' ''; }; pid_file = mkOption { type = types.path; default = "${cfg.paths.var_dir}/master.pid"; description = '' ''; }; }; mta = { # TODO: add Sentmail and qmail type = mkOption { type = types.enum [ "postfix" "exim4" ]; default = "postfix"; example = "exim4"; description = '' Database type to use. ''; }; incoming = mkOption { type = types.str; default = "mailman.mta.${cfg.mta.type}.LMTP"; description = '' ''; }; outgoing = mkOption { type = types.str; default = "mailman.mta.deliver.deliver"; description = '' ''; }; lmtp_host = mkOption { type = types.str; default = "mail.example.com"; description = '' ''; }; lmtp_port = mkOption { type = types.int; default = 8024; description = '' ''; }; smtp_host = mkOption { type = types.str; default = "mail.example.com"; description = '' ''; }; smtp_port = mkOption { type = types.int; default = 25; description = '' ''; }; smtp_user = mkOption { type = types.str; default = ""; description = '' ''; }; smtp_pass = mkOption { type = types.str; default = ""; description = '' ''; }; smtp_passFile = mkOption { type = types.str; default = ""; description = '' ''; }; }; extraConfig = mkOption { type = types.str; default = ""; example = '' [devmode] enabled: yes recipient: your.address@your.domain ''; description = '' Configuration lines appended to the generated mailman3 configuration file. ''; }; }; config = mkIf cfg.enable { users = mkIf (cfg.user == "mailman3") { users.mailman3 = { description = "Mailman3 Service"; home = cfg.paths.var_dir; createHome = true; useDefaultShell = true; packages = [ mailman3.core ]; }; }; services.postfix.recipientDelimiter = mkIf usePostfix (mkDefault "+"); services.postfix.mapFiles."transport_maps" = mkIf usePostfix ( mkDefault "${cfg.paths.data_dir}/postfix_lmtp" ); services.postfix.mapFiles."local_recipient_maps" = mkIf usePostfix ( mkDefault "${cfg.paths.data_dir}/postfix_lmtp" ); services.postfix.mapFiles."relay_domains" = mkIf usePostfix ( mkDefault "${cfg.paths.data_dir}/postfix_domains" ); warnings = optional (cfg.database.password != "") '' config.services.mailman3.database.password will be stored as plaintext in the Nix store. Use database.passwordFile instead.''; # Create database passwordFile default when password is configured. services.mailman3.database.passwordFile = mkDefault ( toString ( pkgs.writeTextFile { name = "mailman3-database-password"; text = cfg.database.password; } ) ); systemd.services.mailman3 = { description = "GNU Mailing List Manager"; after = [ "network.target" ] ++ lib.optional usePostgresql "postgresql.service" ++ lib.optional useMysql "mysql.service"; wantedBy = [ "multi-user.target" ]; preStart = let dbpass = fileContents cfg.database.passwordFile; smtppass = fileContents cfg.mta.smtp_passFile; in '' mkdir -p ${cfg.paths.etc_dir} cp ${configFile} ${cfg.paths.etc_dir}/mailman.cfg ${optionalString (useMysql || usePostgresql) '' sed -e "s/#dbpass#/${dbpass}/g" -e "s/#smtppass#/${smtppass}/g" -i ${cfg.paths.etc_dir}/mailman.cfg ''} chmod 640 ${cfg.paths.etc_dir}/mailman.cfg ''; serviceConfig = { Type = "forking"; User = cfg.user; WorkingDirectory = cfg.paths.var_dir; ExecStart = "${mailman3.core}/bin/mailman start -f"; ExecReload = "${mailman3.core}/bin/mailman restart"; ExecStop = "${mailman3.core}/bin/mailman stop"; }; environment = { USER = cfg.user; HOME = cfg.paths.var_dir; MAILMAN_CONFIG_FILE = "${cfg.paths.etc_dir}/mailman.cfg"; }; }; }; }