Merge pull request #135463 from mayflower/init-postfixadmin

postfixadmin: init at 3.3.10
This commit is contained in:
Maximilian Bosch 2021-08-25 00:16:09 +02:00 committed by GitHub
commit a674bfbff4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 272 additions and 0 deletions

@ -199,6 +199,14 @@
<link linkend="opt-services.xserver.displayManager.sx.enable">services.xserver.displayManager.sx</link> <link linkend="opt-services.xserver.displayManager.sx.enable">services.xserver.displayManager.sx</link>
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<link xlink:href="https://postfixadmin.sourceforge.io/">postfixadmin</link>,
a web based virtual user administration interface for Postfix
mail servers. Available as
<link linkend="opt-services.postfixadmin.enable">postfixadmin</link>.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section xml:id="sec-release-21.11-incompatibilities"> <section xml:id="sec-release-21.11-incompatibilities">

@ -60,6 +60,8 @@ subsonic-compatible api. Available as [navidrome](#opt-services.navidrome.enable
- [sx](https://github.com/earnestly/sx), a simple alternative to both xinit and startx for starting a Xorg server. Available as [services.xserver.displayManager.sx](#opt-services.xserver.displayManager.sx.enable) - [sx](https://github.com/earnestly/sx), a simple alternative to both xinit and startx for starting a Xorg server. Available as [services.xserver.displayManager.sx](#opt-services.xserver.displayManager.sx.enable)
- [postfixadmin](https://postfixadmin.sourceforge.io/), a web based virtual user administration interface for Postfix mail servers. Available as [postfixadmin](#opt-services.postfixadmin.enable).
## Backward Incompatibilities {#sec-release-21.11-incompatibilities} ## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
- The `paperless` module and package have been removed. All users should migrate to the - The `paperless` module and package have been removed. All users should migrate to the

@ -460,6 +460,7 @@
./services/mail/opensmtpd.nix ./services/mail/opensmtpd.nix
./services/mail/pfix-srsd.nix ./services/mail/pfix-srsd.nix
./services/mail/postfix.nix ./services/mail/postfix.nix
./services/mail/postfixadmin.nix
./services/mail/postsrsd.nix ./services/mail/postsrsd.nix
./services/mail/postgrey.nix ./services/mail/postgrey.nix
./services/mail/spamassassin.nix ./services/mail/spamassassin.nix

@ -0,0 +1,199 @@
{ lib, config, pkgs, ... }:
with lib;
let
cfg = config.services.postfixadmin;
fpm = config.services.phpfpm.pools.postfixadmin;
localDB = cfg.database.host == "localhost";
user = if localDB then cfg.database.username else "nginx";
in
{
options.services.postfixadmin = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable postfixadmin.
Also enables nginx virtual host management.
Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
'';
};
hostName = mkOption {
type = types.str;
example = "postfixadmin.example.com";
description = "Hostname to use for the nginx vhost";
};
adminEmail = mkOption {
type = types.str;
example = "postmaster@example.com";
description = ''
Defines the Site Admin's email address.
This will be used to send emails from to create mailboxes and
from Send Email / Broadcast message pages.
'';
};
setupPasswordFile = mkOption {
type = types.path;
description = ''
Password file for the admin.
Generate with <literal>php -r "echo password_hash('some password here', PASSWORD_DEFAULT);"</literal>
'';
};
database = {
username = mkOption {
type = types.str;
default = "postfixadmin";
description = ''
Username for the postgresql connection.
If <literal>database.host</literal> is set to <literal>localhost</literal>, a unix user and group of the same name will be created as well.
'';
};
host = mkOption {
type = types.str;
default = "localhost";
description = ''
Host of the postgresql server. If this is not set to
<literal>localhost</literal>, you have to create the
postgresql user and database yourself, with appropriate
permissions.
'';
};
passwordFile = mkOption {
type = types.path;
description = "Password file for the postgresql connection. Must be readable by user <literal>nginx</literal>.";
};
dbname = mkOption {
type = types.str;
default = "postfixadmin";
description = "Name of the postgresql database";
};
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = "Extra configuration for the postfixadmin instance, see postfixadmin's config.inc.php for available options.";
};
};
config = mkIf cfg.enable {
environment.etc."postfixadmin/config.local.php".text = ''
<?php
$CONF['setup_password'] = file_get_contents('${cfg.setupPasswordFile}');
$CONF['database_type'] = 'pgsql';
$CONF['database_host'] = ${if localDB then "null" else "'${cfg.database.host}'"};
${optionalString localDB "$CONF['database_user'] = '${cfg.database.username}';"}
$CONF['database_password'] = ${if localDB then "'dummy'" else "file_get_contents('${cfg.database.passwordFile}')"};
$CONF['database_name'] = '${cfg.database.dbname}';
$CONF['configured'] = true;
${cfg.extraConfig}
'';
systemd.tmpfiles.rules = [ "d /var/cache/postfixadmin/templates_c 700 ${user} ${user}" ];
services.nginx = {
enable = true;
virtualHosts = {
${cfg.hostName} = {
forceSSL = mkDefault true;
enableACME = mkDefault true;
locations."/" = {
root = "${pkgs.postfixadmin}/public";
index = "index.php";
extraConfig = ''
location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${fpm.socket};
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
}
'';
};
};
};
};
services.postgresql = mkIf localDB {
enable = true;
ensureUsers = [ {
name = cfg.database.username;
} ];
};
# The postgresql module doesn't currently support concepts like
# objects owners and extensions; for now we tack on what's needed
# here.
systemd.services.postfixadmin-postgres = let pgsql = config.services.postgresql; in mkIf localDB {
after = [ "postgresql.service" ];
bindsTo = [ "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
path = [
pgsql.package
pkgs.util-linux
];
script = ''
set -eu
PSQL() {
psql --port=${toString pgsql.port} "$@"
}
PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${cfg.database.dbname}'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "${cfg.database.dbname}" OWNER "${cfg.database.username}"'
current_owner=$(PSQL -tAc "SELECT pg_catalog.pg_get_userbyid(datdba) FROM pg_catalog.pg_database WHERE datname = '${cfg.database.dbname}'")
if [[ "$current_owner" != "${cfg.database.username}" ]]; then
PSQL -tAc 'ALTER DATABASE "${cfg.database.dbname}" OWNER TO "${cfg.database.username}"'
if [[ -e "${config.services.postgresql.dataDir}/.reassigning_${cfg.database.dbname}" ]]; then
echo "Reassigning ownership of database ${cfg.database.dbname} to user ${cfg.database.username} failed on last boot. Failing..."
exit 1
fi
touch "${config.services.postgresql.dataDir}/.reassigning_${cfg.database.dbname}"
PSQL "${cfg.database.dbname}" -tAc "REASSIGN OWNED BY \"$current_owner\" TO \"${cfg.database.username}\""
rm "${config.services.postgresql.dataDir}/.reassigning_${cfg.database.dbname}"
fi
'';
serviceConfig = {
User = pgsql.superUser;
Type = "oneshot";
RemainAfterExit = true;
};
};
users.users.${user} = mkIf localDB {
group = user;
isSystemUser = true;
createHome = false;
};
users.groups.${user} = mkIf localDB {};
services.phpfpm.pools.postfixadmin = {
user = user;
phpPackage = pkgs.php74;
phpOptions = ''
error_log = 'stderr'
log_errors = on
'';
settings = mapAttrs (name: mkDefault) {
"listen.owner" = "nginx";
"listen.group" = "nginx";
"listen.mode" = "0660";
"pm" = "dynamic";
"pm.max_children" = 75;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 20;
"pm.max_requests" = 500;
"catch_workers_output" = true;
};
};
};
}

@ -356,6 +356,7 @@ in
pomerium = handleTestOn ["x86_64-linux"] ./pomerium.nix {}; pomerium = handleTestOn ["x86_64-linux"] ./pomerium.nix {};
postfix = handleTest ./postfix.nix {}; postfix = handleTest ./postfix.nix {};
postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {}; postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {};
postfixadmin = handleTest ./postfixadmin.nix {};
postgis = handleTest ./postgis.nix {}; postgis = handleTest ./postgis.nix {};
postgresql = handleTest ./postgresql.nix {}; postgresql = handleTest ./postgresql.nix {};
postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {}; postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {};

@ -0,0 +1,31 @@
import ./make-test-python.nix ({ pkgs, ...} : {
name = "postfixadmin";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ globin ];
};
nodes = {
postfixadmin = { config, pkgs, ... }: {
services.postfixadmin = {
enable = true;
hostName = "postfixadmin";
setupPasswordFile = pkgs.writeText "insecure-test-setup-pw-file" "$2y$10$r0p63YCjd9rb9nHrV9UtVuFgGTmPDLKu.0UIJoQTkWCZZze2iuB1m";
};
services.nginx.virtualHosts.postfixadmin = {
forceSSL = false;
enableACME = false;
};
};
};
testScript = ''
postfixadmin.start
postfixadmin.wait_for_unit("postgresql.service")
postfixadmin.wait_for_unit("phpfpm-postfixadmin.service")
postfixadmin.wait_for_unit("nginx.service")
postfixadmin.succeed(
"curl -sSfL http://postfixadmin/setup.php -X POST -F 'setup_password=not production'"
)
postfixadmin.succeed("curl -sSfL http://postfixadmin/ | grep 'Mail admins login here'")
'';
})

