<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Vergleich – Serverküche</title><link>https://serverkueche.de/tags/vergleich/</link><description>Vergleich – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>de-DE</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Sat, 10 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/vergleich/index.xml" rel="self" type="application/rss+xml"/><item><title>Stalwart oder Mailcow? Zwei Mailserver, beide aufgesetzt</title><link>https://serverkueche.de/tutorials/mailserver-stalwart-oder-mailcow/</link><pubDate>Sat, 10 Oct 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/mailserver-stalwart-oder-mailcow/</guid><description>Ein Container oder achtzehn? Beide Mailserver real aufgesetzt und verglichen: Aufwand, RAM, Angriffsfläche – und was Mailcow neben Traefik wirklich kostet.</description><content:encoded><![CDATA[<p>Wir haben beide aufgesetzt: <a href="/tutorials/mailserver-mailcow-aufsetzen/">Mailcow</a> am 10. August,
<a href="/tutorials/stalwart-mailserver/">Stalwart</a> am Tag darauf, beide auf demselben Test-VPS. Dieser
Artikel ist kein drittes Rezept, sondern die Antwort auf die Frage, die davor kommt: Welchen von
beiden nimmst du?</p>
<p>Die Antwort hängt nicht an einer Feature-Liste. Sie hängt an einer Architekturentscheidung, die
ein Preisschild trägt.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Nichts – wir entscheiden. Am Ende dieses Artikels weißt du, welchen der beiden Mailserver du
aufsetzt und warum der andere für deinen Fall der falsche wäre.</p>
<p>Die Ausgangslage in Zahlen, nachgemessen statt geschätzt:</p>
<table>
	<thead>
			<tr>
					<th></th>
					<th>Stalwart</th>
					<th>Mailcow</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Container</td>
					<td>1</td>
					<td>18</td>
			</tr>
			<tr>
					<td>Images auf der Platte</td>
					<td>407 MB</td>
					<td>rund 4,5 GB</td>
			</tr>
			<tr>
					<td>RAM</td>
					<td>46 MiB im Leerlauf</td>
					<td>6 GB als Minimum veranschlagt</td>
			</tr>
			<tr>
					<td>Empfohlener Server</td>
					<td>VPS 1000 (8 GB)</td>
					<td>VPS 2000</td>
			</tr>
			<tr>
					<td>Neben einem Traefik</td>
					<td>ein Volume, ein Objekt</td>
					<td>fünf Schalter, Neustart-Hook</td>
			</tr>
			<tr>
					<td>Webmail im Browser</td>
					<td>nein</td>
					<td>ja (SOGo)</td>
			</tr>
			<tr>
					<td>Lizenz</td>
					<td>AGPL-3.0 + kommerziell</td>
					<td>GPL-3.0</td>
			</tr>
	</tbody>
</table>
<p>Der Satz, auf den alles hinausläuft, steht in der dritten Zeile. <strong>Beide</strong> lassen sich hinter
den gemeinsamen <a href="/tutorials/reverse-proxy-traefik/">Traefik</a> stellen – das ist kein
Unterscheidungsmerkmal, auch wenn man das oft liest. Was sie unterscheidet, ist der Preis dafür:
Stalwart ist ein Container neben allem anderen und begnügt sich im Leerlauf mit 46 MiB. Mailcow
sind achtzehn, und sein Minimum von 6 GB RAM musst du neben allem haben, was auf der Maschine
sonst noch läuft.</p>
<p>Das ist keine Empfehlung gegen Mailcow. Es ist die Rechnung, die du vor der Entscheidung
aufmachen solltest – denn meistens endet sie bei einem zweiten Server für 14 bis 27 Euro im
Monat.</p>
<p><figure class="my-6"><img src="architektur-schema.svg" alt="Schema: Traefik und der certs-dumper als gemeinsamer Unterbau, darunter links Stalwart als einzelner Container, rechts Mailcow mit nginx und siebzehn weiteren." title="Derselbe Unterbau für beide – darunter ein Container oder achtzehn." loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Derselbe Unterbau für beide – darunter ein Container oder achtzehn.</figcaption></figure></p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Welche Versionen hier drinstecken
  </p>
  <div class="prose-kitchen text-sm">Die beiden Setups entstanden mit <strong>Stalwart 0.16.21</strong> und <strong>mailcow-dockerized 2026-07b</strong> auf
