Files
app-catalog-felhom.eu/REPORT.md
T
admin d86e25662f fix(vaultwarden): _ENABLE_SMTP boot-gate — fresh email-off deploys crash-looped (campaign F1)
Vaultwarden treats defined-but-empty SMTP_HOST/SMTP_FROM as "set"; with upstream
_enable_smtp defaulting true its validation errors out and the container
crash-loops on every fresh deploy with app-email off (the default). Gate the
SMTP group with _ENABLE_SMTP: compose default false (clean boot, mail off),
flipped "true" by the app-email injection via smtp_mapping.extra. Proven on the
pinned 1.33.2-alpine image (P1 repro exit 12 / P2 off boots / P3 on boots).
REUSE.md: strict-image TRAP row. Sweep note: the other 5 smtp-mapped templates
are campaign-boot-proven tolerant; no edits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-06 14:01:11 +02:00

3.0 KiB

REPORT — vaultwarden F1 fix: _ENABLE_SMTP boot-gate (2026-07-06)

Class: implementation (campaign-finding fix; push = deploy). Baseline: main @ 13eedb1 → (this commit). Provenance: felhom.eu documentation/audits/CAMPAIGN-nomercy-2026-07-06.md finding F1 (pilot-blocking: every fresh vaultwarden deploy with app-email off — the default — crash-loops).

Corrected root cause (the campaign report's hypothesis was wrong)

Not "shim sets SMTP_FROM without SMTP_HOST" — with app-email off the shim injects nothing. The crasher: the template always defines SMTP_HOST=${SMTP_HOST:-} and SMTP_FROM=${SMTP_FROM:-}; vaultwarden's get_env_str_value returns Some("") for a defined-empty var (empty counts as set), and with _enable_smtp defaulting true upstream, its validation smtp_host.is_some() == smtp_from.is_empty()true == true → config error → exit → crash-loop. The old template comment ("empty SMTP_HOST = mail stays disabled") was wrong for this image.

Empirical probe (mandatory gate, run on 180 against the pinned image BEFORE editing)

Probe Env Result
P1 (pre-fix shape) SMTP_HOST= SMTP_FROM= (defined-empty) exit 12"Both SMTP_HOST and SMTP_FROM need to be set for email support without USE_SENDMAIL" (exact campaign error) — the image-level red-proof
P2 (fix, OFF) + _ENABLE_SMTP=false boots — "Rocket has launched", running
P3 (fix, ON) _ENABLE_SMTP=true + host + from boots — running (no SMTP connect at boot)

(P2/P3 needed I_REALLY_WANT_VOLATILE_STORAGE=true to bypass the unrelated no-volume guard in the bare docker run; P1 control re-run with it still crashes on the SMTP error, isolating the cause.) Logs: DooPlex ~/campaign-nomercy-2026-07-05/evidence/PROBE-F1/.

Changes

  • templates/vaultwarden/docker-compose.yml_ENABLE_SMTP=${_ENABLE_SMTP:-false} added to the SMTP group; the wrong comment replaced with the empty-counts-as-set TRAP note (+ config.json admin-panel precedence note). Nothing else touched.
  • templates/vaultwarden/.felhom.ymlsmtp_mapping.extra: _ENABLE_SMTP: "true" (rides the existing smtpEnv extra loop; zero controller change).
  • REUSE.md — TRAP appended to the App-email row: strict images need the enable-flag pattern; boot-prove fresh email-off deploys for every new smtp-mapped app.
  • CHANGELOG.md — entry incl. the sweep note.

Sweep note (documentation only, no edits)

calcom, gitea, mealie, nextcloud, rallly (and gitea's GITEA__mailer__SMTP_ADDR=${...:-}) are boot-proven tolerant of defined-empty mail env — all ran healthy as fresh email-off deploys in the campaign. Vaultwarden was the only strict image.

Validation

  • Probe gate P1/P2/P3 above (image level).
  • Live pipeline validation (Scenario A fresh email-off deploy healthy; Scenario B toggle ON→OFF regression) executed as part of the controller v0.101.0 deployment — see felhom-controller/REPORT.md for the live evidence.