blob: 06e67efec8f32ecdda9e62feba9260917951bd6e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.local;
in
{
options.local.mailHost.enable = mkEnableOption "mailbox host service";
config =
let
imapHostname = cfg.domains.imap.main;
in
mkIf cfg.mailHost.enable {
services.dovecot2 =
let
cert = config.security.acme.certs.${imapHostname}.directory;
in
{
enable = true;
enablePAM = false;
enableLmtp = true;
#sslServerKey = "${cert}/key.pem";
#sslServerCert = "${cert}/fullchain.pem";
mailUser = "vmail";
mailGroup = "vmail";
mailLocation = "maildir:~/mail";
extraConfig =
let
inherit (config.networking) domain;
# https://dovecot.org/list/dovecot/2019-March/115250.html
# Otra solución posible (https://serverfault.com/a/1062274/980378):
# auth_username_format = %{if;%d;eq;${domain};%Ln;%Lu}
localEntry = canonical: username: ''
${username}:::::::user=${canonical} nopassword userdb_user=${canonical}
'';
localEntries = concatStrings
(flatten (mapAttrsToList
(canonical: user:
map (localEntry canonical) ([ canonical ] ++ user.hardAliases))
cfg.users));
localMailboxes = pkgs.writeText "local-mailboxes" localEntries;
vmailPath = "/var/lib/vmail/%{if;%d;ne;;%Ld;${domain}}";
in
''
# Esto enfuerza user@domain.tld
auth_username_format = %{if;%Ld;eq;${domain};%Ln;%{if;%d;ne;;%Lu;%Ln@invalid}}
# FIXME: Esta cadena de passdbs hace que 'doveadm user lookup'
# falle para usuarios locales, pero todo lo demás sirve. Parece
# ser debido a que pam no puede enumerar.
passdb {
driver = passwd-file
args = username_format=%Ln ${vmailPath}/passwd
}
passdb {
driver = passwd-file
args = ${localMailboxes}
# Esta es una forma de determinar si se encontró el usuario en
# el passwd-file por medio de nopassword sin realmente
# autenticarlo. Cuidado con result_success, porque si eso se
# configura mal se permite inicio de sesión con cualquier
# contraseña (!!!).
result_success = continue
result_failure = return-fail
result_internalfail = return-fail
username_filter = !*@*
}
passdb {
driver = pam
args = dovecot2
username_filter = !*@*
#TODO: algo como 'override_fields = allow_nets=...'
}
userdb {
driver = passwd-file
args = username_format=%Ln ${vmailPath}/passwd
override_fields = uid=vmail gid=vmail home=${vmailPath}/home/%Ln
}
userdb {
driver = passwd-file
args = ${localMailboxes}
result_success = continue-ok
result_internalfail = return-fail
skip = found
}
userdb {
driver = passwd
args = blocking=no
skip = notfound
}
'';
};
security = {
# Necesario debido a 'enablePAM = false'
pam.services.dovecot2 = { };
#acme.certs.${imapHostname} = {
# inherit (config.services.dovecot2) group;
#};
};
users = {
users.${config.services.dovecot2.mailUser}.uid = 995;
groups.${config.services.dovecot2.mailGroup}.gid = 993;
};
#networking.firewall.allowedTCPPorts = [ 143 993 ];
#local.certs.imap.enable = true;
};
}
|