Debian 13. Beim Erscheinen dieses Artikels sind <strong>0.16.25</strong> (05.10.) und <strong>2026-09a</strong> (06.10.)
aktuell; die gemessene Image-Größe, der RAM-Wert und der Zertifikatsweg unten stammen aus 0.16.25. An der
Architektur, um die es hier geht, hat sich zwischen diesen Ständen nichts geändert.</div>
</div>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<p>Für diesen Artikel brauchst du nur eines: eine <strong>Domain, deren DNS du selbst steuerst</strong>. Einen
laufenden Server setzen wir ausdrücklich nicht voraus – wer hier liest, entscheidet noch.</p>
<p>Zwei Dinge gelten für beide Lösungen gleichermaßen und taugen deshalb nicht zur Unterscheidung,
kosten dich aber in jedem Fall Zeit:</p>
<ul>
<li><strong>Zustellbarkeit.</strong> Ob deine Mails ankommen oder im Spam landen, entscheiden PTR, SPF, DKIM und
DMARC – nicht die Software. Das ist Thema des Rezepts zur
<a href="/tutorials/mailserver-zustellbarkeit/">E-Mail-Zustellbarkeit</a> und der eigentliche Grund, warum
ein eigener Mailserver Arbeit macht.</li>
<li><strong>Ausgehendes SMTP.</strong> Bei netcup sperrt die Default-Policy „netcup Mail block&quot; die Ports 25, 465
und 587 nach außen. Die nimmst du dem Server im SCP selbst ab, ganz ohne Support-Ticket, siehe
<a href="/tutorials/netcup-firewall-einrichten/">netcup-Firewall einrichten</a>.</li>
</ul>
<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<p>Jeder der folgenden Schritte ist eine Entscheidungsdimension. Wenn eine davon für dich den
Ausschlag gibt, kannst du den Rest überspringen – die Tabelle in Schritt 6 fasst alles zusammen.</p>
<h3 id="schritt-1-die-architektur--ein-container-oder-achtzehn">Schritt 1: Die Architektur – ein Container oder achtzehn</h3>
<p>Stalwart ist ein einziger, in Rust geschriebener Prozess. In diesem einen Binary stecken SMTP,
IMAP, POP3, JMAP, CalDAV, CardDAV, WebDAV, Sieve, ein Spam- und Phishing-Filter und der Datenspeicher
(RocksDB). Das Image ist entsprechend klein:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker pull stalwartlabs/stalwart:v0.16.25
</span></span><span class="line"><span class="cl">docker image ls stalwartlabs/stalwart</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">REPOSITORY              TAG        SIZE
</span></span><span class="line"><span class="cl">stalwartlabs/stalwart   v0.16.25   407MB</span></span></code></pre></div>
</div>
<p>Im Leerlauf – frisch gestartet, ohne Postfächer – belegte der Container bei uns <strong>46 MiB RAM</strong> bei
0 % CPU. Nimm diesen Wert als Untergrenze, nicht als Betriebswert: Mit echten Postfächern wachsen
der RocksDB-Cache und die Trainingsdaten des Spam-Klassifizierers, und der Volltext-Index kommt
dazu. Die Größenordnung stimmt trotzdem, und sie ist der Grund, warum Stalwart auf einem Server
mitläuft, der schon etwas anderes tut.</p>
<p>Mailcow ist das Gegenteil, und zwar bewusst. Der Stack besteht aus <strong>18 Diensten</strong>, die der
<code>docker-compose.yml</code> des Projekts entnommen sind:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">unbound        mysql          redis          clamd
</span></span><span class="line"><span class="cl">rspamd         php-fpm        sogo           dovecot
</span></span><span class="line"><span class="cl">postfix        postfix-tlspol memcached      nginx
</span></span><span class="line"><span class="cl">acme           netfilter      watchdog       dockerapi
</span></span><span class="line"><span class="cl">olefy          ofelia</span></span></code></pre></div>
</div>
<p>Diese Liste ist kein Wildwuchs, sondern die Rechnung für den Funktionsumfang. <code>sogo</code> ist die
Webmail samt Kalender, <code>clamd</code> und <code>olefy</code> sind Virenscanner und Makro-Prüfer, <code>unbound</code> ein
eigener DNS-Resolver, <code>watchdog</code> und <code>ofelia</code> übernehmen Überwachung und Cronjobs. Jedes dieser
Teile ist ein ausgereiftes Spezialwerkzeug, und Postfix und Dovecot gehören zu den am besten
abgehangenen Serverprogrammen überhaupt.</p>
<p>Der Unterschied ist nicht Qualität, sondern <strong>Anzahl der beweglichen Teile</strong>, für die du
geradestehst. Bei Stalwart ist es eines.</p>
<h3 id="schritt-2-was-es-kostet-neben-einen-reverse-proxy-zu-ziehen">Schritt 2: Was es kostet, neben einen Reverse Proxy zu ziehen</h3>
<p>Hier hält sich eine Behauptung, die wir selbst lange mitgetragen haben: Mailcow könne nicht
hinter einem gemeinsamen Traefik laufen, weil sein eigener nginx die Ports 80 und 443 belegt.
Das stimmt nur für die Standardkonfiguration. Mailcow dokumentiert den Weg dahinter
<a href="https://docs.mailcow.email/post_installation/reverse-proxy/r_p-traefik3/">ausdrücklich</a> – man
bindet seinen nginx auf einen lokalen Port um und nimmt ihm das Zertifikat ab:</p>
<div class="sk-code">
  <span class="sk-code-head">INI</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="na">HTTP_BIND</span><span class="o">=</span><span class="s">127.0.0.1</span>
