← Back to Reviews
Self-Hosting / Email

Proton Mail Bridge as a Homelab's Shared SMTP Relay — Reviewed

Proton Mail Bridge exists to let a normal desktop email client talk to a Proton account over standard IMAP and SMTP. Proton's own encryption model does not play nicely with those protocols directly. Running it instead as a small, always-on, headless SMTP relay for a homelab is a different use case than the one it was built for. Monitoring alerts, a contact form, a printer's scan-to-email. It works. It also grew into more than it was sized for, without anyone deciding that on purpose.

Share on X

What it's being used for

One Bridge instance, headless in its own small container, ended up as the shared outbound mail path for four unrelated services. Monitoring-stack email notifications. An office printer's scan-to-email. A public website's contact form. A separate app's feedback system. None of them were planned to share it. Each addition felt small and reasonable on its own. "Just point this one more thing at the relay that already works." That is exactly how it quietly outgrew its sizing.

The real incident: it was genuinely swap-thrashing

BE WARNED: a container sized for one lightweight job can end up in real resource distress once it quietly becomes shared infrastructure for several. Nothing about "it is still sending mail" tells you that is happening. Found during a routine fleet review. The relay's container, still on its original single-purpose allocation, sat at 99.8% swap used with about 10MB of RAM free. Not a slow creeping trend. Active thrashing.

The fix was simple once found. A real memory and swap increase, applied live, then a clean reboot to flush already-swapped pages back into RAM. An LXC's "swap" is host-managed via cgroups, so a guest cannot force that itself without a restart. The more useful lesson sits upstream of the fix. Any shared piece of infrastructure that keeps quietly picking up "just one more" dependent service needs its resource allocation revisited periodically, not only when something visibly breaks. Mail kept flowing the entire time this was happening. No outward symptom pointed at the relay until someone checked its resource usage directly.

A real gotcha that looked like a second incident but wasn't

BE WARNED: on some kernel and container configurations, a Linux container's own load-average reading reflects the host's shared load, not the container's. That covers the usual uptime and /proc/loadavg path. An alert showing a dramatically high load average on this relay's container looked like a serious container-specific problem. It was numerically identical to the physical host's own load at the time, confirmed by checking both directly.

So before you chase a load-average alert on any Linux container as if it describes that container's own contention, cross-check the physical host's load first. On a kernel without proper per-container load-average accounting, every container reports the same host-wide number. A genuinely idle container can look like it is under heavy load purely because something else on the host is busy.

The actual mail-sending experience

Once resourced correctly, the core function has been solid. Reliable outbound delivery for every service pointed at it, using one existing Proton account. No separate SMTP provider, with its own billing and limits and anti-abuse rules, for every small thing that occasionally sends an email. Reusing one relay credential across several unrelated services is a real simplification over minting a separate mail-sending integration for each. As long as whoever runs it remembers this is now shared, load-bearing infrastructure, not the single-purpose relay it started as.

Verdict

A genuinely good pattern. One self-hosted relay, one real account, serving every small "this needs to send an occasional email" need across a homelab, instead of a pile of throwaway integrations. Here is the caution. Resource-check anything you keep quietly attaching more dependents to. "The thing still works" is no proof it has headroom left. And a container's own metrics are not always trustworthy about which layer a problem lives at.