Mostly working postfix+dovecot2+ldap setup
Some checks failed
/ dev-shell (push) Successful in 46s
/ rust-packages (push) Successful in 52s
/ check (push) Failing after 1m8s
/ terraform-providers (push) Successful in 1m15s
/ systems (push) Successful in 4m4s

Missing:

1. Figure out how to do some useful aliases for the mail
   addresses. Either something like assigning @kas.agerlinskovgaard.dk
   to kaare@agerlinskovgaard.dk or usual + aliases.
2. Oauth2 login is not working yet.
3. Need to be able to create accounts not handled by LDAP, such
   that eg. forgejo can have an account to send mails from (maybe
   also an account to receive mails?).
4. Once support in kanidm lands, need to look into application passwords
   such that one doesn't have to use their regular posix password,
   and maybe, ideally, doesn't need a posix password at all.
This commit is contained in:
Kaare Hoff Skovgaard 2025-07-29 11:27:09 +02:00
parent 6a1aca24a9
commit 343c87b279
Signed by: khs
GPG key ID: C7D890804F01E9F0
7 changed files with 39 additions and 14 deletions

View file

@ -0,0 +1,9 @@
{ lib, config, ... }:
let
cfg = config.khscodes.infrastructure.mailserver;
in
{
config = lib.mkIf cfg.enable {
khscodes.services.nginx.virtualHosts."${config.khscodes.networking.fqdn}" = { };
};
}

View file

@ -18,6 +18,7 @@ in
}; };
imports = [ imports = [
inputs.simple-nixos-mailserver.nixosModules.mailserver inputs.simple-nixos-mailserver.nixosModules.mailserver
./acme.nix
./dmarc.nix ./dmarc.nix
./dane.nix ./dane.nix
./dkim.nix ./dkim.nix
@ -106,10 +107,6 @@ in
introspection_url = https://login.kaareskovgaard.net/oauth2/token/introspect introspection_url = https://login.kaareskovgaard.net/oauth2/token/introspect
introspection_mode = post introspection_mode = post
''; '';
services.prometheus.exporters.postfix = {
enable = true;
};
khscodes.infrastructure.vault-prometheus-sender.exporters.enabled = [ "postfix" ];
services.fail2ban.jails = { services.fail2ban.jails = {
postfix = { postfix = {
settings = { settings = {

View file

@ -164,15 +164,24 @@ in
services.rspamd.locals."dkim_signing.conf" = lib.mkForce { services.rspamd.locals."dkim_signing.conf" = lib.mkForce {
text = '' text = ''
enabled = true; enabled = true;
allow_username_mismatch = true;
domain { domain {
${lib.strings.concatStringsSep "\n " (lib.lists.map dkimSigningForDomain cfg.domains)} ${lib.strings.concatStringsSep "\n " (lib.lists.map dkimSigningForDomain cfg.domains)}
} }
''; '';
}; };
services.postfix.config = {
# Need to include this as I disabled the in built support for dkim signing
# without this postfix won't forward the mails to rspamd to be signed.
non_smtpd_milters = [ "unix:/run/rspamd/rspamd-milter.sock" ];
};
systemd.services.rspamd = { systemd.services.rspamd = {
unitConfig = { unitConfig = {
ConditionPathExists = domainKeyPaths; ConditionPathExists = domainKeyPaths;
}; };
serviceConfig = {
ReadOnlyPaths = domainKeyPaths;
};
}; };
systemd.services.postfix = { systemd.services.postfix = {
unitConfig = { unitConfig = {

View file

@ -16,7 +16,6 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
mailserver.debug = true;
mailserver.ldap = { mailserver.ldap = {
enable = true; enable = true;
uris = [ "ldaps://login.kaareskovgaard.net" ]; uris = [ "ldaps://login.kaareskovgaard.net" ];
@ -30,14 +29,28 @@ in
# Map LDAP uid to dovecot user, and ldap userPassword to dovecot password # Map LDAP uid to dovecot user, and ldap userPassword to dovecot password
passAttrs = "uid=user"; passAttrs = "uid=user";
passFilter = "(&(class=account)(memberOf=mail_user)(uid=%u))"; passFilter = "(&(class=account)(memberOf=mail_user)(uid=%u))";
userFilter = "(&(class=account)(memberOf=mail_user)(uid=%u))"; # This filter is used both when receiving mail (thus needing to lookup by mail address, and when authenticating, requriing the lookup by uid.)
# Note that the pass filter only allows looking up by uid, so should still only be able to authenticate using that.
userFilter = "(&(class=account)(memberOf=mail_user)(|(mail=%u)(uid=%u)))";
userAttrs = "uid=user";
}; };
postfix = { postfix = {
filter = "(&(class=account)(memberOf=mail_user)(mail=%s))"; filter = "(&(class=account)(memberOf=mail_user)(mail=%s))";
mailAttribute = "mail"; mailAttribute = "uid";
uidAttribute = "uid"; uidAttribute = "uid";
}; };
}; };
systemd.services.dovecot2 = {
unitConfig = {
ConditionPathExists = [ secretFile ];
};
};
systemd.services.postfix = {
unitConfig = {
ConditionPathExists = [ secretFile ];
};
};
khscodes.services.vault-agent.templates = [ khscodes.services.vault-agent.templates = [
{ {
contents = '' contents = ''

View file

@ -27,7 +27,7 @@ in
name = "mta-sts.${domain}"; name = "mta-sts.${domain}";
value = { value = {
locations."=/.well-known/mta-sts.txt" = { locations."=/.well-known/mta-sts.txt" = {
tryFiles = "${mtaStsWellKnown} =404"; alias = mtaStsWellKnown;
}; };
locations."/" = { locations."/" = {
return = 404; return = 404;

View file

@ -1,15 +1,13 @@
{ config, lib, ... }: { config, lib, ... }:
let let
fqdn = config.khscodes.networking.fqdn;
cfg = config.khscodes.infrastructure.mailserver; cfg = config.khscodes.infrastructure.mailserver;
in in
{ {
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.stalwart-mail.settings.metrics.prometheus = {
services.prometheus.exporters.postfix = {
enable = true; enable = true;
}; };
khscodes.services.nginx.virtualHosts."${fqdn}".locations."=/metrics/prometheus" = { khscodes.infrastructure.vault-prometheus-sender.exporters.enabled = [ "postfix" ];
return = 404;
};
}; };
} }

View file

@ -157,7 +157,6 @@ in
persons.khs = { persons.khs = {
present = true; present = true;
mailAddresses = [ mailAddresses = [
"kaare@kaareskovgaard.net"
"kaare@agerlin-skovgaard.dk" "kaare@agerlin-skovgaard.dk"
"kaare@agerlinskovgaard.dk" "kaare@agerlinskovgaard.dk"
]; ];