</span></span><span class="line"><span class="cl"><span class="na">HTTP_PORT</span><span class="o">=</span><span class="s">8080</span>
</span></span><span class="line"><span class="cl"><span class="na">HTTPS_BIND</span><span class="o">=</span><span class="s">127.0.0.1</span>
</span></span><span class="line"><span class="cl"><span class="na">HTTPS_PORT</span><span class="o">=</span><span class="s">8443</span>
</span></span><span class="line"><span class="cl"><span class="na">SKIP_LETS_ENCRYPT</span><span class="o">=</span><span class="s">y</span>
</span></span><span class="line"><span class="cl"><span class="na">AUTODISCOVER_SAN</span><span class="o">=</span><span class="s">n</span></span></span></code></pre></div>
</div>
<p>Beide können also hinter denselben Proxy. Der Unterschied ist, was dich das kostet.</p>
<p>Bei Mailcow sind es die sechs Schalter oben, drei Traefik-Router (Oberfläche, <code>autoconfig</code>,
<code>autodiscover</code>) – und ein Detail, das man kennen muss: Postfix und Dovecot lesen ihr Zertifikat
nur beim Start. Der Dumper muss sie deshalb nach jeder Verlängerung neu starten:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">certdumper</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">ghcr.io/kereis/traefik-certs-dumper:1.8.28</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span>--<span class="l">restart-containers mailcowdockerized-postfix-mailcow-1,mailcowdockerized-dovecot-mailcow-1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">DOMAIN</span><span class="p">:</span><span class="w"> </span><span class="l">mail.DEINE_DOMAIN  </span><span class="w"> </span><span class="c"># schreibt cert.pem/key.pem flach, wie Mailcow sie erwartet</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">/opt/traefik/:/traefik:ro</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">/var/run/docker.sock:/var/run/docker.sock:ro</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">./data/assets/ssl:/output:rw</span></span></span></code></pre></div>
</div>
<p>Zwei Stellen weichen bewusst von mailcows eigener Vorlage ab. Die Containernamen dort
(<code>mailcow_postfix-mailcow_1</code>) stammen aus dem alten Compose v1; ein aktuelles Docker benennt
die Container <code>mailcowdockerized-…-1</code>, und mit den alten Namen findet der Dumper nichts zum
Neustarten. Und den Docker-Socket braucht er, um überhaupt neu starten zu dürfen.</p>
<p>Dazu kommt, dass mailcow diese Seite selbst als <strong>„community supported&quot;</strong> kennzeichnet – sie
trägt einen Warnkasten. Das ist kein Ausschlusskriterium, aber ein Unterschied zu einem Pfad,
den der Hersteller trägt.</p>
<p>Zwei Dinge bleiben unabhängig davon:</p>
<ol>
<li>Die <strong>Mail-Ports</strong> 25, 465, 587, 143, 993, 110, 995 und 4190 liegen weiter direkt am Host –
bei beiden Lösungen gleichermaßen.</li>
<li>Auf Hosts mit IPv6 legt <code>generate_config.sh</code> eine <code>/etc/docker/daemon.json</code> an und <strong>startet
Docker sofort neu</strong>. Auf einem geteilten Server reißt dieser Neustart alles andere mit. Das
passiert einmal beim Aufsetzen, aber es passiert.</li>
</ol>
<p>Und dann ist da der Punkt, der in der Praxis meistens entscheidet und nichts mit Ports zu tun
hat: <strong>6 GB RAM als Minimum</strong>, mit ClamAV eher 8. Die musst du neben allem haben, was auf der
Maschine schon läuft. Ein VPS 1000 mit 8 GB ist damit faktisch voll. Deshalb landet man bei
Mailcow am Ende doch oft bei einem zweiten Server – nicht weil es nicht anders ginge, sondern
weil der Speicher nicht reicht.</p>
<p>Stalwart dagegen zieht mit 46 MiB im Leerlauf nebenher ein. Einen Haken scheint es zu geben:
Stalwart holt sein Let&rsquo;s-Encrypt-Zertifikat standardmäßig per TLS-ALPN-01 über Port 443, und den
hat dein Proxy längst. Dafür gibt es eine saubere Lösung, und sie steht so in
<a href="https://stalw.art/docs/server/reverse-proxy/traefik">Stalwarts eigener Dokumentation</a>: Stalwart
holt gar kein Zertifikat mehr, sondern <strong>bekommt das von Traefik</strong>.</p>
<p>Dazwischen steht ein winziger Container, der Zertifikat und Schlüssel aus Traefiks <code>acme.json</code>
in ein gemeinsames Volume schreibt:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">traefik-certs-dumper</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">ghcr.io/kereis/traefik-certs-dumper:1.8.28</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">always</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span>--<span class="l">restart-containers stalwart</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">OVERRIDE_UID</span><span class="p">:</span><span class="w"> </span><span class="m">2000</span><span class="w">      </span><span class="c"># Stalwart laeuft im Container als uid 2000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">OVERRIDE_GID</span><span class="p">:</span><span class="w"> </span><span class="m">2000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">/opt/traefik/:/traefik:ro     </span><span class="w"> </span><span class="c"># dort liegt acme.json aus dem Traefik-Rezept</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">/var/run/docker.sock:/var/run/docker.sock:ro</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">certs:/output</span></span></span></code></pre></div>
</div>
<p>Der Dumper sucht <code>acme.json</code> direkt unter <code>/traefik</code>. Eingebunden wird deshalb das Verzeichnis,
in dem Traefiks <code>acme.json</code> liegt – im <a href="/tutorials/reverse-proxy-traefik/">Traefik-Rezept</a> ist
das <code>/opt/traefik/</code>. Zeigt der Pfad daneben, legt Docker stillschweigend ein leeres Verzeichnis
an, der Dumper meldet im Log nur <code>/traefik/acme.json is not a file. Retrying...</code>, und Stalwart
bekommt nie ein Zertifikat.</p>
<p>Die beiden <code>OVERRIDE</code>-Zeilen sind kein Beiwerk: Der Dumper legt <code>key.pem</code> mit Rechten <code>0640</code> ab,
und Stalwart läuft im Container als <strong>uid 2000</strong>. Ohne die Übergabe des Besitzers kommt es an
seinen eigenen Schlüssel nicht heran.</p>
<p>Stalwart bindet dasselbe Volume nur lesend ein (<code>certs:/data/certs:ro</code>), braucht für den
Neustart den festen Namen <code>container_name: stalwart</code>, hängt mit den üblichen
Traefik-Labels an der Weboberfläche und veröffentlicht die Mail-Ports direkt am Container. Im
Einrichtungs-Assistenten schaltest du <strong>„Automatically Obtain TLS Certificate&quot; ab</strong> – sonst
versucht Stalwart weiter, sich selbst eines zu holen. Danach zeigst du in der Konsole unter
<em>Settings → TLS → Certificates</em> auf die beiden Dateien – in der Oberfläche heißen die Typen
<em>Text value read from file</em> und <em>Secret read from file</em>:</p>
<div class="sk-code">
  <span class="sk-code-head">JSON</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;certificate&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;@type&#34;</span><span class="p">:</span> <span class="s2">&#34;File&#34;</span><span class="p">,</span> <span class="nt">&#34;filePath&#34;</span><span class="p">:</span> <span class="s2">&#34;/data/certs/mail.DEINE_DOMAIN/cert.pem&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;privateKey&#34;</span><span class="p">:</span>  <span class="p">{</span> <span class="nt">&#34;@type&#34;</span><span class="p">:</span> <span class="s2">&#34;File&#34;</span><span class="p">,</span> <span class="nt">&#34;filePath&#34;</span><span class="p">:</span> <span class="s2">&#34;/data/certs/mail.DEINE_DOMAIN/key.pem&#34;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
