# Email server configuration # Copyright (C) 2023 Nguyễn Gia Phong # # This file is part of loang configuration. # # Loang configuration is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Loang configuration is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with loang configuration. If not, see . { config, options, pkgs, ... }: let certDir = config.security.acme.certs.${hostname}.directory; domain = config.networking.domain; hostname = "tem.${domain}"; in { networking.firewall.allowedTCPPorts = [ 25 # SMTP-MTA 465 # SMTP-MSA 993 # IMAPS ]; services = { alps = { enable = true; imaps.host = hostname; theme = "alps"; }; maddy = { config = '' auth_map email_localpart '' + (builtins.replaceStrings [ '' auth.pass_table local_authdb { table sql_table { driver sqlite3 dsn credentials.db table_name passwords } } '' "imap tcp://0.0.0.0:143" "submission tcp://0.0.0.0:587" ] [ '' auth.shadow local_authdb { debug yes use_helper no } '' "imap tls://0.0.0.0:993" "submission tls://0.0.0.0:465" ] options.services.maddy.config.default); enable = true; hostname = hostname; primaryDomain = domain; tls = { loader = "file"; certificates = [{ certPath = "${certDir}/cert.pem"; keyPath = "${certDir}/key.pem"; }]; }; }; nginx.virtualHosts = { "mta-sts.${domain}" = { enableACME = true; forceSSL = true; locations."/".root = pkgs.writeTextFile { name = "mta-sts.txt"; text = '' version: STSv1 mode: enforce max_age: 604800 mx: ${hostname} ''; destination = "/.well-known/mta-sts.txt"; }; }; ${hostname} = let alps = config.services.alps; in { enableACME = true; forceSSL = true; locations."/".proxyPass = "http://${alps.bindIP}:${toString alps.port}"; }; }; }; users.extraUsers.maddy.extraGroups = [ "nginx" "shadow" ]; }