422 lines
11 KiB
Nix
422 lines
11 KiB
Nix
|
{ 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 <option>database.user</option>.
|
||
|
Warning: this is stored in cleartext in the Nix store!
|
||
|
Use <option>database.passwordFile</option> instead.
|
||
|
'';
|
||
|
};
|
||
|
|
||
|
passwordFile = mkOption {
|
||
|
type = types.nullOr types.path;
|
||
|
default = null;
|
||
|
example = "/run/keys/mailman3-dbpassword";
|
||
|
description = ''
|
||
|
A file containing the password corresponding to
|
||
|
<option>database.user</option>.
|
||
|
'';
|
||
|
};
|
||
|
|
||
|
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";
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
}
|