parent
e39d7fab27
commit
097ab90850
@ -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 ]; |
||||
} |
@ -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/" |
||||
) |
||||
''; |
||||
}) |
Loading…
Reference in new issue