Your question
Version: v0.16.10
Summary:
Configuring Stalwart declaratively is currently a painful and unreliable experience. This is both a question about whether a better path exists, and feedback on the design.
Core issues:
-
Singleton coupling — objects like
CertificateandDomainare referenced bySystemSettings, which meansdestroyactions silently fail if the reference isn’t cleared first. There’s no dependency resolution, no clear ordering, and no useful error when this happens. A re-apply of the same plan will partially fail with no clean way to recover. -
No true idempotency — there’s no equivalent of
terraform apply: a plan that can be safely re-run and converge to the desired state regardless of what currently exists. Thedestroy+createpattern breaks as soon as objects are linked. -
The CLI feels like an afterthought — there’s no way to express the full server configuration as a single declarative file and apply it cleanly.
For reference, this is the plan structure I’m working with:
{"@type":"destroy","object":"Certificate"}
{"@type":"destroy","object":"Domain"}
{"@type":"create","object":"Certificate","value":{"certificate-main":{"certificate":{"@type":"File","filePath":"/opt/stalwart/etc/certs/tls.crt"},"privateKey":{"@type":"File","filePath":"/opt/stalwart/etc/certs/tls.key"}}}}
{"@type":"create","object":"Domain","value":{"dom-main":{"name":"my.domain","certificateManagement":{"@type":"Manual"},"dkimManagement":{"@type":"Automatic"},"dnsManagement":{"@type":"Manual"},"subAddressing":{"@type":"Enabled"},"reportAddressUri":"mailto:postmaster@..."}}}
{"@type":"update","object":"SystemSettings","value":{"defaultDomainId":"#dom-main","defaultCertificateId":"#certificate-main","defaultHostname":"my.host.example","proxyTrustedNetworks":{"10.111.0.0/16":true},"maxConnections":512}}
What would actually fix this:
- Proper dependency resolution in
stalwart-cli apply(unlink from singletons before destroy) - Expose the full configuration as a flat file that can be committed to Git and applied atomically — similar to how Grafana handles provisioning via YAML files in
/etc/grafana/provisioning, or how tools like Alertmanager and Prometheus are configured entirely through a single config file without any UI interaction required - A proper idempotent CLI that computes a diff against current state and applies changes safely, like Terraform does
Question:
Is there currently any supported way to manage the full Stalwart configuration declaratively and idempotently without the web UI? If not, is this planned?
Additionally — are there any currently available workarounds or patterns that others are using to achieve declarative, idempotent configuration management with Stalwart today?
Thank you.
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on