char/topaz-flake
git clone https://git.t4t.associates/char/topaz-flake
405f936
main
1{ 2config , 3lib , 4pkgs , 5 ... 6} : 7let 8domain = "mail.char.lt" ; 9cert = config . security . acme . certs .${ domain }; 10accounts = { 11som-codes = "charlotte@som.codes" ; 12char-lt = "c@char.lt" ; 13}; 14passwordFile = name :"/var/secrets/mail/ ${ name } .password" ; 15mbsyncConfig = 16name :username : 17pkgs . writeText "mbsync- ${ name } .conf" '' 18IMAPAccount migadu 19Host imap.migadu.com 20Port 993 21User ${ username } 22PassCmd " ${ pkgs . coreutils } /bin/cat $CREDENTIALS_DIRECTORY/password" 23TLSType IMAPS 24CertificateFile /etc/ssl/certs/ca-certificates.crt 25 26IMAPStore remote 27Account migadu 28 29IMAPAccount dovecot 30Host 127.0.0.1 31Port 143 32User ${ username } 33PassCmd " ${ pkgs . coreutils } /bin/cat $CREDENTIALS_DIRECTORY/password" 34TLSType None 35AuthMechs PLAIN 36 37IMAPStore local 38Account dovecot 39 40Channel mail 41Far :remote: 42Near :local: 43Patterns * 44Sync All 45Create Both 46Remove Both 47Expunge Both 48CopyArrivalDate yes 49SyncState /var/lib/mail-sync/ ${ name } / 50'' ; 51in 52{ 53services . nginx . virtualHosts .${ domain } = { 54enableACME = true ; 55locations . "/" . return = "404" ; 56}; 57security . acme . certs .${ domain }. reloadServices = [ "dovecot.service" ]; 58networking . firewall . allowedTCPPorts = [ 993 ]; 59 60services . dovecot2 = { 61enable = true ; 62package = pkgs . dovecot ; 63settings = { 64dovecot_config_version = "2.4.4" ; 65dovecot_storage_version = "2.4.4" ; 66protocols . imap = true ; 67hostname = domain ; 68ssl = "required" ; 69ssl_server_cert_file = " ${ cert . directory } /fullchain.pem" ; 70ssl_server_key_file = " ${ cert . directory } /key.pem" ; 71 72mail_uid = "dovemail" ; 73mail_gid = "dovemail" ; 74first_valid_uid = 1 ; 75mail_driver = "maildir" ; 76mail_path = "~/Maildir" ; 77"namespace inbox" = { 78inbox = true ; 79separator = "/" ; 80}; 81"passdb passwd-file" . passwd_file_path = "/run/dovecot2/passwd" ; 82"userdb passwd-file" . passwd_file_path = "/run/dovecot2/passwd" ; 83 84mail_plugins = { 85fts = true ; 86fts_flatcurve = true ; 87}; 88"fts flatcurve" = { }; 89fts_autoindex = true ; 90fts_flatcurve_substring_search = true ; 91"language en" . default = true ; 92language_tokenizers = "generic email-address" ; 93language_filters = "normalizer-icu" ; 94 95# Sync over IMAP so Dovecot alone manages Maildir UIDs and indexes. 96"service imap-login" = { 97"inet_listener imap" = { 98listen = "127.0.0.1" ; 99port = 143 ; 100}; 101"inet_listener imaps" = { 102port = 993 ; 103ssl = true ; 104}; 105}; 106}; 107}; 108 109systemd . tmpfiles . rules = [ "d /var/lib/mail 0700 dovemail dovemail -" ]; 110 111users . users . mail-sync = { 112isSystemUser = true ; 113group = "mail-sync" ; 114}; 115users . groups . mail-sync = { }; 116 117systemd . services = { 118dovecot = { 119wants = [ "acme-finished- ${ domain } .target" ]; 120after = [ "acme-finished- ${ domain } .target" ]; 121serviceConfig . LoadCredential = lib . mapAttrsToList ( 122name :_ :" ${ name } : ${ passwordFile name } " 123) accounts ; 124preStart = lib . mkAfter '' 125umask 077 126: > /run/dovecot2/passwd.new 127${ lib . concatStringsSep "\n" ( 128lib . mapAttrsToList ( name : username : '' 129test -n "$(cat "$CREDENTIALS_DIRECTORY/ ${ name } ")" 130hash=$( ${ pkgs . openssl } /bin/openssl passwd -6 -stdin < "$CREDENTIALS_DIRECTORY/ ${ name } ") 131[[ "$hash" != *$'\n'* ]] 132printf ' ${ username } :{CRYPT}%s:%s:%s::/var/lib/mail/ ${ username } \n' \ 133"$hash" "$(id -u dovemail)" "$(id -g dovemail)" >> /run/dovecot2/passwd.new 134'' ) accounts 135)} 136chown root:dovecot2 /run/dovecot2/passwd.new 137chmod 640 /run/dovecot2/passwd.new 138mv /run/dovecot2/passwd.new /run/dovecot2/passwd 139'' ; 140}; 141} 142// lib . mapAttrs' ( 143name :username : 144lib . nameValuePair "mail-sync- ${ name } " { 145description = "Synchronise ${ username } with Migadu" ; 146wants = [ "network-online.target" ]; 147requires = [ "dovecot.service" ]; 148after = [ 149"network-online.target" 150"dovecot.service" 151]; 152serviceConfig = { 153Type = "oneshot" ; 154User = "mail-sync" ; 155Group = "mail-sync" ; 156StateDirectory = "mail-sync/ ${ name } " ; 157StateDirectoryMode = "0700" ; 158UMask = "0077" ; 159LoadCredential = [ "password: ${ passwordFile name } " ]; 160ExecStart = " ${ pkgs . isync } /bin/mbsync --config ${ mbsyncConfig name username } --all" ; 161NoNewPrivileges = true ; 162PrivateTmp = true ; 163ProtectHome = true ; 164ProtectSystem = "strict" ; 165}; 166} 167) accounts ; 168 169systemd . timers = lib . mapAttrs' ( 170name :_ : 171lib . nameValuePair "mail-sync- ${ name } " { 172wantedBy = [ "timers.target" ]; 173timerConfig = { 174OnBootSec = "1min" ; 175OnUnitInactiveSec = "1min" ; 176}; 177} 178) accounts ; 179}