Stalwart 1.0 mit Docker Compose: neu installieren und von 0.16 umsteigen
Stalwart 1.0 ist das erste stabile Release des Mail- und Collaboration-Servers und öffnet keine 0.16-Datenbanken mehr. Die Anleitung zeigt die getestete Neuinstallation mit Docker Compose, Setup-Assistent, Domain, Postfach, Testmail über SMTP und IMAP, Backup und Restore der Volumes sowie den Umstieg von 0.16 mit stalwart-migrate.
Geprüft am 27.10.2026 · für Stalwart 1.0.0
Mit KI erstellt – redaktionelle Prüfung ausstehend
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Mehr dazu

Stalwart vereint SMTP, IMAP, POP3, JMAP, CalDAV, CardDAV und WebDAV in einem einzigen Rust-Prozess. Am 26. Oktober 2026 erschien mit Version 1.0.0 das erste stabile Release. Das Datenbankschema ist damit festgeschrieben, künftige Updates sollen ohne Migration auskommen. Der Preis ist ein einmaliger Bruch: Laut Release-Notes lassen sich 0.16-Installationen wegen des neuen Datenbanklayouts nicht direkt aktualisieren. Neu sind unter anderem Volltextsuche in PDF- und Office-Anhängen, DKIM2 mit Post-Quanten-Signaturen und OAuth-Scopes.
Diese Anleitung zeigt die im Labor getestete Neuinstallation mit Docker Compose und erklärt den Umstieg von 0.16. Für 0.16 gilt weiter die Vorgänger-Anleitung Stalwart Mailserver mit Docker Compose installieren. Unterschiede: 1.0 öffnet standardmäßig keine Ports 587 und 143, der Assistent legt den Administrator selbst an, und 0.16-Daten kopiert das neue Werkzeug stalwart-migrate.
Voraussetzungen
Ein Mailserver stellt höhere Anforderungen an Netz und DNS als andere Dienste:
- Linux-Server mit mindestens 2 CPU-Kernen, 4 GB RAM und 20 GB SSD-Speicher, x86_64 oder ARM64 (das Image gibt es für amd64, arm64, ARMv7 und ARMv6).
- Feste öffentliche IPv4-Adresse mit passendem Reverse-DNS-Eintrag auf den Server-Hostnamen, etwa
mail.example.com. Wie das geht, zeigt Reverse-DNS für Mailserver einrichten. - Port 25 in beide Richtungen frei. Viele Anbieter sperren ihn.
- Eine eigene Domain mit Zugriff auf die DNS-Zone und einen A-Eintrag für den Hostnamen.
- Docker Engine mit Docker Compose Plugin. Die Grundinstallation auf Debian 12 oder Ubuntu 24.04 beschreibt Docker Compose unter Linux als Selfhosting-Grundlage.
- Ausgehendes HTTPS für WebUI- und Spamregel-Downloads von GitHub.
Schritt 1: Projektordner und Compose-Datei anlegen
Die Compose-Datei folgt der offiziellen Docker-Anleitung. Wir pinnen den getesteten Tag v1.0.0; die Entwickler empfehlen v1, der automatisch allen 1.x-Releases folgt. Port 8080 bleibt an 127.0.0.1 gebunden, weil der Setup-Listener nicht gegen Passwortraten geschützt ist.
| Eckdaten | Wert |
|---|---|
| Image | stalwartlabs/stalwart:v1.0.0 (Docker Hub, auch ghcr.io) |
| Ports | 25 SMTP, 465 Submission mit TLS, 993 IMAPS, 995 POP3S, 4190 ManageSieve, 443 HTTPS und JMAP, 127.0.0.1:8080 Einrichtung |
| Volumes | /etc/stalwart (config.json), /var/lib/stalwart (RocksDB mit Mails und Einstellungen) |
| Umgebung | keine Pflichtvariablen; optional STALWART_RECOVERY_ADMIN für einen festen Notfallzugang |
sudo mkdir -p /opt/stalwart && cd /opt/stalwart
sudo nano compose.yaml
services:
stalwart:
image: stalwartlabs/stalwart:v1.0.0
init: true
restart: unless-stopped
ports:
- "25:25"
- "465:465"
- "993:993"
- "995:995"
- "4190:4190"
- "443:443"
- "127.0.0.1:8080:8080"
volumes:
- stalwart-etc:/etc/stalwart
- stalwart-data:/var/lib/stalwart
volumes:
stalwart-etc:
stalwart-data:
Das Image bringt einen Healthcheck auf /healthz/live mit. Weitere Härtung erklärt Docker Compose absichern mit Secrets, Healthchecks und Non-Root.
Verifizieren: sudo docker compose config --quiet gibt nichts aus, die Datei ist also gültig.
Schritt 2: Container starten und Einmal-Passwort lesen
Ohne config.json startet Stalwart im Bootstrap-Modus: nur Setup-Assistent auf Port 8080 und ein temporärer Administrator admin, dessen Zufallspasswort einmal im Log steht.
sudo docker compose up -d --pull always
sudo docker compose ps
sudo docker compose logs stalwart 2>&1 | grep -A8 'bootstrap mode'
Stalwart bootstrap mode - temporary administrator account
username: admin
password: ****************
WARN Server started in bootstrap mode (server.bootstrap-mode) hostname = "5e0bd476a0f3",
details = "No configuration file was found. Port 8080 is open for initial setup.", version = "1.0.0"
Jeder Neustart erzeugt ein neues Passwort.
Verifizieren: docker compose ps zeigt nach etwa 20 Sekunden Up (healthy), und die Logzeile nennt version = "1.0.0".
Schritt 3: Setup-Assistent abschließen und neu starten
Öffnen Sie per SSH-Tunnel http://127.0.0.1:8080/admin und melden Sie sich als admin an.
ssh -L 8080:127.0.0.1:8080 admin@mail.example.com
Wichtig sind diese Felder der fünf Seiten:
- Server Hostname und Default Email Domain: Im Container mit der Container-ID vorbelegt. Tragen Sie
mail.example.comundexample.comein. Den Kurznamenmaillehnte Stalwart im Test erst beim Abschicken mitInvalid server hostnameab. - Automatically Obtain TLS Certificate und Generate Email Signing Keys bleiben aktiv. Ohne DNS-Anbieter prüft Let’s Encrypt über Port 443; CNAMEs für mta-sts, autoconfig, autodiscover und ua-auto-config müssen vorher auf den Hostnamen zeigen.
- Storage: RocksDB unter
/var/lib/stalwart/beibehalten. - Logging: unter Docker Console wählen, sonst schreibt der Container kein Log.
- DNS: Bei unterstützten Anbietern wie Cloudflare pflegt Stalwart die Einträge selbst.
Die letzte Seite zeigt einmalig das Passwort des Administrators admin@example.com. Speichern Sie es sofort, dann neu starten:
sudo docker compose restart stalwart
sudo docker compose exec stalwart cat /etc/stalwart/config.json
{"@type":"RocksDb","path":"/var/lib/stalwart/","blobSize":4096,"bufferSize":134217728,...}
INFO Network listener started (network.listen-start) listenerId = "submissions", localPort = 465, tls = true
INFO DKIM signature created (dkim.signature-created) name = "v1-ed25519-20261027", domain = "example.com"
config.json enthält nur den Datenspeicher, alles andere liegt in der Datenbank.
Verifizieren: sudo docker compose logs stalwart | grep listen-start listet sieben Listener, und es erscheint kein Bootstrap-Block mehr.
Schritt 4: In der WebUI Domain, Postfach und DNS einrichten
Nach dem Neustart akzeptiert die WebUI Anmeldungen nur noch per HTTPS unter dem Server-Hostnamen: https://mail.example.com/admin. Über IP-Adresse oder abweichenden Namen bricht die Anmeldung im Test so ab:

