diff options
| author | Alejandro Soto <alejandro@34project.org> | 2023-01-07 17:15:10 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2023-01-09 05:35:17 -0600 |
| commit | de4035c51faccf30c07e9d076738cd595971dc54 (patch) | |
| tree | 810b55d97996f47d9659c722da5f324000931c58 | |
| parent | fd156bcd3028a42b6d6a56dc1956d934bf8ea2c9 (diff) | |
env/users: implement mailbox host
| -rw-r--r-- | env/users/default.nix | 9 | ||||
| -rw-r--r-- | env/users/mailbox.nix | 113 |
2 files changed, 122 insertions, 0 deletions
diff --git a/env/users/default.nix b/env/users/default.nix index 60ee8d8..fed8906 100644 --- a/env/users/default.nix +++ b/env/users/default.nix @@ -1,5 +1,9 @@ { lib, ... }: with lib; { + imports = [ + ./mailbox.nix + ]; + options.local.users = with types; mkOption { default = { }; @@ -17,6 +21,11 @@ with lib; { type = listOf str; default = [ ]; }; + + hardAliases = mkOption { + type = listOf str; + default = [ ]; + }; }; }); }; diff --git a/env/users/mailbox.nix b/env/users/mailbox.nix new file mode 100644 index 0000000..46bbd6a --- /dev/null +++ b/env/users/mailbox.nix @@ -0,0 +1,113 @@ +{ 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} userdb_user=${canonical} + ''; + + localEntries = concatStrings + (flatten (mapAttrsToList + (canonical: user: + map (localEntry canonical) user.hardAliases) + cfg.users)); + + localAliases = 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}} + + passdb { + driver = passwd-file + args = ${localAliases} + + result_internalfail = return-fail + } + + passdb { + driver = passwd-file + args = username_format=%Ln ${vmailPath}/passwd + } + + passdb { + driver = pam + args = dovecot2 + username_filter = !*@*.* + #TODO: algo como 'override_fields = allow_nets=...' + } + + userdb { + driver = passwd-file + args = ${localAliases} + + result_success = continue + result_internalfail = return-fail + } + + userdb { + driver = passwd-file + args = username_format=%Ln ${vmailPath}/passwd + override_fields = uid=vmail gid=vmail home=${vmailPath}/home/%Ln + } + + userdb { + driver = passwd + args = blocking=no + skip = found + } + ''; + }; + + 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; + }; +} |