</div>
<p>Stalwart zeigt das Zertifikat danach sofort in der Liste an, <strong>ausgeliefert wird es aber erst
nach einem Neustart</strong> (<code>docker compose restart stalwart</code>). Bis dahin bekommt ein Mailprogramm
weiter das selbstsignierte Platzhalter-Zertifikat <code>CN=rcgen self signed cert</code>.</p>
<p>Aus demselben Grund steht im Dumper <code>--restart-containers stalwart</code>: Stalwart liest die Dateien
nur beim Start. Erneuert Traefik das Zertifikat, schreibt der Dumper die neuen Dateien und startet
Stalwart neu – das dauert wenige Sekunden. Ohne die Zeile liefe Stalwart nach der ersten
Verlängerung mit dem alten Zertifikat weiter, bis es 90 Tage später abläuft. Der Docker-Socket
ist dabei auch mit <code>:ro</code> ein Vollzugriff auf Docker – der Dumper gehört damit in dieselbe
Vertrauensklasse wie Traefik, das den Socket ebenfalls hat. Die Aktion
<em>Reload → TLS certificates</em> in der Konsole wäre die Alternative, antwortete in der
Community-Edition bei uns aber mit <code>API error 403</code>.</p>
<p>Das ist eleganter als die DNS-01-Challenge, die man hier zuerst vermutet: Du brauchst keine
API-Zugangsdaten bei deinem DNS-Anbieter, und auf dem Host bleibt <strong>ein einziger ACME-Client</strong> –
der, den du ohnehin betreibst.</p>
<p>Wir haben das auf dem Test-VPS nachgebaut, neben dem dort dauerhaft laufenden Traefik, und eine
Verlängerung simuliert: Traefik schreibt <code>acme.json</code>, der Dumper zieht nach und startet Stalwart
neu. Stalwart liefert anschließend auf seinen eigenen Mail-Ports das Zertifikat aus, das es nie selbst
beantragt hat – hier der Handshake auf dem IMAPS-Port:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">subject=CN=mail.DEINE_DOMAIN
</span></span><span class="line"><span class="cl">issuer=C=US, O=Let&#39;s Encrypt, CN=YR2
</span></span><span class="line"><span class="cl">Verify return code: 0 (ok)</span></span></code></pre></div>
</div>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Was dabei trotzdem am Server bleibt
  </p>
  <div class="prose-kitchen text-sm">Die <strong>Mail-Ports</strong> 25, 465, 993 und 4190 musst du weiterhin direkt am Host freihalten – sie
