diff --git a/servers/hetzner/modules/services/stalwart.nix b/servers/hetzner/modules/services/stalwart.nix index eb946fb..fa61c02 100644 --- a/servers/hetzner/modules/services/stalwart.nix +++ b/servers/hetzner/modules/services/stalwart.nix @@ -262,7 +262,12 @@ in { systemd.services.stalwart-cert-perm = { description = "Grant stalwart read access to its TLS private key"; - after = ["tlsa-update.service" "stalwart.service"]; + # Belt-and-suspenders: tlsa-update already chgrps the key after every sync; + # this guarantees the group grant also exists at first boot, before stalwart + # starts (previously ordered after stalwart, so a fresh sync could leave a + # root:root key and webadmin reload would fail with EACCES). + after = ["tlsa-update.service"]; + before = ["stalwart.service"]; partOf = ["tlsa-update.service"]; wantedBy = ["multi-user.target"]; path = [pkgs.coreutils]; diff --git a/servers/hetzner/modules/services/tlsa-updater.nix b/servers/hetzner/modules/services/tlsa-updater.nix index a21d770..9e39ac6 100644 --- a/servers/hetzner/modules/services/tlsa-updater.nix +++ b/servers/hetzner/modules/services/tlsa-updater.nix @@ -33,6 +33,10 @@ # users. install -D -m 0644 "$SRC_CERT" "$DST_CERT" install -D -m 0640 "$SRC_KEY" "$DST_KEY" + # Stalwart reads the key as user "stalwart" via %{file:...}%; regrant the + # group immediately so every sync leaves it readable (0640 root:stalwart) + # and webadmin config reload never fails with EACCES. + chgrp stalwart "$DST_KEY" # 2) TLSA 3 1 1 = SHA-256 of the certificate's SubjectPublicKeyInfo (SPKI), # NOT the whole certificate. Matching type 1 = SHA-256 of the SPKI DER.