Skip to content

ADR-005: Mailstack Migration Kopano → mailcow

Status

Accepted. Migration completed 2026-02-22 (Phase 6 DNS cutover) through Phase 9 (Notes migration 2026-02-26).

Context

Kopano was the largest pain point: 14 services (Server, Webapp, Z-Push, KDav, Gateway, Dagent, Spooler, Search, etc.), custom images from an internal registry, high resource usage, frequent failures, and no active upstream development. Replacement was P1 priority.

Requirements: OIDC/Keycloak SSO (mandatory), CalDAV/CardDAV, mobile push (iPhone/Android), webmail with integrated calendar, ~500 GB mail data migration, multi-domain (6 domains), LDAP user provisioning.

Options evaluated: docker-mailserver + SOGo (auth split), Mailu (no OIDC in mainline), Stalwart (no webmail, no ActiveSync pre-1.0), mailcow (selected).

Decision

mailcow as the mail stack. Reasons: native Keycloak OIDC integration with auto user-import, SOGo ActiveSync for mobile (mail + calendar + contacts in one profile), Docker-native, proven imapsync migration path.

Auth architecture: force_sso (Keycloak SSO for web UI) + per-device app passwords for IMAP/SMTP/ActiveSync. LDAP passdb removed (bypasses Keycloak 2FA).

Consequences

  • ✅ All 6 users migrated (IMAP + CalDAV/CardDAV + Notes), zero errors
  • ✅ Kopano stack fully decommissioned
  • ✅ Single Exchange ActiveSync profile covers mail + calendar + contacts on mobile
  • ⚠️ SOGo ActiveSync bugs: push breaks after hours, all-day events shift by -1 day on EAS
  • ⚠️ mailcow brings its own MariaDB (does not use phil-db)
  • ⚠️ Incompatible with Docker userns-remap by default — requires fix-permissions init container
  • 🔗 See: services/mail.md for architecture, operations, and all pitfalls