playing around with opensmtp

This commit is contained in:
Robin Raymond 2017-12-22 11:17:39 +01:00
parent 67cdb36054
commit a1aff6b61c
5 changed files with 164 additions and 17 deletions

View file

@ -167,7 +167,7 @@ in
vmailUserName = mkOption { vmailUserName = mkOption {
type = types.str; type = types.str;
default = "virtualMail"; default = "vmail";
description = '' description = ''
The user name and group name of the user that owns the directory where all The user name and group name of the user that owns the directory where all
the mail is stored. the mail is stored.
@ -176,7 +176,7 @@ in
vmailGroupName = mkOption { vmailGroupName = mkOption {
type = types.str; type = types.str;
default = "virtualMail"; default = "vmail";
description = '' description = ''
The user name and group name of the user that owns the directory where all The user name and group name of the user that owns the directory where all
the mail is stored. the mail is stored.
@ -331,8 +331,8 @@ in
./mail-server/networking.nix ./mail-server/networking.nix
./mail-server/systemd.nix ./mail-server/systemd.nix
./mail-server/dovecot.nix ./mail-server/dovecot.nix
./mail-server/postfix.nix ./mail-server/opensmtpd.nix
./mail-server/rmilter.nix # ./mail-server/rmilter.nix
./mail-server/nginx.nix ./mail-server/nginx.nix
]; ];

View file

@ -63,10 +63,10 @@ in
ssl = required ssl = required
service lmtp { service lmtp {
unix_listener /var/lib/postfix/queue/private/dovecot-lmtp { unix_listener /run/dovecot/lmtp {
group = postfix group = ${vmailGroupName}
mode = 0600 mode = 0600
user = postfix # TODO: < make variable user = ${vmailUserName}
} }
} }
@ -74,14 +74,6 @@ in
mail_plugins = $mail_plugins sieve mail_plugins = $mail_plugins sieve
} }
service auth {
unix_listener /var/lib/postfix/queue/private/auth {
mode = 0660
user = postfix # TODO: < make variable
group = postfix # TODO: < make variable
}
}
auth_mechanisms = plain login auth_mechanisms = plain login
namespace inbox { namespace inbox {

146
mail-server/opensmtpd.nix Normal file
View file

@ -0,0 +1,146 @@
# nixos-mailserver: a simple mail server
# Copyright (C) 2016-2017 Robin Raymond
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
{ config, pkgs, lib, ... }:
with (import ./common.nix { inherit config; });
let
inherit (lib.strings) concatStringsSep;
cfg = config.mailserver;
# valiases_postfix :: [ String ]
valiases_postfix = lib.flatten (lib.mapAttrsToList
(name: value:
let to = name;
in map (from: "${from} ${to}") value.aliases)
cfg.loginAccounts);
vmailMaps = lib.flatten (lib.mapAttrsToList
(name: value: "${name} ${cfg.vmailUserName}") cfg.loginAccounts);
# catchAllPostfix :: [ String ]
catchAllPostfix = lib.flatten (lib.mapAttrsToList
(name: value:
let to = name;
in map (from: "@${from} ${to}") value.catchAll)
cfg.loginAccounts);
# extra_valiases_postfix :: [ String ]
# TODO: Remove virtualAliases when deprecated -> removed
extra_valiases_postfix = (map
(from:
let to = cfg.virtualAliases.${from};
in "${from} ${to}")
(builtins.attrNames cfg.virtualAliases))
++
(map
(from:
let to = cfg.extraVirtualAliases.${from};
in "${from} ${to}")
(builtins.attrNames cfg.extraVirtualAliases));
# all_valiases_postfix :: [ String ]
all_valiases_postfix = valiases_postfix ++ extra_valiases_postfix ++ catchAllPostfix ++ vmailMaps;
# accountToIdentity :: User -> String
accountToIdentity = account: "${account.name} ${account.name}";
# vaccounts_identity :: [ String ]
vaccounts_identity = map accountToIdentity (lib.attrValues cfg.loginAccounts);
# valiases_file :: Path
valiases_file = builtins.toFile "valias"
(lib.concatStringsSep "\n" all_valiases_postfix);
# vhosts_file :: Path
vhosts_file = builtins.toFile "vhosts" (concatStringsSep "\n" cfg.domains);
passwdList = lib.flatten (lib.mapAttrsToList (name : value:
"${name}:${value.hashedPassword}:5000:5000::/var/vmail/:/run/current-system/sw/bin/nologin")
cfg.loginAccounts);
passwd = lib.concatStringsSep "\n" passwdList;
example =
''
user1@example.com:$6$IsXn9Xe2kUTPETVl$Z.gkkqpwi95/ZsL/FXZaAjMjdv03m5jae6v8Pv7aaNnzdzNd01nbgt3HtKnaS10hZTbXgumqdQyTU0m1wkr76.:5000:5000::/var/vmail:/run/current-system/sw/bin/nologin
'';
passwd_file = builtins.toFile "passwd" passwd;
# vaccounts_file :: Path
# see
# https://blog.grimneko.de/2011/12/24/a-bunch-of-tips-for-improving-your-postfix-setup/
# for details on how this file looks. By using the same file as valiases,
# every alias is owned (uniquely) by its user. We have to add the users own
# address though
vaccounts_file = builtins.toFile "vaccounts" (lib.concatStringsSep "\n"
(vaccounts_identity ++ all_valiases_postfix));
submissionHeaderCleanupRules = pkgs.writeText "submission_header_cleanup_rules" ''
# Removes sensitive headers from mails handed in via the submission port.
# See https://thomas-leister.de/mailserver-debian-stretch/
# Uses "pcre" style regex.
/^Received:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^X-Mailer:/ IGNORE
/^User-Agent:/ IGNORE
/^X-Enigmail:/ IGNORE
'';
in
{
config = with cfg; lib.mkIf enable {
services.opensmtpd = {
enable = true;
procPackages = [ pkgs.opensmtpd-extras ];
extraServerArgs = [ "-v" ];
serverConfiguration =
''
# pki setup
pki ${fqdn} certificate "${certificatePath}"
pki ${fqdn} key "${keyPath}"
# tables setup
# table aliases file:/etc/mail/aliases
table domains file:${vhosts_file}
table passwd passwd:${passwd_file}
table virtuals file:${valiases_file}
# # listen ports setup
listen on 0.0.0.0 port 25 tls pki ${fqdn}
listen on 0.0.0.0 port 587 tls-require pki ${fqdn} auth <passwd> received-auth
# allow local messages
accept from any for domain <domains> virtual <virtuals> deliver to lmtp "/run/dovecot/lmtp" rcpt-to
# DKIM
listen on lo hostname ${fqdn}
listen on lo port 10028 tag DKIM hostname ${fqdn}
accept tagged DKIM \
for any \
relay \
hostname ${fqdn}
accept from local \
for any \
relay via smtp://127.0.0.1:10027
'';
};
};
}

View file

@ -68,13 +68,21 @@ in
{ {
config = with cfg; lib.mkIf enable { config = with cfg; lib.mkIf enable {
# Make sure postfix gets started first, so that the certificates are in place # Make sure postfix gets started first, so that the certificates are in place
systemd.services.dovecot2.after = [ "postfix.service" ]; systemd.services.dovecot2 = {
after = [ "postfix.service" ];
preStart =
''
mkdir -p '/run/dovecot/'
chown 'dovecot2:dovecot2' '/run/dovecot'
'';
};
# Create certificates and maildir folder # Create certificates and maildir folder
systemd.services.postfix = { systemd.services.opensmtpd = {
after = (if (certificateScheme == 3) then [ "nginx.service" ] else []); after = (if (certificateScheme == 3) then [ "nginx.service" ] else []);
preStart = preStart =
'' ''
mkdir -p /var/empty
# Create mail directory and set permissions. See # Create mail directory and set permissions. See
# <http://wiki2.dovecot.org/SharedMailboxes/Permissions>. # <http://wiki2.dovecot.org/SharedMailboxes/Permissions>.
mkdir -p "${mailDirectory}" mkdir -p "${mailDirectory}"

View file

@ -54,6 +54,7 @@ import <nixpkgs/nixos/tests/make-test.nix> {
subtest "vmail gid is set correctly", sub { subtest "vmail gid is set correctly", sub {
$machine->succeed("getent group vmail | grep 5000"); $machine->succeed("getent group vmail | grep 5000");
$machine->succeed("systemctl status opensmtpd.service -l >&2");
}; };
''; '';