{ inputs, pkgs, lib, config, system, host, ... }: let inherit (builtins) toString toFile readFile; inherit (lib) types; inherit (pkgs.lib) loadFile unlines unlinesAttrs unlinesValues unwords; inherit (config) networking; inherit (config.services) dovecot2 postfix openldap; # NOTE: nixpkgs' dovecot2.stateDir is currently not exported stateDir = "/var/lib/dovecot"; sieve_pipe_bin_dir = pkgs.buildEnv { name = "sieve_pipe_bin_dir"; pathsToLink = [ "/bin" ]; paths = [ learn-spam learn-ham ]; }; learn-spam = pkgs.writeShellScriptBin "learn-spam.sh" '' exec ${pkgs.rspamd}/bin/rspamc -h /run/rspamd/learner.sock learn_spam ''; learn-ham = pkgs.writeShellScriptBin "learn-ham.sh" '' exec ${pkgs.rspamd}/bin/rspamc -h /run/rspamd/learner.sock learn_ham ''; dovecot-virtual = pkgs.buildEnv { name = "dovecot-virtual"; pathsToLink = [ "/" ]; paths = [ dovecot-virtual-all dovecot-virtual-recents ]; }; dovecot-virtual-all = pkgs.writeTextFile { name = "dovecot-virtual-all"; destination = "/All/dovecot-virtual"; text = '' * all ''; }; dovecot-virtual-recents = pkgs.writeTextFile { name = "dovecot-virtual-recents"; destination = "/Recents/dovecot-virtual"; text = '' * all younger 172800 ''; }; dovecot-virtual-pop3 = pkgs.writeTextFile { name = "dovecot-virtual-pop3"; destination = "/pop3/INBOX/dovecot-virtual"; text = '' All All+* all ''; }; in { imports = [ dovecot/sourcephile.fr.nix dovecot/autogeree.net.nix ]; users.groups.acme.members = [ dovecot2.user ]; systemd.services.dovecot2 = { after = [ "postfix.service" "openldap.service" ]; /* preStart = '' # SEE: http://wiki2.dovecot.org/SharedMailboxes/Permissions install -D -d -m 0771 \ -o "${dovecot2.user}" \ -g "${dovecot2.group}" \ ${stateDir}/mail ''; */ serviceConfig = { #ExecStart = lib.mkForce "${pkgs.utillinux}/bin/setarch x86_64 --addr-no-randomize /bin/sh -c 'LD_PRELOAD=${pkgs.gcc-unwrapped.lib}/lib/libasan.so ${pkgs.dovecot}/sbin/dovecot -F'"; # Dovecot2 does not work with environment.memoryAllocator.provider="scudo" # https://wiki.dovecot.org/Design/Memory # Scudo ERROR: CHECK failed at /build/compiler-rt-7.1.0.src/lib/scudo/../sanitizer_common/sanitizer_allocator_primary64.h: # 644 ((beg)) == ((address_range.MapOrDie(beg, size))) (4398046511092, 4398046507008) BindReadOnlyPaths = [ "/dev/null:/etc/ld-nix.so.preload" ]; }; }; #users.users."${dovecot2.mailUser}".isSystemUser = true; # Fix nixpkgs networking.nftables.ruleset = '' add rule inet filter net2fw tcp dport 993 counter accept comment "IMAPS" #add rule inet filter net2fw tcp dport 995 counter accept comment "POP3S" add rule inet filter net2fw tcp dport 4190 counter accept comment "Sieve" ''; services.dovecot2 = { enable = true; modules = [ pkgs.dovecot_pigeonhole pkgs.dovecot_fts_xapian ]; enablePAM = false; enableImap = true; enableLmtp = true; enablePop3 = false; protocols = [ "sieve" ]; # If needed, may be overrided by userdb_mail= in passdb, or mail= in userdb # Here INDEX and CONTROL are separated, # it's not useful since there is no quota at the filesystem level # it's just to let this possibility later on. mailLocation = "sdbox:${stateDir}/home/%d/%n/mail:UTF-8:CONTROL=${stateDir}/control/%d/%n:INDEX=${stateDir}/index/%d/%n"; createMailUser = false; mailUser = ""; mailGroup = ""; sslServerCert = null; sieveScripts = { global = dovecot/sieve/global; }; extraConfig = '' auth_verbose = no auth_debug = no mail_debug = no verbose_ssl = no log_timestamp = "%Y-%m-%d %H:%M:%S " ssl = required ssl_dh = <${inputs.secrets + "/openssl/dh.pem"} ssl_cipher_list = HIGH:!LOW:!SSLv2:!EXP:!aNULL ssl_prefer_server_ciphers = yes ssl_cert = service_count = 1 # Number of processes to always keep waiting for more connections. process_min_avail = 0 # If you set service_count=0, you probably need to grow this. #vsz_limit = 64M } service quota-warning { executable = script ${ pkgs.writeShellScript "quota-warning" '' set -eu PERCENT=$1 USER=$2 cat << EOF | ${pkgs.dovecot}/libexec/dovecot/dovecot-lda -d $USER -o "plugin/quota=maildir:User quota:noenforcing" From: postmaster@${networking.domain} Subject: [WARNING] your mailbox is now $PERCENT% full. Please remove some mails to make room for new ones. EOF '' } # use some unprivileged user for executing the quota warnings user = ${dovecot2.user} unix_listener quota-warning { } } protocol pop3 { mail_plugins = $mail_plugins virtual #mail_max_userip_connections = 10 # Virtual namespace for the virtual INBOX. # Use a global directory for dovecot-virtual files. #namespace Inbox { # hidden = yes # list = no # location = virtual:''${dovecot-virtual-pop3}/pop3:INDEX=${stateDir}/index/%d/%n/virtual/pop3:LAYOUT=fs # prefix = pop3+ #} pop3_client_workarounds = pop3_fast_size_lookups = yes pop3_lock_session = yes pop3_no_flag_updates = yes # Use GUIDs to avoid accidental POP3 UIDL changes instead of IMAP UIDs. pop3_uidl_format = %g } service pop3 { process_limit = 1024 } service pop3-login { inet_listener pop3s { port = 995 ssl = yes } } ''; }; }