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:
-
Stalwart
0.14.1via NixOS package -
Bulwark
1.4.12in an OCI container -
NixOS
25.11on Linux6.12.80,x86_64, running Nix2.31.4
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.10patched an authentication bypass whereverifyIdentity()returned true when no session cookies were present (GHSA-4356-876g-rfmh). -
Version
1.4.11followed with a Content-Security-Policy header that had been standing in report-only mode rather than enforcing (GHSA-6q52-98cr-qx65), an S/MIME verifier that accepted self-signed certificates as valid (GHSA-v6w6-338p-p256), and agetClientIP()function that trusted the leftmostX-Forwarded-Forentry, allowing attackers to bypass rate limiting and forge their own audit-log IPs (GHSA-7pj2-232x-6698).
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.