sprechen kein HTTP und lassen sich nicht durch einen HTTP-Proxy leiten. Traefik kann sie als
TCP-Router mit <code>tls.passthrough</code> übernehmen, dann brauchst du zusätzlich das Proxy-Protokoll,
damit Stalwart die echte Absender-IP sieht. Einfacher ist es, die Ports am Container zu
veröffentlichen.</div>
</div>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /tutorials/mailserver-stalwart-oder-mailcow/" data-content-piece="VPS 2000 G12.5">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Empfehlung</span>
    <span title="Mit * markierte Links sind Affiliate-Links.">Anzeige</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 2000 G12.5</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">8 vCore · 16 GB RAM · 256 GB SSD</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 26,92 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Falls die Wahl auf Mailcow fällt: Das ist der zweite Server, den es braucht – 16 GB lassen auch ClamAV mitlaufen.</p>
    </div>
    <a href="https://www.netcup.com/de/server/vps/vps-2000-g12.5-24m-eu?ref=44083#vps-2000-g12.5-12m-eu" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 2000 G12.5 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Zu netcup →
</a>

  </div><div class="px-4 pb-4"><div class="not-prose my-3 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200"
     data-voucher-api="vps-2000" data-voucher-msg-empty="Gerade ist für diesen Tarif kein Code frei – nimm den 5-€-Code." data-voucher-msg-limit="Für heute sind keine weiteren Codes drin – nimm den 5-€-Code oder versuch es morgen." data-voucher-msg-error="Der Code ließ sich gerade nicht abrufen – nimm den 5-€-Code.">
  <p class="flex flex-wrap items-center gap-x-2 gap-y-1"><span>💶 <span class="font-semibold">1 Monat gratis</span>:</span>
    <button type="button" data-voucher-reveal data-copy-title="Zum Kopieren klicken"
            class="cursor-pointer rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 hover:ring-2 hover:ring-herb-500/40 dark:bg-slate-800 dark:text-herb-400">Code anzeigen</button>
    <button type="button" data-voucher-next hidden
            class="rounded border border-herb-500/40 px-2 py-0.5 text-xs text-herb-800 hover:bg-white dark:text-herb-400 dark:hover:bg-slate-800">anderer Code</button>
  </p>
  <p class="mt-1 text-xs text-slate-500 dark:text-slate-400">
    Einmal einlösbar, gilt für VPS 2000 G12.5. Im leeren Warenkorb einlösen – der Code legt den Server selbst hinein.
    <a href="https://www.netcup.com/de/checkout/warenkorb?ref=44083" rel="sponsored noopener" target="_blank"
       data-track-event="Affiliate|netcup: Gutschein einlösen|VPS 2000 G12.5 · {page}"
       class="font-medium text-herb-800 underline underline-offset-2 hover:text-herb-900 dark:text-herb-400">Im Warenkorb einlösen →</a>
  </p><p class="mt-2 flex flex-wrap items-center gap-x-2 gap-y-1 border-t border-herb-500/30 pt-2">
    <span>💶 <span class="font-semibold">5 € Gutschein</span> für netcup-Neukunden:</span>
    <button type="button" data-voucher-code data-track-voucher="36nc17844976032"
            title="Zum Kopieren klicken" class="cursor-pointer rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 hover:ring-2 hover:ring-herb-500/40 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</button>
    <span class="text-xs text-slate-500 dark:text-slate-400">immer gültig · nicht für Domains und VPS Lite</span>
  </p><p class="mt-1 text-xs"><a href="/netcup-gutschein/" class="font-medium text-herb-800 underline underline-offset-2 hover:text-herb-900 dark:text-herb-400">Alle netcup-Gutscheine →</a></p>
</div></div>
</div>

