summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--env/users/default.nix9
-rw-r--r--env/users/mailbox.nix113
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;
+ };
+}