Merge pull request #12293 from abbradar/postfix-updates

Rework postfix module and package
This commit is contained in:
Peter Simons 2016-01-13 14:12:50 +01:00
commit ae6fc4c5be
3 changed files with 247 additions and 94 deletions

View File

@ -9,14 +9,14 @@ let
group = cfg.group; group = cfg.group;
setgidGroup = cfg.setgidGroup; setgidGroup = cfg.setgidGroup;
haveAliases = cfg.postmasterAlias != "" || cfg.rootAlias != "" || cfg.extraAliases != "";
haveTransport = cfg.transport != "";
haveVirtual = cfg.virtual != "";
mainCf = mainCf =
'' ''
compatibility_level = 2 compatibility_level = 2
queue_directory = /var/postfix/queue
command_directory = ${pkgs.postfix}/sbin
daemon_directory = ${pkgs.postfix}/libexec/postfix
mail_owner = ${user} mail_owner = ${user}
default_privs = nobody default_privs = nobody
@ -57,8 +57,6 @@ let
else else
"[" + cfg.relayHost + "]"} "[" + cfg.relayHost + "]"}
alias_maps = hash:/var/postfix/conf/aliases
mail_spool_directory = /var/spool/mail/ mail_spool_directory = /var/spool/mail/
setgid_group = ${setgidGroup} setgid_group = ${setgidGroup}
@ -80,12 +78,15 @@ let
+ optionalString (cfg.recipientDelimiter != "") '' + optionalString (cfg.recipientDelimiter != "") ''
recipient_delimiter = ${cfg.recipientDelimiter} recipient_delimiter = ${cfg.recipientDelimiter}
'' ''
+ optionalString (cfg.virtual != "") '' + optionalString haveAliases ''
virtual_alias_maps = hash:/etc/postfix/virtual alias_maps = hash:/etc/postfix/aliases
'' ''
+ optionalString (cfg.transport != "") '' + optionalString haveTransport ''
transport_maps = hash:/etc/postfix/transport transport_maps = hash:/etc/postfix/transport
'' ''
+ optionalString haveVirtual ''
virtual_alias_maps = hash:/etc/postfix/virtual
''
+ cfg.extraConfig; + cfg.extraConfig;
masterCf = '' masterCf = ''
@ -158,6 +159,7 @@ in
services.postfix = { services.postfix = {
enable = mkOption { enable = mkOption {
type = types.bool;
default = false; default = false;
description = "Whether to run the Postfix mail server."; description = "Whether to run the Postfix mail server.";
}; };
@ -168,21 +170,25 @@ in
}; };
setSendmail = mkOption { setSendmail = mkOption {
type = types.bool;
default = true; default = true;
description = "Whether to set the system sendmail to postfix's."; description = "Whether to set the system sendmail to postfix's.";
}; };
user = mkOption { user = mkOption {
type = types.str;
default = "postfix"; default = "postfix";
description = "What to call the Postfix user (must be used only for postfix)."; description = "What to call the Postfix user (must be used only for postfix).";
}; };
group = mkOption { group = mkOption {
type = types.str;
default = "postfix"; default = "postfix";
description = "What to call the Postfix group (must be used only for postfix)."; description = "What to call the Postfix group (must be used only for postfix).";
}; };
setgidGroup = mkOption { setgidGroup = mkOption {
type = types.str;
default = "postdrop"; default = "postdrop";
description = " description = "
How to call postfix setgid group (for postdrop). Should How to call postfix setgid group (for postdrop). Should
@ -191,6 +197,7 @@ in
}; };
networks = mkOption { networks = mkOption {
type = types.nullOr (types.listOf types.str);
default = null; default = null;
example = ["192.168.0.1/24"]; example = ["192.168.0.1/24"];
description = " description = "
@ -201,6 +208,7 @@ in
}; };
networksStyle = mkOption { networksStyle = mkOption {
type = types.str;
default = ""; default = "";
description = " description = "
Name of standard way of trusted network specification to use, Name of standard way of trusted network specification to use,
@ -210,6 +218,7 @@ in
}; };
hostname = mkOption { hostname = mkOption {
type = types.str;
default = ""; default = "";
description =" description ="
Hostname to use. Leave blank to use just the hostname of machine. Hostname to use. Leave blank to use just the hostname of machine.
@ -218,6 +227,7 @@ in
}; };
domain = mkOption { domain = mkOption {
type = types.str;
default = ""; default = "";
description =" description ="
Domain to use. Leave blank to use hostname minus first component. Domain to use. Leave blank to use hostname minus first component.
@ -225,6 +235,7 @@ in
}; };
origin = mkOption { origin = mkOption {
type = types.str;
default = ""; default = "";
description =" description ="
Origin to use in outgoing e-mail. Leave blank to use hostname. Origin to use in outgoing e-mail. Leave blank to use hostname.
@ -232,6 +243,7 @@ in
}; };
destination = mkOption { destination = mkOption {
type = types.nullOr (types.listOf types.str);
default = null; default = null;
example = ["localhost"]; example = ["localhost"];
description = " description = "
@ -241,6 +253,7 @@ in
}; };
relayDomains = mkOption { relayDomains = mkOption {
type = types.nullOr (types.listOf types.str);
default = null; default = null;
example = ["localdomain"]; example = ["localdomain"];
description = " description = "
@ -249,6 +262,7 @@ in
}; };
relayHost = mkOption { relayHost = mkOption {
type = types.str;
default = ""; default = "";
description = " description = "
Mail relay for outbound mail. Mail relay for outbound mail.
@ -256,6 +270,7 @@ in
}; };
lookupMX = mkOption { lookupMX = mkOption {
type = types.bool;
default = false; default = false;
description = " description = "
Whether relay specified is just domain whose MX must be used. Whether relay specified is just domain whose MX must be used.
@ -263,11 +278,13 @@ in
}; };
postmasterAlias = mkOption { postmasterAlias = mkOption {
type = types.str;
default = "root"; default = "root";
description = "Who should receive postmaster e-mail."; description = "Who should receive postmaster e-mail.";
}; };
rootAlias = mkOption { rootAlias = mkOption {
type = types.str;
default = ""; default = "";
description = " description = "
Who should receive root e-mail. Blank for no redirection. Who should receive root e-mail. Blank for no redirection.
@ -275,6 +292,7 @@ in
}; };
extraAliases = mkOption { extraAliases = mkOption {
type = types.lines;
default = ""; default = "";
description = " description = "
Additional entries to put verbatim into aliases file, cf. man-page aliases(8). Additional entries to put verbatim into aliases file, cf. man-page aliases(8).
@ -282,6 +300,7 @@ in
}; };
extraConfig = mkOption { extraConfig = mkOption {
type = types.str;
default = ""; default = "";
description = " description = "
Extra lines to be added verbatim to the main.cf configuration file. Extra lines to be added verbatim to the main.cf configuration file.
@ -289,21 +308,25 @@ in
}; };
sslCert = mkOption { sslCert = mkOption {
type = types.str;
default = ""; default = "";
description = "SSL certificate to use."; description = "SSL certificate to use.";
}; };
sslCACert = mkOption { sslCACert = mkOption {
type = types.str;
default = ""; default = "";
description = "SSL certificate of CA."; description = "SSL certificate of CA.";
}; };
sslKey = mkOption { sslKey = mkOption {
type = types.str;
default = ""; default = "";
description = "SSL key to use."; description = "SSL key to use.";
}; };
recipientDelimiter = mkOption { recipientDelimiter = mkOption {
type = types.str;
default = ""; default = "";
example = "+"; example = "+";
description = " description = "
@ -312,6 +335,7 @@ in
}; };
virtual = mkOption { virtual = mkOption {
type = types.lines;
default = ""; default = "";
description = " description = "
Entries for the virtual alias map, cf. man-page virtual(8). Entries for the virtual alias map, cf. man-page virtual(8).
@ -326,11 +350,24 @@ in
}; };
extraMasterConf = mkOption { extraMasterConf = mkOption {
type = types.lines;
default = ""; default = "";
example = "submission inet n - n - - smtpd"; example = "submission inet n - n - - smtpd";
description = "Extra lines to append to the generated master.cf file."; description = "Extra lines to append to the generated master.cf file.";
}; };
aliasFiles = mkOption {
type = types.attrsOf types.path;
default = {};
description = "Aliases' tables to be compiled and placed into /var/lib/postfix/conf.";
};
mapFiles = mkOption {
type = types.attrsOf types.path;
default = {};
description = "Maps to be compiled and placed into /var/lib/postfix/conf.";
};
}; };
}; };
@ -338,91 +375,104 @@ in
###### implementation ###### implementation
config = mkIf config.services.postfix.enable { config = mkIf config.services.postfix.enable (mkMerge [
{
environment = { environment = {
etc = singleton etc = singleton
{ source = "/var/postfix/conf"; { source = "/var/lib/postfix/conf";
target = "postfix"; target = "postfix";
}; };
# This makes comfortable for root to run 'postqueue' for example. # This makes comfortable for root to run 'postqueue' for example.
systemPackages = [ pkgs.postfix ]; systemPackages = [ pkgs.postfix ];
};
services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail {
program = "sendmail";
source = "${pkgs.postfix}/bin/sendmail";
owner = "nobody";
group = "postdrop";
setuid = false;
setgid = true;
};
users.extraUsers = singleton
{ name = user;
description = "Postfix mail server user";
uid = config.ids.uids.postfix;
group = group;
}; };
users.extraGroups = services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail {
[ { name = group; program = "sendmail";
source = "${pkgs.postfix}/bin/sendmail";
group = setgidGroup;
setuid = false;
setgid = true;
};
users.extraUsers = optional (user == "postfix")
{ name = "postfix";
description = "Postfix mail server user";
uid = config.ids.uids.postfix;
group = group;
};
users.extraGroups =
optional (group == "postfix")
{ name = group;
gid = config.ids.gids.postfix; gid = config.ids.gids.postfix;
} }
++ optional (setgidGroup == "postdrop")
{ name = setgidGroup; { name = setgidGroup;
gid = config.ids.gids.postdrop; gid = config.ids.gids.postdrop;
}
];
systemd.services.postfix =
{ description = "Postfix mail server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
Type = "forking";
Restart = "always";
PIDFile = "/var/postfix/queue/pid/master.pid";
}; };
preStart = '' systemd.services.postfix =
${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue { description = "Postfix mail server";
${pkgs.coreutils}/bin/chown -R ${user}:${group} /var/postfix wantedBy = [ "multi-user.target" ];
${pkgs.coreutils}/bin/chown -R ${user}:${setgidGroup} /var/postfix/queue after = [ "network.target" ];
${pkgs.coreutils}/bin/chmod -R ug+rwX /var/postfix/queue path = [ pkgs.postfix ];
${pkgs.coreutils}/bin/chown root:root /var/spool/mail
${pkgs.coreutils}/bin/chmod a+rwxt /var/spool/mail
${pkgs.coreutils}/bin/ln -sf /var/spool/mail /var/
ln -sf ${pkgs.postfix}/etc/postfix/postfix-files /var/postfix/conf serviceConfig = {
Type = "forking";
Restart = "always";
PIDFile = "/var/lib/postfix/queue/pid/master.pid";
ExecStart = "${pkgs.postfix}/bin/postfix start";
ExecStop = "${pkgs.postfix}/bin/postfix stop";
ExecReload = "${pkgs.postfix}/bin/postfix reload";
};
ln -sf ${aliasesFile} /var/postfix/conf/aliases preStart = ''
ln -sf ${virtualFile} /var/postfix/conf/virtual # Backwards compatibility
ln -sf ${mainCfFile} /var/postfix/conf/main.cf if [ ! -d /var/lib/postfix ] && [ -d /var/postfix ]; then
ln -sf ${masterCfFile} /var/postfix/conf/master.cf mkdir -p /var/lib
ln -sf ${transportFile} /var/postfix/conf/transport mv /var/postfix /var/lib/postfix
fi
mkdir -p /var/lib/postfix/data /var/lib/postfix/queue/{pid,public,maildrop}
${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases chown -R ${user}:${group} /var/lib/postfix
${pkgs.postfix}/sbin/postmap -c /var/postfix/conf /var/postfix/conf/virtual chown root /var/lib/postfix/queue
''; chown root /var/lib/postfix/queue/pid
chgrp -R ${setgidGroup} /var/lib/postfix/queue/{public,maildrop}
chmod 770 /var/lib/postfix/queue/{public,maildrop}
script = '' rm -rf /var/lib/postfix/conf
${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start mkdir -p /var/lib/postfix/conf
''; ln -sf ${mainCfFile} /var/lib/postfix/conf/main.cf
ln -sf ${masterCfFile} /var/lib/postfix/conf/master.cf
${concatStringsSep "\n" (mapAttrsToList (to: from: ''
ln -sf ${from} /var/lib/postfix/conf/${to}
postalias /var/lib/postfix/conf/${to}
'') cfg.aliasFiles)}
${concatStringsSep "\n" (mapAttrsToList (to: from: ''
ln -sf ${from} /var/lib/postfix/conf/${to}
postmap /var/lib/postfix/conf/${to}
'') cfg.mapFiles)}
reload = '' mkdir -p /var/spool/mail
${pkgs.postfix}/sbin/postfix -c /var/postfix/conf reload chown root:root /var/spool/mail
''; chmod a+rwxt /var/spool/mail
ln -sf /var/spool/mail /var/
'';
};
}
preStop = '' (mkIf haveAliases {
${pkgs.postfix}/sbin/postfix -c /var/postfix/conf stop services.postfix.aliasFiles."aliases" = aliasesFile;
''; })
(mkIf haveTransport {
}; services.postfix.mapFiles."transport" = transportFile;
})
}; (mkIf haveVirtual {
services.postfix.mapFiles."virtual" = virtualFile;
})
]);
} }