<p>Wird es Stalwart und hast du noch gar keinen Server, reicht eine Nummer kleiner; die Tarife
stehen in der <a href="/netcup-empfehlung/">netcup-Übersicht</a>, und was dein konkretes Setup braucht,
schätzt der <a href="/serverempfehlung/">Server-Rechner</a>.</p>
<h3 id="schritt-3-aufwand-beim-aufsetzen-und-im-betrieb">Schritt 3: Aufwand beim Aufsetzen und im Betrieb</h3>
<p>Die Zahlen aus den beiden Rezepten sprechen für sich: Stalwart ist in rund 60 Minuten und sieben
Schritten fertig und als <em>Fortgeschritten</em> eingestuft, Mailcow braucht etwa 90 Minuten, acht
Schritte und gilt als <em>Profi</em>-Thema.</p>
<p>Interessanter ist, was danach kommt. Ein Update sieht bei Stalwart so aus:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/stalwart
</span></span><span class="line"><span class="cl">docker compose pull <span class="o">&amp;&amp;</span> docker compose up -d</span></span></code></pre></div>
</div>
<p>Bei Mailcow so:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/mailcow-dockerized
</span></span><span class="line"><span class="cl">sudo ./update.sh</span></span></code></pre></div>
</div>
<p>Das Skript zieht die Compose-Datei nach, aktualisiert alle Images und startet den Stack neu. Es
nimmt dir Arbeit ab – und es ändert in einem Durchgang 18 Dienste auf einmal.</p>
<p>Die Rhythmen unterscheiden sich deutlich, und beide verlangen Aufmerksamkeit. Stalwart hat
zwischen dem 12. Juli und dem 5. Oktober <strong>dreizehn Releases</strong> veröffentlicht, also ungefähr
wöchentlich; du entscheidest bei jedem, ob du ihn mitnimmst, und bleibst dafür auf einem festen
Versions-Tag. Mailcow kam im selben Jahr auf dreizehn Veröffentlichungen zwischen Januar und
Anfang Oktober, also grob monatlich, hat aber gar keine Versionsnummer im klassischen Sinn: Es ist ein
Rolling Release mit Monats-Tags, und <code>update.sh</code> holt immer den aktuellen Stand.</p>
<p>Keiner der beiden ist ein „einmal aufsetzen und vergessen&quot;. Stalwart lässt dir mehr Kontrolle
darüber, wann etwas passiert; Mailcow nimmt dir die Einzelentscheidungen ab.</p>
<h3 id="schritt-4-funktionsumfang--was-mailcow-hat-und-stalwart-nicht">Schritt 4: Funktionsumfang – was Mailcow hat und Stalwart nicht</h3>
<p>Hier hält sich ein Missverständnis hartnäckig, und es lohnt sich, es zuerst aus dem Weg zu räumen:
<strong>Stalwart kann Kalender und Kontakte.</strong> CalDAV, CardDAV und WebDAV sind vollständig an Bord, und
zwar in der kostenlosen Community-Edition. „Ich will Termine und Adressbuch auf demselben Server&quot;
ist also keine Entscheidungsfrage mehr.</p>
<p>Der echte Unterschied ist der Browser.</p>
<p>Mailcow liefert mit <strong>SOGo</strong> eine fertige Weboberfläche für Mail, Kalender und Kontakte. Du meldest
dich auf einem beliebigen Rechner an und bist drin. Stalwarts Weboberfläche ist etwas anderes: eine
<strong>Administrationskonsole</strong> plus ein kleines Selbstbedienungsportal, in dem Nutzer ihr Passwort, ihre
App-Passwörter und die Zwei-Faktor-Anmeldung verwalten. Ein Webmailer ist nicht dabei.</p>
<p><figure class="my-6"><img src="/tutorials/mailserver-stalwart-oder-mailcow/stalwart-konsole_hu_a19ec6f07805601a.webp" srcset="/tutorials/mailserver-stalwart-oder-mailcow/stalwart-konsole_hu_f57dc908d1a542e3.webp 480w, /tutorials/mailserver-stalwart-oder-mailcow/stalwart-konsole_hu_a19ec6f07805601a.webp 768w, /tutorials/mailserver-stalwart-oder-mailcow/stalwart-konsole_hu_14cb790471e8f0d1.webp 1200w, /tutorials/mailserver-stalwart-oder-mailcow/stalwart-konsole_hu_e97000a8fa212723.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/mailserver-stalwart-oder-mailcow/stalwart-konsole_hu_e4237369675ef16c.webp"
    alt="Die Stalwart-Verwaltungskonsole mit der Übersicht der angelegten Konten." title="Stalwart: eine Konsole zum Verwalten – aber kein Webmail."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Stalwart: eine Konsole zum Verwalten – aber kein Webmail.</figcaption></figure></p>
<p><figure class="my-6"><img src="/tutorials/mailserver-stalwart-oder-mailcow/mailcow-dashboard_hu_ad9179c8d5d1303e.webp" srcset="/tutorials/mailserver-stalwart-oder-mailcow/mailcow-dashboard_hu_6e0d3ec62afbb156.webp 480w, /tutorials/mailserver-stalwart-oder-mailcow/mailcow-dashboard_hu_ad9179c8d5d1303e.webp 768w, /tutorials/mailserver-stalwart-oder-mailcow/mailcow-dashboard_hu_695dfece3465dfb.webp 1200w, /tutorials/mailserver-stalwart-oder-mailcow/mailcow-dashboard_hu_ce16a419b9c361b7.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/mailserver-stalwart-oder-mailcow/mailcow-dashboard_hu_e670b172b8905e61.webp"
    alt="Das mailcow-Dashboard mit dem Systemüberblick nach der Anmeldung." title="Mailcow: dieselbe Admin-Oberfläche – von hier geht es direkt in den SOGo-Webmailer."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Mailcow: dieselbe Admin-Oberfläche – von hier geht es direkt in den SOGo-Webmailer.</figcaption></figure></p>
