cal's sieve leg never had a chance: dovecot wants STARTTLS first #113

Merged
lament merged 1 commit from sieve-starttls into main 2026-07-25 23:39:56 -05:00
Owner

follow-up review of #112 - the sieve leg was wrong on arrival, plus two hardening bits it left on the table.

  • SOGoSieveServer gets ?tls=YES and moves onto the service name: sieve://mail.lament.gay:4190. dovecot runs ssl = required here, so 4190 advertises "SASL" "" until the connection upgrades - a plain sieve:// URL connects fine and then has nothing to authenticate with
    • #112's "reached over WG" framing is what broke it - the WG path needs athena's host name, which the mail cert doesn't cover. going out by service name keeps the presented cert honest and drops the special case, rather than buying the tunnel back with a tlsVerifyMode escape hatch
    • failed quiet: nothing in SOGo touches sieve until someone opens Mail Filters or Vacation, so it's a 500 nobody had tripped over yet
  • enableTCPIP -> settings.listen_addresses, scoped to loopback + the host's own WG address. the bare flag is a * bind, which had postgres.apps listening on a residential LAN for an instance whose every tenant is a unix socket
    • needs mkForce - the nixpkgs module writes that key itself off enableTCPIP, at normal priority
  • the sogo role password stops riding psql -c and goes in on stdin - an argv leaks it through /proc and into pg_stat_activity
  • restartUnits on both identity secrets - sogo.service's restartTriggers only watch the config template, whose text doesn't move when a secret rotates
  • CLAUDE.md: postgres -> postgres.{apps,identity}, and the services registry description picks up proxyConfig/assets

left for later: sieve is unverified live - needs a deploy to verdandi plus a click through Mail Filters to confirm the handshake actually lands.

follow-up review of #112 - the sieve leg was wrong on arrival, plus two hardening bits it left on the table. - `SOGoSieveServer` gets `?tls=YES` and moves onto the service name: `sieve://mail.lament.gay:4190`. dovecot runs `ssl = required` here, so 4190 advertises `"SASL" ""` until the connection upgrades - a plain `sieve://` URL connects fine and then has nothing to authenticate with - #112's "reached over WG" framing is what broke it - the WG path needs athena's *host* name, which the mail cert doesn't cover. going out by service name keeps the presented cert honest and drops the special case, rather than buying the tunnel back with a `tlsVerifyMode` escape hatch - failed quiet: nothing in SOGo touches sieve until someone opens Mail Filters or Vacation, so it's a 500 nobody had tripped over yet - `enableTCPIP` -> `settings.listen_addresses`, scoped to loopback + the host's own WG address. the bare flag is a `*` bind, which had `postgres.apps` listening on a residential LAN for an instance whose every tenant is a unix socket - needs `mkForce` - the nixpkgs module writes that key itself off `enableTCPIP`, at normal priority - the `sogo` role password stops riding `psql -c` and goes in on stdin - an argv leaks it through `/proc` and into `pg_stat_activity` - `restartUnits` on both `identity` secrets - `sogo.service`'s `restartTriggers` only watch the config *template*, whose text doesn't move when a secret rotates - `CLAUDE.md`: `postgres` -> `postgres.{apps,identity}`, and the services registry description picks up `proxyConfig`/`assets` left for later: sieve is unverified live - needs a deploy to verdandi plus a click through Mail Filters to confirm the handshake actually lands.
cal's sieve leg never had a chance: dovecot wants STARTTLS first
All checks were successful
CI / check (pull_request) Successful in 1m15s
CI / deploy (pull_request) Has been skipped
CI / build (pull_request) Successful in 3m3s
CI / dry-activate (pull_request) Successful in 2m20s
CI / check (push) Has been skipped
CI / build (push) Has been skipped
CI / dry-activate (push) Has been skipped
CI / deploy (push) Successful in 3m3s
3d17a2cd85
Found by review, not by failure - nothing in SOGo touches sieve until
someone opens Mail Filters or Vacation, so the 500 sat there unexercised.
`ssl = required` means 4190 advertises `"SASL" ""` until the connection
upgrades. Addressing it by service name keeps the presented cert honest
and drops the WG special case along with it.

Two smaller ones alongside: the role password moves off psql's argv, and
`listen_addresses` replaces the blunt `enableTCPIP` wildcard so the apps
instance stops binding a residential LAN it has no tenant on.

Sieve is untested live - it needs a deploy plus a click through that pane.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8mNcouMTGZzXgcPNvS2VB
lament merged commit 3d17a2cd85 into main 2026-07-25 23:39:56 -05:00
lament deleted branch sieve-starttls 2026-07-25 23:39:56 -05:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
lament/pantheon!113
No description provided.