58a2c8077d
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).
169 lines
5.2 KiB
YAML
169 lines
5.2 KiB
YAML
# Mail-client autodiscovery for dezky.eu — routes ONLY the discovery paths:
|
|
#
|
|
# autodiscover.dezky.eu POST /autodiscover/autodiscover.xml (Outlook + EAS)
|
|
# autoconfig.dezky.eu GET /mail/config-v1.1.xml (Thunderbird)
|
|
#
|
|
# autodiscover.dezky.eu goes to the zpush dispatcher (zpush.yaml), which
|
|
# answers mobilesync-schema requests itself (Exchange ActiveSync devices)
|
|
# and proxies outlook-schema (mail) requests through to host-Stalwart's
|
|
# HTTP listener unchanged. autoconfig.dezky.eu still hits Stalwart directly.
|
|
#
|
|
# Everything else on these hostnames (Stalwart's /admin, /login, /jmap …)
|
|
# falls through to Traefik's 404 — the management surface stays internal.
|
|
# No HTTPS-redirect middleware on purpose: Thunderbird probes plain HTTP and
|
|
# Outlook POSTs, which doesn't survive a 301 in all clients; both schemes
|
|
# serve the same answer.
|
|
#
|
|
# DNS at simply.com: autoconfig + autodiscover CNAME → mail.dezky.eu (the
|
|
# records are listed on the portal's Domains page).
|
|
#
|
|
# Customer domains (autodiscover.<customer>.tld) need per-domain certs and an
|
|
# automated Ingress/Certificate per verified domain — follow-up feature.
|
|
#
|
|
# NB: the ci-deployer Role carries explicit Endpoints write — the namespaced
|
|
# 'admin' role stopped granting it (CVE-2021-25740 hardening).
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: stalwart-http
|
|
labels:
|
|
app.kubernetes.io/name: stalwart-http
|
|
app.kubernetes.io/part-of: dezky
|
|
spec:
|
|
# No selector — Stalwart runs on the HOST, not in a pod. The Endpoints
|
|
# object below pins the cni0 gateway address pods/Traefik can reach.
|
|
ports:
|
|
- name: http
|
|
port: 8080
|
|
targetPort: 8080
|
|
---
|
|
apiVersion: v1
|
|
kind: Endpoints
|
|
metadata:
|
|
name: stalwart-http
|
|
subsets:
|
|
- addresses:
|
|
- ip: 10.42.0.1
|
|
ports:
|
|
- name: http
|
|
port: 8080
|
|
---
|
|
# IMAPS + SMTPS for the zpush EAS gateway (zpush.yaml) — same
|
|
# selectorless-Service-to-host pattern as stalwart-http above. Host-Stalwart
|
|
# exposes ONLY the implicit-TLS variants (993/465; no plain 143/587 —
|
|
# verified on node1 2026-06-12), all bound to the host wildcard, so the
|
|
# cni0 gateway address reaches them just like :8080.
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: stalwart-imaps
|
|
labels:
|
|
app.kubernetes.io/name: stalwart-imaps
|
|
app.kubernetes.io/part-of: dezky
|
|
spec:
|
|
ports:
|
|
- name: imaps
|
|
port: 993
|
|
targetPort: 993
|
|
---
|
|
apiVersion: v1
|
|
kind: Endpoints
|
|
metadata:
|
|
name: stalwart-imaps
|
|
subsets:
|
|
- addresses:
|
|
- ip: 10.42.0.1
|
|
ports:
|
|
- name: imaps
|
|
port: 993
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: stalwart-smtps
|
|
labels:
|
|
app.kubernetes.io/name: stalwart-smtps
|
|
app.kubernetes.io/part-of: dezky
|
|
spec:
|
|
ports:
|
|
- name: smtps
|
|
port: 465
|
|
targetPort: 465
|
|
---
|
|
apiVersion: v1
|
|
kind: Endpoints
|
|
metadata:
|
|
name: stalwart-smtps
|
|
subsets:
|
|
- addresses:
|
|
- ip: 10.42.0.1
|
|
ports:
|
|
- name: smtps
|
|
port: 465
|
|
---
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: mail-autodiscovery
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
|
spec:
|
|
ingressClassName: traefik
|
|
tls:
|
|
- hosts:
|
|
- autodiscover.dezky.eu
|
|
- autoconfig.dezky.eu
|
|
secretName: autodiscovery-dezky-eu-tls
|
|
rules:
|
|
- host: autodiscover.dezky.eu
|
|
http:
|
|
paths:
|
|
# Outlook probes both capitalizations. zpush dispatches by schema:
|
|
# mobilesync → Z-Push, outlook (mail) → proxied to Stalwart.
|
|
- path: /autodiscover/autodiscover.xml
|
|
pathType: Exact
|
|
backend: { service: { name: zpush, port: { number: 80 } } }
|
|
- path: /Autodiscover/Autodiscover.xml
|
|
pathType: Exact
|
|
backend: { service: { name: zpush, port: { number: 80 } } }
|
|
- host: autoconfig.dezky.eu
|
|
http:
|
|
paths:
|
|
- path: /mail/config-v1.1.xml
|
|
pathType: Exact
|
|
backend: { service: { name: stalwart-http, port: { number: 8080 } } }
|
|
---
|
|
# CalDAV/CardDAV for mail.dezky.eu — Apple Calendar/Contacts, Thunderbird and
|
|
# every other DAV client. Separate Ingress from the autodiscovery one because
|
|
# DAV gets the HTTPS-redirect middleware (safe for GET/PROPFIND; the
|
|
# autodiscover Ingress must stay redirect-free for Outlook's POST). Only the
|
|
# well-knowns + /dav are routed — the admin surface stays internal.
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: mail-dav
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
|
traefik.ingress.kubernetes.io/router.middlewares: dezky-apps-redirect-https@kubernetescrd
|
|
spec:
|
|
ingressClassName: traefik
|
|
tls:
|
|
- hosts:
|
|
- mail.dezky.eu
|
|
secretName: mail-dezky-eu-traefik-tls
|
|
rules:
|
|
- host: mail.dezky.eu
|
|
http:
|
|
paths:
|
|
- path: /.well-known/caldav
|
|
pathType: Exact
|
|
backend: { service: { name: stalwart-http, port: { number: 8080 } } }
|
|
- path: /.well-known/carddav
|
|
pathType: Exact
|
|
backend: { service: { name: stalwart-http, port: { number: 8080 } } }
|
|
- path: /dav
|
|
pathType: Prefix
|
|
backend: { service: { name: stalwart-http, port: { number: 8080 } } }
|