summaryrefslogtreecommitdiff
path: root/os/kay/modules/services/mail
diff options
context:
space:
mode:
Diffstat (limited to 'os/kay/modules/services/mail')
-rw-r--r--os/kay/modules/services/mail/default.nix173
-rw-r--r--os/kay/modules/services/mail/secrets.yaml28
2 files changed, 201 insertions, 0 deletions
diff --git a/os/kay/modules/services/mail/default.nix b/os/kay/modules/services/mail/default.nix
new file mode 100644
index 0000000..01f44bb
--- /dev/null
+++ b/os/kay/modules/services/mail/default.nix
@@ -0,0 +1,173 @@
+{ config, ... }:
+let
+ ipv6 = "2001:470:ee65::1337";
+ domain = config.global.userdata.domain;
+ username = config.global.userdata.name;
+ email = [
+ "${username}@${domain}"
+
+ # used by github automation
+ # https://github.com/nocodb/nocodb/blob/32826d4b24e9285b898bb3547fdf550f81c930bb/nix/bumper/bumper.sh#L5
+ "auto@${domain}"
+ # used by mail.sinanmohd.com
+ "postmaster@${domain}"
+ # used by ns1.sinanmohd.com
+ "hostmaster@${domain}"
+ ];
+
+ credentials_directory = "/run/credentials/stalwart-mail.service";
+in
+{
+ security.acme.certs.${domain}.postRun = "systemctl restart stalwart-mail.service";
+ sops.secrets = {
+ "mail.${domain}/dkim_rsa".sopsFile = ./secrets.yaml;
+ "mail.${domain}/dkim_ed25519".sopsFile = ./secrets.yaml;
+ "mail.${domain}/password".sopsFile = ./secrets.yaml;
+ };
+
+ systemd.services.stalwart-mail.serviceConfig.LoadCredential = [
+ "password:${config.sops.secrets."mail.${domain}/password".path}"
+
+ "dkim_rsa:${config.sops.secrets."mail.${domain}/dkim_rsa".path}"
+ "dkim_ed25519:${config.sops.secrets."mail.${domain}/dkim_ed25519".path}"
+
+ "cert:${config.security.acme.certs.${domain}.directory}/fullchain.pem"
+ "key:${config.security.acme.certs.${domain}.directory}/key.pem"
+ ];
+
+ services.postgresql = {
+ ensureDatabases = [ "stalwart" ];
+ ensureUsers = [
+ {
+ name = "stalwart";
+ ensureDBOwnership = true;
+ }
+ ];
+ };
+
+ services.stalwart-mail = {
+ enable = true;
+ openFirewall = true;
+
+ settings = {
+ queue.outbound = {
+ ip-strategy = "ipv6_then_ipv4";
+ source-ip.v6 = "['${ipv6}']";
+ tls.starttls = "optional";
+ };
+ http.url = "'https://stalwart.${domain}'";
+
+ server = {
+ hostname = "mail.${domain}";
+ listener = {
+ smtp = {
+ bind = [
+ "[${ipv6}]:25"
+ "0.0.0.0:25"
+ ];
+ protocol = "smtp";
+ };
+ submission = {
+ bind = "[::]:587";
+ protocol = "smtp";
+ };
+ submissions = {
+ bind = "[::]:465";
+ protocol = "smtp";
+ tls.implicit = true;
+ };
+ imaptls = {
+ bind = "[::]:993";
+ protocol = "imap";
+ tls.implicit = true;
+ };
+ http = {
+ bind = "[::]:8085";
+ protocol = "http";
+ };
+ };
+ };
+
+ signature = {
+ rsa = {
+ private-key = "%{file:${credentials_directory}/dkim_rsa}%";
+ inherit domain;
+ selector = "rsa";
+ headers = [
+ "From"
+ "To"
+ "Date"
+ "Subject"
+ "Message-ID"
+ ];
+ algorithm = "rsa-sha-256";
+ canonicalization = "simple/simple";
+
+ set-body-length = true;
+ expire = "2d";
+ report = true;
+ };
+ ed25519 = {
+ private-key = "%{file:${credentials_directory}/dkim_ed25519}%";
+ inherit domain;
+ selector = "ed25519";
+ headers = [
+ "From"
+ "To"
+ "Date"
+ "Subject"
+ "Message-ID"
+ ];
+ algorithm = "ed25519-sha256";
+ canonicalization = "simple/simple";
+
+ set-body-length = true;
+ expire = "2d";
+ report = true;
+ };
+ };
+
+ certificate."default" = {
+ cert = "%{file:${credentials_directory}/cert}%";
+ private-key = "%{file:${credentials_directory}/key}%";
+ };
+
+ storage = {
+ data = "postgresql";
+ fts = "postgresql";
+ blob = "postgresql";
+ lookup = "postgresql";
+ directory = "memory";
+ };
+ store.postgresql = {
+ type = "postgresql";
+ host = "localhost";
+ database = "stalwart";
+ user = "stalwart";
+ timeout = "15s";
+ tls.enable = false;
+ pool.max-connections = 10;
+ };
+
+ directory."memory" = {
+ type = "memory";
+
+ principals = [
+ {
+ class = "admin";
+ name = "${username}@${domain}";
+ secret = "%{file:${credentials_directory}/password}%";
+ inherit email;
+ }
+ {
+ # for mta-sts & dmarc reports
+ class = "individual";
+ name = "reports@${domain}";
+ secret = "%{file:${credentials_directory}/password}%";
+ email = [ "reports@${domain}" ];
+ }
+ ];
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/services/mail/secrets.yaml b/os/kay/modules/services/mail/secrets.yaml
new file mode 100644
index 0000000..e3b4c5d
--- /dev/null
+++ b/os/kay/modules/services/mail/secrets.yaml
@@ -0,0 +1,28 @@
+mail.sinanmohd.com:
+ dkim_rsa: ENC[AES256_GCM,data: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,iv:W8YAldq0KjrNe7WhGSUNI2+bq2CJrLhq+XPQVR9QsBo=,tag:LRfmBBFuFR8QR8pCj8OzSw==,type:str]
+ dkim_ed25519: ENC[AES256_GCM,data:gmI789Z7c9QZMRWOD300cDw0vLNLv4VMhV2jF4M/1roraLqKE/2cA4qv9i8qFmBMJjsq3iUKJBUJ+tBLsUkIR9UnwplQDjAyNaMZsxg0eT3HyssUZ2w2Dnd+EdJb+n/fGwsezHizYORz5qVU/ZUuSiCtuE4LEg==,iv:eAmJgIu++veapN1M3sYkYPAMP8CROFWdDIBmkXuzofw=,tag:hkCDPDDCBxE7DXSuSBFsGg==,type:str]
+ password: ENC[AES256_GCM,data:LJi8+a1dGus+XLt3k/K/3Mb0tNUJj7HDpPdqfYhU,iv:Iurz9YegxJ/coDQ6PbezeSni2DWYzpzlju6mJ90WLe8=,tag:2HgYlwDGqaklpdc+LOA0bQ==,type:str]
+sops:
+ age:
+ - recipient: age1q5sfy74d53n6jxlgsc2zrsz4wcl9d830nxuagc3wfmdkrrp55ckq9ev6nv
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2MVBCNE45ZFFBeVVrSHpU
+ UnJSTlk0TyttQlg1R1BnK2plYm5uMm95NnkwCmFjNmhxRFBNQVMzNzlJeFcva0Q4
+ cUtzZjF2RnJMd1JLUTMxU1YxQXJOR2sKLS0tIFpBamM5MktOYWwwaS9lcHhFWDVM
+ YlpwKzd1MkNlcXdmNDhpb3lXSjFKS28KngLhoabp4GBdfsGkMwTkClddEI6LgKet
+ EXTJ1PrLm3+5mp/2Ypgo325Cp9xIQKi7BYF9C6783mfN+dpbZ0QcbA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age15989j5lkkf2kn5wa2p6qc8wlxjjksc63k5ync8rz8t4e87394pzqm7h4rm
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwb3d4R0dORXZXOENUSDha
+ bWh3N1lYYVpNVTk2WE4xdXBSVzhrWTJHL0R3Ck1GbU5iTDVVaUpZVm9YK05rNzhs
+ c1dtQmVNSWlCNjg5SENHR3c1TGhwUkkKLS0tIFE0MzlRSkk3T0YyRVptdEpwak1T
+ enJZVFAxdEprdTVzbC8yWGJyWnFNREkK3/OgnLjS/sj4MzZPLH3QhEWd6WKiu4nM
+ wRNvhl7nDe1IwLoHbNSqTwEkalyEA3yIVlst3KyEpKb5q9H2+avqAQ==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2025-12-27T03:23:15Z"
+ mac: ENC[AES256_GCM,data:vlks8inOi7qmCKmx1SsCf1ipbwMNFfHsJGny4YGCUr+GWvvtdsLXsf8+AGUfoDa/2fBp7Wv2h1HIx1QY1JX3JgzKoyjEa1rRczJyWW9C/sR5UjyjUa0/t1MNMB7X1l9GGZObDQj9lrWm1e9JUIR6+63mESeykUzh3Wt8qhEgBAo=,iv:l1JWmFqR3lvsyYbPzHzCT6/Yj5qAvMv18jhhXdh2Ex4=,tag:JgXSqfeFVHzg5SeP/5bE+g==,type:str]
+ unencrypted_suffix: _unencrypted
+ version: 3.11.0