← 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/SMTP, since Proton's own encryption model doesn't play nicely with those protocols directly. Running it instead as a small, always-on, headless SMTP relay for a homelab — monitoring alerts, a contact form, a physical printer's scan-to-email — is a genuinely different use case than the one it was built for. It works. It also grew into more than it was originally sized for without anyone deciding that on purpose.

Share on X

What it's being used for

One Bridge instance, running headless in its own small container, ended up as the shared outbound mail path for four completely unrelated services: monitoring-stack email notifications, a physical office printer's scan-to-email feature, a public website's contact form, and a separate app's own feedback system — none of which were originally 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's exactly how it quietly outgrew its original sizing.

The real incident: it was genuinely swap-thrashing

A container sized for one lightweight job can end up in real, active resource distress once it quietly becomes shared infrastructure for several jobs — and nothing about "it's still sending mail" will necessarily tell you that's happening. Found during a routine fleet review: the relay's container, still sized for its original single-purpose allocation, was sitting at 99.8% swap used with only about 10MB of RAM actually free — not a slow creeping trend, genuine active thrashing.

The fix was simple once found (a real memory and swap increase, applied live, followed by a clean reboot to actually flush already-swapped pages back into RAM — an LXC's "swap" is host-managed via cgroups, so a guest can't force that itself without a restart). The more useful lesson is upstream of the fix: any shared piece of infrastructure that keeps quietly picking up "just one more" dependent service needs its own resource allocation revisited periodically, not just when something visibly breaks. Mail kept flowing the entire time this was happening — there was no outward symptom pointing at the relay specifically until someone actually checked its resource usage directly.

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

On at least some kernel/container configurations, a Linux container's own load-average reading (via the usual uptime//proc/loadavg path) reflects the host's shared load, not the container's own. An alert showing a dramatically high load average on this relay's container looked like a serious, container-specific problem at first — it turned out to be numerically identical to the physical host's own real load at the time, confirmed by checking both directly.

This is worth knowing before chasing a load-average alert on any Linux container as if it definitely describes that container's own contention: cross-check the physical host's own load first. On a kernel without proper per-container load-average accounting, every container reports the exact same host-wide number, and a genuinely idle container can appear to be under heavy load purely because something else on the same 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 already-existing Proton account rather than standing up a separate SMTP provider (and its own billing/limits/anti-abuse rules) for every small thing that occasionally needs to send an email. Reusing one relay credential across several unrelated services is a real, meaningful simplification over minting a separate mail-sending integration for each one individually — 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 separate throwaway integrations. The real caution: resource-check anything you keep quietly attaching more dependents to. Nothing about "the thing still works" is proof it's not silently running out of headroom, and a container's own metrics aren't always trustworthy about which layer a problem actually lives at.