Stalwart under the microscope

email self-hosting nixos

I migrated to Stalwart after years with Modoboa, seeking a more composable approach to email. Setting up Stalwart on NixOS was straightforward: it lands as a Nix package with sensible defaults, and Bulwark (its webmail interface) runs in an OCI image.

My stack, at the time of recording the draft:

The migration from Modoboa to Stalwart took less than I expected and I find it very useful due to its architecture.

What follows is a detailed look at Stalwart and Bulwark’s current trade-offs and limitations, based on my experience days after installation.

Full disclosure: I’m criticizing what I see and personally encounter, I won’t risk testing bleeding-edge software, so by the time you read this, these issues might already be fixed.

Stalwart

DNS validation

Stalwart’s admin panel shows DNS records as a table of text without validation tools, which pushes users toward CLI exploration.

The admin panel at /manage/dns/sitename.tld/view lists the records but lacks the domain validation feature that Modoboa offers.

This makes the workflow less predictable than it could be.

Cryptographic certificates

The cryptographic certificate interface presents configuration as dense tables without clear guidance. For production use, especially with something as critical as DMARC, you need both documentation and automation tools.

Without them, mail risks rejection when steps are missed or procedures change.

“DMARC aggregate report” triage

The “DMARC Aggregate Reports” at /manage/reports/dmarc don’t give administrators enough guidance. Since email setup isn’t daily work, clear triage would help. Let me outline the practical flow I’d expect.

A clean pass means you can relax. A disagreement suggests forwarding artifacts to investigate. A complete failure should trigger helpful guidance, not just red text.

Ideally, this check connects to NTFY or something like it to warn when action is needed.

Message delivery debugging

The message queue at /manage/queue/message/MSG_ID has a “retry” button, but it’s useless when TLS handshakes fail.

Seeing “Error for mxN.some_email_srv.com: TLS error: Handshake failed: received fatal alert: HandshakeFailure” offers no debug path.

A “Retry without TLS” button would help diagnose delivery issues for test messages where debugging matters more than encryption.

Debugging the two-tier config problem

Stalwart’s configuration model clashes with NixOS’s immutable store. Settings split between TOML files and a database, but on NixOS the TOML lives in read-only /nix/store. When the admin UI tries to save database settings, it fails with a generic 500 error.

Be sure to check journalctl -u stalwart-mail if config updates return 500 with no body text. The real error appears there, not in the API response. This mismatch between operator expectations and system behavior is worth a mention for any software with multiple config backends.

For NixOS users, you face a choice: accept a hybrid model where Nix declares infrastructure and the UI manages runtime settings, or fight the framework to maintain full declarative purity.

There’s a detail I didn’t expect: a multi-hour debugging session can resolve into a working system so abruptly that you won’t trust it. The fix, once understood, was click two check-boxes in the admin UI, click Save, restart from systemctl. After hours of thrash, the brain keeps searching for what’s still broken. The weird dissatisfaction of “it just works” after a long fight is real, and it’ll pass.

Bulwark webmail interface

Bulwark is the promising apprentice in a wizard’s tower: capable of basic spells, occasionally jumping out of the window, and not yet trusted with the keys to the restricted section. I do not fault the apprentice: all wizards were apprentices once.

Browser session persistence

Losing your session on page refresh will inevitably bite users. There don’t seem to be keep-alive session queries either, so you can perform actions without knowing if you’re still logged in.

Mailbox organization

No right-click context menu means common operations require extra steps. The inability to drag directories or multi-select emails for bulk operations turns mailbox organization into manual drudgery.

Email list interface

Moving a single email resets the entire list view and filter state, making sorting painful enough that I resort to using email clients instead.

Customization and features

Only a limited set of serious icons are available, with no option to mock groups that have dedicated directories with custom ones. A real pity with many groups having a long presence in the fast-paced world of competitive ridiculousness.

A translate button integrated with clear API calls for translation, whatever you’ll be using, would be straightforward to implement, but isn’t present yet.

These aren’t deal-breakers for a webmail client that’s still evolving, but they’re quality-of-life improvements that would make Bulwark a very nice client and I hope to see them available soon.

Bulwark’s April security advisories for the early deployments read like a dispatch from the front lines.

Version 1.4.12 appears clean. I say “appears” not to cast doubt, but because all versions appear clean until they don’t.

This is simply the geography of early software: you ship, you learn, you discover that your trust model was slightly more optimistic than reality. I have shipped worse (and I’m pretty sure someone still remembers me for it). As someone who just installed the thing, I expect to learn from reading their code. There is no shame in it, only commits.

Future plans

I keep thinking about how I can improve my NixOS setup and what I can do with it.

When I think I have enough to write in terms of configuration, I’ll be sure to share mine, including the scripts I’m personally using.

Until then, I suggest using the official documentation as a reference.

Conclusion

The configuration mismatch between Stalwart’s hybrid model and NixOS’s immutable store requires careful navigation, and Bulwark’s webmail interface remains a work in progress.

The core promise holds: JMAP’s clean API enables automation that was previously cumbersome, and Stalwart itself delivers the reliability that lets you focus on what to do with email rather than how to maintain the server.

The issues I have mentioned are growing pains, not fundamental flaws; they are the kind you expect.