Skip to content

v2.4.6

Latest

Choose a tag to compare

@github-actions github-actions released this 03 Nov 23:27
· 41 commits to develop since this release
39ebfae

A patch release of the 2.4 stable line. It brings yarilo to a single Linux or BSD host (systemd units, a .deb spec, Unix sockets for the internal services, builds on FreeBSD, NetBSD and OpenBSD), an optional Redis Sentinel mode, a username format applied before every lookup, per-protocol connection limits with the userdb's own limits applied, and fixes in the lock client, METADATA, full-text search and JMAP.

Before you upgrade

These change what an existing configuration or rollout does. Read them first.

  • Usernames are lowercased before every lookup (#2513). auth.auth_username_format (default %Lu, chart components.auth.auth_username_format) is applied in yarilo-auth before any passdb or userdb is asked: logins, SCRAM, delivery and the master lookups. The passdb and userdb see the formatted name, the auth cache is keyed by it, and the name the client gave is answered as original_user. A passdb that stores names in mixed case and matches them case-sensitively now gets lowercase names: lowercase the stored names, or set %u to keep the 2.4.5 behaviour.
  • One services entry per process (#2430). A login proxy reads only its own entries (imap_login, imaps_login, pop3_login, pop3s_login, submission_login, submissions_login, lmtp_login, managesieve_login, jmap_login), a session backend only its own (imap, pop3, submission, lmtp, managesieve, jmap). There is no fallback: a missing entry stops the start and names it. services.imaps, pop3s, submissions, managesieve_be and jmap_be refuse the start with the new name. Backends no longer bind implicit-TLS listeners; only the login proxies terminate client TLS. The chart renders the new entries; a hand-written yarilo.yaml has to be renamed.
  • Internal listeners default to loopback outside Kubernetes (#2424). With the keys left out, auth_service, warden_service, the director's ring and API, backend_api, fts, quota_status and sasl_login bind 127.0.0.1. An explicitly empty listen on backend-api, fts, quota-status or sasl-login now refuses the start instead of binding every interface. A new services.<name>.address sets the bind host; empty, session backends bind loopback and login proxies every interface. The chart sets address: "0.0.0.0", so a Helm release listens as before.
  • Client Services keep the client address (#2496, #2500). Every client Service takes ipFamilyPolicy (default PreferDualStack), ipFamilies and externalTrafficPolicy (default Local, off ClusterIP only). Under Local only nodes running a pod of the component accept traffic. Services that share one load-balancer address (MetalLB allow-shared-ip) must all be Cluster; under Local MetalLB shares an address only between Services with the same pods, and the others stay pending.
  • Per-protocol connection limits, and the userdb's own (#2459, #2460). mail_max_userip_connections is counted per protocol; protocol.<name>.mail_max_userip_connections takes precedence over general.limits. The userdb fields mail_max_userip_connections and mail_max_user_connections, parsed but never applied before, now hold that user to them. warden's counters move to new keys; the old shared ones are removed by its maintenance.
  • A reached JMAP limit answers 429 (#2474). jmap-login answers 429 Too Many Requests with Retry-After (protocol.jmap.jmap_limit_retry_after, default 10 s, 0 sends none) instead of 503. warden_service.fail_open now covers an unreachable warden only: with it on, 2.4.5 let a reached JMAP limit through. The chart now renders fail_open (#2484).
  • IMAP QUOTA lists only limited resources (#2458). An account without a limit gets its root with () instead of STORAGE n 0, which told clients the account was full.
  • Server METADATA is no longer INBOX's (#2492). Server annotations (SETMETADATA "") no longer show up under INBOX over IMAP or the admin API, and a write into their subtree through a folder is refused.
  • Full-text search answers a short word as a substring (#2463). A word shorter than fts_flatcurve_min_term_size leaves the index query and the answer is checked by a scan, so SUBJECT xtok-…-7 finds -7 and -1 no longer matches its neighbours. This departs from the reference on purpose, for the substring semantics of IMAP SEARCH.
  • WebSocket tickets are offered only by a login that issues them (#2483). While jmap-login pods disagree during a rollout (or a ticket key is added or removed), sessionState alternates and clients refetch the session a few times; it settles with the rollout.
  • The director moves a domain only above a session floor (#2495). director_service.director_domain_rebalance_min_sessions, default 50: a quiet tag's spread no longer kicks live sessions. 0 judges any load.
  • A telemetry port that cannot be bound stops the start (#2441). Before, the process served without /healthz, /readyz and /metrics.
  • On a Unix master socket only the delivery proxy may issue sessions (#2440). auth_service.master_session_users, default ["yarilo-delivery"], applies only to a unix:/path master listener; over TCP the internal TLS roles decide, as before.
  • Config schema 18 → 29. Upgrade the chart and the image together; a binary newer than its ConfigMap names the settings it defaulted in a warning at start. A hand-written yarilo.yaml without chart_version no longer gets the chart warnings (#2469).
  • Pull the new image onto the backend nodes before helm upgrade, and keep room for one more backend pod, as for 2.4.5. See DEPLOYMENT, "Upgrading the backend StatefulSet".

New

  • A single host. systemd units for every component, yarilo.target, accounts per role and a hardened sandbox, with a .deb spec (#2437, #2448); the single-host sample configures JMAP and yarilo-dict (#2449, #2451). The tree builds on FreeBSD, NetBSD and OpenBSD (#2413, #2414); the FreeBSD port is mail/yarilo.
  • Unix sockets for yarilo-auth (client and master), yarilo-warden, yarilo-locks and yarilo-dict: unix:/path in their listen and dial keys, with socket_mode (default 0660) and socket_group (#2427, #2450). A stale socket is replaced only when a dial to it is refused.
  • Redis Sentinel mode (#2506). sentinel_addrs, sentinel_master, sentinel_user, sentinel_password in locks_service, auth.token, warden_service and a redis dict's settings; chart redis.sentinel. One address stays the default.
  • auth.auth_username_format (#2513), see above, with original_user in the answer.
  • JMAP behind a proxy (#2514). jmap_login_service.client_ip_header names the header a proxy puts the client address in (CF-Connecting-IP, X-Forwarded-For); it is read only from a peer in general.haproxy.haproxy_trusted_networks (chart: general.haproxy.trusted_nets), after any PROXY header, and only a bare IP address is taken.
  • Threads recorded on read (#2436). A message whose save could not take the thread lock joins its conversation on its first FETCH THREADID or JMAP Email/get; --thread-backfill without --force adds only what is missing. Metrics yarilo_threads_save_not_recorded_total, yarilo_threads_recorded_on_read_total.
  • JMAP Email/query without the search service answers subject, from, to, cc, bcc and header by reading headers, when yarilo-fts is not configured (#2468) or cannot answer (#2482); text and body still need it.
  • Lock state generation (#2439). A hold ends at once when the lock service comes back with fresh state, instead of at the next renew. yarilo_locks_client_holds_lost_total{resource,reason}.

Fixed

  • Lock client: a lock store outage reaches the client as NO [UNAVAILABLE], not SERVERBUG (#2504); a failed release still forgets the hold, so the session's next EXPUNGE is not refused (#2510); a renew in flight lands before the release (#2446); the in-memory backend no longer wakes every 100 ms when idle (#2516).
  • Auth client: a write retry gets a fresh reply channel; a reconnect could panic on a closed one (#2465).
  • METADATA: GETMETADATA (DEPTH infinity) INBOX (/private) reads a whole scope instead of answering BAD (#2493).
  • POP3: AUTH SCRAM gave two responses to one command, and did not wait for the client's first message after an empty challenge (#2491).
  • Sieve pipe, filter, execute: a program past its timeout no longer holds the call while a child keeps its output (#2491).
  • Shutdown: yarilo-auth, yarilo-warden and the director stop once their connections close instead of always waiting session_grace_period (#2435); jmap-login no longer waits 5 s on an idle connection (#2462).
  • warden: a CONNECT result is counted before the reply is written (#2444).
  • SQLite files for the passdb and the dict are created 0600 whatever the umask (#2421, #2432).
  • yarctl: every command without a subcommand prints its help and exits 0 (#2491).
  • The shipped example configs use the current key names (#2434).

Operations

  • Go 1.27.3 (#2447); golangci-lint v2.15.0, also over the flatcurve build (#2442, #2467).
  • golang.org/x/net 0.62.0 for GO-2026-6866 and GO-2026-6860, neither reachable from yarilo (#2423); Go module updates (#2478, #2498).
  • Test coverage 83 % of the tree (#2490, #2491).
  • fts-bench is no longer in the image (#2432). The release job calls GitHub without gh (#2412).