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/rss2email.nix
|
||||
./services/mail/roundcube.nix
|
||||
./services/mail/sympa.nix
|
||||
./services/mail/nullmailer.nix
|
||||
./services/misc/airsonic.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 {};
|
||||
sudo = handleTest ./sudo.nix {};
|
||||
switchTest = handleTest ./switch-test.nix {};
|
||||
sympa = handleTest ./sympa.nix {};
|
||||
syncthing-init = handleTest ./syncthing-init.nix {};
|
||||
syncthing-relay = handleTest ./syncthing-relay.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 { };
|
||||
|
||||
sympa = callPackage ../servers/mail/sympa { };
|
||||
|
||||
system-sendmail = lowPrio (callPackage ../servers/mail/system-sendmail { });
|
||||
|
||||
# PulseAudio daemons
|
||||
|
@ -8524,6 +8524,33 @@ let
|
||||
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 {
|
||||
pname = "HTML-TableExtract";
|
||||
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 {
|
||||
pname = "MIME-tools";
|
||||
version = "5.509";
|
||||
|
Loading…
Reference in New Issue
Block a user