diff --git a/modules/services/postgresql/module.nix b/modules/services/postgresql/module.nix index c055d0a..68128ae 100644 --- a/modules/services/postgresql/module.nix +++ b/modules/services/postgresql/module.nix @@ -28,6 +28,7 @@ in { ensureDatabases = [ "git" "grafana" + "stalwart" ]; ensureUsers = [ @@ -49,6 +50,10 @@ in { name = "grafana"; ensureDBOwnership = true; } + { + name = "stalwart"; + ensureDBOwnership = true; + } ]; settings = { # taken from https://pgconfigurator.cybertec.at/ diff --git a/modules/services/stalwart/module.nix b/modules/services/stalwart/module.nix new file mode 100644 index 0000000..107e88c --- /dev/null +++ b/modules/services/stalwart/module.nix @@ -0,0 +1,149 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + domain = "charlieroot.dev"; + acmeRoot = "/var/lib/acme/challenges-stalwart"; + cfg = config.modules.system.services.stalwart; +in { + options.modules.system.services.stalwart.enable = mkEnableOption "stalwart"; + config = mkIf cfg.enable { + services.stalwart-mail = { + enable = true; + package = pkgs.stalwart-mail; + openFirewall = true; + settings = { + email = { + # All incoming messages via SMTP or LMTP are automatically encrypted before they are written to disk, + # provided the user has uploaded their S/MIME certificate or OpenPGP public key. + + encryption.enable = true; + }; + server = { + # The default server hostname is utilized in SMTP EHLO commands, + # as well as included in message headers and reports. + hostname = "mail.${domain}"; + tls = { + # Specifies whether the TLS encryption is available for the listener. + enable = true; + + # Specifies whether the listener should use implicit or explicit TLS encryption. + # If set to false (the default), the listener will use explicit TLS encryption, + # which requires clients to initiate a STARTTLS command before upgrading the connection + # to an encrypted one. If set to true, the listener will use implicit TLS encryption, + # which requires the connection to be encrypted from the start. + implicit = true; + }; + + # Listeners are responsible for receiving incoming TCP connections. + listener = { + # Unencrypted SMTP connections are received on port 25 by default. + # This is the standard port for SMTP, and is used by mail servers to send email to each other. + smtp = { + protocol = "smtp"; + bind = ["localhost::25" "[::]:25"]; + tls.implicit = true; + }; + + # SMTP submissions with implicit TLS are received on port 465 by default. + # This is the standard port for SMTP submissions with native implicit TLS, + # and is used by mail clients to send email to mail servers. + + submissions = { + bind = ["localhost::465" "[::]:465"]; + protocol = "smtp"; + tls.implicit = true; + }; + imaps = { + bind = ["localhost::993" "[::]:993"]; + protocol = "imap"; + tls.implicit = true; + }; + jmap = { + bind = ["localhost::8080" "[::]:8080"]; + url = "https://mail.${domain}"; + protocol = "jmap"; + tls.implicit = true; + }; + management = { + bind = ["localhost:8080"]; + protocol = "http"; + tls.implicit = true; + }; + }; + lookup.default = { + hostname = "mail.${domain}"; + inherit domain; + }; + }; + storage = { + data = "postgresql"; + blob = "postgresql"; + fts = "postgresql"; + lookup = "postgresql"; + full-text = { + default-language = "en"; + }; + }; + store = { + postgresql = { + # Specifies the database type, set to "postgresql" for PostgreSQL. + type = "postgresql"; + + # The hostname or IP address of the PostgreSQL server. + host = "localhost"; + + # Port PostgreSQL runs on. Defaults to 5432. + port = "5432"; + + # Name of the database to connect to. + # TODO: add this to PostgreSQL. + name = "stalwart"; + + # The username used for authentication with the PostgreSQL server. + # TODO: add this to PostgreSQL. + username = "stalwart"; + + # Compression algorithm to use. + compression = "lz4"; + # Clean up every day at 5:30am local time. + purge.frequency = "30 5 *"; + + # Enable TLS + tls.enable = true; + }; + }; + }; + + services.nginx = { + enable = true; + virtualHosts.${domain} = { + addSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://localhost:${toString 8080}"; + }; + }; + }; + security.acme = let + email = "charlie@charlieroot.dev"; + in { + # testing server, do not use in production, but DO use it for setting things up. + # it has much higher rate limits. + # defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory"; + certs = { + ${domain} = { + webroot = acmeRoot; + inherit email; + group = "nginx"; + }; + }; + }; + }; + }; +}