From f66a3434725410f8b6684288be3407a71cd4d032 Mon Sep 17 00:00:00 2001 From: Ronni Baslund Date: Wed, 10 Jun 2026 20:50:25 +0200 Subject: [PATCH] fix(infra): Stalwart v0.16 management admin is a real account (admin@dezky.eu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v0.16 config migration silently dropped the fallback admin — the live server had ZERO accounts, so every platform-api JMAP call 401'd and tenant mail provisioning was dead. Bootstrapped via recovery mode on node1 (STALWART_RECOVERY_ADMIN): created the dezky.eu domain + an admin account with the Admin role and the existing STALWART_ADMIN_PASSWORD. v0.16 logins use the full address, so STALWART_ADMIN_USER becomes admin@dezky.eu; config-rev annotation bump rolls platform-api so it picks up the new env. install.sh follow-ups now document the recovery-mode bootstrap for rebuilds instead of the defunct fallback-admin promise. --- .../production/fleet/apps/platform-api-config.yaml | 6 +++++- .../production/fleet/apps/platform-api.yaml | 4 ++++ infrastructure/production/host/stalwart/install.sh | 13 ++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/infrastructure/production/fleet/apps/platform-api-config.yaml b/infrastructure/production/fleet/apps/platform-api-config.yaml index 59f466f..7e087bb 100644 --- a/infrastructure/production/fleet/apps/platform-api-config.yaml +++ b/infrastructure/production/fleet/apps/platform-api-config.yaml @@ -12,7 +12,11 @@ data: # Stalwart runs on the HOST (not k3s). Pods reach it via the cni0 gateway IP # on the JMAP management port; the firewall lets the pod CIDR through. STALWART_API_URL: "http://10.42.0.1:8080" - STALWART_ADMIN_USER: "admin" + # Full address, not bare "admin": Stalwart v0.16 has no fallback admin — + # the management credential is a real account (admin@dezky.eu, Admin role) + # created during the 2026-06-10 recovery-mode bootstrap, and v0.16 logins + # use the full address. + STALWART_ADMIN_USER: "admin@dezky.eu" STALWART_PROVISIONING_ENABLED: "true" # Base for per-tenant service mail domains ({slug}.dezky.eu) AND the # reserved namespace for customer domains: only the dezky tenant may claim diff --git a/infrastructure/production/fleet/apps/platform-api.yaml b/infrastructure/production/fleet/apps/platform-api.yaml index 373c42d..95b8e3e 100644 --- a/infrastructure/production/fleet/apps/platform-api.yaml +++ b/infrastructure/production/fleet/apps/platform-api.yaml @@ -18,6 +18,10 @@ spec: metadata: labels: app.kubernetes.io/name: platform-api + annotations: + # Bump to force a rolling restart when only the ConfigMap changed — + # pods read it as env, which is only resolved at container start. + dezky.eu/config-rev: "2" spec: containers: - name: platform-api diff --git a/infrastructure/production/host/stalwart/install.sh b/infrastructure/production/host/stalwart/install.sh index 9f88b2d..c6675e9 100755 --- a/infrastructure/production/host/stalwart/install.sh +++ b/infrastructure/production/host/stalwart/install.sh @@ -142,9 +142,20 @@ echo "╚═══════════════════════ systemctl --no-pager --lines=0 status stalwart-mail || true echo "" warn "Follow-ups:" +warn " • v0.16 has NO fallback admin — STALWART_ADMIN_PASSWORD alone does" +warn " nothing. Bootstrap the management account once:" +warn " 1. add to $PREFIX/etc/stalwart.env:" +warn " STALWART_RECOVERY_MODE=1" +warn " STALWART_RECOVERY_ADMIN=admin:" +warn " and restart stalwart-mail (recovery listener on :8080)" +warn " 2. via JMAP (basic auth, those creds): x:Domain/set create the" +warn " primary domain, then x:Account/set create name=admin in it with" +warn " roles {\"@type\":\"Admin\"} and a Password credential" +warn " 3. remove the two STALWART_RECOVERY_* lines, restart again" warn " • PTR/rDNS for the server IP MUST be 'mail.dezky.eu' (Hetzner Robot)." warn " • Publish DNS at simply.com: MX → mail.dezky.eu, SPF, DMARC; per-domain" warn " DKIM records come from Stalwart's dnsZoneFile via platform-api." warn " • platform-api (k3s) env: STALWART_API_URL=http://:8080" -warn " STALWART_ADMIN_USER=admin STALWART_ADMIN_PASSWORD=" +warn " STALWART_ADMIN_USER=admin@ (full address — v0.16 logins)" +warn " STALWART_ADMIN_PASSWORD=" warn " STALWART_WEBHOOK_SECRET= STALWART_PROVISIONING_ENABLED=true"