summaryrefslogtreecommitdiff
path: root/services/email.nix
diff options
context:
space:
mode:
Diffstat (limited to 'services/email.nix')
-rw-r--r--services/email.nix142
1 files changed, 142 insertions, 0 deletions
diff --git a/services/email.nix b/services/email.nix
new file mode 100644
index 0000000..d3f60ab
--- /dev/null
+++ b/services/email.nix
@@ -0,0 +1,142 @@
+{config, pkgs, lib, ...}:
+let
+ cfg = config.wilkuu.services.stalwart;
+ hostname = config.networking.hostName;
+in
+{
+ options.wilkuu.services.stalwart = with lib; {
+ domain = mkOption {
+ type = types.str;
+ default = "mail.${hostname}.local";
+ example = "mail.wilkuu.xyz";
+ description = "Domain for http connections.";
+ };
+ wellKnownDomains = mkOption {
+ type = types.listOf types.str;
+ default = [ "${hostname}.local" ];
+ example = [ "wilkuu.xyz"] ;
+ description = "Domain for well-known items";
+ };
+ doACME = mkEnableOption "Enable ACME for stalwart here";
+ enable = mkEnableOption "Enable the email service";
+ dataDir = mkOption {
+ type = types.path;
+ description = "Storage localtion for Stalwart user data";
+ default = "/srv/data/stalwart";
+ example = "/srv/data/stalwart";
+ };
+ };
+
+ config = lib.mkIf cfg.enable (let
+ sopsPath = ../secrets/${hostname}/stalwart.yaml;
+ secrets = ["user_admin_password"];
+ toSops = (sname: "stalwart/${sname}");
+ toCredfilePath = (name: config.sops.secrets.${toSops name}.path);
+ toStalwartCred = name: "%{file:/run/credentials/stalwart-mail.service/${name}}%";
+
+ basicListener = proto: port: tls: {
+ bind = ["[::]:${toString port}"];
+ protocol = proto;
+ tls.implicit = tls;
+ };
+
+ proxyWellKnown = names: let
+ uris = map (n: "/.well-known/${n}") names;
+ in (lib.genAttrs uris (uri: {
+ proxyPass = "http://localhost:3080${uri}";
+ recommendedProxySettings = true;
+ }));
+
+ makeHttpRedirect = target: https: { return = "302 ${if https then "https" else "http"}://${target}";};
+
+ in {
+ networking.hosts = {
+ "127.0.0.1" = [cfg.domain];
+ };
+
+ # Need this bc otherwise sops will complain for some reason
+ users = {
+ groups.stalwart-mail = { };
+ users.stalwart-mail = {
+ isSystemUser = true;
+ group = "stalwart-mail";
+ };
+ };
+
+
+ # TODO: Move this into a util function or option;
+ sops.secrets =
+ (lib.genAttrs (map toSops secrets)
+ (name: {
+ sopsFile = sopsPath;
+ mode = "0440";
+ owner = "stalwart-mail";
+ }));
+
+
+ services.nginx.virtualHosts = (lib.genAttrs cfg.wellKnownDomains (
+ (wdomain: {
+ locations = (proxyWellKnown ["jmap" "mta-sts.txt" "mail-v1.xml" "autoconfig/mail"])
+ // (lib.genAttrs ["/.well_known/caldav" "/.well_known/webdav" ] (uri: (makeHttpRedirect "${cfg.domain}${uri}") cfg.doACME ));
+ })))
+ //
+
+ (lib.genAttrs (map (x: "${x}${cfg.domain}") ["" "autodiscover." "autoconfig."]) (domain: {
+ addSSL = cfg.doACME;
+ enableACME = cfg.doACME;
+ serverName = "${domain}";
+ locations."/" = {
+ proxyPass = "http://localhost:3080";
+ recommendedProxySettings = true;
+ };
+ }));
+
+
+ services.stalwart-mail = {
+ enable = true;
+ dataDir = cfg.dataDir;
+ openFirewall = false;
+ credentials = lib.genAttrs secrets toCredfilePath;
+ settings = {
+ server.listener = {
+ smtp = basicListener "smtp" 25 false;
+ submission = basicListener "smtp" 465 true;
+ imaptls = basicListener "imap" 993 true;
+ imap = basicListener "imap" 143 true;
+ webdav = basicListener "http" 3080 false;
+ jmap = basicListener "http" 3080 false;
+ http = basicListener "http" 3080 false;
+ };
+
+ store.rocksdb = {
+ type = "rocksdb";
+ path = cfg.dataDir;
+ compression = "lz4";
+ };
+
+ directory.internal = {
+ type = "internal";
+ store = "rocksdb";
+ };
+
+ storage = {
+ data = "rocksdb";
+ fts = "rocksdb";
+ blob = "rocksdb";
+ lookup = "rocksdb";
+ directory = "internal";
+ };
+
+ authentication.fallback-admin = {
+ user = "admin";
+ secret = toStalwartCred "user_admin_password";
+ };
+
+ http = {
+ use-x-forwarded = true;
+ url = "protocol + \"${cfg.domain}\"";
+ };
+ };
+ };
+ });
+}