# Guide: https://nixos-mailserver.readthedocs.io/en/latest/setup-guide.html { container, pkgs, util, const, lib, config, ... }: with lib; let cfg = config.container.module.mail; domain = config.container.domain; in { options = { container.module.mail = { enable = mkEnableOption "Email server."; address = mkOption { default = "10.1.0.5"; type = types.str; }; port = mkOption { default = 80; type = types.int; }; domain = mkOption { default = "mail.${config.container.domain}"; type = types.str; }; storage = mkOption { default = "${config.container.storage}/mail"; type = types.str; }; }; }; config = mkIf cfg.enable { systemd.tmpfiles.rules = container.mkContainerDir cfg [ "data" # "data/indices" # "data/vmail" # "data/sieve" # "data/dkim" ]; containers.mail = container.mkContainer cfg { bindMounts = { "/var/lib/dovecot/indices" = { hostPath = "${cfg.storage}/data/indices"; isReadOnly = false; }; "/var/vmail" = { hostPath = "${cfg.storage}/data/vmail"; isReadOnly = false; }; "/var/sieve" = { hostPath = "${cfg.storage}/data/sieve"; isReadOnly = false; }; "/var/dkim" = { hostPath = "${cfg.storage}/data/dkim"; isReadOnly = false; }; "/acme" = { hostPath = "${config.container.module.proxy.storage}/letsencrypt"; isReadOnly = true; }; }; config = { config, ... }: container.mkContainerConfig cfg { imports = [ (builtins.fetchTarball { url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-${const.stateVersion}/nixos-mailserver-nixos-${const.stateVersion}.tar.gz"; sha256 = "sha256:0clvw4622mqzk1aqw1qn6shl9pai097q62mq1ibzscnjayhp278b"; }) ]; mailserver = { enable = true; domains = [ domain ]; fqdn = cfg.domain; sendingFqdn = domain; # Use `mkpasswd -sm bcrypt`. loginAccounts = let defaultQuota = "1G"; in { "admin@${domain}" = { name = "admin"; hashedPassword = "$2b$05$1O.dxXxaVshcBNybcqDRYuTlnYt3jDBwfPZWoDtP4BjOLoL0StYsi"; quota = defaultQuota; }; "account@${domain}" = { name = "account"; hashedPassword = "$2b$05$sCyZHdk98KqQ1qsTIvbrUeRJlNBOwBqDgpdc1QxiSnONlEkZ8xGNO"; quota = defaultQuota; }; "hi@${domain}" = { name = "hi"; hashedPassword = "$2b$05$6fT5hIhzIasNfp9IQr/ds.5RuxH95VKU3QJWlX3hmrAzDF3mExanq"; quota = defaultQuota; aliases = [ "voronind@${domain}" ]; }; "job@${domain}" = { name = "job"; hashedPassword = "$2b$05$.sUmv2.9EWPfLwJn/oZw2e1UbR7HrpNQ2THc5jjX3ysy7CY8ZWHUC"; quota = defaultQuota; }; "trash@${domain}" = { name = "trash"; hashedPassword = "$2b$05$kn5ygZjN9NR3LXjnKKRw/.DXaZQNW.1XEottlCFIoKiDpIj.JGLJm"; catchAll = [ domain ]; quota = defaultQuota; }; "noreply@${domain}" = { name = "noreply"; hashedPassword = "$2b$05$TaKwoYmcmkAhsRRv6xG5wOkChcz50cB9BP6QPUDKNAcxMbrY6AeMK"; sendOnly = true; quota = defaultQuota; }; }; enableImap = true; enableImapSsl = true; enableSubmission = true; enableSubmissionSsl = true; enableManageSieve = true; virusScanning = false; certificateScheme = "manual"; keyFile = "/acme/live/${domain}/privkey.pem"; certificateFile = "/acme/live/${domain}/cert.pem"; indexDir = "/var/lib/dovecot/indices"; mailDirectory = "/var/vmail"; sieveDirectory = "/var/sieve"; dkimKeyDirectory = "/var/dkim"; mailboxes = { All = { auto = "subscribe"; specialUse = "All"; }; Archive = { auto = "subscribe"; specialUse = "Archive"; }; Drafts = { auto = "subscribe"; specialUse = "Drafts"; }; Junk = { auto = "subscribe"; specialUse = "Junk"; # autoexpunge = "3d"; }; Sent = { auto = "subscribe"; specialUse = "Sent"; }; Trash = { auto = "subscribe"; specialUse = "Trash"; # autoexpunge = "30d"; }; }; dmarcReporting = { inherit domain; enable = true; organizationName = "voronind"; # email = "noreply@${domain}"; }; # monitoring = { # enable = true; # alertAddress = "admin@${domain}"; # }; }; services = { roundcube = { enable = true; dicts = with pkgs.aspellDicts; [ en ru ]; hostName = cfg.domain; plugins = [ "managesieve" ]; extraConfig = '' # starttls needed for authentication, so the fqdn required to match # the certificate # $config['smtp_server'] = "tls://${config.mailserver.fqdn}"; # $config['smtp_server'] = "tls://localhost"; $config['smtp_server'] = "localhost:25"; $config['smtp_auth_type'] = null; $config['smtp_user'] = ""; $config['smtp_pass'] = ""; # $config['smtp_user'] = "%u"; # $config['smtp_pass'] = "%p"; ''; }; nginx = { virtualHosts.${cfg.domain} = { forceSSL = false; enableACME = false; }; }; }; systemd = { services.autoexpunge = { description = "Delete old mail"; serviceConfig.Type = "oneshot"; path = [ pkgs.dovecot ]; script = '' doveadm expunge -A mailbox Junk SENTBEFORE 7d doveadm expunge -A mailbox Trash SENTBEFORE 30d ''; }; timers.autoexpunge = { timerConfig = { OnCalendar = "daily"; Persistent = true; Unit = "autoexpunge.service"; }; wantedBy = [ "timers.target" ]; }; }; }; }; }; }