Merge pull request #65397 from mmilata/sympa
sympa: init at 6.2.52 + NixOS module
This commit is contained in:
commit
b9d7f1fe24
@ -401,6 +401,7 @@
|
|||||||
./services/mail/rspamd.nix
|
./services/mail/rspamd.nix
|
||||||
./services/mail/rss2email.nix
|
./services/mail/rss2email.nix
|
||||||
./services/mail/roundcube.nix
|
./services/mail/roundcube.nix
|
||||||
|
./services/mail/sympa.nix
|
||||||
./services/mail/nullmailer.nix
|
./services/mail/nullmailer.nix
|
||||||
./services/misc/airsonic.nix
|
./services/misc/airsonic.nix
|
||||||
./services/misc/apache-kafka.nix
|
./services/misc/apache-kafka.nix
|
||||||
|
596
nixos/modules/services/mail/sympa.nix
Normal file
596
nixos/modules/services/mail/sympa.nix
Normal file
@ -0,0 +1,596 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.sympa;
|
||||||
|
dataDir = "/var/lib/sympa";
|
||||||
|
user = "sympa";
|
||||||
|
group = "sympa";
|
||||||
|
pkg = pkgs.sympa;
|
||||||
|
fqdns = attrNames cfg.domains;
|
||||||
|
usingNginx = cfg.web.enable && cfg.web.server == "nginx";
|
||||||
|
mysqlLocal = cfg.database.createLocally && cfg.database.type == "MySQL";
|
||||||
|
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "PostgreSQL";
|
||||||
|
|
||||||
|
sympaSubServices = [
|
||||||
|
"sympa-archive.service"
|
||||||
|
"sympa-bounce.service"
|
||||||
|
"sympa-bulk.service"
|
||||||
|
"sympa-task.service"
|
||||||
|
];
|
||||||
|
|
||||||
|
# common for all services including wwsympa
|
||||||
|
commonServiceConfig = {
|
||||||
|
StateDirectory = "sympa";
|
||||||
|
ProtectHome = true;
|
||||||
|
ProtectSystem = "full";
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# wwsympa has its own service config
|
||||||
|
sympaServiceConfig = srv: {
|
||||||
|
Type = "simple";
|
||||||
|
Restart = "always";
|
||||||
|
ExecStart = "${pkg}/bin/${srv}.pl --foreground";
|
||||||
|
PIDFile = "/run/sympa/${srv}.pid";
|
||||||
|
User = user;
|
||||||
|
Group = group;
|
||||||
|
|
||||||
|
# avoid duplicating log messageges in journal
|
||||||
|
StandardError = "null";
|
||||||
|
} // commonServiceConfig;
|
||||||
|
|
||||||
|
configVal = value:
|
||||||
|
if isBool value then
|
||||||
|
if value then "on" else "off"
|
||||||
|
else toString value;
|
||||||
|
configGenerator = c: concatStrings (flip mapAttrsToList c (key: val: "${key}\t${configVal val}\n"));
|
||||||
|
|
||||||
|
mainConfig = pkgs.writeText "sympa.conf" (configGenerator cfg.settings);
|
||||||
|
robotConfig = fqdn: domain: pkgs.writeText "${fqdn}-robot.conf" (configGenerator domain.settings);
|
||||||
|
|
||||||
|
transport = pkgs.writeText "transport.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
|
||||||
|
${domain} error:User unknown in recipient table
|
||||||
|
sympa@${domain} sympa:sympa@${domain}
|
||||||
|
listmaster@${domain} sympa:listmaster@${domain}
|
||||||
|
bounce@${domain} sympabounce:sympa@${domain}
|
||||||
|
abuse-feedback-report@${domain} sympabounce:sympa@${domain}
|
||||||
|
'')));
|
||||||
|
|
||||||
|
virtual = pkgs.writeText "virtual.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
|
||||||
|
sympa-request@${domain} postmaster@localhost
|
||||||
|
sympa-owner@${domain} postmaster@localhost
|
||||||
|
'')));
|
||||||
|
|
||||||
|
listAliases = pkgs.writeText "list_aliases.tt2" ''
|
||||||
|
#--- [% list.name %]@[% list.domain %]: list transport map created at [% date %]
|
||||||
|
[% list.name %]@[% list.domain %] sympa:[% list.name %]@[% list.domain %]
|
||||||
|
[% list.name %]-request@[% list.domain %] sympa:[% list.name %]-request@[% list.domain %]
|
||||||
|
[% list.name %]-editor@[% list.domain %] sympa:[% list.name %]-editor@[% list.domain %]
|
||||||
|
#[% list.name %]-subscribe@[% list.domain %] sympa:[% list.name %]-subscribe@[%list.domain %]
|
||||||
|
[% list.name %]-unsubscribe@[% list.domain %] sympa:[% list.name %]-unsubscribe@[% list.domain %]
|
||||||
|
[% list.name %][% return_path_suffix %]@[% list.domain %] sympabounce:[% list.name %]@[% list.domain %]
|
||||||
|
'';
|
||||||
|
|
||||||
|
enabledFiles = filterAttrs (n: v: v.enable) cfg.settingsFile;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
###### interface
|
||||||
|
options.services.sympa = with types; {
|
||||||
|
|
||||||
|
enable = mkEnableOption "Sympa mailing list manager";
|
||||||
|
|
||||||
|
lang = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "en_US";
|
||||||
|
example = "cs";
|
||||||
|
description = ''
|
||||||
|
Default Sympa language.
|
||||||
|
See <link xlink:href='https://github.com/sympa-community/sympa/tree/sympa-6.2/po/sympa' />
|
||||||
|
for available options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
listMasters = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
example = [ "postmaster@sympa.example.org" ];
|
||||||
|
description = ''
|
||||||
|
The list of the email addresses of the listmasters
|
||||||
|
(users authorized to perform global server commands).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mainDomain = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
example = "lists.example.org";
|
||||||
|
description = ''
|
||||||
|
Main domain to be used in <filename>sympa.conf</filename>.
|
||||||
|
If <literal>null</literal>, one of the <option>services.sympa.domains</option> is chosen for you.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
domains = mkOption {
|
||||||
|
type = attrsOf (submodule ({ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
webHost = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
example = "archive.example.org";
|
||||||
|
description = ''
|
||||||
|
Domain part of the web interface URL (no web interface for this domain if <literal>null</literal>).
|
||||||
|
DNS record of type A (or AAAA or CNAME) has to exist with this value.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
webLocation = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "/";
|
||||||
|
example = "/sympa";
|
||||||
|
description = "URL path part of the web interface.";
|
||||||
|
};
|
||||||
|
settings = mkOption {
|
||||||
|
type = attrsOf (oneOf [ str int bool ]);
|
||||||
|
default = {};
|
||||||
|
example = {
|
||||||
|
default_max_list_members = 3;
|
||||||
|
};
|
||||||
|
description = ''
|
||||||
|
The <filename>robot.conf</filename> configuration file as key value set.
|
||||||
|
See <link xlink:href='https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html' />
|
||||||
|
for list of configuration parameters.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config.settings = mkIf (cfg.web.enable && config.webHost != null) {
|
||||||
|
wwsympa_url = mkDefault "https://${config.webHost}${strings.removeSuffix "/" config.webLocation}";
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
Email domains handled by this instance. There have
|
||||||
|
to be MX records for keys of this attribute set.
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
"lists.example.org" = {
|
||||||
|
webHost = "lists.example.org";
|
||||||
|
webLocation = "/";
|
||||||
|
};
|
||||||
|
"sympa.example.com" = {
|
||||||
|
webHost = "example.com";
|
||||||
|
webLocation = "/sympa";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
database = {
|
||||||
|
type = mkOption {
|
||||||
|
type = enum [ "SQLite" "PostgreSQL" "MySQL" ];
|
||||||
|
default = "SQLite";
|
||||||
|
example = "MySQL";
|
||||||
|
description = "Database engine to use.";
|
||||||
|
};
|
||||||
|
|
||||||
|
host = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Database host address.
|
||||||
|
|
||||||
|
For MySQL, use <literal>localhost</literal> to connect using Unix domain socket.
|
||||||
|
|
||||||
|
For PostgreSQL, use path to directory (e.g. <filename>/run/postgresql</filename>)
|
||||||
|
to connect using Unix domain socket located in this directory.
|
||||||
|
|
||||||
|
Use <literal>null</literal> to fall back on Sympa default, or when using
|
||||||
|
<option>services.sympa.database.createLocally</option>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = nullOr port;
|
||||||
|
default = null;
|
||||||
|
description = "Database port. Use <literal>null</literal> for default port.";
|
||||||
|
};
|
||||||
|
|
||||||
|
name = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = if cfg.database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa";
|
||||||
|
defaultText = ''if database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa"'';
|
||||||
|
description = ''
|
||||||
|
Database name. When using SQLite this must be an absolute
|
||||||
|
path to the database file.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = user;
|
||||||
|
description = "Database user. The system user name is used as a default.";
|
||||||
|
};
|
||||||
|
|
||||||
|
passwordFile = mkOption {
|
||||||
|
type = nullOr path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/keys/sympa-dbpassword";
|
||||||
|
description = ''
|
||||||
|
A file containing the password for <option>services.sympa.database.user</option>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
createLocally = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to create a local database automatically.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
web = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to enable Sympa web interface.";
|
||||||
|
};
|
||||||
|
|
||||||
|
server = mkOption {
|
||||||
|
type = enum [ "nginx" "none" ];
|
||||||
|
default = "nginx";
|
||||||
|
description = ''
|
||||||
|
The webserver used for the Sympa web interface. Set it to `none` if you want to configure it yourself.
|
||||||
|
Further nginx configuration can be done by adapting
|
||||||
|
<option>services.nginx.virtualHosts.<replaceable>name</replaceable></option>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
https = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to use HTTPS. When nginx integration is enabled, this option forces SSL and enables ACME.
|
||||||
|
Please note that Sympa web interface always uses https links even when this option is disabled.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
fcgiProcs = mkOption {
|
||||||
|
type = ints.positive;
|
||||||
|
default = 2;
|
||||||
|
description = "Number of FastCGI processes to fork.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mta = {
|
||||||
|
type = mkOption {
|
||||||
|
type = enum [ "postfix" "none" ];
|
||||||
|
default = "postfix";
|
||||||
|
description = ''
|
||||||
|
Mail transfer agent (MTA) integration. Use <literal>none</literal> if you want to configure it yourself.
|
||||||
|
|
||||||
|
The <literal>postfix</literal> integration sets up local Postfix instance that will pass incoming
|
||||||
|
messages from configured domains to Sympa. You still need to configure at least outgoing message
|
||||||
|
handling using e.g. <option>services.postfix.relayHost</option>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
type = attrsOf (oneOf [ str int bool ]);
|
||||||
|
default = {};
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
default_home = "lists";
|
||||||
|
viewlogs_page_size = 50;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
The <filename>sympa.conf</filename> configuration file as key value set.
|
||||||
|
See <link xlink:href='https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html' />
|
||||||
|
for list of configuration parameters.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
settingsFile = mkOption {
|
||||||
|
type = attrsOf (submodule ({ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether this file should be generated. This option allows specific files to be disabled.";
|
||||||
|
};
|
||||||
|
text = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = nullOr lines;
|
||||||
|
description = "Text of the file.";
|
||||||
|
};
|
||||||
|
source = mkOption {
|
||||||
|
type = path;
|
||||||
|
description = "Path of the source file.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config.source = mkIf (config.text != null) (mkDefault (pkgs.writeText "sympa-${baseNameOf name}" config.text));
|
||||||
|
}));
|
||||||
|
default = {};
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
"list_data/lists.example.org/help" = {
|
||||||
|
text = "subject This list provides help to users";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
description = "Set of files to be linked in <filename>${dataDir}</filename>.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
services.sympa.settings = (mapAttrs (_: v: mkDefault v) {
|
||||||
|
domain = if cfg.mainDomain != null then cfg.mainDomain else head fqdns;
|
||||||
|
listmaster = concatStringsSep "," cfg.listMasters;
|
||||||
|
lang = cfg.lang;
|
||||||
|
|
||||||
|
home = "${dataDir}/list_data";
|
||||||
|
arc_path = "${dataDir}/arc";
|
||||||
|
bounce_path = "${dataDir}/bounce";
|
||||||
|
|
||||||
|
sendmail = "${pkgs.system-sendmail}/bin/sendmail";
|
||||||
|
|
||||||
|
db_type = cfg.database.type;
|
||||||
|
db_name = cfg.database.name;
|
||||||
|
}
|
||||||
|
// (optionalAttrs (cfg.database.host != null) {
|
||||||
|
db_host = cfg.database.host;
|
||||||
|
})
|
||||||
|
// (optionalAttrs mysqlLocal {
|
||||||
|
db_host = "localhost"; # use unix domain socket
|
||||||
|
})
|
||||||
|
// (optionalAttrs pgsqlLocal {
|
||||||
|
db_host = "/run/postgresql"; # use unix domain socket
|
||||||
|
})
|
||||||
|
// (optionalAttrs (cfg.database.port != null) {
|
||||||
|
db_port = cfg.database.port;
|
||||||
|
})
|
||||||
|
// (optionalAttrs (cfg.database.user != null) {
|
||||||
|
db_user = cfg.database.user;
|
||||||
|
})
|
||||||
|
// (optionalAttrs (cfg.mta.type == "postfix") {
|
||||||
|
sendmail_aliases = "${dataDir}/sympa_transport";
|
||||||
|
aliases_program = "${pkgs.postfix}/bin/postmap";
|
||||||
|
aliases_db_type = "hash";
|
||||||
|
})
|
||||||
|
// (optionalAttrs cfg.web.enable {
|
||||||
|
static_content_path = "${dataDir}/static_content";
|
||||||
|
css_path = "${dataDir}/static_content/css";
|
||||||
|
pictures_path = "${dataDir}/static_content/pictures";
|
||||||
|
mhonarc = "${pkgs.perlPackages.MHonArc}/bin/mhonarc";
|
||||||
|
}));
|
||||||
|
|
||||||
|
services.sympa.settingsFile = {
|
||||||
|
"virtual.sympa" = mkDefault { source = virtual; };
|
||||||
|
"transport.sympa" = mkDefault { source = transport; };
|
||||||
|
"etc/list_aliases.tt2" = mkDefault { source = listAliases; };
|
||||||
|
}
|
||||||
|
// (flip mapAttrs' cfg.domains (fqdn: domain:
|
||||||
|
nameValuePair "etc/${fqdn}/robot.conf" (mkDefault { source = robotConfig fqdn domain; })));
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
systemPackages = [ pkg ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.${user} = {
|
||||||
|
description = "Sympa mailing list manager user";
|
||||||
|
group = group;
|
||||||
|
home = dataDir;
|
||||||
|
createHome = false;
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.${group} = {};
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{ assertion = cfg.database.createLocally -> cfg.database.user == user;
|
||||||
|
message = "services.sympa.database.user must be set to ${user} if services.sympa.database.createLocally is set to true";
|
||||||
|
}
|
||||||
|
{ assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
|
||||||
|
message = "a password cannot be specified if services.sympa.database.createLocally is set to true";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d ${dataDir} 0711 ${user} ${group} - -"
|
||||||
|
"d ${dataDir}/etc 0700 ${user} ${group} - -"
|
||||||
|
"d ${dataDir}/spool 0700 ${user} ${group} - -"
|
||||||
|
"d ${dataDir}/list_data 0700 ${user} ${group} - -"
|
||||||
|
"d ${dataDir}/arc 0700 ${user} ${group} - -"
|
||||||
|
"d ${dataDir}/bounce 0700 ${user} ${group} - -"
|
||||||
|
"f ${dataDir}/sympa_transport 0600 ${user} ${group} - -"
|
||||||
|
|
||||||
|
# force-copy static_content so it's up to date with package
|
||||||
|
# set permissions for wwsympa which needs write access (...)
|
||||||
|
"R ${dataDir}/static_content - - - - -"
|
||||||
|
"C ${dataDir}/static_content 0711 ${user} ${group} - ${pkg}/static_content"
|
||||||
|
"e ${dataDir}/static_content/* 0711 ${user} ${group} - -"
|
||||||
|
|
||||||
|
"d /run/sympa 0755 ${user} ${group} - -"
|
||||||
|
]
|
||||||
|
++ (flip concatMap fqdns (fqdn: [
|
||||||
|
"d ${dataDir}/etc/${fqdn} 0700 ${user} ${group} - -"
|
||||||
|
"d ${dataDir}/list_data/${fqdn} 0700 ${user} ${group} - -"
|
||||||
|
]))
|
||||||
|
#++ (flip mapAttrsToList enabledFiles (k: v:
|
||||||
|
# "L+ ${dataDir}/${k} - - - - ${v.source}"
|
||||||
|
#))
|
||||||
|
++ (concatLists (flip mapAttrsToList enabledFiles (k: v: [
|
||||||
|
# sympa doesn't handle symlinks well (e.g. fails to create locks)
|
||||||
|
# force-copy instead
|
||||||
|
"R ${dataDir}/${k} - - - - -"
|
||||||
|
"C ${dataDir}/${k} 0700 ${user} ${group} - ${v.source}"
|
||||||
|
])));
|
||||||
|
|
||||||
|
systemd.services.sympa = {
|
||||||
|
description = "Sympa mailing list manager";
|
||||||
|
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network-online.target" ];
|
||||||
|
wants = sympaSubServices;
|
||||||
|
before = sympaSubServices;
|
||||||
|
serviceConfig = sympaServiceConfig "sympa_msg";
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
umask 0077
|
||||||
|
|
||||||
|
cp -f ${mainConfig} ${dataDir}/etc/sympa.conf
|
||||||
|
${optionalString (cfg.database.passwordFile != null) ''
|
||||||
|
chmod u+w ${dataDir}/etc/sympa.conf
|
||||||
|
echo -n "db_passwd " >> ${dataDir}/etc/sympa.conf
|
||||||
|
cat ${cfg.database.passwordFile} >> ${dataDir}/etc/sympa.conf
|
||||||
|
''}
|
||||||
|
|
||||||
|
${optionalString (cfg.mta.type == "postfix") ''
|
||||||
|
${pkgs.postfix}/bin/postmap hash:${dataDir}/virtual.sympa
|
||||||
|
${pkgs.postfix}/bin/postmap hash:${dataDir}/transport.sympa
|
||||||
|
''}
|
||||||
|
${pkg}/bin/sympa_newaliases.pl
|
||||||
|
${pkg}/bin/sympa.pl --health_check
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
systemd.services.sympa-archive = {
|
||||||
|
description = "Sympa mailing list manager (archiving)";
|
||||||
|
bindsTo = [ "sympa.service" ];
|
||||||
|
serviceConfig = sympaServiceConfig "archived";
|
||||||
|
};
|
||||||
|
systemd.services.sympa-bounce = {
|
||||||
|
description = "Sympa mailing list manager (bounce processing)";
|
||||||
|
bindsTo = [ "sympa.service" ];
|
||||||
|
serviceConfig = sympaServiceConfig "bounced";
|
||||||
|
};
|
||||||
|
systemd.services.sympa-bulk = {
|
||||||
|
description = "Sympa mailing list manager (message distribution)";
|
||||||
|
bindsTo = [ "sympa.service" ];
|
||||||
|
serviceConfig = sympaServiceConfig "bulk";
|
||||||
|
};
|
||||||
|
systemd.services.sympa-task = {
|
||||||
|
description = "Sympa mailing list manager (task management)";
|
||||||
|
bindsTo = [ "sympa.service" ];
|
||||||
|
serviceConfig = sympaServiceConfig "task_manager";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.wwsympa = mkIf usingNginx {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "sympa.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "forking";
|
||||||
|
PIDFile = "/run/sympa/wwsympa.pid";
|
||||||
|
Restart = "always";
|
||||||
|
ExecStart = ''${pkgs.spawn_fcgi}/bin/spawn-fcgi \
|
||||||
|
-u ${user} \
|
||||||
|
-g ${group} \
|
||||||
|
-U nginx \
|
||||||
|
-M 0600 \
|
||||||
|
-F ${toString cfg.web.fcgiProcs} \
|
||||||
|
-P /run/sympa/wwsympa.pid \
|
||||||
|
-s /run/sympa/wwsympa.socket \
|
||||||
|
-- ${pkg}/bin/wwsympa.fcgi
|
||||||
|
'';
|
||||||
|
|
||||||
|
} // commonServiceConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.enable = mkIf usingNginx true;
|
||||||
|
services.nginx.virtualHosts = mkIf usingNginx (let
|
||||||
|
vHosts = unique (remove null (mapAttrsToList (_k: v: v.webHost) cfg.domains));
|
||||||
|
hostLocations = host: map (v: v.webLocation) (filter (v: v.webHost == host) (attrValues cfg.domains));
|
||||||
|
httpsOpts = optionalAttrs cfg.web.https { forceSSL = mkDefault true; enableACME = mkDefault true; };
|
||||||
|
in
|
||||||
|
genAttrs vHosts (host: {
|
||||||
|
locations = genAttrs (hostLocations host) (loc: {
|
||||||
|
extraConfig = ''
|
||||||
|
include ${config.services.nginx.package}/conf/fastcgi_params;
|
||||||
|
|
||||||
|
fastcgi_pass unix:/run/sympa/wwsympa.socket;
|
||||||
|
fastcgi_split_path_info ^(${loc})(.*)$;
|
||||||
|
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_param SCRIPT_FILENAME ${pkg}/bin/wwsympa.fcgi;
|
||||||
|
'';
|
||||||
|
}) // {
|
||||||
|
"/static-sympa/".alias = "${dataDir}/static_content/";
|
||||||
|
};
|
||||||
|
} // httpsOpts));
|
||||||
|
|
||||||
|
services.postfix = mkIf (cfg.mta.type == "postfix") {
|
||||||
|
enable = true;
|
||||||
|
recipientDelimiter = "+";
|
||||||
|
config = {
|
||||||
|
virtual_alias_maps = [ "hash:${dataDir}/virtual.sympa" ];
|
||||||
|
virtual_mailbox_maps = [
|
||||||
|
"hash:${dataDir}/transport.sympa"
|
||||||
|
"hash:${dataDir}/sympa_transport"
|
||||||
|
"hash:${dataDir}/virtual.sympa"
|
||||||
|
];
|
||||||
|
virtual_mailbox_domains = [ "hash:${dataDir}/transport.sympa" ];
|
||||||
|
transport_maps = [
|
||||||
|
"hash:${dataDir}/transport.sympa"
|
||||||
|
"hash:${dataDir}/sympa_transport"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
masterConfig = {
|
||||||
|
"sympa" = {
|
||||||
|
type = "unix";
|
||||||
|
privileged = true;
|
||||||
|
chroot = false;
|
||||||
|
command = "pipe";
|
||||||
|
args = [
|
||||||
|
"flags=hqRu"
|
||||||
|
"user=${user}"
|
||||||
|
"argv=${pkg}/bin/queue"
|
||||||
|
"\${nexthop}"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"sympabounce" = {
|
||||||
|
type = "unix";
|
||||||
|
privileged = true;
|
||||||
|
chroot = false;
|
||||||
|
command = "pipe";
|
||||||
|
args = [
|
||||||
|
"flags=hqRu"
|
||||||
|
"user=${user}"
|
||||||
|
"argv=${pkg}/bin/bouncequeue"
|
||||||
|
"\${nexthop}"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.mysql = optionalAttrs mysqlLocal {
|
||||||
|
enable = true;
|
||||||
|
package = mkDefault pkgs.mariadb;
|
||||||
|
ensureDatabases = [ cfg.database.name ];
|
||||||
|
ensureUsers = [
|
||||||
|
{ name = cfg.database.user;
|
||||||
|
ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql = optionalAttrs pgsqlLocal {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [ cfg.database.name ];
|
||||||
|
ensureUsers = [
|
||||||
|
{ name = cfg.database.user;
|
||||||
|
ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; };
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
meta.maintainers = with maintainers; [ mmilata sorki ];
|
||||||
|
}
|
@ -270,6 +270,7 @@ in
|
|||||||
strongswan-swanctl = handleTest ./strongswan-swanctl.nix {};
|
strongswan-swanctl = handleTest ./strongswan-swanctl.nix {};
|
||||||
sudo = handleTest ./sudo.nix {};
|
sudo = handleTest ./sudo.nix {};
|
||||||
switchTest = handleTest ./switch-test.nix {};
|
switchTest = handleTest ./switch-test.nix {};
|
||||||
|
sympa = handleTest ./sympa.nix {};
|
||||||
syncthing-init = handleTest ./syncthing-init.nix {};
|
syncthing-init = handleTest ./syncthing-init.nix {};
|
||||||
syncthing-relay = handleTest ./syncthing-relay.nix {};
|
syncthing-relay = handleTest ./syncthing-relay.nix {};
|
||||||
systemd = handleTest ./systemd.nix {};
|
systemd = handleTest ./systemd.nix {};
|
||||||
|
36
nixos/tests/sympa.nix
Normal file
36
nixos/tests/sympa.nix
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import ./make-test-python.nix ({ pkgs, lib, ... }: {
|
||||||
|
name = "sympa";
|
||||||
|
meta.maintainers = with lib.maintainers; [ mmilata ];
|
||||||
|
|
||||||
|
machine =
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
virtualisation.memorySize = 1024;
|
||||||
|
|
||||||
|
services.sympa = {
|
||||||
|
enable = true;
|
||||||
|
domains = {
|
||||||
|
"lists.example.org" = {
|
||||||
|
webHost = "localhost";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
listMasters = [ "joe@example.org" ];
|
||||||
|
web.enable = true;
|
||||||
|
web.https = false;
|
||||||
|
database = {
|
||||||
|
type = "PostgreSQL";
|
||||||
|
createLocally = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
start_all()
|
||||||
|
|
||||||
|
machine.wait_for_unit("sympa.service")
|
||||||
|
machine.wait_for_unit("wwsympa.service")
|
||||||
|
assert "Mailing lists service" in machine.succeed(
|
||||||
|
"curl --insecure -L http://localhost/"
|
||||||
|
)
|
||||||
|
'';
|
||||||
|
})
|
116
pkgs/servers/mail/sympa/default.nix
Normal file
116
pkgs/servers/mail/sympa/default.nix
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
{ stdenv, perl, fetchFromGitHub, autoreconfHook
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
dataDir = "/var/lib/sympa";
|
||||||
|
runtimeDir = "/run/sympa";
|
||||||
|
perlEnv = perl.withPackages (p: with p; [
|
||||||
|
ArchiveZip
|
||||||
|
CGI
|
||||||
|
CGIFast
|
||||||
|
ClassSingleton
|
||||||
|
DateTime
|
||||||
|
DBI
|
||||||
|
DateTimeFormatMail
|
||||||
|
DateTimeTimeZone
|
||||||
|
DigestMD5
|
||||||
|
Encode
|
||||||
|
FCGI
|
||||||
|
FileCopyRecursive
|
||||||
|
FileNFSLock
|
||||||
|
FilePath
|
||||||
|
HTMLParser
|
||||||
|
HTMLFormatter
|
||||||
|
HTMLTree
|
||||||
|
HTMLStripScriptsParser
|
||||||
|
IO
|
||||||
|
IOStringy
|
||||||
|
LWP
|
||||||
|
libintl_perl
|
||||||
|
|
||||||
|
MHonArc
|
||||||
|
MIMEBase64
|
||||||
|
MIMECharset
|
||||||
|
MIMETools
|
||||||
|
MIMEEncWords
|
||||||
|
MIMELiteHTML
|
||||||
|
MailTools
|
||||||
|
NetCIDR
|
||||||
|
ScalarListUtils
|
||||||
|
SysSyslog
|
||||||
|
TermProgressBar
|
||||||
|
TemplateToolkit
|
||||||
|
URI
|
||||||
|
UnicodeLineBreak
|
||||||
|
XMLLibXML
|
||||||
|
|
||||||
|
### Features
|
||||||
|
Clone
|
||||||
|
CryptEksblowfish
|
||||||
|
|
||||||
|
DBDPg
|
||||||
|
DBDSQLite
|
||||||
|
DBDmysql
|
||||||
|
|
||||||
|
DataPassword
|
||||||
|
EncodeLocale
|
||||||
|
IOSocketSSL
|
||||||
|
MailDKIM
|
||||||
|
NetDNS
|
||||||
|
NetLDAP
|
||||||
|
NetSMTP
|
||||||
|
SOAPLite
|
||||||
|
]);
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "sympa";
|
||||||
|
version = "6.2.52";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "sympa-community";
|
||||||
|
repo = pname;
|
||||||
|
rev = version;
|
||||||
|
sha256 = "071kx6ryifs2f6fhfky9g297frzp5584kn444af1vb2imzydsbnh";
|
||||||
|
};
|
||||||
|
|
||||||
|
configureFlags = [
|
||||||
|
"--without-initdir"
|
||||||
|
"--without-unitsdir"
|
||||||
|
"--without-smrshdir"
|
||||||
|
|
||||||
|
"--with-lockdir=${runtimeDir}"
|
||||||
|
"--with-piddir=${runtimeDir}"
|
||||||
|
"--with-confdir=${dataDir}/etc"
|
||||||
|
"--sysconfdir=${dataDir}/etc"
|
||||||
|
"--with-spooldir=${dataDir}/spool"
|
||||||
|
"--with-expldir=${dataDir}/list_data"
|
||||||
|
];
|
||||||
|
nativeBuildInputs = [ autoreconfHook ];
|
||||||
|
buildInputs = [ perlEnv ];
|
||||||
|
patches = [ ./make-docs.patch ];
|
||||||
|
|
||||||
|
prePatch = ''
|
||||||
|
patchShebangs po/sympa/add-lang.pl
|
||||||
|
'';
|
||||||
|
|
||||||
|
preInstall = ''
|
||||||
|
mkdir "$TMP/bin"
|
||||||
|
for i in chown chgrp chmod; do
|
||||||
|
echo '#!${stdenv.shell}' >> "$TMP/bin/$i"
|
||||||
|
chmod +x "$TMP/bin/$i"
|
||||||
|
done
|
||||||
|
PATH="$TMP/bin:$PATH"
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
rm -rf "$TMP/bin"
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with stdenv.lib; {
|
||||||
|
description = "Open source mailing list manager";
|
||||||
|
homepage = "https://www.sympa.org";
|
||||||
|
license = licenses.gpl2;
|
||||||
|
maintainers = with maintainers; [ sorki mmilata ];
|
||||||
|
platforms = platforms.all;
|
||||||
|
};
|
||||||
|
}
|
11
pkgs/servers/mail/sympa/make-docs.patch
Normal file
11
pkgs/servers/mail/sympa/make-docs.patch
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
diff -ur sympa-6.2.44-orig/doc/Makefile.am sympa-6.2.44/doc/Makefile.am
|
||||||
|
--- sympa-6.2.44-orig/doc/Makefile.am 2019-08-29 01:57:43.512539087 +0200
|
||||||
|
+++ sympa-6.2.44/doc/Makefile.am 2019-08-29 01:58:24.393531358 +0200
|
||||||
|
@@ -83,6 +83,4 @@
|
||||||
|
--lax --release="$(VERSION)" $< $@
|
||||||
|
|
||||||
|
.podpl.pod:
|
||||||
|
- $(AM_V_GEN)PERL5LIB=$(top_builddir)/src/lib:$(top_srcdir)/src/lib; \
|
||||||
|
- export PERL5LIB; \
|
||||||
|
- $(PERL) $< --top_srcdir=$(top_srcdir) > $*.pod
|
||||||
|
+ $(AM_V_GEN)$(PERL) -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib $< --top_srcdir=$(top_srcdir) > $*.pod
|
@ -15438,6 +15438,8 @@ in
|
|||||||
|
|
||||||
pshs = callPackage ../servers/http/pshs { };
|
pshs = callPackage ../servers/http/pshs { };
|
||||||
|
|
||||||
|
sympa = callPackage ../servers/mail/sympa { };
|
||||||
|
|
||||||
system-sendmail = lowPrio (callPackage ../servers/mail/system-sendmail { });
|
system-sendmail = lowPrio (callPackage ../servers/mail/system-sendmail { });
|
||||||
|
|
||||||
# PulseAudio daemons
|
# PulseAudio daemons
|
||||||
|
@ -8524,6 +8524,33 @@ let
|
|||||||
buildInputs = [ TestDifferences TestMemoryCycle ];
|
buildInputs = [ TestDifferences TestMemoryCycle ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HTMLStripScripts = buildPerlPackage {
|
||||||
|
pname = "HTML-StripScripts";
|
||||||
|
version = "1.06";
|
||||||
|
src = fetchurl {
|
||||||
|
url = mirror://cpan/authors/id/D/DR/DRTECH/HTML-StripScripts-1.06.tar.gz;
|
||||||
|
sha256 = "222bfb7ec1fdfa465e32da3dc4abed2edc7364bbe19e8e3c513c7d585b0109ad";
|
||||||
|
};
|
||||||
|
meta = {
|
||||||
|
description = "Strip scripting constructs out of HTML";
|
||||||
|
license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLStripScriptsParser = buildPerlPackage {
|
||||||
|
pname = "HTML-StripScripts-Parser";
|
||||||
|
version = "1.03";
|
||||||
|
src = fetchurl {
|
||||||
|
url = mirror://cpan/authors/id/D/DR/DRTECH/HTML-StripScripts-Parser-1.03.tar.gz;
|
||||||
|
sha256 = "478c1a4e46eb77fa7bce96ba288168f0b98c27f250e00dc6312365081aed3407";
|
||||||
|
};
|
||||||
|
propagatedBuildInputs = [ HTMLParser HTMLStripScripts ];
|
||||||
|
meta = {
|
||||||
|
description = "XSS filter using HTML::Parser";
|
||||||
|
license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
HTMLTableExtract = buildPerlPackage {
|
HTMLTableExtract = buildPerlPackage {
|
||||||
pname = "HTML-TableExtract";
|
pname = "HTML-TableExtract";
|
||||||
version = "2.13";
|
version = "2.13";
|
||||||
@ -11418,6 +11445,21 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MIMELiteHTML = buildPerlPackage {
|
||||||
|
pname = "MIME-Lite-HTML";
|
||||||
|
version = "1.24";
|
||||||
|
src = fetchurl {
|
||||||
|
url = mirror://cpan/authors/id/A/AL/ALIAN/MIME-Lite-HTML-1.24.tar.gz;
|
||||||
|
sha256 = "db603ccbf6653bcd28cfa824d72e511ead019fc8afb9f1854ec872db2d3cd8da";
|
||||||
|
};
|
||||||
|
doCheck = false;
|
||||||
|
propagatedBuildInputs = [ HTMLParser LWP MIMELite URI ];
|
||||||
|
meta = {
|
||||||
|
description = "Provide routine to transform a HTML page in a MIME-Lite mail";
|
||||||
|
license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
MIMETools = buildPerlPackage {
|
MIMETools = buildPerlPackage {
|
||||||
pname = "MIME-tools";
|
pname = "MIME-tools";
|
||||||
version = "5.509";
|
version = "5.509";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user