View File

@ -1,8 +1,25 @@
{ stdenv, fetchurl, makeWrapper, gnused, db, openssl, cyrus_sasl, coreutils { stdenv, lib, fetchurl, makeWrapper, gnused, db, openssl, cyrus_sasl
, findutils, gnugrep, gawk, icu , coreutils, findutils, gnugrep, gawk, icu, pcre
, withPgSQL ? false, postgresql
, withMySQL ? false, libmysql
, withSQLite ? false, sqlite
}: }:
stdenv.mkDerivation rec { let
ccargs = lib.concatStringsSep " " ([
"-DUSE_TLS" "-DUSE_SASL_AUTH" "-DUSE_CYRUS_SASL" "-I${cyrus_sasl}/include/sasl"
"-DHAS_DB_BYPASS_MAKEDEFS_CHECK"
"-fPIE" "-fstack-protector-all" "--param" "ssp-buffer-size=4" "-O2" "-D_FORTIFY_SOURCE=2"
] ++ lib.optional withPgSQL "-DHAS_PGSQL"
++ lib.optionals withMySQL [ "-DHAS_MYSQL" "-I${libmysql}/include/mysql" ]
++ lib.optional withSQLite "-DHAS_SQLITE");
auxlibs = lib.concatStringsSep " " ([
"-ldb" "-lnsl" "-lresolv" "-lsasl2" "-lcrypto" "-lssl" "-pie" "-Wl,-z,relro,-z,now"
] ++ lib.optional withPgSQL "-lpq"
++ lib.optional withMySQL "-lmysqlclient"
++ lib.optional withSQLite "-lsqlite3");
in stdenv.mkDerivation rec {
name = "postfix-${version}"; name = "postfix-${version}";
@ -13,35 +30,35 @@ stdenv.mkDerivation rec {
sha256 = "00mc12k5p1zlrlqcf33vh5zizaqr5ai8q78dwv69smjh6kn4c7j0"; sha256 = "00mc12k5p1zlrlqcf33vh5zizaqr5ai8q78dwv69smjh6kn4c7j0";
}; };
buildInputs = [ makeWrapper gnused db openssl cyrus_sasl icu ]; buildInputs = [ makeWrapper gnused db openssl cyrus_sasl icu pcre ]
++ lib.optional withPgSQL postgresql
++ lib.optional withMySQL libmysql
++ lib.optional withSQLite sqlite;
patches = [ ./postfix-script-shell.patch ]; patches = [ ./postfix-script-shell.patch ./postfix-3.0-no-warnings.patch ];
preBuild = '' preBuild = ''
sed -e '/^PATH=/d' -i postfix-install sed -e '/^PATH=/d' -i postfix-install
export command_directory=$out/sbin export command_directory=$out/sbin
export config_directory=/etc/postfix export config_directory=/etc/postfix
export meta_directory=$out/etc/postfix
export daemon_directory=$out/libexec/postfix export daemon_directory=$out/libexec/postfix
export data_directory=/var/lib/postfix export data_directory=/var/lib/postfix/data
export html_directory=$out/share/postfix/doc/html export html_directory=$out/share/postfix/doc/html
export mailq_path=$out/bin/mailq export mailq_path=$out/bin/mailq
export manpage_directory=$out/share/man export manpage_directory=$out/share/man
export newaliases_path=$out/bin/newaliases export newaliases_path=$out/bin/newaliases
export queue_directory=/var/spool/postfix export queue_directory=/var/lib/postfix/queue
export readme_directory=$out/share/postfix/doc export readme_directory=$out/share/postfix/doc
export sendmail_path=$out/bin/sendmail export sendmail_path=$out/bin/sendmail
make makefiles \ make makefiles CCARGS='${ccargs}' AUXLIBS='${auxlibs}'
CCARGS='-DUSE_TLS -DUSE_SASL_AUTH -DUSE_CYRUS_SASL -I${cyrus_sasl}/include/sasl \
-DHAS_DB_BYPASS_MAKEDEFS_CHECK \
-fPIE -fstack-protector-all --param ssp-buffer-size=4 -O2 -D_FORTIFY_SOURCE=2' \
AUXLIBS='-ldb -lnsl -lresolv -lsasl2 -lcrypto -lssl -pie -Wl,-z,relro,-z,now'
''; '';
installTargets = [ "non-interactive-package" ]; installTargets = [ "non-interactive-package" ];
installFlags = [ " install_root=installdir " ]; installFlags = [ "install_root=installdir" ];
postInstall = '' postInstall = ''
mkdir -p $out mkdir -p $out
@ -57,9 +74,9 @@ stdenv.mkDerivation rec {
meta = { meta = {
homepage = "http://www.postfix.org/"; homepage = "http://www.postfix.org/";
description = "A fast, easy to administer, and secure mail server"; description = "A fast, easy to administer, and secure mail server";
license = stdenv.lib.licenses.bsdOriginal; license = lib.licenses.bsdOriginal;
platforms = stdenv.lib.platforms.linux; platforms = lib.platforms.linux;
maintainers = [ stdenv.lib.maintainers.rickynils ]; maintainers = [ lib.maintainers.rickynils ];
}; };
} }

