Final attempt at getting stalwart working before revert

Non working parts:

1. OIDC login, stalwart assumes the entire token is base64 encoded,
   which it is not.
2. Apparently there's no support for mixed directories, allowing both
   logins from ldap and from internal database. I want this in order
   to support accounts for services as well as persons.
This commit is contained in:
Kaare Hoff Skovgaard 2025-07-30 11:07:45 +02:00
parent 2d3e02ad78
commit fbcd590bfe
Signed by: khs
GPG key ID: C7D890804F01E9F0
8 changed files with 95 additions and 46 deletions

View file

@ -19,6 +19,7 @@ in
services.stalwart-mail.settings = {
certificate.default = {
cert = "%{file:${acmeDir}/fullchain.pem}%";
default = true;
private-key = "%{file:${config.security.acme.certs.${fqdn}.directory}/key.pem}%";
};
};

View file

@ -36,8 +36,34 @@ in
enable = true;
package = pkgs.callPackage ./package/package.nix { };
settings = {
config = {
local-keys =
# defaults
[
"store.*"
"directory.*"
"tracer.*"
"!server.blocked-ip.*"
"!server.allowed-ip.*"
"server.*"
"authentication.fallback-admin.*"
"cluster.*"
"config.local-keys.*"
"storage.data"
"storage.blob"
"storage.lookup"
"storage.fts"
"storage.directory"
"certificate.*"
]
# KHS addded
++ [
"http.*"
"lookup.default.*"
];
};
http = {
url = "https://${fqdn}";
url = "'https://${fqdn}'";
use-x-forwarded = true;
};
server = {
@ -63,13 +89,9 @@ in
protocol = "imap";
tls.implicit = true;
};
jmap = {
bind = "[::]:8080";
url = "https://${fqdn}";
protocol = "jmap";
};
management = {
bind = "[::]:8080";
url = "https://${fqdn}";
protocol = "http";
};
};
@ -78,7 +100,6 @@ in
hostname = fqdn;
domain = "kaareskovgaard.net";
};
spam-filter.resource = "${config.services.stalwart-mail.package.spam-filter}/spam-filter.toml";
};
};
# TODO: Include a similiar rule for openstack

View file

@ -213,6 +213,10 @@ in
]) cfg.domains
);
services.stalwart-mail.settings = {
config.local-keys = [
"auth.*"
"signature.*"
];
auth.dkim = {
sign = authDkim ++ [
(otherwise false)

View file

@ -17,6 +17,9 @@ in
config = lib.mkIf cfg.enable {
services.stalwart-mail.settings = {
config.local-keys = [
"storage.ldap.*"
];
storage = {
directory = "ldap";
};

View file

@ -5,41 +5,43 @@ let
in
{
config = lib.mkIf cfg.enable {
# khscodes.services.vault-agent.templates = [
# {
# contents = ''
# {{- with secret "kanidm/data/apps/dovecot" -}}
# scope = email openid profile
# username_attribute = username
# debug = yes
# introspection_url = https://dovecot:{{ .Data.data.basic_secret }}@login.kaareskovgaard.net/oauth2/token/introspect
# introspection_mode = post
# {{- end -}}
# '';
# destination = oauthConfigFile;
# perms = "0600";
# owner = "root";
# group = "root";
# restartUnits = [ "dovecot2.service" ];
# }
# ];
# services.dovecot2.extraConfig = ''
# auth_mechanisms = $auth_mechanisms oauthbearer xoauth2
# passdb {
# driver = oauth2
# mechanisms = xoauth2 oauthbearer
# args = ${oauthConfigFile}
# }
# '';
# systemd.services.dovecot2 = {
# serviceConfig.ReadOnlyPaths = [
# oauthConfigFile
# ];
# unitConfig.ConditionPathExists = [
# oauthConfigFile
# ];
# };
services.stalwart-mail.settings = {
tracer.stdout.level = "trace";
directory.oidc = {
type = "oidc";
url = "ldaps://login.kaareskovgaard.net";
timeout = "1s";
endpoint.url = "https://login.kaareskovgaard.net/oauth2/openid/dovecot/userinfo";
endpoint.method = "userinfo";
auth.method = "user-token";
auth.username = "dovecot";
auth.secret = "%{file:${oauthConfigFile}}%";
fields.email = "email";
fields.username = "preferred_username";
fields.full-name = "name";
};
};
khscodes.services.vault-agent.templates = [
{
contents = ''
{{- with secret "kanidm/data/apps/dovecot" -}}
{{ .Data.data.basic_secret }}@login.kaareskovgaard.net/oauth2/token/introspect
{{- end -}}
'';
destination = oauthConfigFile;
perms = "0600";
owner = "stalwart-mail";
group = "stalwart-mail";
restartUnits = [ "stalwart-mail.service" ];
}
];
systemd.services.stalwart-mail = {
serviceConfig.ReadOnlyPaths = [
oauthConfigFile
];
unitConfig.ConditionPathExists = [
oauthConfigFile
];
};
};
}

View file

@ -1,4 +1,5 @@
# This file contains patches for Nixos 25.05 to be compatible with new stalwart mail
# This file contains patches for Nixos 25.05 to be compatible with new stalwart mail.
# Also some minor patches to avoid having warnings on startup
{
lib,
config,
@ -10,6 +11,17 @@ let
configFile = configFormat.generate "stalwart-mail.toml" config.services.stalwart-mail.settings;
in
{
services.stalwart-mail.settings = {
config.local-keys = [
"spam-filter.resource"
]
++ [
# I think these maybe should be added to nixpkgs?
"resolver.*"
"webadmin.*"
];
spam-filter.resource = "file://${config.services.stalwart-mail.package.spam-filter}/spam-filter.toml";
};
systemd.services.stalwart-mail = lib.mkIf config.services.stalwart-mail.enable {
serviceConfig = {
User = "stalwart-mail";
@ -18,6 +30,7 @@ in
""
"${lib.getExe config.services.stalwart-mail.package} --config=${configFile}"
];
ReadOnlyPaths = [ "${config.services.stalwart-mail.package.spam-filter}/spam-filter.toml" ];
};
};
}

View file

@ -5,8 +5,11 @@ let
in
{
config = lib.mkIf cfg.enable {
services.stalwart-mail.settings.metrics.prometheus = {
enable = true;
services.stalwart-mail.settings = {
config.local-keys = [ "metrics.prometheus.*" ];
metrics.prometheus = {
enable = true;
};
};
# Don't expose the endpoint
khscodes.services.nginx.virtualHosts."${fqdn}".locations."=/metrics/prometheus" = {

View file

@ -74,6 +74,8 @@
$config['oauth_identity_uri'] = 'https://login.kaareskovgaard.net/oauth2/openid/dovecot/userinfo';
$config['oauth_identity_fields'] = ['preferred_username'];
$config['oauth_scope'] = 'email openid profile';
# Don't show login dialog, just redirect to oauth login page
# $config['oauth_login_redirect'] = true;
'';
};
khscodes.services.nginx = {