app-email: smtp_mapping for vaultwarden + mealie

Vaultwarden via STARTTLS (accepts self-signed shim cert); Mealie via plaintext
(NONE) — no accept-invalid-cert option, spike-validated mode. Compose files
reference injected ${SMTP_*}. README documents the pattern.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-29 08:45:23 +02:00
parent 5d42ca18bf
commit 4581a92781
7 changed files with 153 additions and 105 deletions
+54
View File
@@ -148,6 +148,60 @@ deploy_fields:
locked_after_deploy: true
```
### App-email mapping (`smtp_mapping`)
Apps that can send outbound email (password resets, invites, confirmations) get it through
one managed path: **app → in-controller SMTP shim → hub → Resend**. The Resend key stays
hub-side; nothing app-specific lives on the box. An app opts in by declaring `smtp_mapping`,
which renames the generic relay settings to that app's own env-var names.
When app-email is on (the household's **global** toggle AND the app's **per-app** toggle),
the controller injects at deploy/redeploy: `host` = the on-box shim, `port` = `2525`,
`from` = `<from_local>@felhom.eu`, the `security` value, the optional display name, and any
fixed `extra` vars. The values are derived from settings on every compose — never written to
`app.yaml` — so a toggle change applies on the next redeploy without touching secrets. The
shim accepts **no-auth** on the Docker network, so leave any `SMTP_USERNAME`/`SMTP_PASSWORD`
unset.
**The compose file must reference the mapped `${VAR}` keys** (with a harmless default) so the
injected values reach the container, e.g. `- SMTP_HOST=${SMTP_HOST:-}`. An empty `SMTP_HOST`
keeps the app's mail disabled when the toggle is off.
| Field | Meaning |
|-------|---------|
| `host_var` | env key receiving the shim host (required) |
| `port_var` | env key receiving the port `2525` (required) |
| `security_var` | env key receiving the TLS mode (optional) |
| `security_value` | the app's term for the chosen mode — `starttls`, `TLS`, `NONE`, … |
| `from_var` | env key receiving the From address (required) |
| `from_name_var` | env key receiving the From display name (optional) |
| `from_local` | local-part of the From address (defaults to the app slug) → `<local>@felhom.eu` |
| `extra` | fixed extra env (e.g. accept-invalid-cert flags) |
```yaml
# Vaultwarden — STARTTLS to the shim (it accepts the self-signed cert):
smtp_mapping:
host_var: SMTP_HOST
port_var: SMTP_PORT
security_var: SMTP_SECURITY
security_value: starttls
from_var: SMTP_FROM
from_name_var: SMTP_FROM_NAME
from_local: vaultwarden
extra:
SMTP_ACCEPT_INVALID_CERTS: "true"
SMTP_ACCEPT_INVALID_HOSTNAMES: "true"
```
> **TLS choice per app.** Prefer STARTTLS to the shim for apps that can accept a self-signed
> cert (an "accept invalid certs" option). For apps that **can't** (e.g. Mealie), use
> plaintext (`security_value: "NONE"`) on `2525` — the shim offers it on the Docker network and
> it was spike-validated. Never publish the shim off-box, so plaintext there is safe.
Currently mapped: **Vaultwarden**, **Mealie** (the two apps proven in
`SPIKE-smtp-app-relay-2026-06-28`). Adding email to another app is just its `smtp_mapping`
block + the matching compose `${VAR}` lines.
## App Catalog
| App | DB Type | RAM (request / limit) | Pi | HDD Data | Subdomain |