diff --git a/hosts/envoy/idmail.nix b/hosts/envoy/idmail.nix index 39ce812..4e590d2 100644 --- a/hosts/envoy/idmail.nix +++ b/hosts/envoy/idmail.nix @@ -1,4 +1,8 @@ -{config, ...}: let +{ + config, + lib, + ... +}: let mailDomains = config.repo.secrets.global.domains.mail; primaryDomain = mailDomains.primary; idmailDomain = "alias.${primaryDomain}"; @@ -13,6 +17,12 @@ in { # } #]; + age.secrets.idmail-admin-hash = { + rekeyFile = ./secrets/idmail-admin-hash.age; + mode = "440"; + group = "stalwart-mail"; + }; + globals.services.idmail.domain = idmailDomain; globals.monitoring.http.idmail = { url = "https://${idmailDomain}"; @@ -28,24 +38,12 @@ in { enable = true; users.admin = { admin = true; - # FIXME: 8e8e1c2eb2f1b8c84f1ef294d2fd746b - password_hash = "$argon2id$v=19$m=4096,t=3,p=1$c29tZXJhbmRvbXNhbHQ$Hf0sBCqn5Zp5+7LalZNLKhG0exNsXN2M5T+y3QAjpMM"; + password_hash = "%{file:${config.age.secrets.idmail-admin-hash.path}}%"; }; - # users.test.password_hash = "$argon2id$v=19$m=4096,t=3,p=1$YXJnbGluYXJsZ2luMjRvaQ$DXdfVNRSFS1QSvJo7OmXIhAYYtT/D92Ku16DiJwxn8U"; - # domains."example.com" = { - # owner = "admin"; - # public = true; - # }; - # mailboxes."me@example.com" = { - # password_hash = "$argon2id$v=19$m=4096,t=3,p=1$YXJnbGluYXJsZ2luMjRvaQ$fiD9Bp3KidVI/E+mGudu6+h9XmF9TU9Bx4VGX0PniDE"; - # owner = "test"; - # api_token = "%{file:${pkgs.writeText "token" token}}%"; - # }; - # aliases."somealias@example.com" = { - # target = "me@example.com"; - # owner = "me@example.com"; - # comment = "Used for xyz"; - # }; + domains = lib.genAttrs mailDomains.all (_: { + owner = "admin"; + public = true; + }); }; }; systemd.services.idmail.serviceConfig.RestartSec = "60"; # Retry every minute diff --git a/hosts/envoy/secrets/idmail-admin-hash.age b/hosts/envoy/secrets/idmail-admin-hash.age new file mode 100644 index 0000000..3d3e61d Binary files /dev/null and b/hosts/envoy/secrets/idmail-admin-hash.age differ diff --git a/hosts/envoy/secrets/stalwart-admin-hash.age b/hosts/envoy/secrets/stalwart-admin-hash.age index 115841d..6870748 100644 --- a/hosts/envoy/secrets/stalwart-admin-hash.age +++ b/hosts/envoy/secrets/stalwart-admin-hash.age @@ -1,11 +1,11 @@ age-encryption.org/v1 --> X25519 4dtyNzQ1aoj+se7IxhCnN9A8bOmhPxm3bibijfCNjVw -PoRE6VrM+shoneZJAS+Fh/kIjn9tX6mw9Kr2vD3xOSE --> piv-p256 xqSe8Q AwvKCfsTHQh3Z05VZ3kRtaa90pqyR3tY+wKwwibfdvzF -dFjn+siQjWdhMVCGsiZyFNBykTrCIrHr9zt3aRxtSQc --> A'xo-grease KM'D -4D/ij+JrWVbUTv75EljIaE8L9JhFP3Dz ---- inyuu2A3QIBGnRj8WyQKX8+XdVDBCmANdyaHkQ0ZS7s -_hu㳊P?I'Fi޶3et)E, 3rQX?mo՗YuHi907*ZH]z:Xz -oT3(D7 -@fUZ<η(ETG:sтƑ4<5Uޚ֪R*_`Bo \ No newline at end of file +-> X25519 t0FJIrbn5q7oX4+1tHvjDnWDCiD6NMkNw7Aq2MfSXw4 +W6aq9jnVOH9W+pjsrSCZG1BJXSNojhiUrTgzANFpM9w +-> piv-p256 xqSe8Q A3qjOwYgwBFDf0beUSyw3nHhkO9ZhsJzGHBh4BTw7+tS +ffyaSOMoOHiIXfXvCJY/apYkEc7wZgkhOGTNT9O7oJ0 +-> n[k#S-grease /{ w79 (TV$':-8 4E +hxVz/9v74X2gEt9y0yvKMClVgId3mAl5PVisyL0r8WUn4extTHoh8qj2fSFl++54 +c0aRZZ5Y+Pdqu/7FyignIhV4WbUtverMWhWdRAhGsXqFm/8ejLqPfELQ54w +--- rTgyJNg/7gotGoTSMt5jDxSFE0tM8CP+azNlDTRjCow +Liݓk.?N@1 lH΢Нm@8N^Uu +σ/dzFIHk+*+;#3vx~3ڂVZ߯oђZC|՛T*ۇ^- .71c+gō \ No newline at end of file diff --git a/hosts/envoy/stalwart-mail.nix b/hosts/envoy/stalwart-mail.nix index 0e72c7e..bf21bd1 100644 --- a/hosts/envoy/stalwart-mail.nix +++ b/hosts/envoy/stalwart-mail.nix @@ -44,10 +44,6 @@ in { services.stalwart-mail = { enable = true; - package = pkgs.stalwart-mail.overrideAttrs (old: { - patches = old.patches ++ [./stalwart.patch]; - }); - settings = let case = field: check: value: data: { "if" = field; @@ -64,7 +60,7 @@ in { lib.mkForce { authentication.fallback-admin = { user = "admin"; - secret = "%{file:/run/stalwart-mail/admin-hash}%"; + secret = "%{file:${config.age.secrets.stalwart-admin-hash.path}}%"; }; tracer.stdout = { @@ -336,9 +332,8 @@ in { default = true; }; - lookup.default.hostname = config.networking.fqdn; + lookup.default.hostname = stalwartDomain; server = { - hostname = config.networking.fqdn; tls = { certificate = "default"; ignore-client-order = true; @@ -366,7 +361,8 @@ in { # jmap, web interface protocol = "http"; bind = "[::]:8080"; - url = "https://${stalwartDomain}/jmap"; + url = "https://${stalwartDomain}"; + use-x-forwarded = true; }; sieve = { protocol = "managesieve"; @@ -376,19 +372,6 @@ in { }; }; - #queue.outbound.next-hop = [ - # (case "rcpt_domain" "in-list" "default/domains" "local") - # (otherwise false) - #]; - - #queue.schedule = { - # retry = ["2m" "5m" "10m" "15m" "30m" "1h" "2h"]; - # notify = ["1d" "3d"]; - # expire = "5d"; - #}; - - # XXX: needed? jmap.directory = "idmail"; - imap = { request.max-size = 52428800; auth = { @@ -443,7 +426,6 @@ in { }; session.rcpt = { - # XXX: needed? directory = "idmail"; catch-all = true; relay = [ (is-authenticated true) @@ -456,23 +438,31 @@ in { services.nginx = { upstreams.stalwart = { - servers."localhost:8080" = {}; + servers."127.0.0.1:8080" = {}; extraConfig = '' zone stalwart 64k; keepalive 2; ''; }; - virtualHosts.${stalwartDomain} = { - forceSSL = true; - useACMEWildcardHost = true; - extraConfig = '' - client_max_body_size 512M; - ''; - locations."/" = { - proxyPass = "http://stalwart"; - proxyWebsockets = true; - }; - }; + virtualHosts = + { + ${stalwartDomain} = { + forceSSL = true; + useACMEWildcardHost = true; + extraConfig = '' + client_max_body_size 512M; + ''; + locations."/" = { + proxyPass = "http://stalwart"; + proxyWebsockets = true; + }; + }; + } + // lib.genAttrs ["autoconfig.${primaryDomain}" "autodiscover.${primaryDomain}" "mta-sts.${primaryDomain}"] (_: { + forceSSL = true; + useACMEWildcardHost = true; + locations."/".proxyPass = "http://stalwart"; + }); }; systemd.services.stalwart-mail = let @@ -482,9 +472,6 @@ in { in { preStart = lib.mkAfter '' cat ${configFile} > /run/stalwart-mail/config.toml - ${pkgs.gnugrep}/bin/grep -v '^\s*$\|^\s*#' \ - < ${config.age.secrets.stalwart-admin-hash.path} \ - | tr -d '\n' > /run/stalwart-mail/admin-hash ''; serviceConfig = { RuntimeDirectory = "stalwart-mail"; diff --git a/hosts/envoy/stalwart.patch b/hosts/envoy/stalwart.patch deleted file mode 100644 index 9b9e420..0000000 --- a/hosts/envoy/stalwart.patch +++ /dev/null @@ -1,76 +0,0 @@ -diff --git a/crates/directory/src/backend/sql/lookup.rs b/crates/directory/src/backend/sql/lookup.rs -index e49c5dab..18c9005e 100644 ---- a/crates/directory/src/backend/sql/lookup.rs -+++ b/crates/directory/src/backend/sql/lookup.rs -@@ -25,6 +25,7 @@ impl SqlDirectory { - QueryBy::Name(username) => { - account_name = username.to_string(); - -+ tracing::info!(context = "directory", event = "sql lookup", username = username, "Name -> query_name"); - self.store - .query::(&self.mappings.query_name, vec![username.into()]) - .await? -@@ -37,6 +38,7 @@ impl SqlDirectory { - } - account_id = Some(uid); - -+ tracing::info!(context = "directory", event = "sql lookup", username = account_name, "Id -> query_name"); - self.store - .query::( - &self.mappings.query_name, -@@ -53,6 +55,7 @@ impl SqlDirectory { - account_name = username.to_string(); - secret = secret_.into(); - -+ tracing::info!(context = "directory", event = "sql lookup", username = username, "Credentials -> query_name"); - self.store - .query::(&self.mappings.query_name, vec![username.into()]) - .await? -@@ -112,6 +115,7 @@ impl SqlDirectory { - - // Obtain emails - if !self.mappings.query_emails.is_empty() { -+ tracing::info!(context = "directory", event = "sql lookup", principal_name = principal.name, "Query emails"); - principal.emails = self - .store - .query::( -@@ -126,6 +130,7 @@ impl SqlDirectory { - } - - pub async fn email_to_ids(&self, address: &str) -> crate::Result> { -+ tracing::info!(context = "directory", event = "sql lookup", address = address, "Query recipients"); - let names = self - .store - .query::(&self.mappings.query_recipients, vec![address.into()]) -@@ -143,6 +148,7 @@ impl SqlDirectory { - } - - pub async fn rcpt(&self, address: &str) -> crate::Result { -+ tracing::info!(context = "directory", event = "sql lookup", address = address, "Query rcpt"); - self.store - .query::( - &self.mappings.query_recipients, -@@ -153,6 +159,7 @@ impl SqlDirectory { - } - - pub async fn vrfy(&self, address: &str) -> crate::Result> { -+ tracing::info!(context = "directory", event = "sql lookup", address = address, "Query vrfy"); - self.store - .query::( - &self.mappings.query_verify, -@@ -164,6 +171,7 @@ impl SqlDirectory { - } - - pub async fn expn(&self, address: &str) -> crate::Result> { -+ tracing::info!(context = "directory", event = "sql lookup", address = address, "Query expn"); - self.store - .query::( - &self.mappings.query_expand, -@@ -175,6 +183,7 @@ impl SqlDirectory { - } - - pub async fn is_local_domain(&self, domain: &str) -> crate::Result { -+ tracing::info!(context = "directory", event = "sql lookup", domain = domain, "Query is local domain"); - self.store - .query::(&self.mappings.query_domains, vec![domain.into()]) - .await diff --git a/secrets/rekeyed/envoy/48b9b9d8780a065399e9dae22f1491b0-stalwart-admin-hash.age b/secrets/rekeyed/envoy/48b9b9d8780a065399e9dae22f1491b0-stalwart-admin-hash.age deleted file mode 100644 index 32e16af..0000000 Binary files a/secrets/rekeyed/envoy/48b9b9d8780a065399e9dae22f1491b0-stalwart-admin-hash.age and /dev/null differ diff --git a/secrets/rekeyed/envoy/49f8669bfcc36ab68f5fde222011430a-idmail-admin-hash.age b/secrets/rekeyed/envoy/49f8669bfcc36ab68f5fde222011430a-idmail-admin-hash.age new file mode 100644 index 0000000..be0e729 Binary files /dev/null and b/secrets/rekeyed/envoy/49f8669bfcc36ab68f5fde222011430a-idmail-admin-hash.age differ diff --git a/secrets/rekeyed/envoy/5163b11b09190472c39d64146441c510-stalwart-admin-hash.age b/secrets/rekeyed/envoy/5163b11b09190472c39d64146441c510-stalwart-admin-hash.age new file mode 100644 index 0000000..c674fdb --- /dev/null +++ b/secrets/rekeyed/envoy/5163b11b09190472c39d64146441c510-stalwart-admin-hash.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 rz300w go7St2w4V+OeN5VgddWbw0WHuMJrZFNAE6ybU9tAbmI +sGjDHvZO56PPiIB0CvCuR1tyk2UzObeZk4IRoi+hvWA +-> wxzPB1{z-grease {^`is<&c [D`g< +Gurn/IfyXKKbuyKJNnlHfxwSOBKyqj3SlW3cxqcw6CwoL9Gc0UXeWlOgEHPzas9L +v2un +--- dmrjPRsNFeNkTPWOD1MbORG3X2AuOBp1lbFIS64kPyg +8 (yZ\{j~Zɨn dHUƱw3?n nQP>P8J0 "_cHtpNh=8%HEuHr.Q+up4\oTN[nX!t;z \ No newline at end of file