Temporary server error

Your question

I’m trying to deploy Stalwart using Docker Compose. The DB is HA Galera (load-balanced). Storage is SeaweedFS mount. The installer works perfectly, but when I try to log in with the creds it gives me, it says “temporary server error”. I’ve tried this on different nodes, different DB addresses, everything. ChatGPT is convinced my datacentre is haunted. What am I doing wrong?

Maybe someone can give me a known working Docker Compose config?

This is my current config

services:
stalwart:
image: stalwartlabs/stalwart:v0.16.5
container_name: cm2

restart: unless-stopped

hostname: mail.cookiehost.uk

ports:
  - "25:25"
  - "465:465"
  - "587:587"
  - "143:143"
  - "993:993"
  - "110:110"
  - "995:995"
  - "3013:8080"

volumes:
  - ./config:/etc/stalwart
  - ./data:/var/lib/stalwart
  - /mnt/cookiejar/mail:/mailstore

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

The “temporary server error” on login almost always means one of a few things went wrong during or after bootstrap. Here is what to check, in order of likelihood:


1. The wizard was completed but the container was never restarted.

After finishing the setup wizard, you must restart the container. Stalwart writes config.json on wizard completion and only fully boots into normal mode after a restart. Until then, the bootstrap temporary account is no longer valid but the permanent account isn’t active yet either.

docker compose restart stalwart

2. The UID on your bind-mounted volumes is wrong.

Your Compose file uses bind mounts (./config, ./data, /mnt/cookiejar/mail). Stalwart runs as UID 2000 inside the container. If those host directories are not owned by UID 2000, the server cannot read config.json or write to the data directory, causing internal errors at login time.

chown -R 2000:2000 ./config ./data /mnt/cookiejar/mail

Then restart the container.

3. The WebUI is accessed on port 8080 after setup – but that’s no longer valid post-setup.

After the wizard completes and the container restarts, the WebUI moves to https://<hostname>/admin (HTTPS on port 443). Port 8080 is only available during bootstrap. You’re mapping 8080 to 3013 externally, so try https://mail.cookiehost.uk/admin instead of http://...:3013/admin.

4. Checking the logs is the fastest diagnostic.

docker logs cm2 2>&1 | tail -100

Look for any error referencing the database connection, config.json, or authentication. If you’re not seeing much, the wizard’s logging step may have left it in file mode – try switching to Console logging (if you haven’t already), which works better in containers.

5. SeaweedFS as a volume mount vs. S3 API

If you’re mounting SeaweedFS as a filesystem path (/mnt/cookiejar/mail), Stalwart can use it as a filesystem blob store – that should work. However, make sure the path is accessible and writable by UID 2000. SeaweedFS’s S3-compatible API is also supported as a proper S3 blob store backend if you prefer that approach.


Relevant docs:

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

So, are you saying login is ONLY valid on https://mail.cookiehost.uk after the bootstrap?

This is the bare /login issue, not your Galera/SeaweedFS layer: /login is the OIDC authorization endpoint, so hit directly it shows “Temporary server error” even though the credentials are fine. Log in via /admin (or /account) instead. Your compose maps host 3013 to container 8080, so the admin UI is at http://:3013/admin after bootstrap. The host just needs to resolve to the server; there’s no hostname lock. Don’t chase the storage layer for this one.