Legen Sie unter Management, Directory, Accounts ein eigenes Postfach an; das Passwort kommt unter Authentication, Credentials hinzu. Unter acht Zeichen meldet Stalwart Password must be at least 8 characters long.

Unter Domains zeigt View Zone File alle berechneten Einträge: MX, SPF, DMARC, DKIM (Ed25519 und RSA), SRV, MTA-STS und TLS-Reporting.


Ohne DNS-Automatik übertragen Sie die Einträge selbst; den MX setzen Sie immer selbst. Gibt es schon einen SPF-Eintrag, führen Sie beide zu einem zusammen, denn zwei v=spf1-Einträge lassen SPF scheitern. Prüfen hilft das SPF- und DMARC-Werkzeug.
dig +short @1.1.1.1 MX example.com
dig +short @1.1.1.1 TXT example.com
dig +short @1.1.1.1 TXT _dmarc.example.com
dig +short @1.1.1.1 TXT v1-ed25519-20261027._domainkey.example.com
Verifizieren: Jede Abfrage liefert denselben Wert wie die Zonendatei, und der Browser zeigt nach kurzer Zeit ein Let’s-Encrypt-Zertifikat statt einer Warnung.
Schritt 5: Testmail senden und per IMAP abrufen
Mailprogramme nutzen IMAP 993 und SMTP 465 mit SSL/TLS und der vollen Adresse als Benutzername. Schnelltest mit curl (fragt das Passwort ab):
printf 'From: lisa@example.com\r\nTo: lisa@example.com\r\nSubject: Test 1.0\r\n\r\nHallo\r\n' > test.eml
curl --url smtps://mail.example.com:465 --user lisa@example.com \
--mail-from lisa@example.com --mail-rcpt lisa@example.com --upload-file test.eml -v
curl --url "imaps://mail.example.com:993/INBOX" --user lisa@example.com -X "SEARCH SUBJECT Test"
< 250 2.0.0 Message queued with id 4adef6de8800000.
* SEARCH 1
Die Mail trug zwei DKIM-Signaturen (a=ed25519-sha256 und a=rsa-sha256). Den Weg nach außen prüfen Sie mit einer Mail an einen anderen Anbieter und einer Antwort; SPF, DKIM und DMARC sollten pass melden.
Verifizieren: Der SMTP-Dialog endet mit 250 2.0.0 Message queued, und die IMAP-Suche liefert mindestens eine Nachrichtennummer.
Schritt 6: Sichern und wiederherstellen
Mit RocksDB liegen Daten und Mailinhalte in einer Datenbank, eine Online-Sicherung gibt es nicht. Nutzen Sie einen atomaren Snapshot (LVM, ZFS, btrfs) oder stoppen Sie den Container; rsync im laufenden Betrieb ergibt eine inkonsistente Kopie.
cd /opt/stalwart && sudo mkdir -p backup
sudo docker compose stop stalwart
sudo docker run --rm -v stalwart_stalwart-etc:/etc/stalwart:ro -v stalwart_stalwart-data:/var/lib/stalwart:ro \
-v "$PWD/backup":/backup alpine:3.22 tar czf /backup/stalwart-$(date +%F).tar.gz -C / etc/stalwart var/lib/stalwart
sudo docker compose start stalwart
Volume-Namen zeigt docker volume ls. Im Test haben wir Marker-Mail und Marker-Konto angelegt, gesichert und mit docker compose down -v alles gelöscht; der leere Server startete im Bootstrap-Modus. Restore:
sudo docker compose down -v
sudo docker compose create
sudo docker run --rm -v stalwart_stalwart-etc:/etc/stalwart -v stalwart_stalwart-data:/var/lib/stalwart \
-v "$PWD/backup":/backup:ro alpine:3.22 tar xzf /backup/stalwart-2026-10-27.tar.gz -C /
sudo docker compose start stalwart
docker compose create legt die Volumes mit Compose-Labels an; mit docker volume create warnt Compose volume ... already exists but was not created by Docker Compose. Besitzer 2000:2000 bleibt erhalten. Marker-Mail und Marker-Konto waren danach wieder da.
Verifizieren: Nach dem Restore erscheint im Log Starting Stalwart Server statt des Bootstrap-Blocks, und Ihr Postfach enthält die Mails vom Sicherungszeitpunkt.
Schritt 7: Innerhalb von 1.x aktualisieren
Patch-Releases wie 1.0.1 enthalten nur Fehlerbehebungen, Minor-Releases können Vorgaben ändern, Major-Releases das Datenformat. Vor Minor- und Major-Updates sichern Sie wie in Schritt 6, dann Tag ändern oder bei v1 einfach:
sudo docker compose pull
sudo docker compose up -d
sudo docker compose logs stalwart | grep 'Starting Stalwart'
Im Test zeigte v1 am 27. Oktober auf denselben Image-Digest wie v1.0.0; nach dem Wechsel waren alle Mails und Konten vorhanden. Meiden Sie latest, er folgt auch Major-Versionen. Watchtower oder Diun sollten nur melden, siehe Container-Updates mit Diun und WUD.
Verifizieren: Die Logzeile Starting Stalwart Server nennt die neue Versionsnummer, und docker compose ps zeigt healthy.
Schritt 8: Von 0.16 auf 1.0 umsteigen
Ein Tag-Wechsel reicht nicht. Mit einer 0.16.27-Instanz beendete sich der 1.0-Container im Test sofort mit Exited (1):
Server startup error (server.startup-error): details = The data store was created by a Stalwart version
prior to 1.0 and cannot be opened by this version.
Die 0.16-Daten bleiben unverändert. Für den Umzug gibt es stalwart-migrate (Image stalwartlabs/stalwart-migrate). Es liest den 0.16-Speicher nur und kopiert alles in einen neuen, leeren 1.0-Speicher; IMAP-UIDs und UIDVALIDITY bleiben erhalten. Laut Dokumentation:
- Die Quelle auf 0.16.27 aktualisieren und Platz für eine zweite Kopie des Datenspeichers schaffen.
- Einen
migrate-Dienst mit alten und zwei neuen Volumes in die Compose-Datei aufnehmen (unten). prepareausführen, Fragen zur Umsetzung beantworten undprepare-report.txtlesen.runim laufenden Betrieb, Wiederholungen kopieren nur Änderungen.- Im Wartungsfenster 0.16 stoppen und
run --finalausführen, danachreport --severity errorprüfen. - 1.0 mit der neuen config.json und dem neuen Daten-Volume starten.
migrate:
image: stalwartlabs/stalwart-migrate:1.0.0
profiles: [migrate]
volumes:
- stalwart-etc:/etc/stalwart:ro
- stalwart-data:/var/lib/stalwart
- stalwart-v1-etc:/etc/stalwart-v1
- stalwart-v1-data:/var/lib/stalwart-v1
- migrate-state:/var/lib/stalwart-migrate
sudo docker compose run --rm migrate prepare --source /etc/stalwart/config.json --state /var/lib/stalwart-migrate
sudo docker compose run --rm migrate run --source /etc/stalwart/config.json \
--target /etc/stalwart-v1/config.json --state /var/lib/stalwart-migrate
sudo docker compose run --rm migrate run --final --source /etc/stalwart/config.json \
--target /etc/stalwart-v1/config.json --state /var/lib/stalwart-migrate
Danach melden sich Nutzer in OAuth-Clients neu an, CalDAV-Clients laden einmal neu, der Suchindex wird neu aufgebaut. Behalten Sie den 0.16-Speicher, bis 1.0 sich bewährt hat; rollback kopiert notfalls zurück. Skripte gegen die Bootstrap-API: Das Hostnamen-Feld heißt in 0.16.27 serverHostname, in 1.0 defaultHostname.
Verifizieren: run --final endet ohne Fehler, der 1.0-Container startet mit Starting Stalwart Server, und ein Test-Postfach zeigt seine bisherigen Mails.
Troubleshooting
| Meldung | Ursache und Lösung |
|---|---|
Invalid server hostname | Kurzname oder Container-ID im Assistenten. Vollständigen Hostnamen eintragen. |
Client metadata documents are disabled | WebUI über IP, Proxy oder fremden Namen geöffnet. https://HOSTNAME/admin verwenden oder die öffentliche URL laut Reverse-Proxy-Doku setzen. |
503 5.5.1 You must authenticate first. | Mailprogramm sendet über 465 ohne Anmeldung. Authentifizierung für den Postausgang aktivieren. |
501 5.5.4 You are not allowed to send from this address. | Absender gehört nicht zum Konto. Adresse oder Alias anpassen. |
The data store was created by a Stalwart version prior to 1.0 | 1.0-Image auf 0.16-Volume. Zurück auf den alten Tag und mit stalwart-migrate umziehen. |
| Wieder Setup-Assistent nach Neuerstellung | Volume für /etc/stalwart fehlt oder ist leer. config.json zurückspielen. |
WARN No TLS certificates available | Zertifikat noch nicht ausgestellt. DNS-Einträge und Erreichbarkeit von Port 443 prüfen. |
Port 8080 sollte nach dem Setup nicht aus dem Internet erreichbar sein. Dazu hilft eine Host-Firewall, siehe Linux-Server mit UFW und Fail2ban absichern beschrieben.
Häufige Fragen
Brauche ich Port 587 und 143?
Stalwart 1.0 legt diese Listener standardmäßig nicht mehr an und empfiehlt implizites TLS auf 465 und 993. Für STARTTLS-Geräte legen Sie die Listener in der WebUI an und veröffentlichen die Ports.
Kann ich das Bootstrap-Passwort festlegen?
Ja, mit STALWART_RECOVERY_ADMIN=admin:PASSWORT in der Umgebung. Sie gilt auch im Normalbetrieb als Vollzugriff, entfernen Sie sie nach dem Setup.
Bleiben meine 0.16-Daten beim Umstieg erhalten?
Ja, stalwart-migrate liest sie nur. Bis 1.0 produktiv läuft, kommen Sie mit dem alten Tag zurück.
Fazit
Die Neuinstallation von Stalwart 1.0 ist schlank: ein Container, zwei Volumes, ein Assistent. Stolpersteine sind der Hostname und die Log-Einstellung Console. Backup und Restore liefen ohne Nacharbeit. Von 0.16 aus planen Sie eine Kopie mit stalwart-migrate samt Wartungsfenster, danach reicht innerhalb von 1.x ein docker compose pull.
Weiterführende Anleitungen und Quellen
- Stalwart 0.16 mit Docker Compose installieren (Vorgänger-Anleitung)
- Alternative: docker-mailserver als eigener Mailserver
- Reverse-DNS und PTR für Mailserver
- Stalwart v1.0.0 Release-Notes (GitHub)
- Stalwart-Blog: Stalwart v1.0
- Stalwart-Doku: Installation mit Docker
- Stalwart-Doku: Setup-Assistent
- Stalwart-Doku: Backup und Restore
- Stalwart-Doku: Upgrading
- Stalwart-Doku: Upgrade von 0.16, Kurzanleitung
- Linuxiac: Stalwart 1.0 erreicht das erste stabile Release


