Repository navigation
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, chartcomponents.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 asoriginal_user. A passdb that stores names in mixed case and matches them case-sensitively now gets lowercase names: lowercase the stored names, or set%uto keep the 2.4.5 behaviour. - One
servicesentry 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_beandjmap_berefuse 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-writtenyarilo.yamlhas 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_statusandsasl_loginbind127.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 newservices.<name>.addresssets the bind host; empty, session backends bind loopback and login proxies every interface. The chart setsaddress: "0.0.0.0", so a Helm release listens as before. - Client Services keep the client address (#2496, #2500). Every client Service takes
ipFamilyPolicy(defaultPreferDualStack),ipFamiliesandexternalTrafficPolicy(defaultLocal, off ClusterIP only). UnderLocalonly nodes running a pod of the component accept traffic. Services that share one load-balancer address (MetalLBallow-shared-ip) must all beCluster; underLocalMetalLB 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_connectionsis counted per protocol;protocol.<name>.mail_max_userip_connectionstakes precedence overgeneral.limits. The userdb fieldsmail_max_userip_connectionsandmail_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 answers429 Too Many RequestswithRetry-After(protocol.jmap.jmap_limit_retry_after, default 10 s,0sends none) instead of503.warden_service.fail_opennow covers an unreachable warden only: with it on, 2.4.5 let a reached JMAP limit through. The chart now rendersfail_open(#2484). - IMAP
QUOTAlists only limited resources (#2458). An account without a limit gets its root with()instead ofSTORAGE 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_sizeleaves the index query and the answer is checked by a scan, soSUBJECT xtok-…-7finds-7and-1no 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),
sessionStatealternates 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.0judges any load. - A telemetry port that cannot be bound stops the start (#2441). Before, the process served without
/healthz,/readyzand/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 aunix:/pathmaster 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.yamlwithoutchart_versionno 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 ismail/yarilo. - Unix sockets for yarilo-auth (client and master), yarilo-warden, yarilo-locks and yarilo-dict:
unix:/pathin their listen and dial keys, withsocket_mode(default0660) andsocket_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_passwordinlocks_service,auth.token,warden_serviceand a redis dict's settings; chartredis.sentinel. One address stays the default. auth.auth_username_format(#2513), see above, withoriginal_userin the answer.- JMAP behind a proxy (#2514).
jmap_login_service.client_ip_headernames the header a proxy puts the client address in (CF-Connecting-IP,X-Forwarded-For); it is read only from a peer ingeneral.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 THREADIDor JMAPEmail/get;--thread-backfillwithout--forceadds only what is missing. Metricsyarilo_threads_save_not_recorded_total,yarilo_threads_recorded_on_read_total. - JMAP
Email/querywithout the search service answerssubject,from,to,cc,bccandheaderby reading headers, when yarilo-fts is not configured (#2468) or cannot answer (#2482);textandbodystill 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], notSERVERBUG(#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 SCRAMgave 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
0600whatever 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/net0.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-benchis no longer in the image (#2432). The release job calls GitHub withoutgh(#2412).