View File

@ -0,0 +1,86 @@
diff -ru3 postfix-3.0.3/conf/postfix-script postfix-3.0.3-new/conf/postfix-script
--- postfix-3.0.3/conf/postfix-script 2014-06-27 18:05:15.000000000 +0400
+++ postfix-3.0.3-new/conf/postfix-script 2016-01-09 17:51:38.545733631 +0300
@@ -84,24 +84,6 @@
exit 1
}
-# If this is a secondary instance, don't touch shared files.
-
-instances=`test ! -f $def_config_directory/main.cf ||
- $command_directory/postconf -c $def_config_directory \
- -h multi_instance_directories | sed 's/,/ /'` || {
- $FATAL cannot execute $command_directory/postconf!
- exit 1
-}
-
-check_shared_files=1
-for name in $instances
-do
- case "$name" in
- "$def_config_directory") ;;
- "$config_directory") check_shared_files=; break;;
- esac
-done
-
#
# Parse JCL
#
@@ -262,22 +244,6 @@
-prune \( -perm -020 -o -perm -002 \) \
-exec $WARN group or other writable: {} \;
- # Check Postfix root-owned directory tree owner/permissions.
-
- todo="$config_directory/."
- test -n "$check_shared_files" && {
- todo="$daemon_directory/. $meta_directory/. $todo"
- test "$shlib_directory" = "no" ||
- todo="$shlib_directory/. $todo"
- }
- todo=`echo "$todo" | tr ' ' '\12' | sort -u`
-
- find $todo ! -user root \
- -exec $WARN not owned by root: {} \;
-
- find $todo \( -perm -020 -o -perm -002 \) \
- -exec $WARN group or other writable: {} \;
-
# Check Postfix mail_owner-owned directory tree owner/permissions.
find $data_directory/. ! -user $mail_owner \
@@ -302,18 +268,11 @@
# Check Postfix setgid_group-owned directory and file group/permissions.
todo="$queue_directory/public $queue_directory/maildrop"
- test -n "$check_shared_files" &&
- todo="$command_directory/postqueue $command_directory/postdrop $todo"
find $todo \
-prune ! -group $setgid_group \
-exec $WARN not owned by group $setgid_group: {} \;
- test -n "$check_shared_files" &&
- find $command_directory/postqueue $command_directory/postdrop \
- -prune ! -perm -02111 \
- -exec $WARN not set-gid or not owner+group+world executable: {} \;
-
# Check non-Postfix root-owned directory tree owner/content.
for dir in bin etc lib sbin usr
@@ -334,15 +293,6 @@
find corrupt -type f -exec $WARN damaged message: {} \;
- # Check for non-Postfix MTA remnants.
-
- test -n "$check_shared_files" -a -f /usr/sbin/sendmail -a \
- -f /usr/lib/sendmail && {
- cmp -s /usr/sbin/sendmail /usr/lib/sendmail || {
- $WARN /usr/lib/sendmail and /usr/sbin/sendmail differ
- $WARN Replace one by a symbolic link to the other
- }
- }
exit 0
;;