Migrate mailserver config to 25.11
This commit is contained in:
parent
3dc4f456cc
commit
e0ea85dcde
4 changed files with 102 additions and 117 deletions
|
|
@ -1,15 +1,9 @@
|
||||||
{ config, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (config.networking) ports;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
#sops.secrets."domain_key_jalr.de".owner = "rspamd";
|
#sops.secrets."domain_key_jalr.de".owner = "rspamd";
|
||||||
jalr = {
|
jalr = {
|
||||||
mailserver = {
|
mailserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
fqdn = "hha.jalr.de";
|
fqdn = "hha.jalr.de";
|
||||||
relayPort = ports.postfix-relay.tcp;
|
|
||||||
domains = [
|
domains = [
|
||||||
{
|
{
|
||||||
domain = "jalr.de";
|
domain = "jalr.de";
|
||||||
|
|
@ -25,14 +19,18 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
services.postfix = {
|
services.postfix = {
|
||||||
config = {
|
settings = {
|
||||||
smtp_bind_address = "159.69.103.126";
|
main = {
|
||||||
smtp_bind_address_enforce = true;
|
smtp_bind_address = "159.69.103.126";
|
||||||
|
smtp_bind_address_enforce = true;
|
||||||
|
};
|
||||||
|
master = {
|
||||||
|
smtp.args = [
|
||||||
|
"-o"
|
||||||
|
"inet_protocols=ipv4"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
masterConfig.smtp.args = [
|
|
||||||
"-o"
|
|
||||||
"inet_protocols=ipv4"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
services.nginx.virtualHosts."hha.jalr.de" = {
|
services.nginx.virtualHosts."hha.jalr.de" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,6 @@ in
|
||||||
{
|
{
|
||||||
options.jalr.mailserver = with lib; with lib.types; {
|
options.jalr.mailserver = with lib; with lib.types; {
|
||||||
enable = mkEnableOption "simple mail server";
|
enable = mkEnableOption "simple mail server";
|
||||||
relayPort = mkOption {
|
|
||||||
description = "SMTP port for relay mail relay.";
|
|
||||||
type = port;
|
|
||||||
default = 25;
|
|
||||||
};
|
|
||||||
fqdn = mkOption {
|
fqdn = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
description = ''
|
description = ''
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,26 @@ let
|
||||||
"\n"
|
"\n"
|
||||||
({ address, passwordHash, ... }: "${address}:${passwordHash}")
|
({ address, passwordHash, ... }: "${address}:${passwordHash}")
|
||||||
cfg.users);
|
cfg.users);
|
||||||
|
|
||||||
|
sieveScripts = {
|
||||||
|
learn-spam = pkgs.writeText "learn-spam.sieve" ''
|
||||||
|
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
|
||||||
|
pipe :copy "rspamc" ["learn_spam"];
|
||||||
|
'';
|
||||||
|
learn-ham = pkgs.writeText "learn-ham.sieve" ''
|
||||||
|
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
|
||||||
|
|
||||||
|
if environment :matches "imap.mailbox" "*" {
|
||||||
|
set "mailbox" "''${1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if string "''${mailbox}" "Trash" {
|
||||||
|
stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe :copy "rspamc" ["learn_ham"];
|
||||||
|
'';
|
||||||
|
};
|
||||||
in
|
in
|
||||||
lib.mkIf cfg.enable {
|
lib.mkIf cfg.enable {
|
||||||
services.dovecot2 = {
|
services.dovecot2 = {
|
||||||
|
|
@ -111,12 +131,12 @@ lib.mkIf cfg.enable {
|
||||||
${lib.optionalString cfg.spam.enable ''
|
${lib.optionalString cfg.spam.enable ''
|
||||||
imapsieve_mailbox1_name = Spam
|
imapsieve_mailbox1_name = Spam
|
||||||
imapsieve_mailbox1_causes = COPY
|
imapsieve_mailbox1_causes = COPY
|
||||||
imapsieve_mailbox1_before = file:/var/lib/dovecot/sieve/learn-spam.sieve
|
imapsieve_mailbox1_before = file:${sieveScripts.learn-spam}
|
||||||
|
|
||||||
imapsieve_mailbox2_name = *
|
imapsieve_mailbox2_name = *
|
||||||
imapsieve_mailbox2_from = Spam
|
imapsieve_mailbox2_from = Spam
|
||||||
imapsieve_mailbox2_causes = COPY
|
imapsieve_mailbox2_causes = COPY
|
||||||
imapsieve_mailbox2_before = file:/var/lib/dovecot/sieve/learn-ham.sieve
|
imapsieve_mailbox2_before = file:${sieveScripts.learn-ham}
|
||||||
sieve_pipe_bin_dir = ${pkgs.symlinkJoin { name = "sieve-pipe-bin-dir"; paths = with pkgs; [ rspamd ]; } }/bin
|
sieve_pipe_bin_dir = ${pkgs.symlinkJoin { name = "sieve-pipe-bin-dir"; paths = with pkgs; [ rspamd ]; } }/bin
|
||||||
''}
|
''}
|
||||||
}
|
}
|
||||||
|
|
@ -125,37 +145,12 @@ lib.mkIf cfg.enable {
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.dovecot_pigeonhole ];
|
environment.systemPackages = [ pkgs.dovecot_pigeonhole ];
|
||||||
|
|
||||||
systemd.services.dovecot2 = {
|
/*
|
||||||
|
systemd.services.dovecot2 = {
|
||||||
wants = [ "acme-finished-${cfg.fqdn}.target" ];
|
wants = [ "acme-finished-${cfg.fqdn}.target" ];
|
||||||
after = [ "acme-finished-${cfg.fqdn}.target" ];
|
after = [ "acme-finished-${cfg.fqdn}.target" ];
|
||||||
|
};
|
||||||
preStart = lib.mkIf cfg.spam.enable
|
*/
|
||||||
(lib.mkAfter
|
|
||||||
(lib.concatStrings
|
|
||||||
(lib.mapAttrsToList
|
|
||||||
(name: content: ''
|
|
||||||
cp ${pkgs.writeText name content} /var/lib/dovecot/sieve/${name}
|
|
||||||
'')
|
|
||||||
{
|
|
||||||
"learn-spam.sieve" = ''
|
|
||||||
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
|
|
||||||
pipe :copy "rspamc" ["learn_spam"];
|
|
||||||
'';
|
|
||||||
"learn-ham.sieve" = ''
|
|
||||||
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
|
|
||||||
|
|
||||||
if environment :matches "imap.mailbox" "*" {
|
|
||||||
set "mailbox" "''${1}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if string "''${mailbox}" "Trash" {
|
|
||||||
stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
pipe :copy "rspamc" ["learn_ham"];
|
|
||||||
'';
|
|
||||||
})));
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [
|
networking.firewall.allowedTCPPorts = [
|
||||||
143 # IMAP
|
143 # IMAP
|
||||||
|
|
|
||||||
|
|
@ -38,75 +38,81 @@ lib.mkIf cfg.enable {
|
||||||
services.postfix = {
|
services.postfix = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
inherit (cfg) relayPort;
|
|
||||||
|
|
||||||
enableSubmission = false; # plain/STARTTLS (latter is forced in submissionOptions)
|
enableSubmission = false; # plain/STARTTLS (latter is forced in submissionOptions)
|
||||||
enableSubmissions = true; # submission with implicit TLS (TCP/465)
|
enableSubmissions = true; # submission with implicit TLS (TCP/465)
|
||||||
|
|
||||||
hostname = cfg.fqdn;
|
settings = {
|
||||||
networksStyle = "host";
|
main = {
|
||||||
|
smtpd_tls_chain_files = [
|
||||||
|
"${cfg.certDir}/key.pem"
|
||||||
|
"${cfg.certDir}/fullchain.pem"
|
||||||
|
];
|
||||||
|
recipient_delimiter = "+";
|
||||||
|
myhostname = cfg.fqdn;
|
||||||
|
mynetworks_style = "host";
|
||||||
|
|
||||||
settings.main.smtpd_tls_chain_files = [
|
# General
|
||||||
"${cfg.certDir}/key.pem"
|
smtpd_banner = "${cfg.fqdn} ESMTP";
|
||||||
"${cfg.certDir}/fullchain.pem"
|
disable_vrfy_command = true; # disable check if mailbox exists
|
||||||
];
|
enable_long_queue_ids = true; # better for debugging
|
||||||
|
strict_rfc821_envelopes = true; # only accept properly formatted envelope
|
||||||
|
message_size_limit = cfg.messageSizeLimit;
|
||||||
|
|
||||||
recipientDelimiter = "+";
|
virtual_mailbox_domains = listToString (map (x: x.domain) cfg.domains);
|
||||||
|
virtual_mailbox_maps = "hash:/var/lib/postfix/conf/valiases";
|
||||||
|
virtual_alias_maps = "hash:/var/lib/postfix/conf/valiases";
|
||||||
|
virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
||||||
|
|
||||||
|
smtpd_recipient_restrictions = listToString [
|
||||||
|
"reject_non_fqdn_recipient"
|
||||||
|
"reject_unknown_recipient_domain"
|
||||||
|
"reject_unverified_recipient"
|
||||||
|
];
|
||||||
|
|
||||||
|
smtpd_client_restrictions = listToString [
|
||||||
|
"reject_unknown_client_hostname"
|
||||||
|
];
|
||||||
|
|
||||||
|
smtpd_sender_restrictions = listToString [
|
||||||
|
"reject_non_fqdn_sender"
|
||||||
|
"reject_unknown_sender_domain"
|
||||||
|
];
|
||||||
|
|
||||||
|
# generated 2021-02-04, Mozilla Guideline v5.6, Postfix 3.5.6, OpenSSL 1.1.1i, intermediate configuration
|
||||||
|
# https://ssl-config.mozilla.org/#server=postfix&version=3.5.6&config=intermediate&openssl=1.1.1i&guideline=5.6
|
||||||
|
smtpd_tls_security_level = "may";
|
||||||
|
smtpd_tls_auth_only = "yes";
|
||||||
|
smtpd_tls_mandatory_protocols = "!SSLv2, !SSLv3, !TLSv1, !TLSv1.1";
|
||||||
|
smtpd_tls_protocols = "!SSLv2, !SSLv3, !TLSv1, !TLSv1.1";
|
||||||
|
smtpd_tls_mandatory_ciphers = "medium";
|
||||||
|
smtpd_tls_loglevel = "1";
|
||||||
|
|
||||||
|
tls_medium_cipherlist = listToString [
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256"
|
||||||
|
"ECDHE-RSA-AES128-GCM-SHA256"
|
||||||
|
"ECDHE-ECDSA-AES256-GCM-SHA384"
|
||||||
|
"ECDHE-RSA-AES256-GCM-SHA384"
|
||||||
|
"ECDHE-ECDSA-CHACHA20-POLY1305"
|
||||||
|
"ECDHE-RSA-CHACHA20-POLY1305"
|
||||||
|
"DHE-RSA-AES128-GCM-SHA256"
|
||||||
|
"DHE-RSA-AES256-GCM-SHA384"
|
||||||
|
];
|
||||||
|
tls_preempt_cipherlist = "no";
|
||||||
|
};
|
||||||
|
master = {
|
||||||
|
submission-header-cleanup = {
|
||||||
|
private = false;
|
||||||
|
maxproc = 0;
|
||||||
|
command = "cleanup";
|
||||||
|
args = [ "-o" "header_checks=pcre:${submissionHeaderCleanupRules}" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
mapFiles = {
|
mapFiles = {
|
||||||
inherit valiases;
|
inherit valiases;
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
|
||||||
# General
|
|
||||||
smtpd_banner = "${cfg.fqdn} ESMTP";
|
|
||||||
disable_vrfy_command = true; # disable check if mailbox exists
|
|
||||||
enable_long_queue_ids = true; # better for debugging
|
|
||||||
strict_rfc821_envelopes = true; # only accept properly formatted envelope
|
|
||||||
message_size_limit = toString cfg.messageSizeLimit;
|
|
||||||
|
|
||||||
virtual_mailbox_domains = listToString (map (x: x.domain) cfg.domains);
|
|
||||||
virtual_mailbox_maps = "hash:/var/lib/postfix/conf/valiases";
|
|
||||||
virtual_alias_maps = "hash:/var/lib/postfix/conf/valiases";
|
|
||||||
virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
|
||||||
|
|
||||||
smtpd_recipient_restrictions = listToString [
|
|
||||||
"reject_non_fqdn_recipient"
|
|
||||||
"reject_unknown_recipient_domain"
|
|
||||||
"reject_unverified_recipient"
|
|
||||||
];
|
|
||||||
|
|
||||||
smtpd_client_restrictions = listToString [
|
|
||||||
"reject_unknown_client_hostname"
|
|
||||||
];
|
|
||||||
|
|
||||||
smtpd_sender_restrictions = listToString [
|
|
||||||
"reject_non_fqdn_sender"
|
|
||||||
"reject_unknown_sender_domain"
|
|
||||||
];
|
|
||||||
|
|
||||||
# generated 2021-02-04, Mozilla Guideline v5.6, Postfix 3.5.6, OpenSSL 1.1.1i, intermediate configuration
|
|
||||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.5.6&config=intermediate&openssl=1.1.1i&guideline=5.6
|
|
||||||
smtpd_tls_security_level = "may";
|
|
||||||
smtpd_tls_auth_only = "yes";
|
|
||||||
smtpd_tls_mandatory_protocols = "!SSLv2, !SSLv3, !TLSv1, !TLSv1.1";
|
|
||||||
smtpd_tls_protocols = "!SSLv2, !SSLv3, !TLSv1, !TLSv1.1";
|
|
||||||
smtpd_tls_mandatory_ciphers = "medium";
|
|
||||||
smtpd_tls_loglevel = "1";
|
|
||||||
|
|
||||||
tls_medium_cipherlist = listToString [
|
|
||||||
"ECDHE-ECDSA-AES128-GCM-SHA256"
|
|
||||||
"ECDHE-RSA-AES128-GCM-SHA256"
|
|
||||||
"ECDHE-ECDSA-AES256-GCM-SHA384"
|
|
||||||
"ECDHE-RSA-AES256-GCM-SHA384"
|
|
||||||
"ECDHE-ECDSA-CHACHA20-POLY1305"
|
|
||||||
"ECDHE-RSA-CHACHA20-POLY1305"
|
|
||||||
"DHE-RSA-AES128-GCM-SHA256"
|
|
||||||
"DHE-RSA-AES256-GCM-SHA384"
|
|
||||||
];
|
|
||||||
tls_preempt_cipherlist = "no";
|
|
||||||
};
|
|
||||||
|
|
||||||
# plain/STARTTLS (forced with smtpd_tls_security_level)
|
# plain/STARTTLS (forced with smtpd_tls_security_level)
|
||||||
submissionOptions = {
|
submissionOptions = {
|
||||||
smtpd_tls_security_level = "encrypt";
|
smtpd_tls_security_level = "encrypt";
|
||||||
|
|
@ -132,15 +138,6 @@ lib.mkIf cfg.enable {
|
||||||
};
|
};
|
||||||
# implicit TLS
|
# implicit TLS
|
||||||
submissionsOptions = config.services.postfix.submissionOptions;
|
submissionsOptions = config.services.postfix.submissionOptions;
|
||||||
|
|
||||||
masterConfig = {
|
|
||||||
submission-header-cleanup = {
|
|
||||||
private = false;
|
|
||||||
maxproc = 0;
|
|
||||||
command = "cleanup";
|
|
||||||
args = [ "-o" "header_checks=pcre:${submissionHeaderCleanupRules}" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue