Wraps Stalwart in EAS so iOS/Android native Mail/Calendar 'Exchange'
accounts get two-way mail+calendar+contacts sync (BackendCombined:
IMAP + CalDAV /dav/cal/%l/ + CardDAV, credentials pass through).
- services/zpush: Z-Push 2.6.4 (AGPLv3, see LICENSE-NOTES.md) on
php:8.2-apache-bookworm (trixie dropped libc-client); PHP 8 sysv
sprintf fatal sed-patched; autodiscover dispatcher answers
mobilesync schema, proxies outlook schema to Stalwart unchanged
- prod: zpush Deployment (replicas:1, Recreate — file sync state),
/Microsoft-Server-ActiveSync Ingress on mail.dezky.eu (no redirect,
POST-heavy), autodiscover.dezky.eu repointed to the dispatcher,
selectorless stalwart-imaps/-smtps Services (host-Stalwart is
implicit-TLS only: 993/465, no plain 143/587 — verified on node1)
- CI: build+deploy zpush like the other apps
EAS tops out at 14.1: covers native mobile clients, NOT the Outlook
mobile app (needs 16.1) and not new Outlook for Windows (no EAS).
Outlook autodiscovers via POST https://autodiscover.<domain>/autodiscover/
autodiscover.xml and Thunderbird via autoconfig.<domain>/mail/
config-v1.1.xml — Stalwart serves both (verified, answers carry
mail.dezky.eu:993/465) but its HTTP listener wasn't reachable from
outside (the node's :443 is Traefik's). New exact-path-only Ingress
routes JUST those discovery endpoints to host-Stalwart via a selectorless
Service + Endpoints on the cni0 gateway; the admin/management surface
stays internal, and there's no HTTPS-redirect middleware because
Thunderbird probes plain HTTP and Outlook POSTs.
Domains page now also lists the autoconfig/autodiscover CNAMEs under the
autodiscovery slot (CNAME verified against the mail host; a bare A record
warns instead of failing). Customer-domain autodiscovery (per-domain
certs + automated Ingress) is a follow-up.
Push to main = release: after build, a deploy job pins each app image to the
commit SHA (kustomize edit set image), kubectl-applies fleet/apps and waits
for the rollouts. The runner already runs in-cluster, so it reaches the API
server on the in-cluster service IP with a kubeconfig for the new ci-deployer
ServiceAccount (namespace-scoped admin, KUBECONFIG_B64 repo secret).
The drafted Flux sync/image-automation layer is removed — a GitOps controller
plus bot tag-bump commits is more machinery than a single-node cluster needs.
Sortable image tags and $imagepolicy markers go with it.
Also: per-router ACME-safe HTTP->HTTPS redirects for the app ingresses,
platform-api prod config completed (Authentik JWT/JWKS + admin API, Stalwart
via the cni0 gateway IP, OCIS/cold-storage placeholders until those tiers
exist) and the secrets template/README updated to match.