<p>Praktisch heißt das: Mit Stalwart braucht jeder Nutzer ein Mailprogramm – Thunderbird, die
Mail-App auf iOS und macOS, DAVx5 auf Android für Kalender und Kontakte. Für dich allein oder im
Haushalt ist das völlig in Ordnung, weil diese Programme ohnehin eingerichtet sind. Sobald aber
jemand von einem fremden Rechner an seine Post muss, fehlt dir etwas. Du kannst eine Webmail wie
Roundcube daneben stellen – dann ist es eben Container Nummer zwei.</p>
<p>Der zweite Unterschied: Mailcow bringt mit ClamAV einen <strong>Virenscanner</strong> mit, Stalwart nicht.
Stalwarts eingebauter Filter deckt Spam und Phishing ab; einen Virenscanner kannst du über Milter
oder MTA-Hooks anbinden, musst ihn aber selbst betreiben.</p>
<h3 id="schritt-5-angriffsfläche-lizenz-und-updates">Schritt 5: Angriffsfläche, Lizenz und Updates</h3>
<p>Das Sicherheitsargument für Stalwart wird oft zu groß erzählt. Rust bringt Speichersicherheit mit,
und Stalwart hat ein veröffentlichtes <a href="https://stalw.art/blog/security-audit">Security-Audit</a>
vorzuweisen. Daraus folgt aber nicht, dass Postfix und Dovecot unsicher wären – sie gehören zu den
am gründlichsten geprüften Programmen im Internet überhaupt.</p>
<p>Das tragfähige Argument ist nüchterner: Es geht um die <strong>Länge der Update-Kette</strong>. Achtzehn
Dienste bedeuten achtzehn Projekte mit eigenen Sicherheitsmeldungen, die jemand aufeinander
abstimmen muss. Dass mailcow genau das zuverlässig tut, ist der eigentliche Wert des Projekts –
aber es ist eine Abhängigkeit, die du eingehst.</p>
<p>Bei den Lizenzen dreht sich das Bild, und das wird selten erwähnt. <strong>Mailcow steht komplett unter
GPL-3.0</strong> – alles, was es kann, kannst du kostenlos nutzen. Stalwart ist doppelt lizenziert: die
Community-Edition unter AGPL-3.0, daneben eine kommerzielle Enterprise-Lizenz. Beide Editionen
teilen sich dieselbe Codebasis und, wie der Hersteller selbst schreibt, dieselben Protokolle und
Kernfunktionen. Was die Enterprise-Edition zusätzlich bietet, ist Betriebswerkzeug für große
Installationen: Mandantenfähigkeit, eigenes Branding, Archivierung und Wiederherstellung
gelöschter Postfächer, ein KI-gestützter Spam-Klassifizierer, Read Replicas.</p>
<p>Für einen Haushalt oder die eigene Firmendomain ist davon nichts relevant. Eine Falle steckt
trotzdem darin: Die große Feature-Liste auf GitHub markiert <strong>nicht</strong>, welcher Punkt zu welcher
Edition gehört. Wenn du dich auf eine bestimmte Funktion verlässt, sieh vorher in der
Editionsübersicht nach, statt der README zu vertrauen.</p>
<h3 id="schritt-6-die-entscheidungstabelle">Schritt 6: Die Entscheidungstabelle</h3>
<table>
	<thead>
			<tr>
					<th>Dein Fall</th>
					<th>Nimm</th>
					<th>Weil</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Du hast einen Server mit Traefik und willst Mail dazu</td>
					<td>Stalwart</td>
					<td>Mailcow passt dort nur, wenn 6 GB RAM frei sind</td>
			</tr>
			<tr>
					<td>Alle sollen aus jedem Browser an ihre Mail kommen</td>
					<td>Mailcow</td>
					<td>SOGo-Webmail ist fertig dabei</td>
			</tr>
			<tr>
					<td>Du betreust Postfächer für andere</td>
					<td>Mailcow</td>
					<td>Mandantenfähigkeit kostet bei Stalwart extra</td>
			</tr>
			<tr>
					<td>Du willst so wenig Wartung wie möglich</td>
					<td>Stalwart</td>
					<td>ein Image statt achtzehn</td>
			</tr>
			<tr>
					<td>Dir stehen weniger als 8 GB RAM zur Verfügung</td>
					<td>Stalwart</td>
					<td>Mailcow setzt 6 GB als Minimum an</td>
			</tr>
			<tr>
					<td>Du willst einen Virenscanner ohne Zusatzarbeit</td>
					<td>Mailcow</td>
					<td>ClamAV ist Teil des Stacks</td>
			</tr>
			<tr>
					<td>Thunderbird, iOS-Mail oder DAVx5 sind ohnehin im Einsatz</td>
					<td>Stalwart</td>
					<td>CalDAV und CardDAV sind frei dabei</td>
			</tr>
			<tr>
					<td>Du brauchst viele Jahre Praxiserfahrung im Rücken</td>
					<td>Mailcow</td>
					<td>seit Ende 2016 im Einsatz</td>
			</tr>
	</tbody>
