Found by running the installer for real rather than testing the hook in
isolation. Stalwart never started: it failed to open its database with
"Permission denied" on /var/lib/stalwart, which meant no mail could be
stored and the setup wizard could not be completed by hand either.
The image runs as its own uid 2000. LibrePortal gives container directories
to the docker install user under rootless and to the manager under rooted,
and 2000 is neither, so the bind mounts were unwritable in both modes. This
was not something the new provisioning introduced — it predates it, and the
app has never been able to hold mail.
Running as container-root maps to whichever host user owns those
directories. Under rootless that is the unprivileged docker install user,
not host root.
Also stop discarding the server's error when setup fails. Both failures
that actually occur — a hostname under a TLD that does not resolve, and the
unwritable data directory above — name themselves precisely, and a bare
"setup failed" turns a one-line fix into guesswork.
Verified end to end through `libreportal app install stalwart` on a clean
install: setup applied, DKIM keys generated, postmaster mailbox created,
and the full record set printed from the server's own zone data.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>