Migrate mailserver config to 25.11

This commit is contained in:
Jakob Lechner 2025-12-08 15:21:51 +01:00
parent 3dc4f456cc
commit e0ea85dcde
4 changed files with 102 additions and 117 deletions

View file

@ -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;

View file

@ -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 = ''

View file

@ -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

View file

@ -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 = [