@ -0,0 +1,28 @@
{ fetchFromGitHub, stdenv, lib }:
stdenv.mkDerivation rec {
pname = "postfixadmin";
version = "3.3.10";
src = fetchFromGitHub {
owner = pname;
repo = pname;
rev = "${pname}-${version}";
sha256 = "0xck6df96r4z8k2j8x20b8h2qvmzyrfsya82s4i7hfhrxii92d3w";
};
installPhase = ''
mkdir $out
cp -r * $out/
ln -sf /etc/postfixadmin/config.local.php $out/
ln -sf /var/cache/postfixadmin/templates_c $out/
'';
meta = {
description = "Web based virtual user administration interface for Postfix mail servers";
homepage = "https://postfixadmin.sourceforge.io/";
maintainers = with lib.maintainers; [ globin ];
license = lib.licenses.gpl2Plus;
platforms = lib.platforms.all;
};
}

@ -20100,6 +20100,8 @@ with pkgs;
postfix = callPackage ../servers/mail/postfix { }; postfix = callPackage ../servers/mail/postfix { };
postfixadmin = callPackage ../servers/postfixadmin { };
postsrsd = callPackage ../servers/mail/postsrsd { }; postsrsd = callPackage ../servers/mail/postsrsd { };
rspamd = callPackage ../servers/mail/rspamd { }; rspamd = callPackage ../servers/mail/rspamd { };