{ config, lib, pkgs, ... }: { microvm.mem = 2048; networking.hostName = "mail"; c3d2 = { deployment.server = "server10"; }; mailserver = let inherit (config.security) ldap; ldapFilter = ldap.searchFilterWithGroupFilter "mail-users" "(uid=%n)"; in { enable = true; certificateScheme = "acme-nginx"; dmarcReporting = { # enable = true; # domain = "c3d2.de"; organizationName = "Netzbiotop Dresden e.V."; }; debug = true; domains = [ "c3d2.social" "netzbiotop.org" ]; dkimKeyBits = 2048; dkimSelector = "default"; dkimSigning = true; enableImap = true; enableImapSsl = true; enableManageSieve = true; enablePop3 = true; enablePop3Ssl = true; enableSubmission = true; enableSubmissionSsl = true; extraVirtualAliases = {}; fqdn = "mail.flpk.zentralwerk.org"; ldap = { enable = true; bind = { dn = ldap.bindDN; passwordFile = config.sops.secrets."dovecot/ldapSearchUserPassword".path; }; dovecot = { passFilter = ldapFilter; # userAttrs = "uidNumber=uid"; userFilter = ldapFilter; }; postfix = { filter = ldap.groupFilter "mail-users"; mailAttribute = "uid"; # uidAttribute = "uid"; }; searchBase = ldap.userBaseDN; uris = [ "ldaps://${ldap.domainName}" ]; }; mailboxes = { Drafts = { auto = "subscribe"; specialUse = "Drafts"; }; Sent = { auto = "subscribe"; specialUse = "Sent"; }; Spam = { auto = "subscribe"; specialUse = "Junk"; }; Trash = { auto = "subscribe"; specialUse = "Trash"; }; }; maxConnectionsPerUser = 10; messageSizeLimit = 10240000; # 10 MiB monitoring = { # enable = true; # alertAddress = "example@c3d2.de"; }; rejectRecipients = [ config.mailserver.dmarcReporting.localpart ]; virusScanning = false; vmailGroupName = "vmail"; vmailUserName = "vmail"; }; networking.enableIPv6 = false; # mail is stuck in the 80s services = { backup = { enable = true; paths = [ "/var/lib/dovecot/" "/var/lib/postfix/" "/var/dkim/" "/var/sieve/" "/var/vmail/" ]; }; nginx = { enable = true; commonHttpConfig = /* nginx */ '' proxy_headers_hash_bucket_size 96; ''; virtualHosts."autoconfig.netzbiotop.org" = { enableACME = true; forceSSL = true; serverAliases = [ "autoconfig.netzbiotop.org" "autodiscover.netzbiotop.org" ]; locations = { "/".proxyPass = "http://127.0.0.1:4243/"; "/initdb".extraConfig = '' # Limit access to clients connecting from localhost allow 127.0.0.1; deny all; ''; }; }; }; portunus.addToHosts = true; postfix.mapFiles."valias" = lib.mkForce "/home/root/valias"; roundcube = { enable = true; hostName = config.mailserver.fqdn; extraConfig = /* php */ '' # starttls needed for authentication, so the fqdn required to match the certificate $config['smtp_server'] = "tls://${config.mailserver.fqdn}"; $config['smtp_user'] = "%u"; $config['smtp_pass'] = "%p"; ''; }; }; sops = { defaultSopsFile = ./secrets.yaml; secrets."dovecot/ldapSearchUserPassword" = { owner = config.users.users.dovecot2.name; }; }; systemd.services.automx2 = { after = [ "network.target" ]; postStart = let json = pkgs.writeText "data.json" (builtins.toJSON { provider = config.mailserver.dmarcReporting.organizationName; domains = config.mailserver.domains; servers = [ { name = config.mailserver.fqdn; type = "imap"; } { name = config.mailserver.fqdn; type = "pop3"; } { name = config.mailserver.fqdn; type = "smtp"; } ]; }); in '' sleep 3 && ${lib.getExe pkgs.curl} -X POST --json @${json} http://127.0.0.1:4243/initdb/ ''; serviceConfig = { Environment = [ "AUTOMX2_CONF=${pkgs.writeText "automx2-conf" /* toml */ '' [automx2] loglevel = WARNING db_uri = sqlite:///:memory: proxy_count = 1 ''}" "FLASK_APP=automx2.server:app" "FLASK_CONFIG=production" ]; ExecStart = "${pkgs.python3.buildEnv.override { extraLibs = [ pkgs.python3Packages.automx2 ]; }}/bin/flask run --host=127.0.0.1 --port=4243"; Restart = "always"; StateDirectory = "automx2"; User = "automx2"; WorkingDirectory = "/var/lib/automx2"; }; unitConfig = { Description = "MUA configuration service"; Documentation = "https://rseichter.github.io/automx2/"; }; wantedBy = [ "multi-user.target" ]; }; system.stateVersion = "23.11"; users = { groups.automx2 = {}; users.automx2 = { group = "automx2"; isSystemUser = true; }; }; }