</table>
<p>Und wenn dich beim Lesen beschlichen hat, dass du eigentlich keines von beidem pflegen willst:
Ein seriöser Mail-Hoster ist eine vollkommen legitime Antwort auf diese Frage. Zustellbarkeit und
Reputation sind Dauerarbeit, und die bleibt bei dir – unabhängig davon, welche Software du wählst.</p>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<p>Die ersten beiden Punkte betreffen jede selbst betriebene Lösung und kosten die meiste Zeit, wenn
man sie nicht kennt.</p>
<div class="troubleshoot not-prose">
<p><strong>Mails nach außen bleiben hängen, die Logs zeigen Timeouts auf Port 25.</strong> Das liegt nicht an der
Software, sondern am Hoster: netcups Default-Policy „netcup Mail block&quot; sperrt 25, 465 und 587
ausgehend. Die Policy nimmst du dem Server im SCP unter <em>Firewall → Policys</em> selbst ab – kein
Supportfall, kein Ticket. Betrifft Stalwart und Mailcow gleichermaßen, siehe
<a href="/tutorials/netcup-firewall-einrichten/">netcup-Firewall einrichten</a>.</p>
<p><strong>Die Mails kommen an, landen aber überall im Spam.</strong> Dann fehlen Reverse-DNS (PTR), SPF, DKIM
oder DMARC. Auch das ist produktunabhängig und in
<a href="/tutorials/mailserver-zustellbarkeit/">E-Mail-Zustellbarkeit</a> Schritt für Schritt beschrieben.</p>
<p><strong>Mailcow startet nicht, die Logs melden <code>address already in use</code> für Port 80 oder 443.</strong> Auf dem
Server läuft bereits ein Reverse Proxy, und mailcows eigener nginx will dieselben Ports. Entweder
gibst du mailcow den Host für sich, oder du bindest seinen nginx wie in Schritt 2 auf einen
lokalen Port um und stellst ihn hinter den Proxy.</p>
<p><strong>Nach dem Mailcow-Setup sind plötzlich alle anderen Container weg.</strong> <code>generate_config.sh</code> hat auf
einem IPv6-Host die <code>/etc/docker/daemon.json</code> angelegt und Docker neu gestartet. Das ist gewolltes
Verhalten und verhindert ein offenes Relay, trifft aber eben den ganzen Host. Container mit
<code>restart: unless-stopped</code> kommen von allein zurück, alle anderen startest du von Hand.</p>
<p><strong>Das Mailprogramm warnt vor einem selbstsignierten Zertifikat <code>CN=rcgen self signed cert</code>.</strong>
Stalwart liefert noch seinen Platzhalter aus. Erst mit
<code>docker compose logs traefik-certs-dumper</code> nachsehen: Steht dort
<code>/traefik/acme.json is not a file</code>, zeigt der Pfad im Dumper nicht auf das Verzeichnis mit
Traefiks <code>acme.json</code>. Liegen die Dateien im Volume, fehlt nur der Neustart von Stalwart –
eingetragene Zertifikate werden erst danach ausgeliefert.</p>
<p><strong>Container werden nach kurzer Zeit vom Kernel beendet (OOM).</strong> Der Server ist für den gewählten
Stack zu klein. Bei Mailcow mit 18 Containern passiert das deutlich früher als bei Stalwart; als
erste Maßnahme schaltest du ClamAV in der <code>mailcow.conf</code> mit <code>SKIP_CLAMD=y</code> ab, denn der
Virenscanner ist der größte Speicherfresser.</p>

</div>
<p class="mt-3 text-sm text-slate-500 dark:text-slate-400">
  Dein Problem ist nicht dabei?
  <a href="/fehler/" class="font-medium text-paprika-700 hover:underline dark:text-paprika-400">Alle Fehlermeldungen durchsuchen →</a>
</p>

<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<p>Der Pflegeaufwand unterscheidet sich weniger, als die Containerzahl vermuten lässt – nur verteilt
er sich anders.</p>
<p><strong>Updates</strong> nimmst du bei Stalwart einzeln und bewusst mit, indem du den Versions-Tag hochziehst;
plane dafür etwa einmal im Monat einen Blick in die Release-Notes ein, auch wenn wöchentlich etwas
erscheint. Bei Mailcow läuft <code>update.sh</code> monatlich und erledigt alles auf einmal; lies die
angezeigten Hinweise, dort stehen bei größeren Sprüngen gelegentlich manuelle Schritte.</p>
<p><strong>Backups</strong> sind bei Stalwart schlicht: zwei Volumes, <code>stalwart_config</code> und <code>stalwart_data</code>, und
für einen konsistenten Stand stoppst du den Container kurz. Mailcow bringt ein eigenes
<code>backup_and_restore.sh</code> mit, das die vielen Volumes und die Datenbank zusammenfasst. In beiden
Fällen gehört das Ergebnis <strong>weg vom Server</strong>, am saubersten verschlüsselt mit
<a href="/tutorials/backups-mit-restic/">restic</a>.</p>
<p>Besonders wichtig sind in beiden Fällen die DKIM-Schlüssel: Gehen sie verloren, brechen nach einer
Wiederherstellung deine Signaturen, bis du die DNS-Records neu setzt. Und ein Backup, das du nie
zurückgespielt hast, ist nur ein Hoffnungswert – teste die Wiederherstellung einmal auf einem
Testsystem.</p>
<p><strong>Reputation</strong> behältst du unabhängig von der Software im Blick: Prüfe gelegentlich, ob deine
Server-IP auf einer Blockliste gelandet ist. Ein kompromittiertes Postfach, das Spam verschickt,
ruiniert die Reputation deiner ganzen Domain schnell – und das ist die einzige Aufgabe, die dir
keiner der beiden Mailserver abnimmt.</p>
]]></content:encoded></item></channel></rss>